diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 23:48:34 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-05-12 23:48:34 +0000 |
commit | 7fd36ebeeec9244a7431bb010e6e3c5e4848a0d5 (patch) | |
tree | 5fb03a9aafdd1cec5f4f6ff7f1873174cb89b66c /drivers | |
parent | ba2dacab305c598cd4c34a604f8e276bf5bab5ff (diff) |
Merge with Linux 2.3.99-pre8. Linus must hate me, too man patches ;-)
Diffstat (limited to 'drivers')
68 files changed, 22043 insertions, 6147 deletions
diff --git a/drivers/acorn/scsi/arxescsi.c b/drivers/acorn/scsi/arxescsi.c index 27e5b266a..2e04df6ca 100644 --- a/drivers/acorn/scsi/arxescsi.c +++ b/drivers/acorn/scsi/arxescsi.c @@ -1,7 +1,7 @@ /* * linux/arch/arm/drivers/scsi/arxescsi.c * - * Copyright (C) 1997-2000 Russell King + * Copyright (C) 1997-2000 Russell King, Stefan Hanske * * This driver is based on experimentation. Hence, it may have made * assumptions about the particular card that I have available, and @@ -11,9 +11,11 @@ * 30-08-1997 RMK 0.0.0 Created, READONLY version as cumana_2.c * 22-01-1998 RMK 0.0.1 Updated to 2.1.80 * 15-04-1998 RMK 0.0.1 Only do PIO if FAS216 will allow it. - * 11-06-1998 0.0.2 Changed to support ARXE 16-bit SCSI card, enabled writing - * by Stefan Hanske - * 02-04-2000 RMK 0.0.3 Updated for new error handling code. + * 11-06-1998 SH 0.0.2 Changed to support ARXE 16-bit SCSI card + * enabled writing + * 01-01-2000 SH 0.1.0 Added *real* pseudo dma writing + * (arxescsi_pseudo_dma_write) + * 02-04-2000 RMK 0.1.1 Updated for new error handling code. */ #include <linux/module.h> @@ -54,8 +56,8 @@ * Version */ #define VER_MAJOR 0 -#define VER_MINOR 0 -#define VER_PATCH 3 +#define VER_MINOR 1 +#define VER_PATCH 1 static struct expansion_card *ecs[MAX_ECARDS]; @@ -115,6 +117,33 @@ static __inline__ void putw(unsigned int address, unsigned int reg, unsigned lon : "r" (value), "r" (address), "r" (reg) ); } +void arxescsi_pseudo_dma_write(unsigned char *addr, unsigned int io) +{ + __asm__ __volatile__( + " stmdb sp!, {r0-r12}\n" + " mov r3, %0\n" + " mov r1, %1\n" + " add r2, r1, #512\n" + " mov r4, #256\n" + ".loop_1: ldmia r3!, {r6, r8, r10, r12}\n" + " mov r5, r6, lsl #16\n" + " mov r7, r8, lsl #16\n" + ".loop_2: ldrb r0, [r1, #1536]\n" + " tst r0, #1\n" + " beq .loop_2\n" + " stmia r2, {r5-r8}\n\t" + " mov r9, r10, lsl #16\n" + " mov r11, r12, lsl #16\n" + ".loop_3: ldrb r0, [r1, #1536]\n" + " tst r0, #1\n" + " beq .loop_3\n" + " stmia r2, {r9-r12}\n" + " subs r4, r4, #16\n" + " bne .loop_1\n" + " ldmia sp!, {r0-r12}\n" + : + : "r" (addr), "r" (io) ); +} /* * Function: int arxescsi_dma_pseudo(host, SCpnt, direction, transfer) @@ -136,26 +165,36 @@ void arxescsi_dma_pseudo(struct Scsi_Host *host, Scsi_Pointer *SCp, io = __ioaddr(host->io_port); if (direction == DMA_OUT) { - while (length > 0) { - unsigned long word; - - - word = *addr | *(addr + 1) << 8; - if (getb(io, 4) & STAT_INT) + unsigned int word; + while (length > 256) { + if (getb(io, 4) & STAT_INT) { + error=1; break; + } + arxescsi_pseudo_dma_write(addr, io); + addr += 256; + length -= 256; + } + + if (!error) + while (length > 0) { + if (getb(io, 4) & STAT_INT) + break; + + if (!(getb(io, 48) & CSTATUS_IRQ)) + continue; - if (!(getb(io, 48) & CSTATUS_IRQ)) - continue; + word = *addr | *(addr + 1) << 8; - putw(io, 16, word); - if (length > 1) { - addr += 2; - length -= 2; - } else { - addr += 1; - length -= 1; + putw(io, 16, word); + if (length > 1) { + addr += 2; + length -= 2; + } else { + addr += 1; + length -= 1; + } } - } } else { if (transfer && (transfer & 255)) { diff --git a/drivers/acorn/scsi/arxescsi.h b/drivers/acorn/scsi/arxescsi.h index dd97233ae..b95c9340a 100644 --- a/drivers/acorn/scsi/arxescsi.h +++ b/drivers/acorn/scsi/arxescsi.h @@ -41,9 +41,7 @@ extern int arxescsi_proc_info (char *buffer, char **start, off_t offset, #include <scsi/scsicam.h> -#ifndef HOSTS_C #include "fas216.h" -#endif #define ARXEScsi { \ proc_info: arxescsi_proc_info, \ diff --git a/drivers/acorn/scsi/cumana_2.h b/drivers/acorn/scsi/cumana_2.h index 48ac695b7..ec63eb347 100644 --- a/drivers/acorn/scsi/cumana_2.h +++ b/drivers/acorn/scsi/cumana_2.h @@ -39,9 +39,7 @@ extern int cumanascsi_2_proc_info (char *buffer, char **start, off_t offset, #include <scsi/scsicam.h> -#ifndef HOSTS_C #include "fas216.h" -#endif #define CUMANASCSI_2 { \ proc_info: cumanascsi_2_proc_info, \ diff --git a/drivers/block/Config.in b/drivers/block/Config.in index 4abd42a54..679545b7c 100644 --- a/drivers/block/Config.in +++ b/drivers/block/Config.in @@ -48,9 +48,12 @@ fi bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD dep_tristate ' Linear (append) mode' CONFIG_MD_LINEAR $CONFIG_BLK_DEV_MD -dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED $CONFIG_BLK_DEV_MD -#dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING $CONFIG_BLK_DEV_MD -#dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +dep_tristate ' RAID-0 (striping) mode' CONFIG_MD_RAID0 $CONFIG_BLK_DEV_MD +bool ' DANGEROUS! RAID1/RAID5 code' CONFIG_RAID15_DANGEROUS +if [ "$CONFIG_RAID15_DANGEROUS" = "y" ]; then + dep_tristate ' RAID-1 (mirroring) mode' CONFIG_MD_RAID1 $CONFIG_BLK_DEV_MD + dep_tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 $CONFIG_BLK_DEV_MD +fi tristate 'RAM disk support' CONFIG_BLK_DEV_RAM dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 9f5c813d7..66d5ba316 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -149,46 +149,32 @@ else endif endif -ifeq ($(CONFIG_MD_STRIPED),y) +ifeq ($(CONFIG_MD_RAID0),y) L_OBJS += raid0.o else - ifeq ($(CONFIG_MD_STRIPED),m) + ifeq ($(CONFIG_MD_RAID0),m) M_OBJS += raid0.o endif endif -ifeq ($(CONFIG_MD_MIRRORING),y) +ifeq ($(CONFIG_MD_RAID1),y) L_OBJS += raid1.o else - ifeq ($(CONFIG_MD_MIRRORING),m) + ifeq ($(CONFIG_MD_RAID1),m) M_OBJS += raid1.o endif endif ifeq ($(CONFIG_MD_RAID5),y) +LX_OBJS += xor.o L_OBJS += raid5.o else ifeq ($(CONFIG_MD_RAID5),m) + LX_OBJS += xor.o M_OBJS += raid5.o endif endif -ifeq ($(CONFIG_MD_TRANSLUCENT),y) -L_OBJS += translucent.o -else - ifeq ($(CONFIG_MD_TRANSLUCENT),m) - M_OBJS += translucent.o - endif -endif - -ifeq ($(CONFIG_MD_HSM),y) -L_OBJS += hsm.o -else - ifeq ($(CONFIG_MD_HSM),m) - M_OBJS += hsm.o - endif -endif - endif ifeq ($(CONFIG_BLK_DEV_NBD),y) diff --git a/drivers/block/linear.c b/drivers/block/linear.c index 978d75b80..926792a0f 100644 --- a/drivers/block/linear.c +++ b/drivers/block/linear.c @@ -184,13 +184,11 @@ static int linear_status (char *page, mddev_t *mddev) static mdk_personality_t linear_personality= { "linear", - NULL, linear_make_request, NULL, linear_run, linear_stop, linear_status, - NULL, 0, NULL, NULL, diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 12a08384f..4380900e9 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -373,40 +373,23 @@ void set_device_ro(kdev_t dev,int flag) else ro_bits[major][minor >> 5] &= ~(1 << (minor & 31)); } -static inline void drive_stat_acct(struct request *req, +inline void drive_stat_acct (kdev_t dev, int rw, unsigned long nr_sectors, int new_io) { - int major = MAJOR(req->rq_dev); - int minor = MINOR(req->rq_dev); - unsigned int disk_index; + unsigned int major = MAJOR(dev); + unsigned int index; - switch (major) { - case DAC960_MAJOR+0: - disk_index = (minor & 0x00f8) >> 3; - break; - case SCSI_DISK0_MAJOR: - disk_index = (minor & 0x00f0) >> 4; - break; - case IDE0_MAJOR: /* same as HD_MAJOR */ - case XT_DISK_MAJOR: - disk_index = (minor & 0x0040) >> 6; - break; - case IDE1_MAJOR: - disk_index = ((minor & 0x0040) >> 6) + 2; - break; - default: - return; - } - if (disk_index >= DK_NDRIVE) + index = disk_index(dev); + if ((index >= DK_MAX_DISK) || (major >= DK_MAX_MAJOR)) return; - kstat.dk_drive[disk_index] += new_io; - if (req->cmd == READ) { - kstat.dk_drive_rio[disk_index] += new_io; - kstat.dk_drive_rblk[disk_index] += nr_sectors; - } else if (req->cmd == WRITE) { - kstat.dk_drive_wio[disk_index] += new_io; - kstat.dk_drive_wblk[disk_index] += nr_sectors; + kstat.dk_drive[major][index] += new_io; + if (rw == READ) { + kstat.dk_drive_rio[major][index] += new_io; + kstat.dk_drive_rblk[major][index] += nr_sectors; + } else if (rw == WRITE) { + kstat.dk_drive_wio[major][index] += new_io; + kstat.dk_drive_wblk[major][index] += nr_sectors; } else printk(KERN_ERR "drive_stat_acct: cmd not R/W?\n"); } @@ -426,7 +409,7 @@ static inline void add_request(request_queue_t * q, struct request * req, { int major; - drive_stat_acct(req, req->nr_sectors, 1); + drive_stat_acct(req->rq_dev, req->cmd, req->nr_sectors, 1); if (list_empty(head)) { req->elevator_sequence = elevator_sequence(&q->elevator, latency); @@ -686,7 +669,7 @@ static inline void __make_request(request_queue_t * q, int rw, req->bhtail->b_reqnext = bh; req->bhtail = bh; req->nr_sectors = req->hard_nr_sectors += count; - drive_stat_acct(req, count, 0); + drive_stat_acct(req->rq_dev, req->cmd, count, 0); elevator_merge_after(elevator, req, latency); @@ -716,7 +699,7 @@ static inline void __make_request(request_queue_t * q, int rw, req->current_nr_sectors = count; req->sector = req->hard_sector = sector; req->nr_sectors = req->hard_nr_sectors += count; - drive_stat_acct(req, count, 0); + drive_stat_acct(req->rq_dev, req->cmd, count, 0); elevator_merge_before(elevator, req, latency); @@ -1090,6 +1073,7 @@ EXPORT_SYMBOL(io_request_lock); EXPORT_SYMBOL(end_that_request_first); EXPORT_SYMBOL(end_that_request_last); EXPORT_SYMBOL(blk_init_queue); +EXPORT_SYMBOL(blk_get_queue); EXPORT_SYMBOL(blk_cleanup_queue); EXPORT_SYMBOL(blk_queue_headactive); EXPORT_SYMBOL(blk_queue_pluggable); diff --git a/drivers/block/md.c b/drivers/block/md.c index d9c1ab9c0..1af15fd05 100644 --- a/drivers/block/md.c +++ b/drivers/block/md.c @@ -1,6 +1,6 @@ /* md.c : Multiple Devices driver for Linux - Copyright (C) 1998, 1999, 2000 Ingo Molnar + Copyright (C) 1998, 1999, 2000 Ingo Molnar completely rewritten, based on the MD driver code from Marc Zyngier @@ -13,6 +13,11 @@ - RAID0 bugfixes: Mark Anthony Lisher <markal@iname.com> - Devfs support by Richard Gooch <rgooch@atnf.csiro.au> + - lots of fixes and improvements to the RAID1/RAID5 and generic + RAID code (such as request based resynchronization): + + Neil Brown <neilb@cse.unsw.edu.au>. + 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) @@ -25,6 +30,7 @@ #include <linux/config.h> #include <linux/raid/md.h> +#include <linux/raid/xor.h> #include <linux/devfs_fs_kernel.h> #ifdef CONFIG_KMOD @@ -39,8 +45,6 @@ extern asmlinkage int sys_sched_yield(void); extern asmlinkage int sys_setsid(void); -extern unsigned long io_events[MAX_BLKDEV]; - #define MAJOR_NR MD_MAJOR #define MD_DRIVER @@ -56,6 +60,41 @@ extern unsigned long io_events[MAX_BLKDEV]; static mdk_personality_t *pers[MAX_PERSONALITY] = {NULL, }; /* + * Current RAID-1,4,5 parallel reconstruction 'guaranteed speed limit' + * is 100 KB/sec, so the extra system load does not show up that much. + * Increase it if you want to have more _guaranteed_ speed. Note that + * the RAID driver will use the maximum available bandwith if the IO + * subsystem is idle. There is also an 'absolute maximum' reconstruction + * speed limit - in case reconstruction slows down your system despite + * idle IO detection. + * + * you can change it via /proc/sys/dev/raid/speed_limit_min and _max. + */ + +static int sysctl_speed_limit_min = 100; +static int sysctl_speed_limit_max = 100000; + +static struct ctl_table_header *raid_table_header; + +static ctl_table raid_table[] = { + {DEV_RAID_SPEED_LIMIT_MIN, "speed_limit_min", + &sysctl_speed_limit_min, sizeof(int), 0644, NULL, &proc_dointvec}, + {DEV_RAID_SPEED_LIMIT_MAX, "speed_limit_max", + &sysctl_speed_limit_max, sizeof(int), 0644, NULL, &proc_dointvec}, + {0} +}; + +static ctl_table raid_dir_table[] = { + {DEV_RAID, "raid", NULL, 0, 0555, raid_table}, + {0} +}; + +static ctl_table raid_root_table[] = { + {CTL_DEV, "dev", NULL, 0, 0555, raid_dir_table}, + {0} +}; + +/* * these have to be allocated separately because external * subsystems want to have a pre-defined structure */ @@ -215,8 +254,8 @@ static mddev_t * alloc_mddev (kdev_t dev) blk_queue_make_request(q, md_make_request); q->plug_tq.sync = 0; - q->plug_tq.routine = &md_unplug_device; - q->plug_tq.data = mddev; + q->plug_tq.routine = &md_unplug_device; + q->plug_tq.data = mddev; /* * The 'base' mddev is the one with data NULL. @@ -504,7 +543,7 @@ static int read_disk_sb (mdk_rdev_t * rdev) struct buffer_head *bh = NULL; kdev_t dev = rdev->dev; mdp_super_t *sb; - u32 sb_offset; + unsigned long sb_offset; if (!rdev->sb) { MD_BUG(); @@ -517,8 +556,7 @@ static int read_disk_sb (mdk_rdev_t * rdev) */ sb_offset = calc_dev_sboffset(rdev->dev, rdev->mddev, 1); rdev->sb_offset = sb_offset; - printk("(read) %s's sb offset: %d", partition_name(dev), - sb_offset); + printk("(read) %s's sb offset: %ld", partition_name(dev), sb_offset); fsync_dev(dev); set_blocksize (dev, MD_SB_BYTES); bh = bread (dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); @@ -606,6 +644,18 @@ static mdk_rdev_t * match_dev_unit(mddev_t *mddev, kdev_t dev) return NULL; } +static int match_mddev_units(mddev_t *mddev1, mddev_t *mddev2) +{ + struct md_list_head *tmp; + mdk_rdev_t *rdev; + + ITERATE_RDEV(mddev1,rdev,tmp) + if (match_dev_unit(mddev2, rdev->dev)) + return 1; + + return 0; +} + static MD_LIST_HEAD(all_raid_disks); static MD_LIST_HEAD(pending_raid_disks); @@ -798,7 +848,7 @@ static void print_sb(mdp_super_t *sb) static void print_rdev(mdk_rdev_t *rdev) { - printk(" rdev %s: O:%s, SZ:%08d F:%d DN:%d ", + printk(" rdev %s: O:%s, SZ:%08ld F:%d DN:%d ", partition_name(rdev->dev), partition_name(rdev->old_dev), rdev->size, rdev->faulty, rdev->desc_nr); if (rdev->sb) { @@ -815,9 +865,9 @@ void md_print_devices (void) mddev_t *mddev; printk("\n"); - printk(" **********************************\n"); - printk(" * <COMPLETE RAID STATE PRINTOUT> *\n"); - printk(" **********************************\n"); + printk(" **********************************\n"); + printk(" * <COMPLETE RAID STATE PRINTOUT> *\n"); + printk(" **********************************\n"); ITERATE_MDDEV(mddev,tmp) { printk("md%d: ", mdidx(mddev)); @@ -833,7 +883,7 @@ void md_print_devices (void) ITERATE_RDEV(mddev,rdev,tmp2) print_rdev(rdev); } - printk(" **********************************\n"); + printk(" **********************************\n"); printk("\n"); } @@ -907,7 +957,7 @@ static int write_disk_sb(mdk_rdev_t * rdev) { struct buffer_head *bh; kdev_t dev; - u32 sb_offset, size; + unsigned long sb_offset, size; mdp_super_t *sb; if (!rdev->sb) { @@ -926,7 +976,7 @@ static int write_disk_sb(mdk_rdev_t * rdev) dev = rdev->dev; sb_offset = calc_dev_sboffset(dev, rdev->mddev, 1); if (rdev->sb_offset != sb_offset) { - printk("%s's sb offset has changed from %d to %d, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset); + printk("%s's sb offset has changed from %ld to %ld, skipping\n", partition_name(dev), rdev->sb_offset, sb_offset); goto skip; } /* @@ -936,11 +986,11 @@ static int write_disk_sb(mdk_rdev_t * rdev) */ size = calc_dev_size(dev, rdev->mddev, 1); if (size != rdev->size) { - printk("%s's size has changed from %d to %d since import, skipping\n", partition_name(dev), rdev->size, size); + printk("%s's size has changed from %ld to %ld since import, skipping\n", partition_name(dev), rdev->size, size); goto skip; } - printk("(write) %s's sb offset: %d\n", partition_name(dev), sb_offset); + printk("(write) %s's sb offset: %ld\n", partition_name(dev), sb_offset); fsync_dev(dev); set_blocksize(dev, MD_SB_BYTES); bh = getblk(dev, sb_offset / MD_SB_BLOCKS, MD_SB_BYTES); @@ -1053,7 +1103,7 @@ repeat: printk("%s ", partition_name(rdev->dev)); if (!rdev->faulty) { printk("[events: %08lx]", - (unsigned long)get_unaligned(&rdev->sb->events)); + (unsigned long)get_unaligned(&rdev->sb->events)); err += write_disk_sb(rdev); } else printk(")\n"); @@ -1244,7 +1294,7 @@ static int analyze_sbs (mddev_t * mddev) } printk("%s's event counter: %08lx\n", partition_name(rdev->dev), - (unsigned long)get_unaligned(&rdev->sb->events)); + (unsigned long)get_unaligned(&rdev->sb->events)); if (!freshest) { freshest = rdev; continue; @@ -1488,7 +1538,7 @@ static int device_size_calculation (mddev_t * mddev) rdev->size = calc_dev_size(rdev->dev, mddev, persistent); if (rdev->size < sb->chunk_size / 1024) { printk (KERN_WARNING - "Dev %s smaller than chunk_size: %dk < %dk\n", + "Dev %s smaller than chunk_size: %ldk < %dk\n", partition_name(rdev->dev), rdev->size, sb->chunk_size / 1024); return -EINVAL; @@ -2640,7 +2690,7 @@ static int md_ioctl (struct inode *inode, struct file *file, case STOP_ARRAY: err = do_md_stop (mddev, 0); - goto done_unlock; + goto done; case STOP_ARRAY_RO: err = do_md_stop (mddev, 1); @@ -2817,13 +2867,13 @@ int md_thread(void * arg) DECLARE_WAITQUEUE(wait, current); add_wait_queue(&thread->wqueue, &wait); + set_task_state(current, TASK_INTERRUPTIBLE); if (!test_bit(THREAD_WAKEUP, &thread->flags)) { - set_task_state(current, TASK_INTERRUPTIBLE); dprintk("thread %p went to sleep.\n", thread); schedule(); dprintk("thread %p woke up.\n", thread); - current->state = TASK_RUNNING; } + current->state = TASK_RUNNING; remove_wait_queue(&thread->wqueue, &wait); clear_bit(THREAD_WAKEUP, &thread->flags); @@ -2914,12 +2964,13 @@ void md_recover_arrays (void) int md_error (kdev_t dev, kdev_t rdev) { - mddev_t *mddev = kdev_to_mddev(dev); + mddev_t *mddev; mdk_rdev_t * rrdev; int rc; - printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3)); - + mddev = kdev_to_mddev(dev); +/* printk("md_error dev:(%d:%d), rdev:(%d:%d), (caller: %p,%p,%p,%p).\n",MAJOR(dev),MINOR(dev),MAJOR(rdev),MINOR(rdev), __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2),__builtin_return_address(3)); + */ if (!mddev) { MD_BUG(); return 0; @@ -2970,11 +3021,10 @@ static int status_unused (char * page) static int status_resync (char * page, mddev_t * mddev) { int sz = 0; - unsigned int blocksize, max_blocks, resync, res, dt, tt, et; + unsigned int max_blocks, resync, res, dt, tt, et; resync = mddev->curr_resync; - blocksize = blksize_size[MD_MAJOR][mdidx(mddev)]; - max_blocks = blk_size[MD_MAJOR][mdidx(mddev)] / (blocksize >> 10); + max_blocks = mddev->sb->size; /* * Should not happen. @@ -3093,7 +3143,7 @@ static int md_status_read_proc(char *page, char **start, off_t off, sz += status_resync (page+sz, mddev); } else { if (md_atomic_read(&mddev->resync_sem.count) != 1) - sz += sprintf(page + sz, " resync=DELAYED"); + sz += sprintf(page + sz, " resync=DELAYED"); } sz += sprintf(page + sz, "\n"); } @@ -3125,6 +3175,298 @@ int unregister_md_personality (int pnum) return 0; } +static mdp_disk_t *get_spare(mddev_t *mddev) +{ + mdp_super_t *sb = mddev->sb; + mdp_disk_t *disk; + mdk_rdev_t *rdev; + struct md_list_head *tmp; + + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) + continue; + if (!rdev->sb) { + MD_BUG(); + continue; + } + disk = &sb->disks[rdev->desc_nr]; + if (disk_faulty(disk)) { + MD_BUG(); + continue; + } + if (disk_active(disk)) + continue; + return disk; + } + return NULL; +} + +static int is_mddev_idle (mddev_t *mddev) +{ + mdk_rdev_t * rdev; + struct md_list_head *tmp; + int idle; + unsigned long curr_events; + + idle = 1; + ITERATE_RDEV(mddev,rdev,tmp) { + int major = MAJOR(rdev->dev); + int idx = disk_index(rdev->dev); + + curr_events = kstat.dk_drive_rblk[major][idx] + + kstat.dk_drive_wblk[major][idx] ; +// printk("events(major: %d, idx: %d): %ld\n", major, idx, curr_events); + if (curr_events != rdev->last_events) { +// printk("!I(%ld)", curr_events - rdev->last_events); + rdev->last_events = curr_events; + idle = 0; + } + } + return idle; +} + +MD_DECLARE_WAIT_QUEUE_HEAD(resync_wait); + +void md_done_sync(mddev_t *mddev, int blocks, int ok) +{ + /* another "blocks" (1K) blocks have been synced */ + atomic_sub(blocks, &mddev->recovery_active); + wake_up(&mddev->recovery_wait); + if (!ok) { + // stop recovery, signal do_sync .... + } +} + +int md_do_sync(mddev_t *mddev, mdp_disk_t *spare) +{ + mddev_t *mddev2; + unsigned int max_blocks, currspeed, + j, window, err, serialize; + kdev_t read_disk = mddev_to_kdev(mddev); + unsigned long starttime; + struct md_list_head *tmp; + unsigned long last_check; + + + err = down_interruptible(&mddev->resync_sem); + if (err) + goto out_nolock; + +recheck: + serialize = 0; + ITERATE_MDDEV(mddev2,tmp) { + if (mddev2 == mddev) + continue; + if (mddev2->curr_resync && match_mddev_units(mddev,mddev2)) { + printk(KERN_INFO "md: serializing resync, md%d has overlapping physical units with md%d!\n", mdidx(mddev), mdidx(mddev2)); + serialize = 1; + break; + } + } + if (serialize) { + interruptible_sleep_on(&resync_wait); + if (md_signal_pending(current)) { + md_flush_signals(); + err = -EINTR; + goto out; + } + goto recheck; + } + + mddev->curr_resync = 1; + + max_blocks = mddev->sb->size; + + printk(KERN_INFO "md: syncing RAID array md%d\n", mdidx(mddev)); + printk(KERN_INFO "md: minimum _guaranteed_ reconstruction speed: %d KB/sec/disc.\n", + sysctl_speed_limit_min); + printk(KERN_INFO "md: using maximum available idle IO bandwith (but not more than %d KB/sec) for reconstruction.\n", sysctl_speed_limit_max); + + /* + * Resync has low priority. + */ + current->priority = 1; + + is_mddev_idle(mddev); /* this also initializes IO event counters */ + starttime = jiffies; + mddev->resync_start = starttime; + + /* + * Tune reconstruction: + */ + window = md_maxreadahead[mdidx(mddev)]/1024; + printk(KERN_INFO "md: using %dk window, over a total of %d blocks.\n",window,max_blocks); + + atomic_set(&mddev->recovery_active, 0); + init_waitqueue_head(&mddev->recovery_wait); + last_check = 0; + for (j = 0; j < max_blocks;) { + int blocks; + if (j) + mddev->curr_resync = j; + +/* wait_event(mddev->recovery_wait, + atomic_read(&mddev->recovery_active) < window); +*/ + blocks = mddev->pers->sync_request(mddev, j); + + if (blocks < 0) { + err = blocks; + goto out; + } + atomic_add(blocks, &mddev->recovery_active); + j += blocks; + + if (last_check + window > j) + continue; + + run_task_queue(&tq_disk); //?? + + + if (md_signal_pending(current)) { + /* + * got a signal, exit. + */ + mddev->curr_resync = 0; + printk("md_do_sync() got signal ... exiting\n"); + md_flush_signals(); + err = -EINTR; + goto out; + } + + /* + * this loop exits only if either when we are slower than + * the 'hard' speed limit, or the system was IO-idle for + * a jiffy. + * the system might be non-idle CPU-wise, but we only care + * about not overloading the IO subsystem. (things like an + * e2fsck being done on the RAID array should execute fast) + */ +repeat: + if (md_need_resched(current)) + schedule(); + + currspeed = j/((jiffies-starttime)/HZ + 1) + 1; + if (currspeed > sysctl_speed_limit_min) { + current->priority = 1; + + if ((currspeed > sysctl_speed_limit_max) || + !is_mddev_idle(mddev)) { + current->state = TASK_INTERRUPTIBLE; + md_schedule_timeout(HZ/4); + if (!md_signal_pending(current)) + goto repeat; + } + } else + current->priority = 40; + } + wait_event(mddev->recovery_wait, atomic_read(&mddev->recovery_active)==0); + fsync_dev(read_disk); + printk(KERN_INFO "md: md%d: sync done.\n",mdidx(mddev)); + err = 0; + /* + * this also signals 'finished resyncing' to md_stop + */ +out: + up(&mddev->resync_sem); +out_nolock: + mddev->curr_resync = 0; + wake_up(&resync_wait); + return err; +} + + +/* + * This is a kernel thread which syncs a spare disk with the active array + * + * the amount of foolproofing might seem to be a tad excessive, but an + * early (not so error-safe) version of raid1syncd synced the first 0.5 gigs + * of my root partition with the first 0.5 gigs of my /home partition ... so + * i'm a bit nervous ;) + */ +void md_do_recovery (void *data) +{ + int err; + mddev_t *mddev; + mdp_super_t *sb; + mdp_disk_t *spare; + struct md_list_head *tmp; + + printk(KERN_INFO "md: recovery thread got woken up ...\n"); +restart: + ITERATE_MDDEV(mddev,tmp) { + sb = mddev->sb; + if (!sb) + continue; + if (mddev->recovery_running) + continue; + if (sb->active_disks == sb->raid_disks) + continue; + if (!sb->spare_disks) { + printk(KERN_ERR "md%d: no spare disk to reconstruct array! -- continuing in degraded mode\n", mdidx(mddev)); + continue; + } + /* + * now here we get the spare and resync it. + */ + if ((spare = get_spare(mddev)) == NULL) + continue; + printk(KERN_INFO "md%d: resyncing spare disk %s to replace failed disk\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor))); + if (!mddev->pers->diskop) + continue; + if (mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_WRITE)) + continue; + down(&mddev->recovery_sem); + mddev->recovery_running = 1; + err = md_do_sync(mddev, spare); + if (err == -EIO) { + printk(KERN_INFO "md%d: spare disk %s failed, skipping to next spare.\n", mdidx(mddev), partition_name(MKDEV(spare->major,spare->minor))); + if (!disk_faulty(spare)) { + mddev->pers->diskop(mddev,&spare,DISKOP_SPARE_INACTIVE); + mark_disk_faulty(spare); + mark_disk_nonsync(spare); + mark_disk_inactive(spare); + sb->spare_disks--; + sb->working_disks--; + sb->failed_disks++; + } + } else + if (disk_faulty(spare)) + mddev->pers->diskop(mddev, &spare, + DISKOP_SPARE_INACTIVE); + if (err == -EINTR) { + /* + * Recovery got interrupted ... + * signal back that we have finished using the array. + */ + mddev->pers->diskop(mddev, &spare, + DISKOP_SPARE_INACTIVE); + up(&mddev->recovery_sem); + mddev->recovery_running = 0; + continue; + } else { + mddev->recovery_running = 0; + up(&mddev->recovery_sem); + } + if (!disk_faulty(spare)) { + /* + * the SPARE_ACTIVE diskop possibly changes the + * pointer too + */ + mddev->pers->diskop(mddev, &spare, DISKOP_SPARE_ACTIVE); + mark_disk_sync(spare); + mark_disk_active(spare); + sb->active_disks++; + sb->spare_disks--; + } + mddev->sb_dirty = 1; + md_update_sb(mddev); + goto restart; + } + printk(KERN_INFO "md: recovery thread finished ...\n"); + +} + int md_notify_reboot(struct notifier_block *this, unsigned long code, void *x) { @@ -3211,6 +3553,8 @@ void raid5_init (void); int md__init md_init (void) { + static char * name = "mdrecoveryd"; + printk (KERN_INFO "md driver %d.%d.%d MAX_MD_DEVS=%d, MAX_REAL=%d\n", MD_MAJOR_VERSION, MD_MINOR_VERSION, MD_PATCHLEVEL_VERSION, MAX_MD_DEVS, MAX_REAL); @@ -3222,8 +3566,8 @@ int md__init md_init (void) } devfs_handle = devfs_mk_dir (NULL, "md", 0, NULL); devfs_register_series (devfs_handle, "%u",MAX_MD_DEVS,DEVFS_FL_DEFAULT, - MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, 0, 0, - &md_fops, NULL); + MAJOR_NR, 0, S_IFBLK | S_IRUSR | S_IWUSR, 0, 0, + &md_fops, NULL); blk_dev[MD_MAJOR].queue = md_get_queue; @@ -3232,24 +3576,29 @@ int md__init md_init (void) gendisk_head = &md_gendisk; + md_recovery_thread = md_register_thread(md_do_recovery, NULL, name); + if (!md_recovery_thread) + printk(KERN_ALERT "bug: couldn't allocate md_recovery_thread\n"); + md_register_reboot_notifier(&md_notifier); + raid_table_header = register_sysctl_table(raid_root_table, 1); #ifdef CONFIG_MD_LINEAR linear_init (); #endif -#ifdef CONFIG_MD_STRIPED +#ifdef CONFIG_MD_RAID0 raid0_init (); #endif -#ifdef CONFIG_MD_MIRRORING +#ifdef CONFIG_MD_RAID1 raid1_init (); #endif #ifdef CONFIG_MD_RAID5 raid5_init (); #endif #if defined(CONFIG_MD_RAID5) || defined(CONFIG_MD_RAID5_MODULE) - /* - * pick a XOR routine, runtime. - */ + /* + * pick a XOR routine, runtime. + */ calibrate_xor_block(); #endif md_geninit(); @@ -3261,6 +3610,8 @@ MD_EXPORT_SYMBOL(register_md_personality); MD_EXPORT_SYMBOL(unregister_md_personality); MD_EXPORT_SYMBOL(partition_name); MD_EXPORT_SYMBOL(md_error); +MD_EXPORT_SYMBOL(md_do_sync); +MD_EXPORT_SYMBOL(md_done_sync); MD_EXPORT_SYMBOL(md_recover_arrays); MD_EXPORT_SYMBOL(md_register_thread); MD_EXPORT_SYMBOL(md_unregister_thread); diff --git a/drivers/block/raid0.c b/drivers/block/raid0.c index 0e075277a..83700e235 100644 --- a/drivers/block/raid0.c +++ b/drivers/block/raid0.c @@ -41,7 +41,7 @@ static int create_strip_zones (mddev_t *mddev) printk("raid0: looking at %s\n", partition_name(rdev1->dev)); c = 0; ITERATE_RDEV_ORDERED(mddev,rdev2,j2) { - printk("raid0: comparing %s(%d) with %s(%d)\n", partition_name(rdev1->dev), rdev1->size, partition_name(rdev2->dev), rdev2->size); + printk("raid0: comparing %s(%ld) with %s(%ld)\n", partition_name(rdev1->dev), rdev1->size, partition_name(rdev2->dev), rdev2->size); if (rdev2 == rdev1) { printk("raid0: END\n"); break; @@ -95,7 +95,7 @@ static int create_strip_zones (mddev_t *mddev) c++; if (!smallest || (rdev->size <smallest->size)) { smallest = rdev; - printk(" (%d) is smallest!.\n", rdev->size); + printk(" (%ld) is smallest!.\n", rdev->size); } } else printk(" nope.\n"); @@ -326,13 +326,11 @@ static int raid0_status (char *page, mddev_t *mddev) static mdk_personality_t raid0_personality= { "raid0", - NULL, /* no special map */ raid0_make_request, NULL, /* no special end_request */ raid0_run, raid0_stop, raid0_status, - NULL, /* no ioctls */ 0, NULL, /* no error_handler */ NULL, /* no diskop */ diff --git a/drivers/block/raid1.c b/drivers/block/raid1.c index 057be0d64..89b3e7514 100644 --- a/drivers/block/raid1.c +++ b/drivers/block/raid1.c @@ -1,6 +1,9 @@ -/************************************************************************ +/* * raid1.c : Multiple Devices driver for Linux - * Copyright (C) 1996 Ingo Molnar, Miguel de Icaza, Gadi Oxman + * + * Copyright (C) 1999, 2000 Ingo Molnar, Red Hat + * + * Copyright (C) 1996, 1997, 1998 Ingo Molnar, Miguel de Icaza, Gadi Oxman * * RAID-1 management functions. * @@ -15,50 +18,86 @@ */ #include <linux/module.h> -#include <linux/locks.h> #include <linux/malloc.h> -#include <linux/md.h> -#include <linux/raid1.h> -#include <asm/bitops.h> +#include <linux/raid/raid1.h> #include <asm/atomic.h> #define MAJOR_NR MD_MAJOR #define MD_DRIVER #define MD_PERSONALITY +#define MAX_LINEAR_SECTORS 128 + +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) + /* * The following can be used to debug the driver */ -/*#define RAID1_DEBUG*/ -#ifdef RAID1_DEBUG -#define PRINTK(x) do { printk x; } while (0); +#define RAID1_DEBUG 0 + +#if RAID1_DEBUG +#define PRINTK(x...) printk(x) +#define inline +#define __inline__ #else -#define PRINTK(x) do { ; } while (0); +#define inline +#define __inline__ +#define PRINTK(x...) do { } while (0) #endif -#define MAX(a,b) ((a) > (b) ? (a) : (b)) -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -static struct md_personality raid1_personality; -static struct md_thread *raid1_thread = NULL; -struct buffer_head *raid1_retry_list = NULL; +static mdk_personality_t raid1_personality; +static md_spinlock_t retry_list_lock = MD_SPIN_LOCK_UNLOCKED; +struct buffer_head *raid1_retry_list = NULL, **raid1_retry_tail; + +static void * raid1_kmalloc (int size) +{ + void * ptr; + /* + * now we are rather fault tolerant than nice, but + * there are a couple of places in the RAID code where we + * simply can not afford to fail an allocation because + * there is no failure return path (eg. make_request()) + */ + while (!(ptr = kmalloc (size, GFP_KERNEL))) + printk ("raid1: out of memory, retrying...\n"); + + memset(ptr, 0, size); + return ptr; +} + +static struct page * raid1_gfp (void) +{ + struct page *page; + /* + * now we are rather fault tolerant than nice, but + * there are a couple of places in the RAID code where we + * simply can not afford to fail an allocation because + * there is no failure return path (eg. make_request()) + * FIXME: be nicer here. + */ + while (!(page = (void*)alloc_page(GFP_KERNEL))) { + printk ("raid1: GFP out of memory, retrying...\n"); + schedule_timeout(2); + } + + return page; +} -static int __raid1_map (struct md_dev *mddev, kdev_t *rdev, - unsigned long *rsector, unsigned long size) +static int raid1_map (mddev_t *mddev, kdev_t *rdev, unsigned long size) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - int i, n = raid_conf->raid_disks; + raid1_conf_t *conf = mddev_to_conf(mddev); + int i, disks = MD_SB_DISKS; /* * Later we do read balancing on the read side * now we use the first available disk. */ - PRINTK(("raid1_map().\n")); - - for (i=0; i<n; i++) { - if (raid_conf->mirrors[i].operational) { - *rdev = raid_conf->mirrors[i].dev; + for (i = 0; i < disks; i++) { + if (conf->mirrors[i].operational) { + *rdev = conf->mirrors[i].dev; return (0); } } @@ -67,59 +106,80 @@ static int __raid1_map (struct md_dev *mddev, kdev_t *rdev, return (-1); } -static int raid1_map (struct md_dev *mddev, kdev_t *rdev, - unsigned long *rsector, unsigned long size) +static void raid1_reschedule_retry (struct buffer_head *bh) { - return 0; + unsigned long flags; + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + mddev_t *mddev = r1_bh->mddev; + raid1_conf_t *conf = mddev_to_conf(mddev); + + md_spin_lock_irqsave(&retry_list_lock, flags); + if (raid1_retry_list == NULL) + raid1_retry_tail = &raid1_retry_list; + *raid1_retry_tail = bh; + raid1_retry_tail = &r1_bh->next_retry; + r1_bh->next_retry = NULL; + md_spin_unlock_irqrestore(&retry_list_lock, flags); + md_wakeup_thread(conf->thread); } -void raid1_reschedule_retry (struct buffer_head *bh) -{ - struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); - PRINTK(("raid1_reschedule_retry().\n")); +static void inline io_request_done(unsigned long sector, raid1_conf_t *conf, int phase) +{ + unsigned long flags; + spin_lock_irqsave(&conf->segment_lock, flags); + if (sector < conf->start_active) + conf->cnt_done--; + else if (sector >= conf->start_future && conf->phase == phase) + conf->cnt_future--; + else if (!--conf->cnt_pending) + wake_up(&conf->wait_ready); + + spin_unlock_irqrestore(&conf->segment_lock, flags); +} - r1_bh->next_retry = raid1_retry_list; - raid1_retry_list = bh; - md_wakeup_thread(raid1_thread); +static void inline sync_request_done (unsigned long sector, raid1_conf_t *conf) +{ + unsigned long flags; + spin_lock_irqsave(&conf->segment_lock, flags); + if (sector >= conf->start_ready) + --conf->cnt_ready; + else if (sector >= conf->start_active) { + if (!--conf->cnt_active) { + conf->start_active = conf->start_ready; + wake_up(&conf->wait_done); + } + } + spin_unlock_irqrestore(&conf->segment_lock, flags); } /* - * raid1_end_buffer_io() is called when we have finished servicing a mirrored + * raid1_end_bh_io() is called when we have finished servicing a mirrored * operation and are ready to return a success/failure code to the buffer * cache layer. */ -static inline void raid1_end_buffer_io(struct raid1_bh *r1_bh, int uptodate) +static void raid1_end_bh_io (struct raid1_bh *r1_bh, int uptodate) { struct buffer_head *bh = r1_bh->master_bh; + io_request_done(bh->b_rsector, mddev_to_conf(r1_bh->mddev), + test_bit(R1BH_SyncPhase, &r1_bh->state)); + bh->b_end_io(bh, uptodate); kfree(r1_bh); } - -int raid1_one_error=0; - void raid1_end_request (struct buffer_head *bh, int uptodate) { struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); - unsigned long flags; - save_flags(flags); - cli(); - PRINTK(("raid1_end_request().\n")); - - if (raid1_one_error) { - raid1_one_error=0; - uptodate=0; - } /* * this branch is our 'one mirror IO has finished' event handler: */ if (!uptodate) md_error (bh->b_dev, bh->b_rdev); - else { + else /* - * Set BH_Uptodate in our master buffer_head, so that + * Set R1BH_Uptodate in our master buffer_head, so that * we will return a good error code for to the higher * levels even if IO on some other mirrored buffer fails. * @@ -127,8 +187,7 @@ void raid1_end_request (struct buffer_head *bh, int uptodate) * user-side. So if something waits for IO, then it will * wait for the 'master' buffer_head. */ - set_bit (BH_Uptodate, &r1_bh->state); - } + set_bit (R1BH_Uptodate, &r1_bh->state); /* * We split up the read and write side, imho they are @@ -136,239 +195,253 @@ void raid1_end_request (struct buffer_head *bh, int uptodate) */ if ( (r1_bh->cmd == READ) || (r1_bh->cmd == READA) ) { - - PRINTK(("raid1_end_request(), read branch.\n")); - /* * we have only one buffer_head on the read side */ + if (uptodate) { - PRINTK(("raid1_end_request(), read branch, uptodate.\n")); - raid1_end_buffer_io(r1_bh, uptodate); - restore_flags(flags); + raid1_end_bh_io(r1_bh, uptodate); return; } /* * oops, read error: */ printk(KERN_ERR "raid1: %s: rescheduling block %lu\n", - kdevname(bh->b_dev), bh->b_blocknr); - raid1_reschedule_retry (bh); - restore_flags(flags); + partition_name(bh->b_dev), bh->b_blocknr); + raid1_reschedule_retry(bh); return; } /* - * WRITE. - */ - PRINTK(("raid1_end_request(), write branch.\n")); - - /* + * WRITE: + * * Let's see if all mirrored write operations have finished - * already [we have irqs off, so we can decrease]: + * already. */ - if (!--r1_bh->remaining) { - struct md_dev *mddev = r1_bh->mddev; - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - int i, n = raid_conf->raid_disks; - - PRINTK(("raid1_end_request(), remaining == 0.\n")); + if (atomic_dec_and_test(&r1_bh->remaining)) { + int i, disks = MD_SB_DISKS; - for ( i=0; i<n; i++) - if (r1_bh->mirror_bh[i]) kfree(r1_bh->mirror_bh[i]); + for ( i = 0; i < disks; i++) { + struct buffer_head *bh = r1_bh->mirror_bh[i]; + if (bh) { + // FIXME: make us a regular bcache member + kfree(bh); + } + } - raid1_end_buffer_io(r1_bh, test_bit(BH_Uptodate, &r1_bh->state)); + raid1_end_bh_io(r1_bh, test_bit(R1BH_Uptodate, &r1_bh->state)); } - else PRINTK(("raid1_end_request(), remaining == %u.\n", r1_bh->remaining)); - restore_flags(flags); } -/* This routine checks if the undelying device is an md device and in that - * case it maps the blocks before putting the request on the queue - */ -static inline void -map_and_make_request (int rw, struct buffer_head *bh) -{ - if (MAJOR (bh->b_rdev) == MD_MAJOR) - md_map (MINOR (bh->b_rdev), &bh->b_rdev, &bh->b_rsector, bh->b_size >> 9); - clear_bit(BH_Lock, &bh->b_state); - make_request (MAJOR (bh->b_rdev), rw, bh); -} - -static int -raid1_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) +static int raid1_make_request (request_queue_t *q, mddev_t *mddev, int rw, + struct buffer_head * bh) { - - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); struct buffer_head *mirror_bh[MD_SB_DISKS], *bh_req; struct raid1_bh * r1_bh; - int n = raid_conf->raid_disks, i, sum_bhs = 0, switch_disks = 0, sectors; + int disks = MD_SB_DISKS; + int i, sum_bhs = 0, switch_disks = 0, sectors; struct mirror_info *mirror; + DECLARE_WAITQUEUE(wait, current); - PRINTK(("raid1_make_request().\n")); - - while (!( /* FIXME: now we are rather fault tolerant than nice */ - r1_bh = kmalloc (sizeof (struct raid1_bh), GFP_KERNEL) - ) ) - { - printk ("raid1_make_request(#1): out of memory\n"); - current->policy |= SCHED_YIELD; - schedule(); - } - memset (r1_bh, 0, sizeof (struct raid1_bh)); - + if (!buffer_locked(bh)) + BUG(); + /* * make_request() can abort the operation when READA is being * used and no empty request is available. * * Currently, just replace the command with READ/WRITE. */ - if (rw == READA) rw = READ; + if (rw == READA) + rw = READ; - if (rw == WRITE) - mark_buffer_clean(bh); /* Too early ? */ + if (rw == WRITE) { + rw = WRITERAW; + /* + * we first clean the bh, then we start the IO, then + * when the IO has finished, we end_io the bh and + * mark it uptodate. This way we do not miss the + * case when the bh got dirty again during the IO. + * + * We do an important optimization here - if the + * buffer was not dirty and we are during resync or + * reconstruction, then we can skip writing it back + * to the master disk! (we still have to write it + * back to the other disks, because we are not sync + * yet.) + */ + if (atomic_set_buffer_clean(bh)) + __mark_buffer_clean(bh); + else { + bh->b_end_io(bh, test_bit(BH_Uptodate, &bh->b_state)); + return 0; + } + } + r1_bh = raid1_kmalloc (sizeof (struct raid1_bh)); -/* - * i think the read and write branch should be separated completely, since we want - * to do read balancing on the read side for example. Comments? :) --mingo - */ - r1_bh->master_bh=bh; - r1_bh->mddev=mddev; + spin_lock_irq(&conf->segment_lock); + wait_event_lock_irq(conf->wait_done, + bh->b_rsector < conf->start_active || + bh->b_rsector >= conf->start_future, + conf->segment_lock); + if (bh->b_rsector < conf->start_active) + conf->cnt_done++; + else { + conf->cnt_future++; + if (conf->phase) + set_bit(R1BH_SyncPhase, &r1_bh->state); + } + spin_unlock_irq(&conf->segment_lock); + + /* + * i think the read and write branch should be separated completely, + * since we want to do read balancing on the read side for example. + * Alternative implementations? :) --mingo + */ + + r1_bh->master_bh = bh; + r1_bh->mddev = mddev; r1_bh->cmd = rw; + bh->b_rsector = bh->b_blocknr * (bh->b_size>>9); + + if (rw == READ) { + int last_used = conf->last_used; - if (rw==READ || rw==READA) { - int last_used = raid_conf->last_used; - PRINTK(("raid1_make_request(), read branch.\n")); - mirror = raid_conf->mirrors + last_used; + /* + * read balancing logic: + */ + mirror = conf->mirrors + last_used; bh->b_rdev = mirror->dev; sectors = bh->b_size >> 9; - if (bh->b_blocknr * sectors == raid_conf->next_sect) { - raid_conf->sect_count += sectors; - if (raid_conf->sect_count >= mirror->sect_limit) + + switch_disks = 0; + if (bh->b_blocknr * sectors == conf->next_sect) { + conf->sect_count += sectors; + if (conf->sect_count >= mirror->sect_limit) switch_disks = 1; } else switch_disks = 1; - raid_conf->next_sect = (bh->b_blocknr + 1) * sectors; - if (switch_disks) { - PRINTK(("read-balancing: switching %d -> %d (%d sectors)\n", last_used, mirror->next, raid_conf->sect_count)); - raid_conf->sect_count = 0; - last_used = raid_conf->last_used = mirror->next; + conf->next_sect = (bh->b_blocknr + 1) * sectors; + /* + * Do not switch disks if full resync is in progress ... + */ + if (switch_disks && !conf->resync_mirrors) { + conf->sect_count = 0; + last_used = conf->last_used = mirror->next; /* - * Do not switch to write-only disks ... resyncing - * is in progress + * Do not switch to write-only disks ... + * reconstruction is in progress */ - while (raid_conf->mirrors[last_used].write_only) - raid_conf->last_used = raid_conf->mirrors[last_used].next; + while (conf->mirrors[last_used].write_only) + conf->last_used = conf->mirrors[last_used].next; } - PRINTK (("raid1 read queue: %d %d\n", MAJOR (bh->b_rdev), MINOR (bh->b_rdev))); bh_req = &r1_bh->bh_req; memcpy(bh_req, bh, sizeof(*bh)); bh_req->b_end_io = raid1_end_request; bh_req->b_dev_id = r1_bh; - map_and_make_request (rw, bh_req); + q = blk_get_queue(bh_req->b_rdev); + generic_make_request (q, rw, bh_req); return 0; } /* - * WRITE. + * WRITE: */ - PRINTK(("raid1_make_request(n=%d), write branch.\n",n)); - for (i = 0; i < n; i++) { + for (i = 0; i < disks; i++) { - if (!raid_conf->mirrors [i].operational) { + if (!conf->mirrors[i].operational) { /* * the r1_bh->mirror_bh[i] pointer remains NULL */ mirror_bh[i] = NULL; continue; } - + /* * We should use a private pool (size depending on NR_REQUEST), * to avoid writes filling up the memory with bhs * - * Such pools are much faster than kmalloc anyways (so we waste almost - * nothing by not using the master bh when writing and win alot of cleanness) - * - * but for now we are cool enough. --mingo - * + * Such pools are much faster than kmalloc anyways (so we waste + * almost nothing by not using the master bh when writing and + * win alot of cleanness) but for now we are cool enough. --mingo + * * It's safe to sleep here, buffer heads cannot be used in a shared - * manner in the write branch. Look how we lock the buffer at the beginning - * of this function to grok the difference ;) + * manner in the write branch. Look how we lock the buffer at the + * beginning of this function to grok the difference ;) */ - while (!( /* FIXME: now we are rather fault tolerant than nice */ - mirror_bh[i] = kmalloc (sizeof (struct buffer_head), GFP_KERNEL) - ) ) - { - printk ("raid1_make_request(#2): out of memory\n"); - current->policy |= SCHED_YIELD; - schedule(); - } - memset (mirror_bh[i], 0, sizeof (struct buffer_head)); - - /* - * prepare mirrored bh (fields ordered for max mem throughput): - */ - mirror_bh [i]->b_blocknr = bh->b_blocknr; - mirror_bh [i]->b_dev = bh->b_dev; - mirror_bh [i]->b_rdev = raid_conf->mirrors [i].dev; - mirror_bh [i]->b_rsector = bh->b_rsector; - mirror_bh [i]->b_state = (1<<BH_Req) | (1<<BH_Dirty); - atomic_set(&mirror_bh [i]->b_count, 1); - mirror_bh [i]->b_size = bh->b_size; - mirror_bh [i]->b_data = bh->b_data; - mirror_bh [i]->b_list = BUF_LOCKED; - mirror_bh [i]->b_end_io = raid1_end_request; - mirror_bh [i]->b_dev_id = r1_bh; - - r1_bh->mirror_bh[i] = mirror_bh[i]; + mirror_bh[i] = raid1_kmalloc(sizeof(struct buffer_head)); + mirror_bh[i]->b_this_page = (struct buffer_head *)1; + + /* + * prepare mirrored bh (fields ordered for max mem throughput): + */ + mirror_bh[i]->b_blocknr = bh->b_blocknr; + mirror_bh[i]->b_dev = bh->b_dev; + mirror_bh[i]->b_rdev = conf->mirrors[i].dev; + mirror_bh[i]->b_rsector = bh->b_rsector; + mirror_bh[i]->b_state = (1<<BH_Req) | (1<<BH_Dirty) | + (1<<BH_Mapped) | (1<<BH_Lock); + + atomic_set(&mirror_bh[i]->b_count, 1); + mirror_bh[i]->b_size = bh->b_size; + mirror_bh[i]->b_data = bh->b_data; + mirror_bh[i]->b_list = BUF_LOCKED; + mirror_bh[i]->b_end_io = raid1_end_request; + mirror_bh[i]->b_dev_id = r1_bh; + + r1_bh->mirror_bh[i] = mirror_bh[i]; sum_bhs++; } - r1_bh->remaining = sum_bhs; - - PRINTK(("raid1_make_request(), write branch, sum_bhs=%d.\n",sum_bhs)); + md_atomic_set(&r1_bh->remaining, sum_bhs); /* - * We have to be a bit careful about the semaphore above, thats why we - * start the requests separately. Since kmalloc() could fail, sleep and - * make_request() can sleep too, this is the safer solution. Imagine, - * end_request decreasing the semaphore before we could have set it up ... - * We could play tricks with the semaphore (presetting it and correcting - * at the end if sum_bhs is not 'n' but we have to do end_request by hand - * if all requests finish until we had a chance to set up the semaphore - * correctly ... lots of races). + * We have to be a bit careful about the semaphore above, thats + * why we start the requests separately. Since kmalloc() could + * fail, sleep and make_request() can sleep too, this is the + * safer solution. Imagine, end_request decreasing the semaphore + * before we could have set it up ... We could play tricks with + * the semaphore (presetting it and correcting at the end if + * sum_bhs is not 'n' but we have to do end_request by hand if + * all requests finish until we had a chance to set up the + * semaphore correctly ... lots of races). */ - for (i = 0; i < n; i++) - if (mirror_bh [i] != NULL) - map_and_make_request (rw, mirror_bh [i]); - + for (i = 0; i < disks; i++) { + struct buffer_head *mbh = mirror_bh[i]; + if (mbh) { + q = blk_get_queue(mbh->b_rdev); + generic_make_request(q, rw, mbh); + } + } return (0); } - -static int raid1_status (char *page, int minor, struct md_dev *mddev) + +static int raid1_status (char *page, mddev_t *mddev) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); int sz = 0, i; - sz += sprintf (page+sz, " [%d/%d] [", raid_conf->raid_disks, raid_conf->working_disks); - for (i = 0; i < raid_conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", raid_conf->mirrors [i].operational ? "U" : "_"); + sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, + conf->working_disks); + for (i = 0; i < conf->raid_disks; i++) + sz += sprintf (page+sz, "%s", + conf->mirrors[i].operational ? "U" : "_"); sz += sprintf (page+sz, "]"); return sz; } -static void raid1_fix_links (struct raid1_data *raid_conf, int failed_index) +static void unlink_disk (raid1_conf_t *conf, int target) { - int disks = raid_conf->raid_disks; - int j; + int disks = MD_SB_DISKS; + int i; - for (j = 0; j < disks; j++) - if (raid_conf->mirrors [j].next == failed_index) - raid_conf->mirrors [j].next = raid_conf->mirrors [failed_index].next; + for (i = 0; i < disks; i++) + if (conf->mirrors[i].next == target) + conf->mirrors[i].next = conf->mirrors[target].next; } #define LAST_DISK KERN_ALERT \ @@ -379,7 +452,7 @@ static void raid1_fix_links (struct raid1_data *raid_conf, int failed_index) #define DISK_FAILED KERN_ALERT \ "raid1: Disk failure on %s, disabling device. \n" \ -" Operation continuing on %d devices\n" +" Operation continuing on %d devices\n" #define START_SYNCING KERN_ALERT \ "raid1: start syncing spare disk.\n" @@ -387,48 +460,53 @@ static void raid1_fix_links (struct raid1_data *raid_conf, int failed_index) #define ALREADY_SYNCING KERN_INFO \ "raid1: syncing already in progress.\n" -static int raid1_error (struct md_dev *mddev, kdev_t dev) +static void mark_disk_bad (mddev_t *mddev, int failed) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - struct mirror_info *mirror; - md_superblock_t *sb = mddev->sb; - int disks = raid_conf->raid_disks; - int i; + raid1_conf_t *conf = mddev_to_conf(mddev); + struct mirror_info *mirror = conf->mirrors+failed; + mdp_super_t *sb = mddev->sb; + + mirror->operational = 0; + unlink_disk(conf, failed); + mark_disk_faulty(sb->disks+mirror->number); + mark_disk_nonsync(sb->disks+mirror->number); + mark_disk_inactive(sb->disks+mirror->number); + sb->active_disks--; + sb->working_disks--; + sb->failed_disks++; + mddev->sb_dirty = 1; + md_wakeup_thread(conf->thread); + conf->working_disks--; + printk (DISK_FAILED, partition_name (mirror->dev), + conf->working_disks); +} - PRINTK(("raid1_error called\n")); +static int raid1_error (mddev_t *mddev, kdev_t dev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + struct mirror_info * mirrors = conf->mirrors; + int disks = MD_SB_DISKS; + int i; - if (raid_conf->working_disks == 1) { + if (conf->working_disks == 1) { /* * Uh oh, we can do nothing if this is our last disk, but * first check if this is a queued request for a device * which has just failed. */ - for (i = 0, mirror = raid_conf->mirrors; i < disks; - i++, mirror++) - if (mirror->dev == dev && !mirror->operational) + for (i = 0; i < disks; i++) { + if (mirrors[i].dev==dev && !mirrors[i].operational) return 0; + } printk (LAST_DISK); } else { - /* Mark disk as unusable */ - for (i = 0, mirror = raid_conf->mirrors; i < disks; - i++, mirror++) { - if (mirror->dev == dev && mirror->operational){ - mirror->operational = 0; - raid1_fix_links (raid_conf, i); - sb->disks[mirror->number].state |= - (1 << MD_FAULTY_DEVICE); - sb->disks[mirror->number].state &= - ~(1 << MD_SYNC_DEVICE); - sb->disks[mirror->number].state &= - ~(1 << MD_ACTIVE_DEVICE); - sb->active_disks--; - sb->working_disks--; - sb->failed_disks++; - mddev->sb_dirty = 1; - md_wakeup_thread(raid1_thread); - raid_conf->working_disks--; - printk (DISK_FAILED, kdevname (dev), - raid_conf->working_disks); + /* + * Mark disk as unusable + */ + for (i = 0; i < disks; i++) { + if (mirrors[i].dev==dev && mirrors[i].operational) { + mark_disk_bad(mddev, i); + break; } } } @@ -441,219 +519,658 @@ static int raid1_error (struct md_dev *mddev, kdev_t dev) #undef START_SYNCING /* - * This is the personality-specific hot-addition routine + * Insert the spare disk into the drive-ring */ +static void link_disk(raid1_conf_t *conf, struct mirror_info *mirror) +{ + int j, next; + int disks = MD_SB_DISKS; + struct mirror_info *p = conf->mirrors; -#define NO_SUPERBLOCK KERN_ERR \ -"raid1: cannot hot-add disk to the array with no RAID superblock\n" - -#define WRONG_LEVEL KERN_ERR \ -"raid1: hot-add: level of disk is not RAID-1\n" + for (j = 0; j < disks; j++, p++) + if (p->operational && !p->write_only) { + next = p->next; + p->next = mirror->raid_disk; + mirror->next = next; + return; + } -#define HOT_ADD_SUCCEEDED KERN_INFO \ -"raid1: device %s hot-added\n" + printk("raid1: bug: no read-operational devices\n"); +} -static int raid1_hot_add_disk (struct md_dev *mddev, kdev_t dev) +static void print_raid1_conf (raid1_conf_t *conf) { - unsigned long flags; - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; - struct mirror_info *mirror; - md_superblock_t *sb = mddev->sb; - struct real_dev * realdev; - int n; + int i; + struct mirror_info *tmp; + + printk("RAID1 conf printout:\n"); + if (!conf) { + printk("(conf==NULL)\n"); + return; + } + printk(" --- wd:%d rd:%d nd:%d\n", conf->working_disks, + conf->raid_disks, conf->nr_disks); + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + printk(" disk %d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", + i, tmp->spare,tmp->operational, + tmp->number,tmp->raid_disk,tmp->used_slot, + partition_name(tmp->dev)); + } +} +static int raid1_diskop(mddev_t *mddev, mdp_disk_t **d, int state) +{ + int err = 0; + int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; + raid1_conf_t *conf = mddev->private; + struct mirror_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *failed_desc, *spare_desc, *added_desc; + + print_raid1_conf(conf); + md_spin_lock_irq(&conf->device_lock); /* - * The device has its superblock already read and it was found - * to be consistent for generic RAID usage. Now we check whether - * it's usable for RAID-1 hot addition. + * find the disk ... */ + switch (state) { - n = mddev->nb_dev++; - realdev = &mddev->devices[n]; - if (!realdev->sb) { - printk (NO_SUPERBLOCK); - return -EINVAL; - } - if (realdev->sb->level != 1) { - printk (WRONG_LEVEL); - return -EINVAL; + case DISKOP_SPARE_ACTIVE: + + /* + * Find the failed disk within the RAID1 configuration ... + * (this can only be in the first conf->working_disks part) + */ + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->mirrors + i; + if ((!tmp->operational && !tmp->spare) || + !tmp->used_slot) { + failed_disk = i; + break; + } + } + /* + * When we activate a spare disk we _must_ have a disk in + * the lower (active) part of the array to replace. + */ + if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + /* fall through */ + + case DISKOP_SPARE_WRITE: + case DISKOP_SPARE_INACTIVE: + + /* + * Find the spare disk ... (can only be in the 'high' + * area of the array) + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (tmp->spare && tmp->number == (*d)->number) { + spare_disk = i; + break; + } + } + if (spare_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_REMOVE_DISK: + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (tmp->used_slot && (tmp->number == (*d)->number)) { + if (tmp->operational) { + err = -EBUSY; + goto abort; + } + removed_disk = i; + break; + } + } + if (removed_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_ADD_DISK: + + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->mirrors + i; + if (!tmp->used_slot) { + added_disk = i; + break; + } + } + if (added_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; } - /* FIXME: are there other things left we could sanity-check? */ + switch (state) { + /* + * Switch the spare disk to write-only mode: + */ + case DISKOP_SPARE_WRITE: + sdisk = conf->mirrors + spare_disk; + sdisk->operational = 1; + sdisk->write_only = 1; + break; /* - * We have to disable interrupts, as our RAID-1 state is used - * from irq handlers as well. + * Deactivate a spare disk: */ - save_flags(flags); - cli(); + case DISKOP_SPARE_INACTIVE: + sdisk = conf->mirrors + spare_disk; + sdisk->operational = 0; + sdisk->write_only = 0; + break; + /* + * Activate (mark read-write) the (now sync) spare disk, + * which means we switch it's 'raid position' (->raid_disk) + * with the failed disk. (only the first 'conf->nr_disks' + * slots are used for 'real' disks and we must preserve this + * property) + */ + case DISKOP_SPARE_ACTIVE: - raid_conf->raid_disks++; - mirror = raid_conf->mirrors+n; + sdisk = conf->mirrors + spare_disk; + fdisk = conf->mirrors + failed_disk; - mirror->number=n; - mirror->raid_disk=n; - mirror->dev=dev; - mirror->next=0; /* FIXME */ - mirror->sect_limit=128; + spare_desc = &sb->disks[sdisk->number]; + failed_desc = &sb->disks[fdisk->number]; - mirror->operational=0; - mirror->spare=1; - mirror->write_only=0; + if (spare_desc != *d) { + MD_BUG(); + err = 1; + goto abort; + } - sb->disks[n].state |= (1 << MD_FAULTY_DEVICE); - sb->disks[n].state &= ~(1 << MD_SYNC_DEVICE); - sb->disks[n].state &= ~(1 << MD_ACTIVE_DEVICE); - sb->nr_disks++; - sb->spare_disks++; + if (spare_desc->raid_disk != sdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (sdisk->raid_disk != spare_disk) { + MD_BUG(); + err = 1; + goto abort; + } - restore_flags(flags); + if (failed_desc->raid_disk != fdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } - md_update_sb(MINOR(dev)); + if (fdisk->raid_disk != failed_disk) { + MD_BUG(); + err = 1; + goto abort; + } - printk (HOT_ADD_SUCCEEDED, kdevname(realdev->dev)); + /* + * do the switch finally + */ + xchg_values(*spare_desc, *failed_desc); + xchg_values(*fdisk, *sdisk); - return 0; -} + /* + * (careful, 'failed' and 'spare' are switched from now on) + * + * we want to preserve linear numbering and we want to + * give the proper raid_disk number to the now activated + * disk. (this means we switch back these values) + */ + + xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); + xchg_values(sdisk->raid_disk, fdisk->raid_disk); + xchg_values(spare_desc->number, failed_desc->number); + xchg_values(sdisk->number, fdisk->number); -#undef NO_SUPERBLOCK -#undef WRONG_LEVEL -#undef HOT_ADD_SUCCEEDED + *d = failed_desc; -/* - * Insert the spare disk into the drive-ring - */ -static void add_ring(struct raid1_data *raid_conf, struct mirror_info *mirror) -{ - int j, next; - struct mirror_info *p = raid_conf->mirrors; + if (sdisk->dev == MKDEV(0,0)) + sdisk->used_slot = 0; + /* + * this really activates the spare. + */ + fdisk->spare = 0; + fdisk->write_only = 0; + link_disk(conf, fdisk); - for (j = 0; j < raid_conf->raid_disks; j++, p++) - if (p->operational && !p->write_only) { - next = p->next; - p->next = mirror->raid_disk; - mirror->next = next; - return; + /* + * if we activate a spare, we definitely replace a + * non-operational disk slot in the 'low' area of + * the disk array. + */ + + conf->working_disks++; + + break; + + case DISKOP_HOT_REMOVE_DISK: + rdisk = conf->mirrors + removed_disk; + + if (rdisk->spare && (removed_disk < conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + rdisk->dev = MKDEV(0,0); + rdisk->used_slot = 0; + conf->nr_disks--; + break; + + case DISKOP_HOT_ADD_DISK: + adisk = conf->mirrors + added_disk; + added_desc = *d; + + if (added_disk != added_desc->number) { + MD_BUG(); + err = 1; + goto abort; } - printk("raid1: bug: no read-operational devices\n"); -} -static int raid1_mark_spare(struct md_dev *mddev, md_descriptor_t *spare, - int state) -{ - int i = 0, failed_disk = -1; - struct raid1_data *raid_conf = mddev->private; - struct mirror_info *mirror = raid_conf->mirrors; - md_descriptor_t *descriptor; - unsigned long flags; + adisk->number = added_desc->number; + adisk->raid_disk = added_desc->raid_disk; + adisk->dev = MKDEV(added_desc->major,added_desc->minor); - for (i = 0; i < MD_SB_DISKS; i++, mirror++) { - if (mirror->spare && mirror->number == spare->number) - goto found; - } - return 1; -found: - for (i = 0, mirror = raid_conf->mirrors; i < raid_conf->raid_disks; - i++, mirror++) - if (!mirror->operational) - failed_disk = i; + adisk->operational = 0; + adisk->write_only = 0; + adisk->spare = 1; + adisk->used_slot = 1; + conf->nr_disks++; - save_flags(flags); - cli(); - switch (state) { - case SPARE_WRITE: - mirror->operational = 1; - mirror->write_only = 1; - raid_conf->raid_disks = MAX(raid_conf->raid_disks, - mirror->raid_disk + 1); - break; - case SPARE_INACTIVE: - mirror->operational = 0; - mirror->write_only = 0; - break; - case SPARE_ACTIVE: - mirror->spare = 0; - mirror->write_only = 0; - raid_conf->working_disks++; - add_ring(raid_conf, mirror); - - if (failed_disk != -1) { - descriptor = &mddev->sb->disks[raid_conf->mirrors[failed_disk].number]; - i = spare->raid_disk; - spare->raid_disk = descriptor->raid_disk; - descriptor->raid_disk = i; - } - break; - default: - printk("raid1_mark_spare: bug: state == %d\n", state); - restore_flags(flags); - return 1; + break; + + default: + MD_BUG(); + err = 1; + goto abort; } - restore_flags(flags); - return 0; +abort: + md_spin_unlock_irq(&conf->device_lock); + print_raid1_conf(conf); + return err; } + +#define IO_ERROR KERN_ALERT \ +"raid1: %s: unrecoverable I/O read error for block %lu\n" + +#define REDIRECT_SECTOR KERN_ERR \ +"raid1: %s: redirecting sector %lu to another mirror\n" + /* * This is a kernel thread which: * * 1. Retries failed read operations on working mirrors. * 2. Updates the raid superblock when problems encounter. + * 3. Performs writes following reads for array syncronising. */ -void raid1d (void *data) +static void end_sync_write(struct buffer_head *bh, int uptodate); +static void end_sync_read(struct buffer_head *bh, int uptodate); + +static void raid1d (void *data) { + struct raid1_bh *r1_bh; struct buffer_head *bh; - kdev_t dev; unsigned long flags; - struct raid1_bh * r1_bh; - struct md_dev *mddev; + request_queue_t *q; + mddev_t *mddev; + kdev_t dev; - PRINTK(("raid1d() active\n")); - save_flags(flags); - cli(); - while (raid1_retry_list) { + + for (;;) { + md_spin_lock_irqsave(&retry_list_lock, flags); bh = raid1_retry_list; + if (!bh) + break; r1_bh = (struct raid1_bh *)(bh->b_dev_id); raid1_retry_list = r1_bh->next_retry; - restore_flags(flags); + md_spin_unlock_irqrestore(&retry_list_lock, flags); - mddev = md_dev + MINOR(bh->b_dev); + mddev = kdev_to_mddev(bh->b_dev); if (mddev->sb_dirty) { - printk("dirty sb detected, updating.\n"); + printk(KERN_INFO "dirty sb detected, updating.\n"); mddev->sb_dirty = 0; - md_update_sb(MINOR(bh->b_dev)); - } - dev = bh->b_rdev; - __raid1_map (md_dev + MINOR(bh->b_dev), &bh->b_rdev, &bh->b_rsector, bh->b_size >> 9); - if (bh->b_rdev == dev) { - printk (KERN_ALERT - "raid1: %s: unrecoverable I/O read error for block %lu\n", - kdevname(bh->b_dev), bh->b_blocknr); - raid1_end_buffer_io(r1_bh, 0); - } else { - printk (KERN_ERR "raid1: %s: redirecting sector %lu to another mirror\n", - kdevname(bh->b_dev), bh->b_blocknr); - map_and_make_request (r1_bh->cmd, bh); + md_update_sb(mddev); } - cli(); + switch(r1_bh->cmd) { + case SPECIAL: + /* have to allocate lots of bh structures and + * schedule writes + */ + if (test_bit(R1BH_Uptodate, &r1_bh->state)) { + int i, sum_bhs = 0; + int disks = MD_SB_DISKS; + struct buffer_head *mirror_bh[MD_SB_DISKS]; + raid1_conf_t *conf; + + conf = mddev_to_conf(mddev); + for (i = 0; i < disks ; i++) { + if (!conf->mirrors[i].operational) { + mirror_bh[i] = NULL; + continue; + } + if (i==conf->last_used) { + /* we read from here, no need to write */ + mirror_bh[i] = NULL; + continue; + } + if (i < conf->raid_disks + && !conf->resync_mirrors) { + /* don't need to write this, + * we are just rebuilding */ + mirror_bh[i] = NULL; + continue; + } + + mirror_bh[i] = raid1_kmalloc(sizeof(struct buffer_head)); + mirror_bh[i]->b_this_page = (struct buffer_head *)1; + + /* + * prepare mirrored bh (fields ordered for max mem throughput): + */ + mirror_bh[i]->b_blocknr = bh->b_blocknr; + mirror_bh[i]->b_dev = bh->b_dev; + mirror_bh[i]->b_rdev = conf->mirrors[i].dev; + mirror_bh[i]->b_rsector = bh->b_rsector; + mirror_bh[i]->b_state = (1<<BH_Req) | (1<<BH_Dirty) | + (1<<BH_Mapped) | (1<<BH_Lock); + + atomic_set(&mirror_bh[i]->b_count, 1); + mirror_bh[i]->b_size = bh->b_size; + mirror_bh[i]->b_data = bh->b_data; + mirror_bh[i]->b_list = BUF_LOCKED; + mirror_bh[i]->b_end_io = end_sync_write; + mirror_bh[i]->b_dev_id = r1_bh; + + r1_bh->mirror_bh[i] = mirror_bh[i]; + sum_bhs++; + } + md_atomic_set(&r1_bh->remaining, sum_bhs); + for ( i = 0; i < disks ; i++) { + struct buffer_head *mbh = mirror_bh[i]; + if (mbh) { + q = blk_get_queue(mbh->b_rdev); + generic_make_request(q, WRITE, mbh); + } + } + } else { + dev = bh->b_rdev; + raid1_map (mddev, &bh->b_rdev, bh->b_size >> 9); + if (bh->b_rdev == dev) { + printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr); + md_done_sync(mddev, bh->b_size>>10, 0); + } else { + printk (REDIRECT_SECTOR, + partition_name(bh->b_dev), bh->b_blocknr); + q = blk_get_queue(bh->b_rdev); + generic_make_request (q, READ, bh); + } + } + + break; + case READ: + case READA: + dev = bh->b_rdev; + + raid1_map (mddev, &bh->b_rdev, bh->b_size >> 9); + if (bh->b_rdev == dev) { + printk (IO_ERROR, partition_name(bh->b_dev), bh->b_blocknr); + raid1_end_bh_io(r1_bh, 0); + } else { + printk (REDIRECT_SECTOR, + partition_name(bh->b_dev), bh->b_blocknr); + q = blk_get_queue(bh->b_rdev); + generic_make_request (q, r1_bh->cmd, bh); + } + break; + } + } + md_spin_unlock_irqrestore(&retry_list_lock, flags); +} +#undef IO_ERROR +#undef REDIRECT_SECTOR + +/* + * Private kernel thread to reconstruct mirrors after an unclean + * shutdown. + */ +static void raid1syncd (void *data) +{ + raid1_conf_t *conf = data; + mddev_t *mddev = conf->mddev; + + if (!conf->resync_mirrors) + return; + if (conf->resync_mirrors == 2) + return; + down(&mddev->recovery_sem); + if (md_do_sync(mddev, NULL)) { + up(&mddev->recovery_sem); + return; + } + /* + * Only if everything went Ok. + */ + conf->resync_mirrors = 0; + up(&mddev->recovery_sem); +} + +/* + * perform a "sync" on one "block" + * + * We need to make sure that no normal I/O request - particularly write + * requests - conflict with active sync requests. + * This is achieved by conceptually dividing the device space into a + * number of sections: + * DONE: 0 .. a-1 These blocks are in-sync + * ACTIVE: a.. b-1 These blocks may have active sync requests, but + * no normal IO requests + * READY: b .. c-1 These blocks have no normal IO requests - sync + * request may be happening + * PENDING: c .. d-1 These blocks may have IO requests, but no new + * ones will be added + * FUTURE: d .. end These blocks are not to be considered yet. IO may + * be happening, but not sync + * + * We keep a + * phase which flips (0 or 1) each time d moves and + * a count of: + * z = active io requests in FUTURE since d moved - marked with + * current phase + * y = active io requests in FUTURE before d moved, or PENDING - + * marked with previous phase + * x = active sync requests in READY + * w = active sync requests in ACTIVE + * v = active io requests in DONE + * + * Normally, a=b=c=d=0 and z= active io requests + * or a=b=c=d=END and v= active io requests + * Allowed changes to a,b,c,d: + * A: c==d && y==0 -> d+=window, y=z, z=0, phase=!phase + * B: y==0 -> c=d + * C: b=c, w+=x, x=0 + * D: w==0 -> a=b + * E: a==b==c==d==end -> a=b=c=d=0, z=v, v=0 + * + * At start of sync we apply A. + * When y reaches 0, we apply B then A then being sync requests + * When sync point reaches c-1, we wait for y==0, and W==0, and + * then apply apply B then A then D then C. + * Finally, we apply E + * + * The sync request simply issues a "read" against a working drive + * This is marked so that on completion the raid1d thread is woken to + * issue suitable write requests + */ + +static int raid1_sync_request (mddev_t *mddev, unsigned long block_nr) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + struct mirror_info *mirror; + request_queue_t *q; + struct raid1_bh *r1_bh; + struct buffer_head *bh; + int bsize; + + spin_lock_irq(&conf->segment_lock); + if (!block_nr) { + /* initialize ...*/ + conf->start_active = 0; + conf->start_ready = 0; + conf->start_pending = 0; + conf->start_future = 0; + conf->phase = 0; + conf->window = 128; + conf->cnt_future += conf->cnt_done+conf->cnt_pending; + conf->cnt_done = conf->cnt_pending = 0; + if (conf->cnt_ready || conf->cnt_active) + MD_BUG(); + } + while ((block_nr<<1) >= conf->start_pending) { + PRINTK("wait .. sect=%lu start_active=%d ready=%d pending=%d future=%d, cnt_done=%d active=%d ready=%d pending=%d future=%d\n", + block_nr<<1, conf->start_active, conf->start_ready, conf->start_pending, conf->start_future, + conf->cnt_done, conf->cnt_active, conf->cnt_ready, conf->cnt_pending, conf->cnt_future); + wait_event_lock_irq(conf->wait_done, + !conf->cnt_active, + conf->segment_lock); + wait_event_lock_irq(conf->wait_ready, + !conf->cnt_pending, + conf->segment_lock); + conf->start_active = conf->start_ready; + conf->start_ready = conf->start_pending; + conf->start_pending = conf->start_future; + conf->start_future = conf->start_future+conf->window; + // Note: falling of the end is not a problem + conf->phase = conf->phase ^1; + conf->cnt_active = conf->cnt_ready; + conf->cnt_ready = 0; + conf->cnt_pending = conf->cnt_future; + conf->cnt_future = 0; + wake_up(&conf->wait_done); + } + conf->cnt_ready++; + spin_unlock_irq(&conf->segment_lock); + + + /* If reconstructing, and >1 working disc, + * could dedicate one to rebuild and others to + * service read requests .. + */ + mirror = conf->mirrors+conf->last_used; + + r1_bh = raid1_kmalloc (sizeof (struct raid1_bh)); + r1_bh->master_bh = NULL; + r1_bh->mddev = mddev; + r1_bh->cmd = SPECIAL; + bh = &r1_bh->bh_req; + memset(bh, 0, sizeof(*bh)); + + bh->b_blocknr = block_nr; + bsize = 1024; + while (!(bh->b_blocknr & 1) && bsize < PAGE_SIZE + && (bh->b_blocknr+2)*(bsize>>10) < mddev->sb->size) { + bh->b_blocknr >>= 1; + bsize <<= 1; + } + bh->b_size = bsize; + bh->b_list = BUF_LOCKED; + bh->b_dev = mddev_to_kdev(mddev); + bh->b_rdev = mirror->dev; + bh->b_state = (1<<BH_Req) | (1<<BH_Mapped); + bh->b_page = raid1_gfp(); + bh->b_data = (char *) page_address(bh->b_page); + bh->b_end_io = end_sync_read; + bh->b_dev_id = (void *) r1_bh; + bh->b_rsector = block_nr<<1; + init_waitqueue_head(&bh->b_wait); + + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, READ, bh); + drive_stat_acct(bh->b_rdev, READ, -bh->b_size/512, 0); + + return (bsize >> 10); +} + +static void end_sync_read(struct buffer_head *bh, int uptodate) +{ + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + + /* we have read a block, now it needs to be re-written, + * or re-read if the read failed. + * We don't do much here, just schedule handling by raid1d + */ + if (!uptodate) + md_error (bh->b_dev, bh->b_rdev); + else + set_bit(R1BH_Uptodate, &r1_bh->state); + raid1_reschedule_retry(bh); +} + +static void end_sync_write(struct buffer_head *bh, int uptodate) +{ + struct raid1_bh * r1_bh = (struct raid1_bh *)(bh->b_dev_id); + + if (!uptodate) + md_error (bh->b_dev, bh->b_rdev); + if (atomic_dec_and_test(&r1_bh->remaining)) { + int i, disks = MD_SB_DISKS; + mddev_t *mddev = r1_bh->mddev; + unsigned long sect = bh->b_rsector; + int size = bh->b_size; + + free_page((unsigned long)bh->b_data); + for ( i = 0; i < disks; i++) { + struct buffer_head *bh = r1_bh->mirror_bh[i]; + if (bh) { + // FIXME: make us a regular bcache member + kfree(bh); + } + } + kfree(r1_bh); + sync_request_done(sect, mddev_to_conf(mddev)); + md_done_sync(mddev,size>>10, uptodate); } - restore_flags(flags); } /* * This will catch the scenario in which one of the mirrors was * mounted as a normal device rather than as a part of a raid set. + * + * check_consistency is very personality-dependent, eg. RAID5 cannot + * do this check, it uses another method. */ -static int __check_consistency (struct md_dev *mddev, int row) +static int __check_consistency (mddev_t *mddev, int row) { - struct raid1_data *raid_conf = mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); + int disks = MD_SB_DISKS; kdev_t dev; struct buffer_head *bh = NULL; int i, rc = 0; char *buffer = NULL; - for (i = 0; i < raid_conf->raid_disks; i++) { - if (!raid_conf->mirrors[i].operational) + for (i = 0; i < disks; i++) { + printk("(checking disk %d)\n",i); + if (!conf->mirrors[i].operational) continue; - dev = raid_conf->mirrors[i].dev; + printk("(really checking disk %d)\n",i); + dev = conf->mirrors[i].dev; set_blocksize(dev, 4096); if ((bh = bread(dev, row / 4, 4096)) == NULL) break; @@ -682,187 +1199,389 @@ static int __check_consistency (struct md_dev *mddev, int row) return rc; } -static int check_consistency (struct md_dev *mddev) +static int check_consistency (mddev_t *mddev) { - int size = mddev->sb->size; - int row; + if (__check_consistency(mddev, 0)) +/* + * we do not do this currently, as it's perfectly possible to + * have an inconsistent array when it's freshly created. Only + * newly written data has to be consistent. + */ + return 0; - for (row = 0; row < size; row += size / 8) - if (__check_consistency(mddev, row)) - return 1; return 0; } -static int raid1_run (int minor, struct md_dev *mddev) +#define INVALID_LEVEL KERN_WARNING \ +"raid1: md%d: raid level not set to mirroring (%d)\n" + +#define NO_SB KERN_ERR \ +"raid1: disabled mirror %s (couldn't access raid superblock)\n" + +#define ERRORS KERN_ERR \ +"raid1: disabled mirror %s (errors detected)\n" + +#define NOT_IN_SYNC KERN_ERR \ +"raid1: disabled mirror %s (not in sync)\n" + +#define INCONSISTENT KERN_ERR \ +"raid1: disabled mirror %s (inconsistent descriptor)\n" + +#define ALREADY_RUNNING KERN_ERR \ +"raid1: disabled mirror %s (mirror %d already operational)\n" + +#define OPERATIONAL KERN_INFO \ +"raid1: device %s operational as mirror %d\n" + +#define MEM_ERROR KERN_ERR \ +"raid1: couldn't allocate memory for md%d\n" + +#define SPARE KERN_INFO \ +"raid1: spare disk %s\n" + +#define NONE_OPERATIONAL KERN_ERR \ +"raid1: no operational mirrors for md%d\n" + +#define RUNNING_CKRAID KERN_ERR \ +"raid1: detected mirror differences -- running resync\n" + +#define ARRAY_IS_ACTIVE KERN_INFO \ +"raid1: raid set md%d active with %d out of %d mirrors\n" + +#define THREAD_ERROR KERN_ERR \ +"raid1: couldn't allocate thread for md%d\n" + +#define START_RESYNC KERN_WARNING \ +"raid1: raid set md%d not clean; reconstructing mirrors\n" + +static int raid1_run (mddev_t *mddev) { - struct raid1_data *raid_conf; - int i, j, raid_disk; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; - struct real_dev *realdev; + raid1_conf_t *conf; + int i, j, disk_idx; + struct mirror_info *disk; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *descriptor; + mdk_rdev_t *rdev; + struct md_list_head *tmp; + int start_recovery = 0; MOD_INC_USE_COUNT; if (sb->level != 1) { - printk("raid1: %s: raid level not set to mirroring (%d)\n", - kdevname(MKDEV(MD_MAJOR, minor)), sb->level); - MOD_DEC_USE_COUNT; - return -EIO; - } - /**** - * copy the now verified devices into our private RAID1 bookkeeping - * area. [whatever we allocate in raid1_run(), should be freed in - * raid1_stop()] + printk(INVALID_LEVEL, mdidx(mddev), sb->level); + goto out; + } + /* + * copy the already verified devices into our private RAID1 + * bookkeeping area. [whatever we allocate in raid1_run(), + * should be freed in raid1_stop()] */ - while (!( /* FIXME: now we are rather fault tolerant than nice */ - mddev->private = kmalloc (sizeof (struct raid1_data), GFP_KERNEL) - ) ) - { - printk ("raid1_run(): out of memory\n"); - current->policy |= SCHED_YIELD; - schedule(); + conf = raid1_kmalloc(sizeof(raid1_conf_t)); + mddev->private = conf; + if (!conf) { + printk(MEM_ERROR, mdidx(mddev)); + goto out; } - raid_conf = mddev->private; - memset(raid_conf, 0, sizeof(*raid_conf)); - PRINTK(("raid1_run(%d) called.\n", minor)); - - for (i = 0; i < mddev->nb_dev; i++) { - realdev = &mddev->devices[i]; - if (!realdev->sb) { - printk(KERN_ERR "raid1: disabled mirror %s (couldn't access raid superblock)\n", kdevname(realdev->dev)); + ITERATE_RDEV(mddev,rdev,tmp) { + if (rdev->faulty) { + printk(ERRORS, partition_name(rdev->dev)); + } else { + if (!rdev->sb) { + MD_BUG(); + continue; + } + } + if (rdev->desc_nr == -1) { + MD_BUG(); continue; } - - /* - * This is important -- we are using the descriptor on - * the disk only to get a pointer to the descriptor on - * the main superblock, which might be more recent. - */ - descriptor = &sb->disks[realdev->sb->descriptor.number]; - if (descriptor->state & (1 << MD_FAULTY_DEVICE)) { - printk(KERN_ERR "raid1: disabled mirror %s (errors detected)\n", kdevname(realdev->dev)); + descriptor = &sb->disks[rdev->desc_nr]; + disk_idx = descriptor->raid_disk; + disk = conf->mirrors + disk_idx; + + if (disk_faulty(descriptor)) { + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; continue; } - if (descriptor->state & (1 << MD_ACTIVE_DEVICE)) { - if (!(descriptor->state & (1 << MD_SYNC_DEVICE))) { - printk(KERN_ERR "raid1: disabled mirror %s (not in sync)\n", kdevname(realdev->dev)); + if (disk_active(descriptor)) { + if (!disk_sync(descriptor)) { + printk(NOT_IN_SYNC, + partition_name(rdev->dev)); continue; } - raid_disk = descriptor->raid_disk; - if (descriptor->number > sb->nr_disks || raid_disk > sb->raid_disks) { - printk(KERN_ERR "raid1: disabled mirror %s (inconsistent descriptor)\n", kdevname(realdev->dev)); + if ((descriptor->number > MD_SB_DISKS) || + (disk_idx > sb->raid_disks)) { + + printk(INCONSISTENT, + partition_name(rdev->dev)); continue; } - if (raid_conf->mirrors[raid_disk].operational) { - printk(KERN_ERR "raid1: disabled mirror %s (mirror %d already operational)\n", kdevname(realdev->dev), raid_disk); + if (disk->operational) { + printk(ALREADY_RUNNING, + partition_name(rdev->dev), + disk_idx); continue; } - printk(KERN_INFO "raid1: device %s operational as mirror %d\n", kdevname(realdev->dev), raid_disk); - raid_conf->mirrors[raid_disk].number = descriptor->number; - raid_conf->mirrors[raid_disk].raid_disk = raid_disk; - raid_conf->mirrors[raid_disk].dev = mddev->devices [i].dev; - raid_conf->mirrors[raid_disk].operational = 1; - raid_conf->mirrors[raid_disk].sect_limit = 128; - raid_conf->working_disks++; + printk(OPERATIONAL, partition_name(rdev->dev), + disk_idx); + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 1; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + conf->working_disks++; } else { /* * Must be a spare disk .. */ - printk(KERN_INFO "raid1: spare disk %s\n", kdevname(realdev->dev)); - raid_disk = descriptor->raid_disk; - raid_conf->mirrors[raid_disk].number = descriptor->number; - raid_conf->mirrors[raid_disk].raid_disk = raid_disk; - raid_conf->mirrors[raid_disk].dev = mddev->devices [i].dev; - raid_conf->mirrors[raid_disk].sect_limit = 128; - - raid_conf->mirrors[raid_disk].operational = 0; - raid_conf->mirrors[raid_disk].write_only = 0; - raid_conf->mirrors[raid_disk].spare = 1; - } - } - if (!raid_conf->working_disks) { - printk(KERN_ERR "raid1: no operational mirrors for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - kfree(raid_conf); - mddev->private = NULL; - MOD_DEC_USE_COUNT; - return -EIO; - } - - raid_conf->raid_disks = sb->raid_disks; - raid_conf->mddev = mddev; - - for (j = 0; !raid_conf->mirrors[j].operational; j++); - raid_conf->last_used = j; - for (i = raid_conf->raid_disks - 1; i >= 0; i--) { - if (raid_conf->mirrors[i].operational) { - PRINTK(("raid_conf->mirrors[%d].next == %d\n", i, j)); - raid_conf->mirrors[i].next = j; + printk(SPARE, partition_name(rdev->dev)); + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = rdev->dev; + disk->sect_limit = MAX_LINEAR_SECTORS; + disk->operational = 0; + disk->write_only = 0; + disk->spare = 1; + disk->used_slot = 1; + } + } + if (!conf->working_disks) { + printk(NONE_OPERATIONAL, mdidx(mddev)); + goto out_free_conf; + } + + conf->raid_disks = sb->raid_disks; + conf->nr_disks = sb->nr_disks; + conf->mddev = mddev; + conf->device_lock = MD_SPIN_LOCK_UNLOCKED; + + conf->segment_lock = MD_SPIN_LOCK_UNLOCKED; + init_waitqueue_head(&conf->wait_done); + init_waitqueue_head(&conf->wait_ready); + + + for (i = 0; i < MD_SB_DISKS; i++) { + + descriptor = sb->disks+i; + disk_idx = descriptor->raid_disk; + disk = conf->mirrors + disk_idx; + + if (disk_faulty(descriptor) && (disk_idx < conf->raid_disks) && + !disk->used_slot) { + + disk->number = descriptor->number; + disk->raid_disk = disk_idx; + disk->dev = MKDEV(0,0); + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + } + } + + /* + * find the first working one and use it as a starting point + * to read balancing. + */ + for (j = 0; !conf->mirrors[j].operational; j++) + /* nothing */; + conf->last_used = j; + + /* + * initialize the 'working disks' list. + */ + for (i = conf->raid_disks - 1; i >= 0; i--) { + if (conf->mirrors[i].operational) { + conf->mirrors[i].next = j; j = i; } } - if (check_consistency(mddev)) { - printk(KERN_ERR "raid1: detected mirror differences -- run ckraid\n"); - sb->state |= 1 << MD_SB_ERRORS; - kfree(raid_conf); - mddev->private = NULL; - MOD_DEC_USE_COUNT; - return -EIO; + if (conf->working_disks != sb->raid_disks) { + printk(KERN_ALERT "raid1: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev)); + start_recovery = 1; + } + + if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN))) { + /* + * we do sanity checks even if the device says + * it's clean ... + */ + if (check_consistency(mddev)) { + printk(RUNNING_CKRAID); + sb->state &= ~(1 << MD_SB_CLEAN); + } + } + + { + const char * name = "raid1d"; + + conf->thread = md_register_thread(raid1d, conf, name); + if (!conf->thread) { + printk(THREAD_ERROR, mdidx(mddev)); + goto out_free_conf; + } + } + + if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) { + const char * name = "raid1syncd"; + + conf->resync_thread = md_register_thread(raid1syncd, conf,name); + if (!conf->resync_thread) { + printk(THREAD_ERROR, mdidx(mddev)); + goto out_free_conf; + } + + printk(START_RESYNC, mdidx(mddev)); + conf->resync_mirrors = 1; + md_wakeup_thread(conf->resync_thread); } /* * Regenerate the "device is in sync with the raid set" bit for * each device. */ - for (i = 0; i < sb->nr_disks ; i++) { - sb->disks[i].state &= ~(1 << MD_SYNC_DEVICE); + for (i = 0; i < MD_SB_DISKS; i++) { + mark_disk_nonsync(sb->disks+i); for (j = 0; j < sb->raid_disks; j++) { - if (!raid_conf->mirrors[j].operational) + if (!conf->mirrors[j].operational) continue; - if (sb->disks[i].number == raid_conf->mirrors[j].number) - sb->disks[i].state |= 1 << MD_SYNC_DEVICE; + if (sb->disks[i].number == conf->mirrors[j].number) + mark_disk_sync(sb->disks+i); } } - sb->active_disks = raid_conf->working_disks; + sb->active_disks = conf->working_disks; - printk("raid1: raid set %s active with %d out of %d mirrors\n", kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks); - /* Ok, everything is just fine now */ - return (0); + if (start_recovery) + md_recover_arrays(); + + + printk(ARRAY_IS_ACTIVE, mdidx(mddev), sb->active_disks, sb->raid_disks); + /* + * Ok, everything is just fine now + */ + return 0; + +out_free_conf: + kfree(conf); + mddev->private = NULL; +out: + MOD_DEC_USE_COUNT; + return -EIO; +} + +#undef INVALID_LEVEL +#undef NO_SB +#undef ERRORS +#undef NOT_IN_SYNC +#undef INCONSISTENT +#undef ALREADY_RUNNING +#undef OPERATIONAL +#undef SPARE +#undef NONE_OPERATIONAL +#undef RUNNING_CKRAID +#undef ARRAY_IS_ACTIVE + +static int raid1_stop_resync (mddev_t *mddev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + + if (conf->resync_thread) { + if (conf->resync_mirrors) { + conf->resync_mirrors = 2; + md_interrupt_thread(conf->resync_thread); + + /* this is really needed when recovery stops too... */ + spin_lock_irq(&conf->segment_lock); + wait_event_lock_irq(conf->wait_done, !conf->cnt_active, conf->segment_lock); + conf->start_active = conf->start_ready; + conf->start_ready = conf->start_pending; + conf->cnt_active = conf->cnt_ready; + conf->cnt_ready = 0; + wait_event_lock_irq(conf->wait_done, !conf->cnt_active, conf->segment_lock); + conf->start_active = conf->start_ready; + conf->cnt_ready = 0; + wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); + conf->start_active =conf->start_ready = conf->start_pending = conf->start_future; + conf->start_future = mddev->sb->size+1; + conf->cnt_pending = conf->cnt_future; + conf->cnt_future = 0; + conf->phase = conf->phase ^1; + wait_event_lock_irq(conf->wait_ready, !conf->cnt_pending, conf->segment_lock); + conf->start_active = conf->start_ready = conf->start_pending = conf->start_future = 0; + conf->phase = 0; + conf->cnt_done = conf->cnt_future; + conf->cnt_future = 0; + wake_up(&conf->wait_done); + + printk(KERN_INFO "raid1: mirror resync was not fully finished, restarting next time.\n"); + return 1; + } + return 0; + } + return 0; +} + +static int raid1_restart_resync (mddev_t *mddev) +{ + raid1_conf_t *conf = mddev_to_conf(mddev); + + if (conf->resync_mirrors) { + if (!conf->resync_thread) { + MD_BUG(); + return 0; + } + conf->resync_mirrors = 1; + md_wakeup_thread(conf->resync_thread); + return 1; + } + return 0; } -static int raid1_stop (int minor, struct md_dev *mddev) +static int raid1_stop (mddev_t *mddev) { - struct raid1_data *raid_conf = (struct raid1_data *) mddev->private; + raid1_conf_t *conf = mddev_to_conf(mddev); - kfree (raid_conf); + md_unregister_thread(conf->thread); + if (conf->resync_thread) + md_unregister_thread(conf->resync_thread); + kfree(conf); mddev->private = NULL; MOD_DEC_USE_COUNT; return 0; } -static struct md_personality raid1_personality= +static mdk_personality_t raid1_personality= { "raid1", - raid1_map, raid1_make_request, raid1_end_request, raid1_run, raid1_stop, raid1_status, - NULL, /* no ioctls */ 0, raid1_error, - raid1_hot_add_disk, - /* raid1_hot_remove_drive */ NULL, - raid1_mark_spare + raid1_diskop, + raid1_stop_resync, + raid1_restart_resync, + raid1_sync_request }; int raid1_init (void) { - if ((raid1_thread = md_register_thread(raid1d, NULL)) == NULL) - return -EBUSY; return register_md_personality (RAID1, &raid1_personality); } @@ -874,7 +1593,6 @@ int init_module (void) void cleanup_module (void) { - md_unregister_thread (raid1_thread); unregister_md_personality (RAID1); } #endif diff --git a/drivers/block/raid5.c b/drivers/block/raid5.c index 83fc26fad..2379ac6a2 100644 --- a/drivers/block/raid5.c +++ b/drivers/block/raid5.c @@ -1,6 +1,7 @@ -/***************************************************************************** +/* * raid5.c : Multiple Devices driver for Linux - * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman + * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman + * Copyright (C) 1999, 2000 Ingo Molnar * * RAID-5 management functions. * @@ -14,130 +15,108 @@ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + #include <linux/module.h> #include <linux/locks.h> #include <linux/malloc.h> -#include <linux/md.h> -#include <linux/raid5.h> +#include <linux/raid/raid5.h> #include <asm/bitops.h> #include <asm/atomic.h> -#include <asm/md.h> -static struct md_personality raid5_personality; +static mdk_personality_t raid5_personality; /* * Stripe cache */ + #define NR_STRIPES 128 #define HASH_PAGES 1 #define HASH_PAGES_ORDER 0 #define NR_HASH (HASH_PAGES * PAGE_SIZE / sizeof(struct stripe_head *)) #define HASH_MASK (NR_HASH - 1) -#define stripe_hash(raid_conf, sect, size) ((raid_conf)->stripe_hashtbl[((sect) / (size >> 9)) & HASH_MASK]) +#define stripe_hash(conf, sect, size) ((conf)->stripe_hashtbl[((sect) / (size >> 9)) & HASH_MASK]) /* * The following can be used to debug the driver */ #define RAID5_DEBUG 0 +#define RAID5_PARANOIA 1 +#define CHECK_DEVLOCK() if (!spin_is_locked(&conf->device_lock)) BUG() +#define CHECK_SHLOCK(sh) if (!stripe_locked(sh)) BUG() #if RAID5_DEBUG -#define PRINTK(x) do { printk x; } while (0); +#define PRINTK(x...) printk(x) +#define inline +#define __inline__ #else -#define PRINTK(x) do { ; } while (0) +#define inline +#define __inline__ +#define PRINTK(x...) do { } while (0) #endif +static void print_raid5_conf (raid5_conf_t *conf); + static inline int stripe_locked(struct stripe_head *sh) { return test_bit(STRIPE_LOCKED, &sh->state); } -static inline int stripe_error(struct stripe_head *sh) -{ - return test_bit(STRIPE_ERROR, &sh->state); -} - -/* - * Stripes are locked whenever new buffers can't be added to them. - */ -static inline void lock_stripe(struct stripe_head *sh) +static void __unlock_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - if (!test_and_set_bit(STRIPE_LOCKED, &sh->state)) { - PRINTK(("locking stripe %lu\n", sh->sector)); - raid_conf->nr_locked_stripes++; - } + if (!md_test_and_clear_bit(STRIPE_LOCKED, &sh->state)) + BUG(); + PRINTK("unlocking stripe %lu\n", sh->sector); + wake_up(&sh->wait); } -static inline void unlock_stripe(struct stripe_head *sh) +static void finish_unlock_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - if (test_and_clear_bit(STRIPE_LOCKED, &sh->state)) { - PRINTK(("unlocking stripe %lu\n", sh->sector)); - raid_conf->nr_locked_stripes--; - wake_up(&sh->wait); - } -} - -static inline void finish_stripe(struct stripe_head *sh) -{ - struct raid5_data *raid_conf = sh->raid_conf; - unlock_stripe(sh); + raid5_conf_t *conf = sh->raid_conf; sh->cmd = STRIPE_NONE; sh->phase = PHASE_COMPLETE; - raid_conf->nr_pending_stripes--; - raid_conf->nr_cached_stripes++; - wake_up(&raid_conf->wait_for_stripe); -} - -void __wait_on_stripe(struct stripe_head *sh) -{ - DECLARE_WAITQUEUE(wait, current); - - PRINTK(("wait_on_stripe %lu\n", sh->sector)); - sh->count++; - add_wait_queue(&sh->wait, &wait); -repeat: - set_current_state(TASK_UNINTERRUPTIBLE); - if (stripe_locked(sh)) { - schedule(); - goto repeat; - } - PRINTK(("wait_on_stripe %lu done\n", sh->sector)); - remove_wait_queue(&sh->wait, &wait); - sh->count--; - current->state = TASK_RUNNING; -} - -static inline void wait_on_stripe(struct stripe_head *sh) -{ - if (stripe_locked(sh)) - __wait_on_stripe(sh); + atomic_dec(&conf->nr_pending_stripes); + atomic_inc(&conf->nr_cached_stripes); + __unlock_stripe(sh); + atomic_dec(&sh->count); + wake_up(&conf->wait_for_stripe); } -static inline void remove_hash(struct raid5_data *raid_conf, struct stripe_head *sh) +static void remove_hash(raid5_conf_t *conf, struct stripe_head *sh) { - PRINTK(("remove_hash(), stripe %lu\n", sh->sector)); + PRINTK("remove_hash(), stripe %lu\n", sh->sector); + CHECK_DEVLOCK(); + CHECK_SHLOCK(sh); if (sh->hash_pprev) { if (sh->hash_next) sh->hash_next->hash_pprev = sh->hash_pprev; *sh->hash_pprev = sh->hash_next; sh->hash_pprev = NULL; - raid_conf->nr_hashed_stripes--; + atomic_dec(&conf->nr_hashed_stripes); } } -static inline void insert_hash(struct raid5_data *raid_conf, struct stripe_head *sh) +static void lock_get_bh (struct buffer_head *bh) { - struct stripe_head **shp = &stripe_hash(raid_conf, sh->sector, sh->size); + while (md_test_and_set_bit(BH_Lock, &bh->b_state)) + __wait_on_buffer(bh); + atomic_inc(&bh->b_count); +} + +static __inline__ void insert_hash(raid5_conf_t *conf, struct stripe_head *sh) +{ + struct stripe_head **shp = &stripe_hash(conf, sh->sector, sh->size); - PRINTK(("insert_hash(), stripe %lu, nr_hashed_stripes %d\n", sh->sector, raid_conf->nr_hashed_stripes)); + PRINTK("insert_hash(), stripe %lu, nr_hashed_stripes %d\n", + sh->sector, atomic_read(&conf->nr_hashed_stripes)); + CHECK_DEVLOCK(); + CHECK_SHLOCK(sh); if ((sh->hash_next = *shp) != NULL) (*shp)->hash_pprev = &sh->hash_next; *shp = sh; sh->hash_pprev = shp; - raid_conf->nr_hashed_stripes++; + atomic_inc(&conf->nr_hashed_stripes); } static struct buffer_head *get_free_buffer(struct stripe_head *sh, int b_size) @@ -145,13 +124,18 @@ static struct buffer_head *get_free_buffer(struct stripe_head *sh, int b_size) struct buffer_head *bh; unsigned long flags; - save_flags(flags); - cli(); - if ((bh = sh->buffer_pool) == NULL) - return NULL; + CHECK_SHLOCK(sh); + md_spin_lock_irqsave(&sh->stripe_lock, flags); + bh = sh->buffer_pool; + if (!bh) + goto out_unlock; sh->buffer_pool = bh->b_next; bh->b_size = b_size; - restore_flags(flags); + if (atomic_read(&bh->b_count)) + BUG(); +out_unlock: + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); + return bh; } @@ -160,12 +144,17 @@ static struct buffer_head *get_free_bh(struct stripe_head *sh) struct buffer_head *bh; unsigned long flags; - save_flags(flags); - cli(); - if ((bh = sh->bh_pool) == NULL) - return NULL; + CHECK_SHLOCK(sh); + md_spin_lock_irqsave(&sh->stripe_lock, flags); + bh = sh->bh_pool; + if (!bh) + goto out_unlock; sh->bh_pool = bh->b_next; - restore_flags(flags); + if (atomic_read(&bh->b_count)) + BUG(); +out_unlock: + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); + return bh; } @@ -173,55 +162,58 @@ static void put_free_buffer(struct stripe_head *sh, struct buffer_head *bh) { unsigned long flags; - save_flags(flags); - cli(); + if (atomic_read(&bh->b_count)) + BUG(); + CHECK_SHLOCK(sh); + md_spin_lock_irqsave(&sh->stripe_lock, flags); bh->b_next = sh->buffer_pool; sh->buffer_pool = bh; - restore_flags(flags); + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); } static void put_free_bh(struct stripe_head *sh, struct buffer_head *bh) { unsigned long flags; - save_flags(flags); - cli(); + if (atomic_read(&bh->b_count)) + BUG(); + CHECK_SHLOCK(sh); + md_spin_lock_irqsave(&sh->stripe_lock, flags); bh->b_next = sh->bh_pool; sh->bh_pool = bh; - restore_flags(flags); + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); } -static struct stripe_head *get_free_stripe(struct raid5_data *raid_conf) +static struct stripe_head *get_free_stripe(raid5_conf_t *conf) { struct stripe_head *sh; - unsigned long flags; - save_flags(flags); - cli(); - if ((sh = raid_conf->free_sh_list) == NULL) { - restore_flags(flags); - return NULL; - } - raid_conf->free_sh_list = sh->free_next; - raid_conf->nr_free_sh--; - if (!raid_conf->nr_free_sh && raid_conf->free_sh_list) - printk ("raid5: bug: free_sh_list != NULL, nr_free_sh == 0\n"); - restore_flags(flags); - if (sh->hash_pprev || sh->nr_pending || sh->count) - printk("get_free_stripe(): bug\n"); + md_spin_lock_irq(&conf->device_lock); + sh = conf->free_sh_list; + if (!sh) + goto out; + conf->free_sh_list = sh->free_next; + atomic_dec(&conf->nr_free_sh); + if (!atomic_read(&conf->nr_free_sh) && conf->free_sh_list) + BUG(); + if (sh->hash_pprev || md_atomic_read(&sh->nr_pending) || + atomic_read(&sh->count)) + BUG(); +out: + md_spin_unlock_irq(&conf->device_lock); return sh; } -static void put_free_stripe(struct raid5_data *raid_conf, struct stripe_head *sh) +static void __put_free_stripe (raid5_conf_t *conf, struct stripe_head *sh) { - unsigned long flags; - - save_flags(flags); - cli(); - sh->free_next = raid_conf->free_sh_list; - raid_conf->free_sh_list = sh; - raid_conf->nr_free_sh++; - restore_flags(flags); + if (atomic_read(&sh->count) != 0) + BUG(); + CHECK_DEVLOCK(); + CHECK_SHLOCK(sh); + clear_bit(STRIPE_LOCKED, &sh->state); + sh->free_next = conf->free_sh_list; + conf->free_sh_list = sh; + atomic_inc(&conf->nr_free_sh); } static void shrink_buffers(struct stripe_head *sh, int num) @@ -229,7 +221,8 @@ static void shrink_buffers(struct stripe_head *sh, int num) struct buffer_head *bh; while (num--) { - if ((bh = get_free_buffer(sh, -1)) == NULL) + bh = get_free_buffer(sh, -1); + if (!bh) return; free_page((unsigned long) bh->b_data); kfree(bh); @@ -241,26 +234,33 @@ static void shrink_bh(struct stripe_head *sh, int num) struct buffer_head *bh; while (num--) { - if ((bh = get_free_bh(sh)) == NULL) + bh = get_free_bh(sh); + if (!bh) return; kfree(bh); } } -static int grow_buffers(struct stripe_head *sh, int num, int b_size, int priority) +static int grow_raid5_buffers(struct stripe_head *sh, int num, int b_size, int priority) { struct buffer_head *bh; while (num--) { - if ((bh = kmalloc(sizeof(struct buffer_head), priority)) == NULL) + struct page *page; + bh = kmalloc(sizeof(struct buffer_head), priority); + if (!bh) return 1; memset(bh, 0, sizeof (struct buffer_head)); - bh->b_data = (char *) __get_free_page(priority); + init_waitqueue_head(&bh->b_wait); + page = alloc_page(priority); + bh->b_data = (char *) page_address(page); if (!bh->b_data) { kfree(bh); return 1; } bh->b_size = b_size; + atomic_set(&bh->b_count, 0); + set_bh_page(bh, page, 0); put_free_buffer(sh, bh); } return 0; @@ -271,259 +271,314 @@ static int grow_bh(struct stripe_head *sh, int num, int priority) struct buffer_head *bh; while (num--) { - if ((bh = kmalloc(sizeof(struct buffer_head), priority)) == NULL) + bh = kmalloc(sizeof(struct buffer_head), priority); + if (!bh) return 1; memset(bh, 0, sizeof (struct buffer_head)); + init_waitqueue_head(&bh->b_wait); put_free_bh(sh, bh); } return 0; } -static void raid5_kfree_buffer(struct stripe_head *sh, struct buffer_head *bh) +static void raid5_free_buffer(struct stripe_head *sh, struct buffer_head *bh) { - unsigned long flags; - - save_flags(flags); - cli(); put_free_buffer(sh, bh); - restore_flags(flags); } -static void raid5_kfree_bh(struct stripe_head *sh, struct buffer_head *bh) +static void raid5_free_bh(struct stripe_head *sh, struct buffer_head *bh) { - unsigned long flags; - - save_flags(flags); - cli(); put_free_bh(sh, bh); - restore_flags(flags); } -static void raid5_kfree_old_bh(struct stripe_head *sh, int i) +static void raid5_free_old_bh(struct stripe_head *sh, int i) { - if (!sh->bh_old[i]) { - printk("raid5_kfree_old_bh: bug: sector %lu, index %d not present\n", sh->sector, i); - return; - } - raid5_kfree_buffer(sh, sh->bh_old[i]); + CHECK_SHLOCK(sh); + if (!sh->bh_old[i]) + BUG(); + raid5_free_buffer(sh, sh->bh_old[i]); sh->bh_old[i] = NULL; } static void raid5_update_old_bh(struct stripe_head *sh, int i) { - PRINTK(("stripe %lu, idx %d, updating cache copy\n", sh->sector, i)); - if (!sh->bh_copy[i]) { - printk("raid5_update_old_bh: bug: sector %lu, index %d not present\n", sh->sector, i); - return; - } + CHECK_SHLOCK(sh); + PRINTK("stripe %lu, idx %d, updating cache copy\n", sh->sector, i); + if (!sh->bh_copy[i]) + BUG(); if (sh->bh_old[i]) - raid5_kfree_old_bh(sh, i); + raid5_free_old_bh(sh, i); sh->bh_old[i] = sh->bh_copy[i]; sh->bh_copy[i] = NULL; } -static void kfree_stripe(struct stripe_head *sh) +static void free_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks, j; - - PRINTK(("kfree_stripe called, stripe %lu\n", sh->sector)); - if (sh->phase != PHASE_COMPLETE || stripe_locked(sh) || sh->count) { - printk("raid5: kfree_stripe(), sector %lu, phase %d, locked %d, count %d\n", sh->sector, sh->phase, stripe_locked(sh), sh->count); + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks, j; + + if (atomic_read(&sh->count) != 0) + BUG(); + CHECK_DEVLOCK(); + CHECK_SHLOCK(sh); + PRINTK("free_stripe called, stripe %lu\n", sh->sector); + if (sh->phase != PHASE_COMPLETE || atomic_read(&sh->count)) { + PRINTK("raid5: free_stripe(), sector %lu, phase %d, count %d\n", sh->sector, sh->phase, atomic_read(&sh->count)); return; } for (j = 0; j < disks; j++) { if (sh->bh_old[j]) - raid5_kfree_old_bh(sh, j); + raid5_free_old_bh(sh, j); if (sh->bh_new[j] || sh->bh_copy[j]) - printk("raid5: bug: sector %lu, new %p, copy %p\n", sh->sector, sh->bh_new[j], sh->bh_copy[j]); + BUG(); } - remove_hash(raid_conf, sh); - put_free_stripe(raid_conf, sh); + remove_hash(conf, sh); + __put_free_stripe(conf, sh); } -static int shrink_stripe_cache(struct raid5_data *raid_conf, int nr) +static int shrink_stripe_cache(raid5_conf_t *conf, int nr) { struct stripe_head *sh; int i, count = 0; - PRINTK(("shrink_stripe_cache called, %d/%d, clock %d\n", nr, raid_conf->nr_hashed_stripes, raid_conf->clock)); + PRINTK("shrink_stripe_cache called, %d/%d, clock %d\n", nr, atomic_read(&conf->nr_hashed_stripes), conf->clock); + md_spin_lock_irq(&conf->device_lock); for (i = 0; i < NR_HASH; i++) { -repeat: - sh = raid_conf->stripe_hashtbl[(i + raid_conf->clock) & HASH_MASK]; + sh = conf->stripe_hashtbl[(i + conf->clock) & HASH_MASK]; for (; sh; sh = sh->hash_next) { if (sh->phase != PHASE_COMPLETE) continue; - if (stripe_locked(sh)) + if (atomic_read(&sh->count)) continue; - if (sh->count) + /* + * Try to lock this stripe: + */ + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) continue; - kfree_stripe(sh); + free_stripe(sh); if (++count == nr) { - PRINTK(("shrink completed, nr_hashed_stripes %d\n", raid_conf->nr_hashed_stripes)); - raid_conf->clock = (i + raid_conf->clock) & HASH_MASK; - return nr; + conf->clock = (i + conf->clock) & HASH_MASK; + goto out; } - goto repeat; } } - PRINTK(("shrink completed, nr_hashed_stripes %d\n", raid_conf->nr_hashed_stripes)); +out: + md_spin_unlock_irq(&conf->device_lock); + PRINTK("shrink completed, nr_hashed_stripes %d, nr_pending_strips %d\n", + atomic_read(&conf->nr_hashed_stripes), + atomic_read(&conf->nr_pending_stripes)); return count; } -static struct stripe_head *find_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) +void __wait_lock_stripe(struct stripe_head *sh) { - struct stripe_head *sh; + MD_DECLARE_WAITQUEUE(wait, current); - if (raid_conf->buffer_size != size) { - PRINTK(("switching size, %d --> %d\n", raid_conf->buffer_size, size)); - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes); - raid_conf->buffer_size = size; + PRINTK("wait_lock_stripe %lu\n", sh->sector); + if (!atomic_read(&sh->count)) + BUG(); + add_wait_queue(&sh->wait, &wait); +repeat: + set_current_state(TASK_UNINTERRUPTIBLE); + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) { + schedule(); + goto repeat; } + PRINTK("wait_lock_stripe %lu done\n", sh->sector); + remove_wait_queue(&sh->wait, &wait); + current->state = TASK_RUNNING; +} - PRINTK(("find_stripe, sector %lu\n", sector)); - for (sh = stripe_hash(raid_conf, sector, size); sh; sh = sh->hash_next) - if (sh->sector == sector && sh->raid_conf == raid_conf) { - if (sh->size == size) { - PRINTK(("found stripe %lu\n", sector)); - return sh; - } else { - PRINTK(("switching size for %lu, %d --> %d\n", sector, sh->size, size)); - kfree_stripe(sh); - break; - } +static struct stripe_head *__find_stripe(raid5_conf_t *conf, unsigned long sector, int size) +{ + struct stripe_head *sh; + + PRINTK("__find_stripe, sector %lu\n", sector); + for (sh = stripe_hash(conf, sector, size); sh; sh = sh->hash_next) { + if (sh->sector == sector && sh->raid_conf == conf) { + if (sh->size != size) + BUG(); + return sh; } - PRINTK(("stripe %lu not in cache\n", sector)); + } + PRINTK("__stripe %lu not in cache\n", sector); return NULL; } -static int grow_stripes(struct raid5_data *raid_conf, int num, int priority) +static inline struct stripe_head *alloc_stripe(raid5_conf_t *conf, unsigned long sector, int size) +{ + struct stripe_head *sh; + struct buffer_head *buffer_pool, *bh_pool; + MD_DECLARE_WAITQUEUE(wait, current); + + PRINTK("alloc_stripe called\n"); + + + while ((sh = get_free_stripe(conf)) == NULL) { + int cnt; + add_wait_queue(&conf->wait_for_stripe, &wait); + set_current_state(TASK_UNINTERRUPTIBLE); + cnt = shrink_stripe_cache(conf, conf->max_nr_stripes / 8); + sh = get_free_stripe(conf); + if (!sh && cnt < (conf->max_nr_stripes/8)) { + md_wakeup_thread(conf->thread); + PRINTK("waiting for some stripes to complete - %d %d\n", cnt, conf->max_nr_stripes/8); + schedule(); + } + remove_wait_queue(&conf->wait_for_stripe, &wait); + current->state = TASK_RUNNING; + if (sh) + break; + } + + buffer_pool = sh->buffer_pool; + bh_pool = sh->bh_pool; + memset(sh, 0, sizeof(*sh)); + sh->stripe_lock = MD_SPIN_LOCK_UNLOCKED; + md_init_waitqueue_head(&sh->wait); + sh->buffer_pool = buffer_pool; + sh->bh_pool = bh_pool; + sh->phase = PHASE_COMPLETE; + sh->cmd = STRIPE_NONE; + sh->raid_conf = conf; + sh->sector = sector; + sh->size = size; + atomic_inc(&conf->nr_cached_stripes); + + return sh; +} + +static struct stripe_head *get_lock_stripe(raid5_conf_t *conf, unsigned long sector, int size) +{ + struct stripe_head *sh, *new = NULL; + + PRINTK("get_stripe, sector %lu\n", sector); + + /* + * Do this in set_blocksize()! + */ + if (conf->buffer_size != size) { + PRINTK("switching size, %d --> %d\n", conf->buffer_size, size); + shrink_stripe_cache(conf, conf->max_nr_stripes); + conf->buffer_size = size; + } + +repeat: + md_spin_lock_irq(&conf->device_lock); + sh = __find_stripe(conf, sector, size); + if (!sh) { + if (!new) { + md_spin_unlock_irq(&conf->device_lock); + new = alloc_stripe(conf, sector, size); + goto repeat; + } + sh = new; + new = NULL; + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) + BUG(); + insert_hash(conf, sh); + atomic_inc(&sh->count); + md_spin_unlock_irq(&conf->device_lock); + } else { + atomic_inc(&sh->count); + if (new) { + if (md_test_and_set_bit(STRIPE_LOCKED, &new->state)) + BUG(); + __put_free_stripe(conf, new); + } + md_spin_unlock_irq(&conf->device_lock); + PRINTK("get_stripe, waiting, sector %lu\n", sector); + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) + __wait_lock_stripe(sh); + } + return sh; +} + +static int grow_stripes(raid5_conf_t *conf, int num, int priority) { struct stripe_head *sh; while (num--) { - if ((sh = kmalloc(sizeof(struct stripe_head), priority)) == NULL) + sh = kmalloc(sizeof(struct stripe_head), priority); + if (!sh) return 1; memset(sh, 0, sizeof(*sh)); - if (grow_buffers(sh, 2 * raid_conf->raid_disks, PAGE_SIZE, priority)) { - shrink_buffers(sh, 2 * raid_conf->raid_disks); + sh->raid_conf = conf; + sh->stripe_lock = MD_SPIN_LOCK_UNLOCKED; + md_init_waitqueue_head(&sh->wait); + + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) + BUG(); + if (grow_raid5_buffers(sh, 2 * conf->raid_disks, PAGE_SIZE, priority)) { + shrink_buffers(sh, 2 * conf->raid_disks); kfree(sh); return 1; } - if (grow_bh(sh, raid_conf->raid_disks, priority)) { - shrink_buffers(sh, 2 * raid_conf->raid_disks); - shrink_bh(sh, raid_conf->raid_disks); + if (grow_bh(sh, conf->raid_disks, priority)) { + shrink_buffers(sh, 2 * conf->raid_disks); + shrink_bh(sh, conf->raid_disks); kfree(sh); return 1; } - put_free_stripe(raid_conf, sh); - raid_conf->nr_stripes++; + md_spin_lock_irq(&conf->device_lock); + __put_free_stripe(conf, sh); + atomic_inc(&conf->nr_stripes); + md_spin_unlock_irq(&conf->device_lock); } return 0; } -static void shrink_stripes(struct raid5_data *raid_conf, int num) +static void shrink_stripes(raid5_conf_t *conf, int num) { struct stripe_head *sh; while (num--) { - sh = get_free_stripe(raid_conf); + sh = get_free_stripe(conf); if (!sh) break; - shrink_buffers(sh, raid_conf->raid_disks * 2); - shrink_bh(sh, raid_conf->raid_disks); + if (md_test_and_set_bit(STRIPE_LOCKED, &sh->state)) + BUG(); + shrink_buffers(sh, conf->raid_disks * 2); + shrink_bh(sh, conf->raid_disks); kfree(sh); - raid_conf->nr_stripes--; - } -} - -static struct stripe_head *kmalloc_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) -{ - struct stripe_head *sh = NULL, *tmp; - struct buffer_head *buffer_pool, *bh_pool; - - PRINTK(("kmalloc_stripe called\n")); - - while ((sh = get_free_stripe(raid_conf)) == NULL) { - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes / 8); - if ((sh = get_free_stripe(raid_conf)) != NULL) - break; - if (!raid_conf->nr_pending_stripes) - printk("raid5: bug: nr_free_sh == 0, nr_pending_stripes == 0\n"); - md_wakeup_thread(raid_conf->thread); - PRINTK(("waiting for some stripes to complete\n")); - sleep_on(&raid_conf->wait_for_stripe); + atomic_dec(&conf->nr_stripes); } - - /* - * The above might have slept, so perhaps another process - * already created the stripe for us.. - */ - if ((tmp = find_stripe(raid_conf, sector, size)) != NULL) { - put_free_stripe(raid_conf, sh); - wait_on_stripe(tmp); - return tmp; - } - if (sh) { - buffer_pool = sh->buffer_pool; - bh_pool = sh->bh_pool; - memset(sh, 0, sizeof(*sh)); - sh->buffer_pool = buffer_pool; - sh->bh_pool = bh_pool; - sh->phase = PHASE_COMPLETE; - sh->cmd = STRIPE_NONE; - sh->raid_conf = raid_conf; - sh->sector = sector; - sh->size = size; - raid_conf->nr_cached_stripes++; - insert_hash(raid_conf, sh); - } else printk("raid5: bug: kmalloc_stripe() == NULL\n"); - return sh; -} - -static struct stripe_head *get_stripe(struct raid5_data *raid_conf, unsigned long sector, int size) -{ - struct stripe_head *sh; - - PRINTK(("get_stripe, sector %lu\n", sector)); - sh = find_stripe(raid_conf, sector, size); - if (sh) - wait_on_stripe(sh); - else - sh = kmalloc_stripe(raid_conf, sector, size); - return sh; } -static struct buffer_head *raid5_kmalloc_buffer(struct stripe_head *sh, int b_size) +static struct buffer_head *raid5_alloc_buffer(struct stripe_head *sh, int b_size) { struct buffer_head *bh; - if ((bh = get_free_buffer(sh, b_size)) == NULL) - printk("raid5: bug: raid5_kmalloc_buffer() == NULL\n"); + bh = get_free_buffer(sh, b_size); + if (!bh) + BUG(); return bh; } -static struct buffer_head *raid5_kmalloc_bh(struct stripe_head *sh) +static struct buffer_head *raid5_alloc_bh(struct stripe_head *sh) { struct buffer_head *bh; - if ((bh = get_free_bh(sh)) == NULL) - printk("raid5: bug: raid5_kmalloc_bh() == NULL\n"); + bh = get_free_bh(sh); + if (!bh) + BUG(); return bh; } -static inline void raid5_end_buffer_io (struct stripe_head *sh, int i, int uptodate) +static void raid5_end_buffer_io (struct stripe_head *sh, int i, int uptodate) { struct buffer_head *bh = sh->bh_new[i]; + PRINTK("raid5_end_buffer_io %lu, uptodate: %d.\n", bh->b_rsector, uptodate); sh->bh_new[i] = NULL; - raid5_kfree_bh(sh, sh->bh_req[i]); + raid5_free_bh(sh, sh->bh_req[i]); sh->bh_req[i] = NULL; + PRINTK("calling %p->end_io: %p.\n", bh, bh->b_end_io); bh->b_end_io(bh, uptodate); if (!uptodate) printk(KERN_ALERT "raid5: %s: unrecoverable I/O error for " - "block %lu\n", kdevname(bh->b_dev), bh->b_blocknr); + "block %lu\n", partition_name(bh->b_dev), bh->b_blocknr); } static inline void raid5_mark_buffer_uptodate (struct buffer_head *bh, int uptodate) @@ -537,61 +592,55 @@ static inline void raid5_mark_buffer_uptodate (struct buffer_head *bh, int uptod static void raid5_end_request (struct buffer_head * bh, int uptodate) { struct stripe_head *sh = bh->b_dev_id; - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks, i; + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks, i; unsigned long flags; - PRINTK(("end_request %lu, nr_pending %d\n", sh->sector, sh->nr_pending)); - save_flags(flags); - cli(); + PRINTK("end_request %lu, nr_pending %d, uptodate: %d, (caller: %p,%p,%p,%p).\n", sh->sector, atomic_read(&sh->nr_pending), uptodate, __builtin_return_address(0),__builtin_return_address(1),__builtin_return_address(2), __builtin_return_address(3)); + md_spin_lock_irqsave(&sh->stripe_lock, flags); raid5_mark_buffer_uptodate(bh, uptodate); - --sh->nr_pending; - if (!sh->nr_pending) { - md_wakeup_thread(raid_conf->thread); - atomic_inc(&raid_conf->nr_handle); - } if (!uptodate) md_error(bh->b_dev, bh->b_rdev); - if (raid_conf->failed_disks) { + if (conf->failed_disks) { for (i = 0; i < disks; i++) { - if (raid_conf->disks[i].operational) + if (conf->disks[i].operational) continue; if (bh != sh->bh_old[i] && bh != sh->bh_req[i] && bh != sh->bh_copy[i]) continue; - if (bh->b_rdev != raid_conf->disks[i].dev) + if (bh->b_rdev != conf->disks[i].dev) continue; set_bit(STRIPE_ERROR, &sh->state); } } - restore_flags(flags); -} + md_spin_unlock_irqrestore(&sh->stripe_lock, flags); -static int raid5_map (struct md_dev *mddev, kdev_t *rdev, - unsigned long *rsector, unsigned long size) -{ - /* No complex mapping used: the core of the work is done in the - * request routine - */ - return 0; + if (atomic_dec_and_test(&sh->nr_pending)) { + atomic_inc(&conf->nr_handle); + md_wakeup_thread(conf->thread); + } } static void raid5_build_block (struct stripe_head *sh, struct buffer_head *bh, int i) { - struct raid5_data *raid_conf = sh->raid_conf; - struct md_dev *mddev = raid_conf->mddev; - int minor = (int) (mddev - md_dev); + raid5_conf_t *conf = sh->raid_conf; + mddev_t *mddev = conf->mddev; char *b_data; - kdev_t dev = MKDEV(MD_MAJOR, minor); + struct page *b_page; + kdev_t dev = mddev_to_kdev(mddev); int block = sh->sector / (sh->size >> 9); - b_data = ((volatile struct buffer_head *) bh)->b_data; + b_data = bh->b_data; + b_page = bh->b_page; memset (bh, 0, sizeof (struct buffer_head)); + init_waitqueue_head(&bh->b_wait); init_buffer(bh, raid5_end_request, sh); bh->b_dev = dev; bh->b_blocknr = block; - ((volatile struct buffer_head *) bh)->b_data = b_data; - bh->b_rdev = raid_conf->disks[i].dev; + bh->b_data = b_data; + bh->b_page = b_page; + + bh->b_rdev = conf->disks[i].dev; bh->b_rsector = sh->sector; bh->b_state = (1 << BH_Req) | (1 << BH_Mapped); @@ -599,49 +648,77 @@ static void raid5_build_block (struct stripe_head *sh, struct buffer_head *bh, i bh->b_list = BUF_LOCKED; } -static int raid5_error (struct md_dev *mddev, kdev_t dev) +static int raid5_error (mddev_t *mddev, kdev_t dev) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - md_superblock_t *sb = mddev->sb; + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + mdp_super_t *sb = mddev->sb; struct disk_info *disk; int i; - PRINTK(("raid5_error called\n")); - raid_conf->resync_parity = 0; - for (i = 0, disk = raid_conf->disks; i < raid_conf->raid_disks; i++, disk++) + PRINTK("raid5_error called\n"); + conf->resync_parity = 0; + for (i = 0, disk = conf->disks; i < conf->raid_disks; i++, disk++) { if (disk->dev == dev && disk->operational) { disk->operational = 0; - sb->disks[disk->number].state |= (1 << MD_FAULTY_DEVICE); - sb->disks[disk->number].state &= ~(1 << MD_SYNC_DEVICE); - sb->disks[disk->number].state &= ~(1 << MD_ACTIVE_DEVICE); + mark_disk_faulty(sb->disks+disk->number); + mark_disk_nonsync(sb->disks+disk->number); + mark_disk_inactive(sb->disks+disk->number); sb->active_disks--; sb->working_disks--; sb->failed_disks++; mddev->sb_dirty = 1; - raid_conf->working_disks--; - raid_conf->failed_disks++; - md_wakeup_thread(raid_conf->thread); + conf->working_disks--; + conf->failed_disks++; + md_wakeup_thread(conf->thread); printk (KERN_ALERT - "RAID5: Disk failure on %s, disabling device." - "Operation continuing on %d devices\n", - kdevname (dev), raid_conf->working_disks); + "raid5: Disk failure on %s, disabling device." + " Operation continuing on %d devices\n", + partition_name (dev), conf->working_disks); + return 0; } - return 0; + } + /* + * handle errors in spares (during reconstruction) + */ + if (conf->spare) { + disk = conf->spare; + if (disk->dev == dev) { + printk (KERN_ALERT + "raid5: Disk failure on spare %s\n", + partition_name (dev)); + if (!conf->spare->operational) { + MD_BUG(); + return -EIO; + } + disk->operational = 0; + disk->write_only = 0; + conf->spare = NULL; + mark_disk_faulty(sb->disks+disk->number); + mark_disk_nonsync(sb->disks+disk->number); + mark_disk_inactive(sb->disks+disk->number); + sb->spare_disks--; + sb->working_disks--; + sb->failed_disks++; + + return 0; + } + } + MD_BUG(); + return -EIO; } /* * Input: a 'big' sector number, * Output: index of the data and parity disk, and the sector # in them. */ -static inline unsigned long -raid5_compute_sector (int r_sector, unsigned int raid_disks, unsigned int data_disks, - unsigned int * dd_idx, unsigned int * pd_idx, - struct raid5_data *raid_conf) +static unsigned long raid5_compute_sector(int r_sector, unsigned int raid_disks, + unsigned int data_disks, unsigned int * dd_idx, + unsigned int * pd_idx, raid5_conf_t *conf) { unsigned int stripe; int chunk_number, chunk_offset; unsigned long new_sector; - int sectors_per_chunk = raid_conf->chunk_size >> 9; + int sectors_per_chunk = conf->chunk_size >> 9; /* First compute the information on this sector */ @@ -664,9 +741,9 @@ raid5_compute_sector (int r_sector, unsigned int raid_disks, unsigned int data_d /* * Select the parity disk based on the user selected algorithm. */ - if (raid_conf->level == 4) + if (conf->level == 4) *pd_idx = data_disks; - else switch (raid_conf->algorithm) { + else switch (conf->algorithm) { case ALGORITHM_LEFT_ASYMMETRIC: *pd_idx = data_disks - stripe % raid_disks; if (*dd_idx >= *pd_idx) @@ -686,7 +763,7 @@ raid5_compute_sector (int r_sector, unsigned int raid_disks, unsigned int data_d *dd_idx = (*pd_idx + 1 + *dd_idx) % raid_disks; break; default: - printk ("raid5: unsupported algorithm %d\n", raid_conf->algorithm); + printk ("raid5: unsupported algorithm %d\n", conf->algorithm); } /* @@ -707,16 +784,16 @@ raid5_compute_sector (int r_sector, unsigned int raid_disks, unsigned int data_d static unsigned long compute_blocknr(struct stripe_head *sh, int i) { - struct raid5_data *raid_conf = sh->raid_conf; - int raid_disks = raid_conf->raid_disks, data_disks = raid_disks - 1; + raid5_conf_t *conf = sh->raid_conf; + int raid_disks = conf->raid_disks, data_disks = raid_disks - 1; unsigned long new_sector = sh->sector, check; - int sectors_per_chunk = raid_conf->chunk_size >> 9; + int sectors_per_chunk = conf->chunk_size >> 9; unsigned long stripe = new_sector / sectors_per_chunk; int chunk_offset = new_sector % sectors_per_chunk; int chunk_number, dummy1, dummy2, dd_idx = i; unsigned long r_sector, blocknr; - switch (raid_conf->algorithm) { + switch (conf->algorithm) { case ALGORITHM_LEFT_ASYMMETRIC: case ALGORITHM_RIGHT_ASYMMETRIC: if (i > sh->pd_idx) @@ -729,14 +806,14 @@ static unsigned long compute_blocknr(struct stripe_head *sh, int i) i -= (sh->pd_idx + 1); break; default: - printk ("raid5: unsupported algorithm %d\n", raid_conf->algorithm); + printk ("raid5: unsupported algorithm %d\n", conf->algorithm); } chunk_number = stripe * data_disks + i; r_sector = chunk_number * sectors_per_chunk + chunk_offset; blocknr = r_sector / (sh->size >> 9); - check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, raid_conf); + check = raid5_compute_sector (r_sector, raid_disks, data_disks, &dummy1, &dummy2, conf); if (check != sh->sector || dummy1 != dd_idx || dummy2 != sh->pd_idx) { printk("compute_blocknr: map not correct\n"); return 0; @@ -744,144 +821,153 @@ static unsigned long compute_blocknr(struct stripe_head *sh, int i) return blocknr; } -#ifdef HAVE_ARCH_XORBLOCK -static void xor_block(struct buffer_head *dest, struct buffer_head *source) -{ - __xor_block((char *) dest->b_data, (char *) source->b_data, dest->b_size); -} -#else -static void xor_block(struct buffer_head *dest, struct buffer_head *source) -{ - long lines = dest->b_size / (sizeof (long)) / 8, i; - long *destp = (long *) dest->b_data, *sourcep = (long *) source->b_data; - - for (i = lines; i > 0; i--) { - *(destp + 0) ^= *(sourcep + 0); - *(destp + 1) ^= *(sourcep + 1); - *(destp + 2) ^= *(sourcep + 2); - *(destp + 3) ^= *(sourcep + 3); - *(destp + 4) ^= *(sourcep + 4); - *(destp + 5) ^= *(sourcep + 5); - *(destp + 6) ^= *(sourcep + 6); - *(destp + 7) ^= *(sourcep + 7); - destp += 8; - sourcep += 8; - } -} -#endif - static void compute_block(struct stripe_head *sh, int dd_idx) { - struct raid5_data *raid_conf = sh->raid_conf; - int i, disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int i, count, disks = conf->raid_disks; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; - PRINTK(("compute_block, stripe %lu, idx %d\n", sh->sector, dd_idx)); + PRINTK("compute_block, stripe %lu, idx %d\n", sh->sector, dd_idx); if (sh->bh_old[dd_idx] == NULL) - sh->bh_old[dd_idx] = raid5_kmalloc_buffer(sh, sh->size); + sh->bh_old[dd_idx] = raid5_alloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_old[dd_idx], dd_idx); memset(sh->bh_old[dd_idx]->b_data, 0, sh->size); + bh_ptr[0] = sh->bh_old[dd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == dd_idx) continue; if (sh->bh_old[i]) { - xor_block(sh->bh_old[dd_idx], sh->bh_old[i]); - continue; - } else + bh_ptr[count++] = sh->bh_old[i]; + } else { printk("compute_block() %d, stripe %lu, %d not present\n", dd_idx, sh->sector, i); + } + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; + } + } + if(count != 1) { + xor_block(count, &bh_ptr[0]); } raid5_mark_buffer_uptodate(sh->bh_old[dd_idx], 1); } static void compute_parity(struct stripe_head *sh, int method) { - struct raid5_data *raid_conf = sh->raid_conf; - int i, pd_idx = sh->pd_idx, disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int i, pd_idx = sh->pd_idx, disks = conf->raid_disks, count; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; - PRINTK(("compute_parity, stripe %lu, method %d\n", sh->sector, method)); + PRINTK("compute_parity, stripe %lu, method %d\n", sh->sector, method); for (i = 0; i < disks; i++) { if (i == pd_idx || !sh->bh_new[i]) continue; if (!sh->bh_copy[i]) - sh->bh_copy[i] = raid5_kmalloc_buffer(sh, sh->size); + sh->bh_copy[i] = raid5_alloc_buffer(sh, sh->size); raid5_build_block(sh, sh->bh_copy[i], i); - mark_buffer_clean(sh->bh_new[i]); + if (atomic_set_buffer_clean(sh->bh_new[i])) + atomic_set_buffer_dirty(sh->bh_copy[i]); memcpy(sh->bh_copy[i]->b_data, sh->bh_new[i]->b_data, sh->size); } - if (sh->bh_copy[pd_idx] == NULL) - sh->bh_copy[pd_idx] = raid5_kmalloc_buffer(sh, sh->size); + if (sh->bh_copy[pd_idx] == NULL) { + sh->bh_copy[pd_idx] = raid5_alloc_buffer(sh, sh->size); + atomic_set_buffer_dirty(sh->bh_copy[pd_idx]); + } raid5_build_block(sh, sh->bh_copy[pd_idx], sh->pd_idx); if (method == RECONSTRUCT_WRITE) { memset(sh->bh_copy[pd_idx]->b_data, 0, sh->size); + bh_ptr[0] = sh->bh_copy[pd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == sh->pd_idx) continue; if (sh->bh_new[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_copy[i]); - continue; + bh_ptr[count++] = sh->bh_copy[i]; + } else if (sh->bh_old[i]) { + bh_ptr[count++] = sh->bh_old[i]; } - if (sh->bh_old[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_old[i]); - continue; + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; } } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } } else if (method == READ_MODIFY_WRITE) { memcpy(sh->bh_copy[pd_idx]->b_data, sh->bh_old[pd_idx]->b_data, sh->size); + bh_ptr[0] = sh->bh_copy[pd_idx]; + count = 1; for (i = 0; i < disks; i++) { if (i == sh->pd_idx) continue; if (sh->bh_new[i] && sh->bh_old[i]) { - xor_block(sh->bh_copy[pd_idx], sh->bh_copy[i]); - xor_block(sh->bh_copy[pd_idx], sh->bh_old[i]); - continue; + bh_ptr[count++] = sh->bh_copy[i]; + bh_ptr[count++] = sh->bh_old[i]; + } + if (count >= (MAX_XOR_BLOCKS - 1)) { + xor_block(count, &bh_ptr[0]); + count = 1; } } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } } raid5_mark_buffer_uptodate(sh->bh_copy[pd_idx], 1); } static void add_stripe_bh (struct stripe_head *sh, struct buffer_head *bh, int dd_idx, int rw) { - struct raid5_data *raid_conf = sh->raid_conf; + raid5_conf_t *conf = sh->raid_conf; struct buffer_head *bh_req; - if (sh->bh_new[dd_idx]) { - printk("raid5: bug: stripe->bh_new[%d], sector %lu exists\n", dd_idx, sh->sector); - printk("forcing oops.\n"); - *(int*)0=0; - } - - set_bit(BH_Lock, &bh->b_state); + PRINTK("adding bh b#%lu to stripe s#%lu\n", bh->b_blocknr, sh->sector); + CHECK_SHLOCK(sh); + if (sh->bh_new[dd_idx]) + BUG(); - bh_req = raid5_kmalloc_bh(sh); + bh_req = raid5_alloc_bh(sh); raid5_build_block(sh, bh_req, dd_idx); bh_req->b_data = bh->b_data; + bh_req->b_page = bh->b_page; + md_spin_lock_irq(&conf->device_lock); if (sh->phase == PHASE_COMPLETE && sh->cmd == STRIPE_NONE) { + PRINTK("stripe s#%lu => PHASE_BEGIN (%s)\n", sh->sector, rw == READ ? "read" : "write"); sh->phase = PHASE_BEGIN; sh->cmd = (rw == READ) ? STRIPE_READ : STRIPE_WRITE; - raid_conf->nr_pending_stripes++; - atomic_inc(&raid_conf->nr_handle); + atomic_inc(&conf->nr_pending_stripes); + atomic_inc(&conf->nr_handle); + PRINTK("# of pending stripes: %u, # of handle: %u\n", atomic_read(&conf->nr_pending_stripes), atomic_read(&conf->nr_handle)); } sh->bh_new[dd_idx] = bh; sh->bh_req[dd_idx] = bh_req; sh->cmd_new[dd_idx] = rw; sh->new[dd_idx] = 1; + md_spin_unlock_irq(&conf->device_lock); + + PRINTK("added bh b#%lu to stripe s#%lu, disk %d.\n", bh->b_blocknr, sh->sector, dd_idx); } static void complete_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - int disks = raid_conf->raid_disks; + raid5_conf_t *conf = sh->raid_conf; + int disks = conf->raid_disks; int i, new = 0; - PRINTK(("complete_stripe %lu\n", sh->sector)); + PRINTK("complete_stripe %lu\n", sh->sector); for (i = 0; i < disks; i++) { + if (sh->cmd == STRIPE_SYNC && sh->bh_copy[i]) + raid5_update_old_bh(sh, i); if (sh->cmd == STRIPE_WRITE && i == sh->pd_idx) raid5_update_old_bh(sh, i); if (sh->bh_new[i]) { + PRINTK("stripe %lu finishes new bh, sh->new == %d\n", sh->sector, sh->new[i]); if (!sh->new[i]) { #if 0 if (sh->cmd == STRIPE_WRITE) { @@ -903,14 +989,351 @@ static void complete_stripe(struct stripe_head *sh) if (new && sh->cmd == STRIPE_WRITE) printk("raid5: bug, completed STRIPE_WRITE with new == %d\n", new); } + if (sh->cmd == STRIPE_SYNC) + md_done_sync(conf->mddev, (sh->size>>10) - sh->sync_redone,1); if (!new) - finish_stripe(sh); + finish_unlock_stripe(sh); else { - PRINTK(("stripe %lu, new == %d\n", sh->sector, new)); + PRINTK("stripe %lu, new == %d\n", sh->sector, new); sh->phase = PHASE_BEGIN; } } + +static int is_stripe_allclean(struct stripe_head *sh, int disks) +{ + int i; + + return 0; + for (i = 0; i < disks; i++) { + if (sh->bh_new[i]) + if (test_bit(BH_Dirty, &sh->bh_new[i])) + return 0; + if (sh->bh_old[i]) + if (test_bit(BH_Dirty, &sh->bh_old[i])) + return 0; + } + return 1; +} + +static void handle_stripe_write (mddev_t *mddev , raid5_conf_t *conf, + struct stripe_head *sh, int nr_write, int * operational, int disks, + int parity, int parity_failed, int nr_cache, int nr_cache_other, + int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) +{ + int i, allclean; + request_queue_t *q; + unsigned int block; + struct buffer_head *bh; + int method1 = INT_MAX, method2 = INT_MAX; + + /* + * Attempt to add entries :-) + */ + if (nr_write != disks - 1) { + for (i = 0; i < disks; i++) { + if (i == sh->pd_idx) + continue; + if (sh->bh_new[i]) + continue; + block = (int) compute_blocknr(sh, i); + bh = get_hash_table(mddev_to_kdev(mddev), block, sh->size); + if (!bh) + continue; + if (buffer_dirty(bh) && !md_test_and_set_bit(BH_Lock, &bh->b_state)) { + PRINTK("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block); + add_stripe_bh(sh, bh, i, WRITE); + sh->new[i] = 0; + nr_write++; + if (sh->bh_old[i]) { + nr_cache_overwrite++; + nr_cache_other--; + } else + if (!operational[i]) { + nr_failed_overwrite++; + nr_failed_other--; + } + } + atomic_dec(&bh->b_count); + } + } + PRINTK("handle_stripe() -- begin writing, stripe %lu\n", sh->sector); + /* + * Writing, need to update parity buffer. + * + * Compute the number of I/O requests in the "reconstruct + * write" and "read modify write" methods. + */ + if (!nr_failed_other) + method1 = (disks - 1) - (nr_write + nr_cache_other); + if (!nr_failed_overwrite && !parity_failed) + method2 = nr_write - nr_cache_overwrite + (1 - parity); + + if (method1 == INT_MAX && method2 == INT_MAX) + BUG(); + PRINTK("handle_stripe(), sector %lu, nr_write %d, method1 %d, method2 %d\n", sh->sector, nr_write, method1, method2); + + if (!method1 || !method2) { + allclean = is_stripe_allclean(sh, disks); + sh->phase = PHASE_WRITE; + compute_parity(sh, method1 <= method2 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE); + + for (i = 0; i < disks; i++) { + if (!operational[i] && !conf->spare && !conf->resync_parity) + continue; + bh = sh->bh_copy[i]; + if (i != sh->pd_idx && ((bh == NULL) ^ (sh->bh_new[i] == NULL))) + printk("raid5: bug: bh == %p, bh_new[%d] == %p\n", bh, i, sh->bh_new[i]); + if (i == sh->pd_idx && !bh) + printk("raid5: bug: bh == NULL, i == pd_idx == %d\n", i); + if (bh) { + PRINTK("making request for buffer %d\n", i); + lock_get_bh(bh); + if (!operational[i] && !conf->resync_parity) { + PRINTK("writing spare %d\n", i); + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->spare->dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); + } else { +#if 0 + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->disks[i].dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); +#else + if (!allclean || (i==sh->pd_idx)) { + PRINTK("writing dirty %d\n", i); + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->disks[i].dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); + } else { + PRINTK("not writing clean %d\n", i); + raid5_end_request(bh, 1); + sh->new[i] = 0; + } +#endif + } + atomic_dec(&bh->b_count); + } + } + PRINTK("handle_stripe() %lu, writing back %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); + return; + } + + if (method1 < method2) { + sh->write_method = RECONSTRUCT_WRITE; + for (i = 0; i < disks; i++) { + if (i == sh->pd_idx) + continue; + if (sh->bh_new[i] || sh->bh_old[i]) + continue; + sh->bh_old[i] = raid5_alloc_buffer(sh, sh->size); + raid5_build_block(sh, sh->bh_old[i], i); + } + } else { + sh->write_method = READ_MODIFY_WRITE; + for (i = 0; i < disks; i++) { + if (sh->bh_old[i]) + continue; + if (!sh->bh_new[i] && i != sh->pd_idx) + continue; + sh->bh_old[i] = raid5_alloc_buffer(sh, sh->size); + raid5_build_block(sh, sh->bh_old[i], i); + } + } + sh->phase = PHASE_READ_OLD; + for (i = 0; i < disks; i++) { + if (!sh->bh_old[i]) + continue; + if (test_bit(BH_Uptodate, &sh->bh_old[i]->b_state)) + continue; + lock_get_bh(sh->bh_old[i]); + atomic_inc(&sh->nr_pending); + sh->bh_old[i]->b_rdev = conf->disks[i].dev; + q = blk_get_queue(sh->bh_old[i]->b_rdev); + generic_make_request(q, READ, sh->bh_old[i]); + atomic_dec(&sh->bh_old[i]->b_count); + } + PRINTK("handle_stripe() %lu, reading %d old buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); +} + +/* + * Reading + */ +static void handle_stripe_read (mddev_t *mddev , raid5_conf_t *conf, + struct stripe_head *sh, int nr_read, int * operational, int disks, + int parity, int parity_failed, int nr_cache, int nr_cache_other, + int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) +{ + int i; + request_queue_t *q; + int method1 = INT_MAX; + + method1 = nr_read - nr_cache_overwrite; + + PRINTK("handle_stripe(), sector %lu, nr_read %d, nr_cache %d, method1 %d\n", sh->sector, nr_read, nr_cache, method1); + + if (!method1 || (method1 == 1 && nr_cache == disks - 1)) { + PRINTK("read %lu completed from cache\n", sh->sector); + for (i = 0; i < disks; i++) { + if (!sh->bh_new[i]) + continue; + if (!sh->bh_old[i]) + compute_block(sh, i); + memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); + } + complete_stripe(sh); + return; + } + if (nr_failed_overwrite) { + sh->phase = PHASE_READ_OLD; + for (i = 0; i < disks; i++) { + if (sh->bh_old[i]) + continue; + if (!operational[i]) + continue; + sh->bh_old[i] = raid5_alloc_buffer(sh, sh->size); + raid5_build_block(sh, sh->bh_old[i], i); + lock_get_bh(sh->bh_old[i]); + atomic_inc(&sh->nr_pending); + sh->bh_old[i]->b_rdev = conf->disks[i].dev; + q = blk_get_queue(sh->bh_old[i]->b_rdev); + generic_make_request(q, READ, sh->bh_old[i]); + atomic_dec(&sh->bh_old[i]->b_count); + } + PRINTK("handle_stripe() %lu, phase READ_OLD, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); + return; + } + sh->phase = PHASE_READ; + for (i = 0; i < disks; i++) { + if (!sh->bh_new[i]) + continue; + if (sh->bh_old[i]) { + memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); + continue; + } +#if RAID5_PARANOIA + if (sh->bh_req[i] == NULL || test_bit(BH_Lock, &sh->bh_req[i]->b_state)) { + int j; + printk("req %d is NULL! or locked \n", i); + for (j=0; j<disks; j++) { + printk("%d: new=%p old=%p req=%p new=%d cmd=%d\n", + j, sh->bh_new[j], sh->bh_old[j], sh->bh_req[j], + sh->new[j], sh->cmd_new[j]); + } + + } +#endif + lock_get_bh(sh->bh_req[i]); + atomic_inc(&sh->nr_pending); + sh->bh_req[i]->b_rdev = conf->disks[i].dev; + q = blk_get_queue(sh->bh_req[i]->b_rdev); + generic_make_request(q, READ, sh->bh_req[i]); + atomic_dec(&sh->bh_req[i]->b_count); + } + PRINTK("handle_stripe() %lu, phase READ, pending %d\n", sh->sector, md_atomic_read(&sh->nr_pending)); +} + +/* + * Syncing + */ +static void handle_stripe_sync (mddev_t *mddev , raid5_conf_t *conf, + struct stripe_head *sh, int * operational, int disks, + int parity, int parity_failed, int nr_cache, int nr_cache_other, + int nr_failed_other, int nr_cache_overwrite, int nr_failed_overwrite) +{ + request_queue_t *q; + struct buffer_head *bh; + int i, pd_idx; + + /* firstly, we want to have data from all non-failed drives + * in bh_old + */ + PRINTK("handle_stripe_sync: sec=%lu disks=%d nr_cache=%d\n", sh->sector, disks, nr_cache); + if (nr_cache < disks-1 + || (nr_cache==disks-1 && !(parity_failed+nr_failed_other+nr_failed_overwrite)) + ) { + sh->phase = PHASE_READ_OLD; + for (i = 0; i < disks; i++) { + if (sh->bh_old[i]) + continue; + if (!conf->disks[i].operational) + continue; + + bh = raid5_alloc_buffer(sh, sh->size); + sh->bh_old[i] = bh; + raid5_build_block(sh, bh, i); + lock_get_bh(bh); + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->disks[i].dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, READ, bh); + drive_stat_acct(bh->b_rdev, READ, -bh->b_size/512, 0); + atomic_dec(&sh->bh_old[i]->b_count); + } + PRINTK("handle_stripe_sync() %lu, phase READ_OLD, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); + + return; + } + /* now, if there is a failed drive, rebuild and write to spare */ + if (nr_cache == disks-1) { + sh->phase = PHASE_WRITE; + /* we can generate the missing block, which will be on the failed drive */ + for (i=0; i<disks; i++) { + if (operational[i]) + continue; + compute_block(sh, i); + if (conf->spare) { + bh = sh->bh_copy[i]; + if (bh) { + memcpy(bh->b_data, sh->bh_old[i]->b_data, sh->size); + set_bit(BH_Uptodate, &bh->b_state); + } else { + bh = sh->bh_old[i]; + sh->bh_old[i] = NULL; + sh->bh_copy[i] = bh; + } + atomic_inc(&sh->nr_pending); + lock_get_bh(bh); + bh->b_rdev = conf->spare->dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); + drive_stat_acct(bh->b_rdev, WRITE, -bh->b_size/512, 0); + atomic_dec(&bh->b_count); + PRINTK("handle_stripe_sync() %lu, phase WRITE, pending %d buffers\n", sh->sector, md_atomic_read(&sh->nr_pending)); + } + break; + } + return; + } + + /* nr_cache == disks: + * check parity and compute/write if needed + */ + + compute_parity(sh, RECONSTRUCT_WRITE); + pd_idx = sh->pd_idx; + if (!memcmp(sh->bh_copy[pd_idx]->b_data, sh->bh_old[pd_idx]->b_data, sh->size)) { + /* the parity is correct - Yay! */ + complete_stripe(sh); + } else { + sh->phase = PHASE_WRITE; + bh = sh->bh_copy[pd_idx]; + atomic_set_buffer_dirty(bh); + lock_get_bh(bh); + atomic_inc(&sh->nr_pending); + bh->b_rdev = conf->disks[pd_idx].dev; + q = blk_get_queue(bh->b_rdev); + generic_make_request(q, WRITERAW, bh); + drive_stat_acct(bh->b_rdev, WRITE, -bh->b_size/512, 0); + atomic_dec(&bh->b_count); + PRINTK("handle_stripe_sync() %lu phase WRITE, pending %d buffers\n", + sh->sector, md_atomic_read(&sh->nr_pending)); + } +} + /* * handle_stripe() is our main logic routine. Note that: * @@ -921,45 +1344,39 @@ static void complete_stripe(struct stripe_head *sh) * 2. We should be careful to set sh->nr_pending whenever we sleep, * to prevent re-entry of handle_stripe() for the same sh. * - * 3. raid_conf->failed_disks and disk->operational can be changed + * 3. conf->failed_disks and disk->operational can be changed * from an interrupt. This complicates things a bit, but it allows * us to stop issuing requests for a failed drive as soon as possible. */ static void handle_stripe(struct stripe_head *sh) { - struct raid5_data *raid_conf = sh->raid_conf; - struct md_dev *mddev = raid_conf->mddev; - int minor = (int) (mddev - md_dev); - struct buffer_head *bh; - int disks = raid_conf->raid_disks; - int i, nr = 0, nr_read = 0, nr_write = 0; - int nr_cache = 0, nr_cache_other = 0, nr_cache_overwrite = 0, parity = 0; + raid5_conf_t *conf = sh->raid_conf; + mddev_t *mddev = conf->mddev; + int disks = conf->raid_disks; + int i, nr_read = 0, nr_write = 0, parity = 0; + int nr_cache = 0, nr_cache_other = 0, nr_cache_overwrite = 0; int nr_failed_other = 0, nr_failed_overwrite = 0, parity_failed = 0; - int reading = 0, nr_writing = 0; - int method1 = INT_MAX, method2 = INT_MAX; - int block; - unsigned long flags; - int operational[MD_SB_DISKS], failed_disks = raid_conf->failed_disks; + int operational[MD_SB_DISKS], failed_disks = conf->failed_disks; - PRINTK(("handle_stripe(), stripe %lu\n", sh->sector)); - if (sh->nr_pending) { - printk("handle_stripe(), stripe %lu, io still pending\n", sh->sector); - return; - } - if (sh->phase == PHASE_COMPLETE) { - printk("handle_stripe(), stripe %lu, already complete\n", sh->sector); - return; - } + PRINTK("handle_stripe(), stripe %lu\n", sh->sector); + if (!stripe_locked(sh)) + BUG(); + if (md_atomic_read(&sh->nr_pending)) + BUG(); + if (sh->phase == PHASE_COMPLETE) + BUG(); - atomic_dec(&raid_conf->nr_handle); + atomic_dec(&conf->nr_handle); - if (test_and_clear_bit(STRIPE_ERROR, &sh->state)) { + if (md_test_and_clear_bit(STRIPE_ERROR, &sh->state)) { printk("raid5: restarting stripe %lu\n", sh->sector); sh->phase = PHASE_BEGIN; } if ((sh->cmd == STRIPE_WRITE && sh->phase == PHASE_WRITE) || - (sh->cmd == STRIPE_READ && sh->phase == PHASE_READ)) { + (sh->cmd == STRIPE_READ && sh->phase == PHASE_READ) || + (sh->cmd == STRIPE_SYNC && sh->phase == PHASE_WRITE) + ) { /* * Completed */ @@ -968,16 +1385,18 @@ static void handle_stripe(struct stripe_head *sh) return; } - save_flags(flags); - cli(); + md_spin_lock_irq(&conf->device_lock); for (i = 0; i < disks; i++) { - operational[i] = raid_conf->disks[i].operational; - if (i == sh->pd_idx && raid_conf->resync_parity) + operational[i] = conf->disks[i].operational; + if (i == sh->pd_idx && conf->resync_parity) operational[i] = 0; } - failed_disks = raid_conf->failed_disks; - restore_flags(flags); + failed_disks = conf->failed_disks; + md_spin_unlock_irq(&conf->device_lock); + /* + * Make this one more graceful? + */ if (failed_disks > 1) { for (i = 0; i < disks; i++) { if (sh->bh_new[i]) { @@ -985,267 +1404,184 @@ static void handle_stripe(struct stripe_head *sh) continue; } } - finish_stripe(sh); + if (sh->cmd == STRIPE_SYNC) + md_done_sync(conf->mddev, (sh->size>>10) - sh->sync_redone,1); + finish_unlock_stripe(sh); return; } + PRINTK("=== stripe index START ===\n"); for (i = 0; i < disks; i++) { - if (sh->bh_old[i]) + PRINTK("disk %d, ", i); + if (sh->bh_old[i]) { nr_cache++; + PRINTK(" (old cached, %d)", nr_cache); + } if (i == sh->pd_idx) { - if (sh->bh_old[i]) + PRINTK(" PARITY."); + if (sh->bh_old[i]) { + PRINTK(" CACHED."); parity = 1; - else if(!operational[i]) - parity_failed = 1; + } else { + PRINTK(" UNCACHED."); + if (!operational[i]) { + PRINTK(" FAILED."); + parity_failed = 1; + } + } + PRINTK("\n"); continue; } if (!sh->bh_new[i]) { - if (sh->bh_old[i]) + PRINTK(" (no new data block) "); + if (sh->bh_old[i]) { + PRINTK(" (but old block cached) "); nr_cache_other++; - else if (!operational[i]) - nr_failed_other++; + } else { + if (!operational[i]) { + PRINTK(" (because failed disk) "); + nr_failed_other++; + } else + PRINTK(" (no old block either) "); + } + PRINTK("\n"); continue; } sh->new[i] = 0; - nr++; - if (sh->cmd_new[i] == READ) + if (sh->cmd_new[i] == READ) { nr_read++; - if (sh->cmd_new[i] == WRITE) - nr_write++; - if (sh->bh_old[i]) - nr_cache_overwrite++; - else if (!operational[i]) - nr_failed_overwrite++; - } - - if (nr_write && nr_read) - printk("raid5: bug, nr_write == %d, nr_read == %d, sh->cmd == %d\n", nr_write, nr_read, sh->cmd); - - if (nr_write) { - /* - * Attempt to add entries :-) - */ - if (nr_write != disks - 1) { - for (i = 0; i < disks; i++) { - if (i == sh->pd_idx) - continue; - if (sh->bh_new[i]) - continue; - block = (int) compute_blocknr(sh, i); - bh = get_hash_table(MKDEV(MD_MAJOR, minor), block, sh->size); - if (bh) { - if (atomic_read(&bh->b_count) == 1 && - buffer_dirty(bh) && - !buffer_locked(bh)) { - PRINTK(("Whee.. sector %lu, index %d (%d) found in the buffer cache!\n", sh->sector, i, block)); - add_stripe_bh(sh, bh, i, WRITE); - sh->new[i] = 0; - nr++; nr_write++; - if (sh->bh_old[i]) { - nr_cache_overwrite++; - nr_cache_other--; - } else if (!operational[i]) { - nr_failed_overwrite++; - nr_failed_other--; - } - } - atomic_dec(&bh->b_count); - } - } + PRINTK(" (new READ %d)", nr_read); } - PRINTK(("handle_stripe() -- begin writing, stripe %lu\n", sh->sector)); - /* - * Writing, need to update parity buffer. - * - * Compute the number of I/O requests in the "reconstruct - * write" and "read modify write" methods. - */ - if (!nr_failed_other) - method1 = (disks - 1) - (nr_write + nr_cache_other); - if (!nr_failed_overwrite && !parity_failed) - method2 = nr_write - nr_cache_overwrite + (1 - parity); - - if (method1 == INT_MAX && method2 == INT_MAX) - printk("raid5: bug: method1 == method2 == INT_MAX\n"); - PRINTK(("handle_stripe(), sector %lu, nr_write %d, method1 %d, method2 %d\n", sh->sector, nr_write, method1, method2)); - - if (!method1 || !method2) { - lock_stripe(sh); - sh->nr_pending++; - sh->phase = PHASE_WRITE; - compute_parity(sh, method1 <= method2 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE); - for (i = 0; i < disks; i++) { - if (!operational[i] && !raid_conf->spare && !raid_conf->resync_parity) - continue; - if (i == sh->pd_idx || sh->bh_new[i]) - nr_writing++; - } - - sh->nr_pending = nr_writing; - PRINTK(("handle_stripe() %lu, writing back %d\n", sh->sector, sh->nr_pending)); - - for (i = 0; i < disks; i++) { - if (!operational[i] && !raid_conf->spare && !raid_conf->resync_parity) - continue; - bh = sh->bh_copy[i]; - if (i != sh->pd_idx && ((bh == NULL) ^ (sh->bh_new[i] == NULL))) - printk("raid5: bug: bh == %p, bh_new[%d] == %p\n", bh, i, sh->bh_new[i]); - if (i == sh->pd_idx && !bh) - printk("raid5: bug: bh == NULL, i == pd_idx == %d\n", i); - if (bh) { - bh->b_state |= (1<<BH_Dirty); - PRINTK(("making request for buffer %d\n", i)); - clear_bit(BH_Lock, &bh->b_state); - if (!operational[i] && !raid_conf->resync_parity) { - bh->b_rdev = raid_conf->spare->dev; - make_request(MAJOR(raid_conf->spare->dev), WRITE, bh); - } else - make_request(MAJOR(raid_conf->disks[i].dev), WRITE, bh); - } - } - return; - } - - lock_stripe(sh); - sh->nr_pending++; - if (method1 < method2) { - sh->write_method = RECONSTRUCT_WRITE; - for (i = 0; i < disks; i++) { - if (i == sh->pd_idx) - continue; - if (sh->bh_new[i] || sh->bh_old[i]) - continue; - sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); - raid5_build_block(sh, sh->bh_old[i], i); - reading++; - } - } else { - sh->write_method = READ_MODIFY_WRITE; - for (i = 0; i < disks; i++) { - if (sh->bh_old[i]) - continue; - if (!sh->bh_new[i] && i != sh->pd_idx) - continue; - sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); - raid5_build_block(sh, sh->bh_old[i], i); - reading++; - } - } - sh->phase = PHASE_READ_OLD; - sh->nr_pending = reading; - PRINTK(("handle_stripe() %lu, reading %d old buffers\n", sh->sector, sh->nr_pending)); - for (i = 0; i < disks; i++) { - if (!sh->bh_old[i]) - continue; - if (buffer_uptodate(sh->bh_old[i])) - continue; - clear_bit(BH_Lock, &sh->bh_old[i]->b_state); - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_old[i]); - } - } else { - /* - * Reading - */ - method1 = nr_read - nr_cache_overwrite; - lock_stripe(sh); - sh->nr_pending++; - - PRINTK(("handle_stripe(), sector %lu, nr_read %d, nr_cache %d, method1 %d\n", sh->sector, nr_read, nr_cache, method1)); - if (!method1 || (method1 == 1 && nr_cache == disks - 1)) { - PRINTK(("read %lu completed from cache\n", sh->sector)); - for (i = 0; i < disks; i++) { - if (!sh->bh_new[i]) - continue; - if (!sh->bh_old[i]) - compute_block(sh, i); - memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); - } - sh->nr_pending--; - complete_stripe(sh); - return; + if (sh->cmd_new[i] == WRITE) { + nr_write++; + PRINTK(" (new WRITE %d)", nr_write); } - if (nr_failed_overwrite) { - sh->phase = PHASE_READ_OLD; - sh->nr_pending = (disks - 1) - nr_cache; - PRINTK(("handle_stripe() %lu, phase READ_OLD, pending %d\n", sh->sector, sh->nr_pending)); - for (i = 0; i < disks; i++) { - if (sh->bh_old[i]) - continue; - if (!operational[i]) - continue; - sh->bh_old[i] = raid5_kmalloc_buffer(sh, sh->size); - raid5_build_block(sh, sh->bh_old[i], i); - clear_bit(BH_Lock, &sh->bh_old[i]->b_state); - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_old[i]); - } + if (sh->bh_old[i]) { + nr_cache_overwrite++; + PRINTK(" (overwriting old %d)", nr_cache_overwrite); } else { - sh->phase = PHASE_READ; - sh->nr_pending = nr_read - nr_cache_overwrite; - PRINTK(("handle_stripe() %lu, phase READ, pending %d\n", sh->sector, sh->nr_pending)); - for (i = 0; i < disks; i++) { - if (!sh->bh_new[i]) - continue; - if (sh->bh_old[i]) { - memcpy(sh->bh_new[i]->b_data, sh->bh_old[i]->b_data, sh->size); - continue; - } - make_request(MAJOR(raid_conf->disks[i].dev), READ, sh->bh_req[i]); + if (!operational[i]) { + nr_failed_overwrite++; + PRINTK(" (overwriting failed %d)", nr_failed_overwrite); } } + PRINTK("\n"); } + PRINTK("=== stripe index END ===\n"); + + if (nr_write && nr_read) + BUG(); + + if (nr_write) + handle_stripe_write( + mddev, conf, sh, nr_write, operational, disks, + parity, parity_failed, nr_cache, nr_cache_other, + nr_failed_other, nr_cache_overwrite, + nr_failed_overwrite + ); + else if (nr_read) + handle_stripe_read( + mddev, conf, sh, nr_read, operational, disks, + parity, parity_failed, nr_cache, nr_cache_other, + nr_failed_other, nr_cache_overwrite, + nr_failed_overwrite + ); + else if (sh->cmd == STRIPE_SYNC) + handle_stripe_sync( + mddev, conf, sh, operational, disks, + parity, parity_failed, nr_cache, nr_cache_other, + nr_failed_other, nr_cache_overwrite, nr_failed_overwrite + ); } -static int raid5_make_request (struct md_dev *mddev, int rw, struct buffer_head * bh) + +static int raid5_make_request (request_queue_t *q, mddev_t *mddev, int rw, struct buffer_head * bh) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - const unsigned int raid_disks = raid_conf->raid_disks; + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + const unsigned int raid_disks = conf->raid_disks; const unsigned int data_disks = raid_disks - 1; unsigned int dd_idx, pd_idx; unsigned long new_sector; struct stripe_head *sh; - if (rw == READA) rw = READ; + if (rw == READA) + rw = READ; - new_sector = raid5_compute_sector(bh->b_rsector, raid_disks, data_disks, - &dd_idx, &pd_idx, raid_conf); + new_sector = raid5_compute_sector(bh->b_blocknr*(bh->b_size>>9), + raid_disks, data_disks, &dd_idx, &pd_idx, conf); - PRINTK(("raid5_make_request, sector %lu\n", new_sector)); -repeat: - sh = get_stripe(raid_conf, new_sector, bh->b_size); + PRINTK("raid5_make_request, sector %lu\n", new_sector); + sh = get_lock_stripe(conf, new_sector, bh->b_size); +#if 0 if ((rw == READ && sh->cmd == STRIPE_WRITE) || (rw == WRITE && sh->cmd == STRIPE_READ)) { - PRINTK(("raid5: lock contention, rw == %d, sh->cmd == %d\n", rw, sh->cmd)); + PRINTK("raid5: lock contention, rw == %d, sh->cmd == %d\n", rw, sh->cmd); lock_stripe(sh); - if (!sh->nr_pending) + if (!md_atomic_read(&sh->nr_pending)) handle_stripe(sh); goto repeat; } +#endif sh->pd_idx = pd_idx; if (sh->phase != PHASE_COMPLETE && sh->phase != PHASE_BEGIN) - PRINTK(("stripe %lu catching the bus!\n", sh->sector)); - if (sh->bh_new[dd_idx]) { - printk("raid5: bug: stripe->bh_new[%d], sector %lu exists\n", dd_idx, sh->sector); - printk("raid5: bh %p, bh_new %p\n", bh, sh->bh_new[dd_idx]); - lock_stripe(sh); - md_wakeup_thread(raid_conf->thread); - wait_on_stripe(sh); - goto repeat; - } + PRINTK("stripe %lu catching the bus!\n", sh->sector); + if (sh->bh_new[dd_idx]) + BUG(); add_stripe_bh(sh, bh, dd_idx, rw); - md_wakeup_thread(raid_conf->thread); + md_wakeup_thread(conf->thread); return 0; } -static void unplug_devices(struct stripe_head *sh) +/* + * Determine correct block size for this device. + */ +unsigned int device_bsize (kdev_t dev) { -#if 0 - struct raid5_data *raid_conf = sh->raid_conf; - int i; + unsigned int i, correct_size; - for (i = 0; i < raid_conf->raid_disks; i++) - unplug_device(blk_dev + MAJOR(raid_conf->disks[i].dev)); -#endif + correct_size = BLOCK_SIZE; + if (blksize_size[MAJOR(dev)]) { + i = blksize_size[MAJOR(dev)][MINOR(dev)]; + if (i) + correct_size = i; + } + + return correct_size; +} + +static int raid5_sync_request (mddev_t *mddev, unsigned long block_nr) +{ + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + struct stripe_head *sh; + int sectors_per_chunk = conf->chunk_size >> 9; + unsigned long stripe = (block_nr<<2)/sectors_per_chunk; + int chunk_offset = (block_nr<<2) % sectors_per_chunk; + int dd_idx, pd_idx; + unsigned long first_sector; + int raid_disks = conf->raid_disks; + int data_disks = raid_disks-1; + int redone = 0; + int bufsize; + + if (!conf->buffer_size) + conf->buffer_size = /* device_bsize(mddev_to_kdev(mddev))*/ PAGE_SIZE; + bufsize = conf->buffer_size; + /* Hmm... race on buffer_size ?? */ + redone = block_nr% (bufsize>>10); + block_nr -= redone; + sh = get_lock_stripe(conf, block_nr<<1, bufsize); + first_sector = raid5_compute_sector(stripe*data_disks*sectors_per_chunk+chunk_offset, + raid_disks, data_disks, + &dd_idx, &pd_idx, conf); + sh->pd_idx = pd_idx; + sh->cmd = STRIPE_SYNC; + sh->phase = PHASE_BEGIN; + sh->sync_redone = redone; + atomic_inc(&conf->nr_pending_stripes); + atomic_inc(&conf->nr_handle); + md_wakeup_thread(conf->thread); + return (bufsize>>10)-redone; } /* @@ -1258,56 +1594,53 @@ static void unplug_devices(struct stripe_head *sh) static void raid5d (void *data) { struct stripe_head *sh; - struct raid5_data *raid_conf = data; - struct md_dev *mddev = raid_conf->mddev; - int i, handled = 0, unplug = 0; - unsigned long flags; + raid5_conf_t *conf = data; + mddev_t *mddev = conf->mddev; + int i, handled; - PRINTK(("+++ raid5d active\n")); + PRINTK("+++ raid5d active\n"); + handled = 0; + md_spin_lock_irq(&conf->device_lock); + clear_bit(THREAD_WAKEUP, &conf->thread->flags); +repeat_pass: if (mddev->sb_dirty) { + md_spin_unlock_irq(&conf->device_lock); mddev->sb_dirty = 0; - md_update_sb((int) (mddev - md_dev)); + md_update_sb(mddev); + md_spin_lock_irq(&conf->device_lock); } for (i = 0; i < NR_HASH; i++) { repeat: - sh = raid_conf->stripe_hashtbl[i]; + sh = conf->stripe_hashtbl[i]; for (; sh; sh = sh->hash_next) { - if (sh->raid_conf != raid_conf) + if (sh->raid_conf != conf) continue; if (sh->phase == PHASE_COMPLETE) continue; - if (sh->nr_pending) + if (md_atomic_read(&sh->nr_pending)) continue; - if (sh->sector == raid_conf->next_sector) { - raid_conf->sector_count += (sh->size >> 9); - if (raid_conf->sector_count >= 128) - unplug = 1; - } else - unplug = 1; - if (unplug) { - PRINTK(("unplugging devices, sector == %lu, count == %d\n", sh->sector, raid_conf->sector_count)); - unplug_devices(sh); - unplug = 0; - raid_conf->sector_count = 0; - } - raid_conf->next_sector = sh->sector + (sh->size >> 9); + md_spin_unlock_irq(&conf->device_lock); + if (!atomic_read(&sh->count)) + BUG(); + handled++; handle_stripe(sh); + md_spin_lock_irq(&conf->device_lock); goto repeat; } } - if (raid_conf) { - PRINTK(("%d stripes handled, nr_handle %d\n", handled, atomic_read(&raid_conf->nr_handle))); - save_flags(flags); - cli(); - if (!atomic_read(&raid_conf->nr_handle)) - clear_bit(THREAD_WAKEUP, &raid_conf->thread->flags); + if (conf) { + PRINTK("%d stripes handled, nr_handle %d\n", handled, md_atomic_read(&conf->nr_handle)); + if (test_and_clear_bit(THREAD_WAKEUP, &conf->thread->flags) && + md_atomic_read(&conf->nr_handle)) + goto repeat_pass; } - PRINTK(("--- raid5d inactive\n")); + md_spin_unlock_irq(&conf->device_lock); + + PRINTK("--- raid5d inactive\n"); } -#if SUPPORT_RECONSTRUCTION /* * Private kernel thread for parity reconstruction after an unclean * shutdown. Reconstruction on spare drives in case of a failed drive @@ -1315,44 +1648,68 @@ repeat: */ static void raid5syncd (void *data) { - struct raid5_data *raid_conf = data; - struct md_dev *mddev = raid_conf->mddev; + raid5_conf_t *conf = data; + mddev_t *mddev = conf->mddev; - if (!raid_conf->resync_parity) + if (!conf->resync_parity) + return; + if (conf->resync_parity == 2) return; - md_do_sync(mddev); - raid_conf->resync_parity = 0; + down(&mddev->recovery_sem); + if (md_do_sync(mddev,NULL)) { + up(&mddev->recovery_sem); + printk("raid5: resync aborted!\n"); + return; + } + conf->resync_parity = 0; + up(&mddev->recovery_sem); + printk("raid5: resync finished.\n"); } -#endif /* SUPPORT_RECONSTRUCTION */ -static int __check_consistency (struct md_dev *mddev, int row) +static int __check_consistency (mddev_t *mddev, int row) { - struct raid5_data *raid_conf = mddev->private; + raid5_conf_t *conf = mddev->private; kdev_t dev; - struct buffer_head *bh[MD_SB_DISKS], tmp; - int i, rc = 0, nr = 0; - - if (raid_conf->working_disks != raid_conf->raid_disks) - return 0; - tmp.b_size = 4096; - if ((tmp.b_data = (char *) get_free_page(GFP_KERNEL)) == NULL) - return 0; + struct buffer_head *bh[MD_SB_DISKS], *tmp = NULL; + int i, ret = 0, nr = 0, count; + struct buffer_head *bh_ptr[MAX_XOR_BLOCKS]; + + if (conf->working_disks != conf->raid_disks) + goto out; + tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); + tmp->b_size = 4096; + tmp->b_page = alloc_page(GFP_KERNEL); + tmp->b_data = (char *)page_address(tmp->b_page); + if (!tmp->b_data) + goto out; + md_clear_page((unsigned long)tmp->b_data); memset(bh, 0, MD_SB_DISKS * sizeof(struct buffer_head *)); - for (i = 0; i < raid_conf->raid_disks; i++) { - dev = raid_conf->disks[i].dev; + for (i = 0; i < conf->raid_disks; i++) { + dev = conf->disks[i].dev; set_blocksize(dev, 4096); - if ((bh[i] = bread(dev, row / 4, 4096)) == NULL) + bh[i] = bread(dev, row / 4, 4096); + if (!bh[i]) break; nr++; } - if (nr == raid_conf->raid_disks) { - for (i = 1; i < nr; i++) - xor_block(&tmp, bh[i]); - if (memcmp(tmp.b_data, bh[0]->b_data, 4096)) - rc = 1; + if (nr == conf->raid_disks) { + bh_ptr[0] = tmp; + count = 1; + for (i = 1; i < nr; i++) { + bh_ptr[count++] = bh[i]; + if (count == MAX_XOR_BLOCKS) { + xor_block(count, &bh_ptr[0]); + count = 1; + } + } + if (count != 1) { + xor_block(count, &bh_ptr[0]); + } + if (memcmp(tmp->b_data, bh[0]->b_data, 4096)) + ret = 1; } - for (i = 0; i < raid_conf->raid_disks; i++) { - dev = raid_conf->disks[i].dev; + for (i = 0; i < conf->raid_disks; i++) { + dev = conf->disks[i].dev; if (bh[i]) { bforget(bh[i]); bh[i] = NULL; @@ -1360,308 +1717,691 @@ static int __check_consistency (struct md_dev *mddev, int row) fsync_dev(dev); invalidate_buffers(dev); } - free_page((unsigned long) tmp.b_data); - return rc; + free_page((unsigned long) tmp->b_data); +out: + if (tmp) + kfree(tmp); + return ret; } -static int check_consistency (struct md_dev *mddev) +static int check_consistency (mddev_t *mddev) { - int size = mddev->sb->size; - int row; + if (__check_consistency(mddev, 0)) +/* + * We are not checking this currently, as it's legitimate to have + * an inconsistent array, at creation time. + */ + return 0; - for (row = 0; row < size; row += size / 8) - if (__check_consistency(mddev, row)) - return 1; return 0; } -static int raid5_run (int minor, struct md_dev *mddev) +static int raid5_run (mddev_t *mddev) { - struct raid5_data *raid_conf; + raid5_conf_t *conf; int i, j, raid_disk, memory; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; - struct real_dev *realdev; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *desc; + mdk_rdev_t *rdev; + struct disk_info *disk; + struct md_list_head *tmp; + int start_recovery = 0; MOD_INC_USE_COUNT; if (sb->level != 5 && sb->level != 4) { - printk("raid5: %s: raid level not set to 4/5 (%d)\n", kdevname(MKDEV(MD_MAJOR, minor)), sb->level); + printk("raid5: md%d: raid level not set to 4/5 (%d)\n", mdidx(mddev), sb->level); MOD_DEC_USE_COUNT; return -EIO; } - mddev->private = kmalloc (sizeof (struct raid5_data), GFP_KERNEL); - if ((raid_conf = mddev->private) == NULL) + mddev->private = kmalloc (sizeof (raid5_conf_t), GFP_KERNEL); + if ((conf = mddev->private) == NULL) goto abort; - memset (raid_conf, 0, sizeof (*raid_conf)); - raid_conf->mddev = mddev; + memset (conf, 0, sizeof (*conf)); + conf->mddev = mddev; - if ((raid_conf->stripe_hashtbl = (struct stripe_head **) __get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) + if ((conf->stripe_hashtbl = (struct stripe_head **) md__get_free_pages(GFP_ATOMIC, HASH_PAGES_ORDER)) == NULL) goto abort; - memset(raid_conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); + memset(conf->stripe_hashtbl, 0, HASH_PAGES * PAGE_SIZE); - init_waitqueue_head(&raid_conf->wait_for_stripe); - PRINTK(("raid5_run(%d) called.\n", minor)); - - for (i = 0; i < mddev->nb_dev; i++) { - realdev = &mddev->devices[i]; - if (!realdev->sb) { - printk(KERN_ERR "raid5: disabled device %s (couldn't access raid superblock)\n", kdevname(realdev->dev)); - continue; - } + conf->device_lock = MD_SPIN_LOCK_UNLOCKED; + md_init_waitqueue_head(&conf->wait_for_stripe); + PRINTK("raid5_run(md%d) called.\n", mdidx(mddev)); + ITERATE_RDEV(mddev,rdev,tmp) { /* * This is important -- we are using the descriptor on * the disk only to get a pointer to the descriptor on * the main superblock, which might be more recent. */ - descriptor = &sb->disks[realdev->sb->descriptor.number]; - if (descriptor->state & (1 << MD_FAULTY_DEVICE)) { - printk(KERN_ERR "raid5: disabled device %s (errors detected)\n", kdevname(realdev->dev)); + desc = sb->disks + rdev->desc_nr; + raid_disk = desc->raid_disk; + disk = conf->disks + raid_disk; + + if (disk_faulty(desc)) { + printk(KERN_ERR "raid5: disabled device %s (errors detected)\n", partition_name(rdev->dev)); + if (!rdev->faulty) { + MD_BUG(); + goto abort; + } + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; continue; } - if (descriptor->state & (1 << MD_ACTIVE_DEVICE)) { - if (!(descriptor->state & (1 << MD_SYNC_DEVICE))) { - printk(KERN_ERR "raid5: disabled device %s (not in sync)\n", kdevname(realdev->dev)); - continue; + if (disk_active(desc)) { + if (!disk_sync(desc)) { + printk(KERN_ERR "raid5: disabled device %s (not in sync)\n", partition_name(rdev->dev)); + MD_BUG(); + goto abort; } - raid_disk = descriptor->raid_disk; - if (descriptor->number > sb->nr_disks || raid_disk > sb->raid_disks) { - printk(KERN_ERR "raid5: disabled device %s (inconsistent descriptor)\n", kdevname(realdev->dev)); + if (raid_disk > sb->raid_disks) { + printk(KERN_ERR "raid5: disabled device %s (inconsistent descriptor)\n", partition_name(rdev->dev)); continue; } - if (raid_conf->disks[raid_disk].operational) { - printk(KERN_ERR "raid5: disabled device %s (device %d already operational)\n", kdevname(realdev->dev), raid_disk); + if (disk->operational) { + printk(KERN_ERR "raid5: disabled device %s (device %d already operational)\n", partition_name(rdev->dev), raid_disk); continue; } - printk(KERN_INFO "raid5: device %s operational as raid disk %d\n", kdevname(realdev->dev), raid_disk); + printk(KERN_INFO "raid5: device %s operational as raid disk %d\n", partition_name(rdev->dev), raid_disk); - raid_conf->disks[raid_disk].number = descriptor->number; - raid_conf->disks[raid_disk].raid_disk = raid_disk; - raid_conf->disks[raid_disk].dev = mddev->devices[i].dev; - raid_conf->disks[raid_disk].operational = 1; + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; + disk->operational = 1; + disk->used_slot = 1; - raid_conf->working_disks++; + conf->working_disks++; } else { /* * Must be a spare disk .. */ - printk(KERN_INFO "raid5: spare disk %s\n", kdevname(realdev->dev)); - raid_disk = descriptor->raid_disk; - raid_conf->disks[raid_disk].number = descriptor->number; - raid_conf->disks[raid_disk].raid_disk = raid_disk; - raid_conf->disks[raid_disk].dev = mddev->devices [i].dev; - - raid_conf->disks[raid_disk].operational = 0; - raid_conf->disks[raid_disk].write_only = 0; - raid_conf->disks[raid_disk].spare = 1; - } - } - raid_conf->raid_disks = sb->raid_disks; - raid_conf->failed_disks = raid_conf->raid_disks - raid_conf->working_disks; - raid_conf->mddev = mddev; - raid_conf->chunk_size = sb->chunk_size; - raid_conf->level = sb->level; - raid_conf->algorithm = sb->parity_algorithm; - raid_conf->max_nr_stripes = NR_STRIPES; - - if (raid_conf->working_disks != sb->raid_disks && sb->state != (1 << MD_SB_CLEAN)) { - printk(KERN_ALERT "raid5: raid set %s not clean and not all disks are operational -- run ckraid\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + printk(KERN_INFO "raid5: spare disk %s\n", partition_name(rdev->dev)); + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = rdev->dev; + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 1; + disk->used_slot = 1; + } } - if (!raid_conf->chunk_size || raid_conf->chunk_size % 4) { - printk(KERN_ERR "raid5: invalid chunk size %d for %s\n", raid_conf->chunk_size, kdevname(MKDEV(MD_MAJOR, minor))); + + for (i = 0; i < MD_SB_DISKS; i++) { + desc = sb->disks + i; + raid_disk = desc->raid_disk; + disk = conf->disks + raid_disk; + + if (disk_faulty(desc) && (raid_disk < sb->raid_disks) && + !conf->disks[raid_disk].used_slot) { + + disk->number = desc->number; + disk->raid_disk = raid_disk; + disk->dev = MKDEV(0,0); + + disk->operational = 0; + disk->write_only = 0; + disk->spare = 0; + disk->used_slot = 1; + } + } + + conf->raid_disks = sb->raid_disks; + /* + * 0 for a fully functional array, 1 for a degraded array. + */ + conf->failed_disks = conf->raid_disks - conf->working_disks; + conf->mddev = mddev; + conf->chunk_size = sb->chunk_size; + conf->level = sb->level; + conf->algorithm = sb->layout; + conf->max_nr_stripes = NR_STRIPES; + +#if 0 + for (i = 0; i < conf->raid_disks; i++) { + if (!conf->disks[i].used_slot) { + MD_BUG(); + goto abort; + } + } +#endif + if (!conf->chunk_size || conf->chunk_size % 4) { + printk(KERN_ERR "raid5: invalid chunk size %d for md%d\n", conf->chunk_size, mdidx(mddev)); goto abort; } - if (raid_conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { - printk(KERN_ERR "raid5: unsupported parity algorithm %d for %s\n", raid_conf->algorithm, kdevname(MKDEV(MD_MAJOR, minor))); + if (conf->algorithm > ALGORITHM_RIGHT_SYMMETRIC) { + printk(KERN_ERR "raid5: unsupported parity algorithm %d for md%d\n", conf->algorithm, mdidx(mddev)); goto abort; } - if (raid_conf->failed_disks > 1) { - printk(KERN_ERR "raid5: not enough operational devices for %s (%d/%d failed)\n", kdevname(MKDEV(MD_MAJOR, minor)), raid_conf->failed_disks, raid_conf->raid_disks); + if (conf->failed_disks > 1) { + printk(KERN_ERR "raid5: not enough operational devices for md%d (%d/%d failed)\n", mdidx(mddev), conf->failed_disks, conf->raid_disks); goto abort; } - if ((sb->state & (1 << MD_SB_CLEAN)) && check_consistency(mddev)) { - printk(KERN_ERR "raid5: detected raid-5 xor inconsistenty -- run ckraid\n"); - sb->state |= 1 << MD_SB_ERRORS; - goto abort; + if (conf->working_disks != sb->raid_disks) { + printk(KERN_ALERT "raid5: md%d, not all disks are operational -- trying to recover array\n", mdidx(mddev)); + start_recovery = 1; } - if ((raid_conf->thread = md_register_thread(raid5d, raid_conf)) == NULL) { - printk(KERN_ERR "raid5: couldn't allocate thread for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + if (!start_recovery && (sb->state & (1 << MD_SB_CLEAN)) && + check_consistency(mddev)) { + printk(KERN_ERR "raid5: detected raid-5 superblock xor inconsistency -- running resync\n"); + sb->state &= ~(1 << MD_SB_CLEAN); } -#if SUPPORT_RECONSTRUCTION - if ((raid_conf->resync_thread = md_register_thread(raid5syncd, raid_conf)) == NULL) { - printk(KERN_ERR "raid5: couldn't allocate thread for %s\n", kdevname(MKDEV(MD_MAJOR, minor))); - goto abort; + { + const char * name = "raid5d"; + + conf->thread = md_register_thread(raid5d, conf, name); + if (!conf->thread) { + printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); + goto abort; + } } -#endif /* SUPPORT_RECONSTRUCTION */ - memory = raid_conf->max_nr_stripes * (sizeof(struct stripe_head) + - raid_conf->raid_disks * (sizeof(struct buffer_head) + + memory = conf->max_nr_stripes * (sizeof(struct stripe_head) + + conf->raid_disks * (sizeof(struct buffer_head) + 2 * (sizeof(struct buffer_head) + PAGE_SIZE))) / 1024; - if (grow_stripes(raid_conf, raid_conf->max_nr_stripes, GFP_KERNEL)) { + if (grow_stripes(conf, conf->max_nr_stripes, GFP_KERNEL)) { printk(KERN_ERR "raid5: couldn't allocate %dkB for buffers\n", memory); - shrink_stripes(raid_conf, raid_conf->max_nr_stripes); + shrink_stripes(conf, conf->max_nr_stripes); goto abort; } else - printk(KERN_INFO "raid5: allocated %dkB for %s\n", memory, kdevname(MKDEV(MD_MAJOR, minor))); + printk(KERN_INFO "raid5: allocated %dkB for md%d\n", memory, mdidx(mddev)); /* * Regenerate the "device is in sync with the raid set" bit for * each device. */ - for (i = 0; i < sb->nr_disks ; i++) { - sb->disks[i].state &= ~(1 << MD_SYNC_DEVICE); + for (i = 0; i < MD_SB_DISKS ; i++) { + mark_disk_nonsync(sb->disks + i); for (j = 0; j < sb->raid_disks; j++) { - if (!raid_conf->disks[j].operational) + if (!conf->disks[j].operational) continue; - if (sb->disks[i].number == raid_conf->disks[j].number) - sb->disks[i].state |= 1 << MD_SYNC_DEVICE; + if (sb->disks[i].number == conf->disks[j].number) + mark_disk_sync(sb->disks + i); } } - sb->active_disks = raid_conf->working_disks; + sb->active_disks = conf->working_disks; if (sb->active_disks == sb->raid_disks) - printk("raid5: raid level %d set %s active with %d out of %d devices, algorithm %d\n", raid_conf->level, kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks, raid_conf->algorithm); + printk("raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), sb->active_disks, sb->raid_disks, conf->algorithm); else - printk(KERN_ALERT "raid5: raid level %d set %s active with %d out of %d devices, algorithm %d\n", raid_conf->level, kdevname(MKDEV(MD_MAJOR, minor)), sb->active_disks, sb->raid_disks, raid_conf->algorithm); + printk(KERN_ALERT "raid5: raid level %d set md%d active with %d out of %d devices, algorithm %d\n", conf->level, mdidx(mddev), sb->active_disks, sb->raid_disks, conf->algorithm); + + if (!start_recovery && !(sb->state & (1 << MD_SB_CLEAN))) { + const char * name = "raid5syncd"; + + conf->resync_thread = md_register_thread(raid5syncd, conf,name); + if (!conf->resync_thread) { + printk(KERN_ERR "raid5: couldn't allocate thread for md%d\n", mdidx(mddev)); + goto abort; + } - if ((sb->state & (1 << MD_SB_CLEAN)) == 0) { - printk("raid5: raid set %s not clean; re-constructing parity\n", kdevname(MKDEV(MD_MAJOR, minor))); - raid_conf->resync_parity = 1; -#if SUPPORT_RECONSTRUCTION - md_wakeup_thread(raid_conf->resync_thread); -#endif /* SUPPORT_RECONSTRUCTION */ + printk("raid5: raid set md%d not clean; reconstructing parity\n", mdidx(mddev)); + conf->resync_parity = 1; + md_wakeup_thread(conf->resync_thread); } + print_raid5_conf(conf); + if (start_recovery) + md_recover_arrays(); + print_raid5_conf(conf); + /* Ok, everything is just fine now */ return (0); abort: - if (raid_conf) { - if (raid_conf->stripe_hashtbl) - free_pages((unsigned long) raid_conf->stripe_hashtbl, HASH_PAGES_ORDER); - kfree(raid_conf); + if (conf) { + print_raid5_conf(conf); + if (conf->stripe_hashtbl) + free_pages((unsigned long) conf->stripe_hashtbl, + HASH_PAGES_ORDER); + kfree(conf); } mddev->private = NULL; - printk(KERN_ALERT "raid5: failed to run raid set %s\n", kdevname(MKDEV(MD_MAJOR, minor))); + printk(KERN_ALERT "raid5: failed to run raid set md%d\n", mdidx(mddev)); MOD_DEC_USE_COUNT; return -EIO; } -static int raid5_stop (int minor, struct md_dev *mddev) +static int raid5_stop_resync (mddev_t *mddev) +{ + raid5_conf_t *conf = mddev_to_conf(mddev); + mdk_thread_t *thread = conf->resync_thread; + + if (thread) { + if (conf->resync_parity) { + conf->resync_parity = 2; + md_interrupt_thread(thread); + printk(KERN_INFO "raid5: parity resync was not fully finished, restarting next time.\n"); + return 1; + } + return 0; + } + return 0; +} + +static int raid5_restart_resync (mddev_t *mddev) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; + raid5_conf_t *conf = mddev_to_conf(mddev); - shrink_stripe_cache(raid_conf, raid_conf->max_nr_stripes); - shrink_stripes(raid_conf, raid_conf->max_nr_stripes); - md_unregister_thread(raid_conf->thread); -#if SUPPORT_RECONSTRUCTION - md_unregister_thread(raid_conf->resync_thread); -#endif /* SUPPORT_RECONSTRUCTION */ - free_pages((unsigned long) raid_conf->stripe_hashtbl, HASH_PAGES_ORDER); - kfree(raid_conf); + if (conf->resync_parity) { + if (!conf->resync_thread) { + MD_BUG(); + return 0; + } + printk("raid5: waking up raid5resync.\n"); + conf->resync_parity = 1; + md_wakeup_thread(conf->resync_thread); + return 1; + } else + printk("raid5: no restart-resync needed.\n"); + return 0; +} + + +static int raid5_stop (mddev_t *mddev) +{ + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + + shrink_stripe_cache(conf, conf->max_nr_stripes); + shrink_stripes(conf, conf->max_nr_stripes); + md_unregister_thread(conf->thread); + if (conf->resync_thread) + md_unregister_thread(conf->resync_thread); + free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER); + kfree(conf); mddev->private = NULL; MOD_DEC_USE_COUNT; return 0; } -static int raid5_status (char *page, int minor, struct md_dev *mddev) +#if RAID5_DEBUG +static void print_sh (struct stripe_head *sh) +{ + int i; + + printk("sh %lu, phase %d, size %d, pd_idx %d, state %ld, cmd %d.\n", sh->sector, sh->phase, sh->size, sh->pd_idx, sh->state, sh->cmd); + printk("sh %lu, write_method %d, nr_pending %d, count %d.\n", sh->sector, sh->write_method, atomic_read(&sh->nr_pending), atomic_read(&sh->count)); + printk("sh %lu, ", sh->sector); + for (i = 0; i < MD_SB_DISKS; i++) { + if (sh->bh_old[i]) + printk("(old%d: %p) ", i, sh->bh_old[i]); + if (sh->bh_new[i]) + printk("(new%d: %p) ", i, sh->bh_new[i]); + if (sh->bh_copy[i]) + printk("(copy%d: %p) ", i, sh->bh_copy[i]); + if (sh->bh_req[i]) + printk("(req%d: %p) ", i, sh->bh_req[i]); + } + printk("\n"); + for (i = 0; i < MD_SB_DISKS; i++) + printk("%d(%d/%d) ", i, sh->cmd_new[i], sh->new[i]); + printk("\n"); +} + +static void printall (raid5_conf_t *conf) { - struct raid5_data *raid_conf = (struct raid5_data *) mddev->private; - md_superblock_t *sb = mddev->sb; + struct stripe_head *sh; + int i; + + md_spin_lock_irq(&conf->device_lock); + for (i = 0; i < NR_HASH; i++) { + sh = conf->stripe_hashtbl[i]; + for (; sh; sh = sh->hash_next) { + if (sh->raid_conf != conf) + continue; + print_sh(sh); + } + } + md_spin_unlock_irq(&conf->device_lock); + + PRINTK("--- raid5d inactive\n"); +} +#endif + +static int raid5_status (char *page, mddev_t *mddev) +{ + raid5_conf_t *conf = (raid5_conf_t *) mddev->private; + mdp_super_t *sb = mddev->sb; int sz = 0, i; - sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", sb->level, sb->chunk_size >> 10, sb->parity_algorithm); - sz += sprintf (page+sz, " [%d/%d] [", raid_conf->raid_disks, raid_conf->working_disks); - for (i = 0; i < raid_conf->raid_disks; i++) - sz += sprintf (page+sz, "%s", raid_conf->disks[i].operational ? "U" : "_"); + sz += sprintf (page+sz, " level %d, %dk chunk, algorithm %d", sb->level, sb->chunk_size >> 10, sb->layout); + sz += sprintf (page+sz, " [%d/%d] [", conf->raid_disks, conf->working_disks); + for (i = 0; i < conf->raid_disks; i++) + sz += sprintf (page+sz, "%s", conf->disks[i].operational ? "U" : "_"); sz += sprintf (page+sz, "]"); +#if RAID5_DEBUG +#define D(x) \ + sz += sprintf (page+sz, "<"#x":%d>", atomic_read(&conf->x)) + D(nr_handle); + D(nr_stripes); + D(nr_hashed_stripes); + D(nr_locked_stripes); + D(nr_pending_stripes); + D(nr_cached_stripes); + D(nr_free_sh); + printall(conf); +#endif return sz; } -static int raid5_mark_spare(struct md_dev *mddev, md_descriptor_t *spare, int state) +static void print_raid5_conf (raid5_conf_t *conf) { - int i = 0, failed_disk = -1; - struct raid5_data *raid_conf = mddev->private; - struct disk_info *disk = raid_conf->disks; - unsigned long flags; - md_superblock_t *sb = mddev->sb; - md_descriptor_t *descriptor; + int i; + struct disk_info *tmp; - for (i = 0; i < MD_SB_DISKS; i++, disk++) { - if (disk->spare && disk->number == spare->number) - goto found; + printk("RAID5 conf printout:\n"); + if (!conf) { + printk("(conf==NULL)\n"); + return; } - return 1; -found: - for (i = 0, disk = raid_conf->disks; i < raid_conf->raid_disks; i++, disk++) - if (!disk->operational) - failed_disk = i; - if (failed_disk == -1) - return 1; - save_flags(flags); - cli(); + printk(" --- rd:%d wd:%d fd:%d\n", conf->raid_disks, + conf->working_disks, conf->failed_disks); + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + printk(" disk %d, s:%d, o:%d, n:%d rd:%d us:%d dev:%s\n", + i, tmp->spare,tmp->operational, + tmp->number,tmp->raid_disk,tmp->used_slot, + partition_name(tmp->dev)); + } +} + +static int raid5_diskop(mddev_t *mddev, mdp_disk_t **d, int state) +{ + int err = 0; + int i, failed_disk=-1, spare_disk=-1, removed_disk=-1, added_disk=-1; + raid5_conf_t *conf = mddev->private; + struct disk_info *tmp, *sdisk, *fdisk, *rdisk, *adisk; + mdp_super_t *sb = mddev->sb; + mdp_disk_t *failed_desc, *spare_desc, *added_desc; + + print_raid5_conf(conf); + md_spin_lock_irq(&conf->device_lock); + /* + * find the disk ... + */ switch (state) { - case SPARE_WRITE: - disk->operational = 1; - disk->write_only = 1; - raid_conf->spare = disk; - break; - case SPARE_INACTIVE: - disk->operational = 0; - disk->write_only = 0; - raid_conf->spare = NULL; - break; - case SPARE_ACTIVE: - disk->spare = 0; - disk->write_only = 0; - descriptor = &sb->disks[raid_conf->disks[failed_disk].number]; - i = spare->raid_disk; - disk->raid_disk = spare->raid_disk = descriptor->raid_disk; - if (disk->raid_disk != failed_disk) - printk("raid5: disk->raid_disk != failed_disk"); - descriptor->raid_disk = i; - - raid_conf->spare = NULL; - raid_conf->working_disks++; - raid_conf->failed_disks--; - raid_conf->disks[failed_disk] = *disk; - break; - default: - printk("raid5_mark_spare: bug: state == %d\n", state); - restore_flags(flags); - return 1; + case DISKOP_SPARE_ACTIVE: + + /* + * Find the failed disk within the RAID5 configuration ... + * (this can only be in the first conf->raid_disks part) + */ + for (i = 0; i < conf->raid_disks; i++) { + tmp = conf->disks + i; + if ((!tmp->operational && !tmp->spare) || + !tmp->used_slot) { + failed_disk = i; + break; + } + } + /* + * When we activate a spare disk we _must_ have a disk in + * the lower (active) part of the array to replace. + */ + if ((failed_disk == -1) || (failed_disk >= conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + /* fall through */ + + case DISKOP_SPARE_WRITE: + case DISKOP_SPARE_INACTIVE: + + /* + * Find the spare disk ... (can only be in the 'high' + * area of the array) + */ + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (tmp->spare && tmp->number == (*d)->number) { + spare_disk = i; + break; + } + } + if (spare_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_REMOVE_DISK: + + for (i = 0; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (tmp->used_slot && (tmp->number == (*d)->number)) { + if (tmp->operational) { + err = -EBUSY; + goto abort; + } + removed_disk = i; + break; + } + } + if (removed_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; + + case DISKOP_HOT_ADD_DISK: + + for (i = conf->raid_disks; i < MD_SB_DISKS; i++) { + tmp = conf->disks + i; + if (!tmp->used_slot) { + added_disk = i; + break; + } + } + if (added_disk == -1) { + MD_BUG(); + err = 1; + goto abort; + } + break; } - restore_flags(flags); - return 0; + + switch (state) { + /* + * Switch the spare disk to write-only mode: + */ + case DISKOP_SPARE_WRITE: + if (conf->spare) { + MD_BUG(); + err = 1; + goto abort; + } + sdisk = conf->disks + spare_disk; + sdisk->operational = 1; + sdisk->write_only = 1; + conf->spare = sdisk; + break; + /* + * Deactivate a spare disk: + */ + case DISKOP_SPARE_INACTIVE: + sdisk = conf->disks + spare_disk; + sdisk->operational = 0; + sdisk->write_only = 0; + /* + * Was the spare being resynced? + */ + if (conf->spare == sdisk) + conf->spare = NULL; + break; + /* + * Activate (mark read-write) the (now sync) spare disk, + * which means we switch it's 'raid position' (->raid_disk) + * with the failed disk. (only the first 'conf->raid_disks' + * slots are used for 'real' disks and we must preserve this + * property) + */ + case DISKOP_SPARE_ACTIVE: + if (!conf->spare) { + MD_BUG(); + err = 1; + goto abort; + } + sdisk = conf->disks + spare_disk; + fdisk = conf->disks + failed_disk; + + spare_desc = &sb->disks[sdisk->number]; + failed_desc = &sb->disks[fdisk->number]; + + if (spare_desc != *d) { + MD_BUG(); + err = 1; + goto abort; + } + + if (spare_desc->raid_disk != sdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (sdisk->raid_disk != spare_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (failed_desc->raid_disk != fdisk->raid_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + if (fdisk->raid_disk != failed_disk) { + MD_BUG(); + err = 1; + goto abort; + } + + /* + * do the switch finally + */ + xchg_values(*spare_desc, *failed_desc); + xchg_values(*fdisk, *sdisk); + + /* + * (careful, 'failed' and 'spare' are switched from now on) + * + * we want to preserve linear numbering and we want to + * give the proper raid_disk number to the now activated + * disk. (this means we switch back these values) + */ + + xchg_values(spare_desc->raid_disk, failed_desc->raid_disk); + xchg_values(sdisk->raid_disk, fdisk->raid_disk); + xchg_values(spare_desc->number, failed_desc->number); + xchg_values(sdisk->number, fdisk->number); + + *d = failed_desc; + + if (sdisk->dev == MKDEV(0,0)) + sdisk->used_slot = 0; + + /* + * this really activates the spare. + */ + fdisk->spare = 0; + fdisk->write_only = 0; + + /* + * if we activate a spare, we definitely replace a + * non-operational disk slot in the 'low' area of + * the disk array. + */ + conf->failed_disks--; + conf->working_disks++; + conf->spare = NULL; + + break; + + case DISKOP_HOT_REMOVE_DISK: + rdisk = conf->disks + removed_disk; + + if (rdisk->spare && (removed_disk < conf->raid_disks)) { + MD_BUG(); + err = 1; + goto abort; + } + rdisk->dev = MKDEV(0,0); + rdisk->used_slot = 0; + + break; + + case DISKOP_HOT_ADD_DISK: + adisk = conf->disks + added_disk; + added_desc = *d; + + if (added_disk != added_desc->number) { + MD_BUG(); + err = 1; + goto abort; + } + + adisk->number = added_desc->number; + adisk->raid_disk = added_desc->raid_disk; + adisk->dev = MKDEV(added_desc->major,added_desc->minor); + + adisk->operational = 0; + adisk->write_only = 0; + adisk->spare = 1; + adisk->used_slot = 1; + + + break; + + default: + MD_BUG(); + err = 1; + goto abort; + } +abort: + md_spin_unlock_irq(&conf->device_lock); + print_raid5_conf(conf); + return err; } -static struct md_personality raid5_personality= +static mdk_personality_t raid5_personality= { "raid5", - raid5_map, raid5_make_request, raid5_end_request, raid5_run, raid5_stop, raid5_status, - NULL, /* no ioctls */ 0, raid5_error, - /* raid5_hot_add_disk, */ NULL, - /* raid1_hot_remove_drive */ NULL, - raid5_mark_spare + raid5_diskop, + raid5_stop_resync, + raid5_restart_resync, + raid5_sync_request }; int raid5_init (void) { - return register_md_personality (RAID5, &raid5_personality); + int err; + + err = register_md_personality (RAID5, &raid5_personality); + if (err) + return err; + return 0; } #ifdef MODULE diff --git a/drivers/block/xor.c b/drivers/block/xor.c new file mode 100644 index 000000000..ca1bb1564 --- /dev/null +++ b/drivers/block/xor.c @@ -0,0 +1,1894 @@ +/* + * xor.c : Multiple Devices driver for Linux + * + * Copyright (C) 1996, 1997, 1998, 1999 Ingo Molnar, Matti Aarnio, Jakub Jelinek + * + * + * optimized RAID-5 checksumming functions. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * You should have received a copy of the GNU General Public License + * (for example /usr/src/linux/COPYING); if not, write to the Free + * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ +#define BH_TRACE 0 +#include <linux/module.h> +#include <linux/raid/md.h> +#ifdef __sparc_v9__ +#include <asm/head.h> +#include <asm/asi.h> +#include <asm/visasm.h> +#endif + +/* + * we use the 'XOR function template' to register multiple xor + * functions runtime. The kernel measures their speed upon bootup + * and decides which one to use. (compile-time registration is + * not enough as certain CPU features like MMX can only be detected + * runtime) + * + * this architecture makes it pretty easy to add new routines + * that are faster on certain CPUs, without killing other CPU's + * 'native' routine. Although the current routines are belived + * to be the physically fastest ones on all CPUs tested, but + * feel free to prove me wrong and add yet another routine =B-) + * --mingo + */ + +#define MAX_XOR_BLOCKS 5 + +#define XOR_ARGS (unsigned int count, struct buffer_head **bh_ptr) + +typedef void (*xor_block_t) XOR_ARGS; +xor_block_t xor_block = NULL; + +#ifndef __sparc_v9__ + +struct xor_block_template; + +struct xor_block_template { + char * name; + xor_block_t xor_block; + int speed; + struct xor_block_template * next; +}; + +struct xor_block_template * xor_functions = NULL; + +#define XORBLOCK_TEMPLATE(x) \ +static void xor_block_##x XOR_ARGS; \ +static struct xor_block_template t_xor_block_##x = \ + { #x, xor_block_##x, 0, NULL }; \ +static void xor_block_##x XOR_ARGS + +#ifdef __i386__ + +#ifdef CONFIG_X86_XMM +/* + * Cache avoiding checksumming functions utilizing KNI instructions + * Copyright (C) 1999 Zach Brown (with obvious credit due Ingo) + */ + +XORBLOCK_TEMPLATE(pIII_kni) +{ + char xmm_save[16*4]; + int cr0; + int lines = (bh_ptr[0]->b_size>>8); + + __asm__ __volatile__ ( + "movl %%cr0,%0 ;\n\t" + "clts ;\n\t" + "movups %%xmm0,(%1) ;\n\t" + "movups %%xmm1,0x10(%1) ;\n\t" + "movups %%xmm2,0x20(%1) ;\n\t" + "movups %%xmm3,0x30(%1) ;\n\t" + : "=r" (cr0) + : "r" (xmm_save) + : "memory" ); + +#define OFFS(x) "8*("#x"*2)" +#define PF0(x) \ + " prefetcht0 "OFFS(x)"(%1) ;\n" +#define LD(x,y) \ + " movaps "OFFS(x)"(%1), %%xmm"#y" ;\n" +#define ST(x,y) \ + " movaps %%xmm"#y", "OFFS(x)"(%1) ;\n" +#define PF1(x) \ + " prefetchnta "OFFS(x)"(%2) ;\n" +#define PF2(x) \ + " prefetchnta "OFFS(x)"(%3) ;\n" +#define PF3(x) \ + " prefetchnta "OFFS(x)"(%4) ;\n" +#define PF4(x) \ + " prefetchnta "OFFS(x)"(%5) ;\n" +#define PF5(x) \ + " prefetchnta "OFFS(x)"(%6) ;\n" +#define XO1(x,y) \ + " xorps "OFFS(x)"(%2), %%xmm"#y" ;\n" +#define XO2(x,y) \ + " xorps "OFFS(x)"(%3), %%xmm"#y" ;\n" +#define XO3(x,y) \ + " xorps "OFFS(x)"(%4), %%xmm"#y" ;\n" +#define XO4(x,y) \ + " xorps "OFFS(x)"(%5), %%xmm"#y" ;\n" +#define XO5(x,y) \ + " xorps "OFFS(x)"(%6), %%xmm"#y" ;\n" + + switch(count) { + case 2: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + PF1(i) \ + PF1(i+2) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF0(i+4) \ + PF0(i+6) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory" ); + break; + case 3: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory" ); + break; + case 4: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + PF3(i) \ + PF3(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " addl $256, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory" ); + break; + case 5: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + PF1(i) \ + PF1(i+2) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + PF2(i) \ + PF2(i+2) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + PF3(i) \ + PF3(i+2) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + PF4(i) \ + PF4(i+2) \ + PF0(i+4) \ + PF0(i+6) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + XO4(i,0) \ + XO4(i+1,1) \ + XO4(i+2,2) \ + XO4(i+3,3) \ + ST(i,0) \ + ST(i+1,1) \ + ST(i+2,2) \ + ST(i+3,3) \ + + + PF0(0) + PF0(2) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $256, %1 ;\n" + " addl $256, %2 ;\n" + " addl $256, %3 ;\n" + " addl $256, %4 ;\n" + " addl $256, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory"); + break; + } + + __asm__ __volatile__ ( + "sfence ;\n\t" + "movups (%1),%%xmm0 ;\n\t" + "movups 0x10(%1),%%xmm1 ;\n\t" + "movups 0x20(%1),%%xmm2 ;\n\t" + "movups 0x30(%1),%%xmm3 ;\n\t" + "movl %0,%%cr0 ;\n\t" + : + : "r" (cr0), "r" (xmm_save) + : "memory" ); +} + +#undef OFFS +#undef LD +#undef ST +#undef PF0 +#undef PF1 +#undef PF2 +#undef PF3 +#undef PF4 +#undef PF5 +#undef XO1 +#undef XO2 +#undef XO3 +#undef XO4 +#undef XO5 +#undef BLOCK + +#endif /* CONFIG_X86_XMM */ + +/* + * high-speed RAID5 checksumming functions utilizing MMX instructions + * Copyright (C) 1998 Ingo Molnar + */ +XORBLOCK_TEMPLATE(pII_mmx) +{ + char fpu_save[108]; + int lines = (bh_ptr[0]->b_size>>7); + + if (!(current->flags & PF_USEDFPU)) + __asm__ __volatile__ ( " clts;\n"); + + __asm__ __volatile__ ( " fsave %0; fwait\n"::"m"(fpu_save[0]) ); + +#define LD(x,y) \ + " movq 8*("#x")(%1), %%mm"#y" ;\n" +#define ST(x,y) \ + " movq %%mm"#y", 8*("#x")(%1) ;\n" +#define XO1(x,y) \ + " pxor 8*("#x")(%2), %%mm"#y" ;\n" +#define XO2(x,y) \ + " pxor 8*("#x")(%3), %%mm"#y" ;\n" +#define XO3(x,y) \ + " pxor 8*("#x")(%4), %%mm"#y" ;\n" +#define XO4(x,y) \ + " pxor 8*("#x")(%5), %%mm"#y" ;\n" + + switch(count) { + case 2: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + ST(i,0) \ + XO1(i+1,1) \ + ST(i+1,1) \ + XO1(i+2,2) \ + ST(i+2,2) \ + XO1(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory"); + break; + case 3: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + ST(i,0) \ + XO2(i+1,1) \ + ST(i+1,1) \ + XO2(i+2,2) \ + ST(i+2,2) \ + XO2(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory"); + break; + case 4: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + ST(i,0) \ + XO3(i+1,1) \ + ST(i+1,1) \ + XO3(i+2,2) \ + ST(i+2,2) \ + XO3(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " addl $128, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory"); + break; + case 5: + __asm__ __volatile__ ( +#undef BLOCK +#define BLOCK(i) \ + LD(i,0) \ + LD(i+1,1) \ + LD(i+2,2) \ + LD(i+3,3) \ + XO1(i,0) \ + XO1(i+1,1) \ + XO1(i+2,2) \ + XO1(i+3,3) \ + XO2(i,0) \ + XO2(i+1,1) \ + XO2(i+2,2) \ + XO2(i+3,3) \ + XO3(i,0) \ + XO3(i+1,1) \ + XO3(i+2,2) \ + XO3(i+3,3) \ + XO4(i,0) \ + ST(i,0) \ + XO4(i+1,1) \ + ST(i+1,1) \ + XO4(i+2,2) \ + ST(i+2,2) \ + XO4(i+3,3) \ + ST(i+3,3) + + " .align 32,0x90 ;\n" + " 1: ;\n" + + BLOCK(0) + BLOCK(4) + BLOCK(8) + BLOCK(12) + + " addl $128, %1 ;\n" + " addl $128, %2 ;\n" + " addl $128, %3 ;\n" + " addl $128, %4 ;\n" + " addl $128, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + : + : "g" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory"); + break; + } + + __asm__ __volatile__ ( " frstor %0;\n"::"m"(fpu_save[0]) ); + + if (!(current->flags & PF_USEDFPU)) + stts(); +} + +#undef LD +#undef XO1 +#undef XO2 +#undef XO3 +#undef XO4 +#undef ST +#undef BLOCK + +XORBLOCK_TEMPLATE(p5_mmx) +{ + char fpu_save[108]; + int lines = (bh_ptr[0]->b_size>>6); + + if (!(current->flags & PF_USEDFPU)) + __asm__ __volatile__ ( " clts;\n"); + + __asm__ __volatile__ ( " fsave %0; fwait\n"::"m"(fpu_save[0]) ); + + switch(count) { + case 2: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 8(%2), %%mm1 ;\n" + " movq 24(%1), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " pxor 16(%2), %%mm2 ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq 40(%1), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%2), %%mm4 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq 56(%1), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%2), %%mm6 ;\n" + " pxor 56(%2), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data) + : "memory" ); + break; + case 3: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " movq 24(%1), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 32(%2), %%mm4 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " movq 56(%1), %%mm7 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 56(%2), %%mm7 ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data) + : "memory" ); + break; + case 4: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor (%4), %%mm0 ;\n" + " movq 24(%1), %%mm3 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " pxor 8(%4), %%mm1 ;\n" + " movq %%mm0, (%1) ;\n" + " movq 32(%1), %%mm4 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " pxor 16(%4), %%mm2 ;\n" + " movq %%mm1, 8(%1) ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 32(%2), %%mm4 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 40(%2), %%mm5 ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 24(%4), %%mm3 ;\n" + " movq %%mm3, 24(%1) ;\n" + " movq 56(%1), %%mm7 ;\n" + " movq 48(%1), %%mm6 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " pxor 32(%4), %%mm4 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 56(%2), %%mm7 ;\n" + " pxor 40(%4), %%mm5 ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%4), %%mm6 ;\n" + " pxor 56(%4), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " addl $64, %4 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "r" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data) + : "memory" ); + break; + case 5: + __asm__ __volatile__ ( + + " .align 32,0x90 ;\n" + " 1: ;\n" + " movq (%1), %%mm0 ;\n" + " movq 8(%1), %%mm1 ;\n" + " pxor (%2), %%mm0 ;\n" + " pxor 8(%2), %%mm1 ;\n" + " movq 16(%1), %%mm2 ;\n" + " pxor (%3), %%mm0 ;\n" + " pxor 8(%3), %%mm1 ;\n" + " pxor 16(%2), %%mm2 ;\n" + " pxor (%4), %%mm0 ;\n" + " pxor 8(%4), %%mm1 ;\n" + " pxor 16(%3), %%mm2 ;\n" + " movq 24(%1), %%mm3 ;\n" + " pxor (%5), %%mm0 ;\n" + " pxor 8(%5), %%mm1 ;\n" + " movq %%mm0, (%1) ;\n" + " pxor 16(%4), %%mm2 ;\n" + " pxor 24(%2), %%mm3 ;\n" + " movq %%mm1, 8(%1) ;\n" + " pxor 16(%5), %%mm2 ;\n" + " pxor 24(%3), %%mm3 ;\n" + " movq 32(%1), %%mm4 ;\n" + " movq %%mm2, 16(%1) ;\n" + " pxor 24(%4), %%mm3 ;\n" + " pxor 32(%2), %%mm4 ;\n" + " movq 40(%1), %%mm5 ;\n" + " pxor 24(%5), %%mm3 ;\n" + " pxor 32(%3), %%mm4 ;\n" + " pxor 40(%2), %%mm5 ;\n" + " movq %%mm3, 24(%1) ;\n" + " pxor 32(%4), %%mm4 ;\n" + " pxor 40(%3), %%mm5 ;\n" + " movq 48(%1), %%mm6 ;\n" + " movq 56(%1), %%mm7 ;\n" + " pxor 32(%5), %%mm4 ;\n" + " pxor 40(%4), %%mm5 ;\n" + " pxor 48(%2), %%mm6 ;\n" + " pxor 56(%2), %%mm7 ;\n" + " movq %%mm4, 32(%1) ;\n" + " pxor 48(%3), %%mm6 ;\n" + " pxor 56(%3), %%mm7 ;\n" + " pxor 40(%5), %%mm5 ;\n" + " pxor 48(%4), %%mm6 ;\n" + " pxor 56(%4), %%mm7 ;\n" + " movq %%mm5, 40(%1) ;\n" + " pxor 48(%5), %%mm6 ;\n" + " pxor 56(%5), %%mm7 ;\n" + " movq %%mm6, 48(%1) ;\n" + " movq %%mm7, 56(%1) ;\n" + + " addl $64, %1 ;\n" + " addl $64, %2 ;\n" + " addl $64, %3 ;\n" + " addl $64, %4 ;\n" + " addl $64, %5 ;\n" + " decl %0 ;\n" + " jnz 1b ;\n" + + : + : "g" (lines), + "r" (bh_ptr[0]->b_data), + "r" (bh_ptr[1]->b_data), + "r" (bh_ptr[2]->b_data), + "r" (bh_ptr[3]->b_data), + "r" (bh_ptr[4]->b_data) + : "memory" ); + break; + } + + __asm__ __volatile__ ( " frstor %0;\n"::"m"(fpu_save[0]) ); + + if (!(current->flags & PF_USEDFPU)) + stts(); +} +#endif /* __i386__ */ +#endif /* !__sparc_v9__ */ + +#ifdef __sparc_v9__ +/* + * High speed xor_block operation for RAID4/5 utilizing the + * UltraSparc Visual Instruction Set. + * + * Copyright (C) 1997, 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + * Requirements: + * !(((long)dest | (long)sourceN) & (64 - 1)) && + * !(len & 127) && len >= 256 + * + * It is done in pure assembly, as otherwise gcc makes it + * a non-leaf function, which is not what we want. + * Also, we don't measure the speeds as on other architectures, + * as the measuring routine does not take into account cold caches + * and the fact that xor_block_VIS bypasses the caches. + * xor_block_32regs might be 5% faster for count 2 if caches are hot + * and things just right (for count 3 VIS is about as fast as 32regs for + * hot caches and for count 4 and 5 VIS is faster by good margin always), + * but I think it is better not to pollute the caches. + * Actually, if I'd just fight for speed for hot caches, I could + * write a hybrid VIS/integer routine, which would do always two + * 64B blocks in VIS and two in IEUs, but I really care more about + * caches. + */ +extern void *VISenter(void); +extern void xor_block_VIS XOR_ARGS; + +void __xor_block_VIS(void) +{ +__asm__ (" + .globl xor_block_VIS +xor_block_VIS: + ldx [%%o1 + 0], %%o4 + ldx [%%o1 + 8], %%o3 + ldx [%%o4 + %1], %%g5 + ldx [%%o4 + %0], %%o4 + ldx [%%o3 + %0], %%o3 + rd %%fprs, %%o5 + andcc %%o5, %2, %%g0 + be,pt %%icc, 297f + sethi %%hi(%5), %%g1 + jmpl %%g1 + %%lo(%5), %%g7 + add %%g7, 8, %%g7 +297: wr %%g0, %4, %%fprs + membar #LoadStore|#StoreLoad|#StoreStore + sub %%g5, 64, %%g5 + ldda [%%o4] %3, %%f0 + ldda [%%o3] %3, %%f16 + cmp %%o0, 4 + bgeu,pt %%xcc, 10f + cmp %%o0, 3 + be,pn %%xcc, 13f + mov -64, %%g1 + sub %%g5, 64, %%g5 + rd %%asi, %%g1 + wr %%g0, %3, %%asi + +2: ldda [%%o4 + 64] %%asi, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + stda %%f16, [%%o4] %3 + ldda [%%o3 + 64] %%asi, %%f48 + ldda [%%o4 + 128] %%asi, %%f0 + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + add %%o4, 128, %%o4 + fxor %%f36, %%f52, %%f52 + add %%o3, 128, %%o3 + fxor %%f38, %%f54, %%f54 + subcc %%g5, 128, %%g5 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o4 - 64] %%asi + bne,pt %%xcc, 2b + ldda [%%o3] %3, %%f16 + + ldda [%%o4 + 64] %%asi, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + stda %%f16, [%%o4] %3 + ldda [%%o3 + 64] %%asi, %%f48 + membar #Sync + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + fxor %%f36, %%f52, %%f52 + fxor %%f38, %%f54, %%f54 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o4 + 64] %%asi + membar #Sync|#StoreStore|#StoreLoad + wr %%g0, 0, %%fprs + retl + wr %%g1, %%g0, %%asi + +13: ldx [%%o1 + 16], %%o2 + ldx [%%o2 + %0], %%o2 + +3: ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f48 + fxor %%f2, %%f18, %%f50 + add %%o4, 64, %%o4 + fxor %%f4, %%f20, %%f52 + fxor %%f6, %%f22, %%f54 + add %%o3, 64, %%o3 + fxor %%f8, %%f24, %%f56 + fxor %%f10, %%f26, %%f58 + fxor %%f12, %%f28, %%f60 + fxor %%f14, %%f30, %%f62 + ldda [%%o4] %3, %%f0 + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + add %%o2, 64, %%o2 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + subcc %%g5, 64, %%g5 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + stda %%f48, [%%o4 + %%g1] %3 + bne,pt %%xcc, 3b + ldda [%%o3] %3, %%f16 + + ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f48 + fxor %%f2, %%f18, %%f50 + fxor %%f4, %%f20, %%f52 + fxor %%f6, %%f22, %%f54 + fxor %%f8, %%f24, %%f56 + fxor %%f10, %%f26, %%f58 + fxor %%f12, %%f28, %%f60 + fxor %%f14, %%f30, %%f62 + membar #Sync + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + stda %%f48, [%%o4] %3 + membar #Sync|#StoreStore|#StoreLoad + retl + wr %%g0, 0, %%fprs + +10: cmp %%o0, 5 + be,pt %%xcc, 15f + mov -64, %%g1 + +14: ldx [%%o1 + 16], %%o2 + ldx [%%o1 + 24], %%o0 + ldx [%%o2 + %0], %%o2 + ldx [%%o0 + %0], %%o0 + +4: ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + add %%o4, 64, %%o4 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + add %%o3, 64, %%o3 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + ldda [%%o0] %3, %%f48 + fxor %%f16, %%f32, %%f32 + fxor %%f18, %%f34, %%f34 + fxor %%f20, %%f36, %%f36 + fxor %%f22, %%f38, %%f38 + add %%o2, 64, %%o2 + fxor %%f24, %%f40, %%f40 + fxor %%f26, %%f42, %%f42 + fxor %%f28, %%f44, %%f44 + fxor %%f30, %%f46, %%f46 + ldda [%%o4] %3, %%f0 + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + fxor %%f36, %%f52, %%f52 + add %%o0, 64, %%o0 + fxor %%f38, %%f54, %%f54 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + subcc %%g5, 64, %%g5 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o4 + %%g1] %3 + bne,pt %%xcc, 4b + ldda [%%o3] %3, %%f16 + + ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f16 + fxor %%f2, %%f18, %%f18 + fxor %%f4, %%f20, %%f20 + fxor %%f6, %%f22, %%f22 + fxor %%f8, %%f24, %%f24 + fxor %%f10, %%f26, %%f26 + fxor %%f12, %%f28, %%f28 + fxor %%f14, %%f30, %%f30 + ldda [%%o0] %3, %%f48 + fxor %%f16, %%f32, %%f32 + fxor %%f18, %%f34, %%f34 + fxor %%f20, %%f36, %%f36 + fxor %%f22, %%f38, %%f38 + fxor %%f24, %%f40, %%f40 + fxor %%f26, %%f42, %%f42 + fxor %%f28, %%f44, %%f44 + fxor %%f30, %%f46, %%f46 + membar #Sync + fxor %%f32, %%f48, %%f48 + fxor %%f34, %%f50, %%f50 + fxor %%f36, %%f52, %%f52 + fxor %%f38, %%f54, %%f54 + fxor %%f40, %%f56, %%f56 + fxor %%f42, %%f58, %%f58 + fxor %%f44, %%f60, %%f60 + fxor %%f46, %%f62, %%f62 + stda %%f48, [%%o4] %3 + membar #Sync|#StoreStore|#StoreLoad + retl + wr %%g0, 0, %%fprs + +15: ldx [%%o1 + 16], %%o2 + ldx [%%o1 + 24], %%o0 + ldx [%%o1 + 32], %%o1 + ldx [%%o2 + %0], %%o2 + ldx [%%o0 + %0], %%o0 + ldx [%%o1 + %0], %%o1 + +5: ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f48 + fxor %%f2, %%f18, %%f50 + add %%o4, 64, %%o4 + fxor %%f4, %%f20, %%f52 + fxor %%f6, %%f22, %%f54 + add %%o3, 64, %%o3 + fxor %%f8, %%f24, %%f56 + fxor %%f10, %%f26, %%f58 + fxor %%f12, %%f28, %%f60 + fxor %%f14, %%f30, %%f62 + ldda [%%o0] %3, %%f16 + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + add %%o2, 64, %%o2 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + ldda [%%o1] %3, %%f32 + fxor %%f48, %%f16, %%f48 + fxor %%f50, %%f18, %%f50 + add %%o0, 64, %%o0 + fxor %%f52, %%f20, %%f52 + fxor %%f54, %%f22, %%f54 + add %%o1, 64, %%o1 + fxor %%f56, %%f24, %%f56 + fxor %%f58, %%f26, %%f58 + fxor %%f60, %%f28, %%f60 + fxor %%f62, %%f30, %%f62 + ldda [%%o4] %3, %%f0 + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + subcc %%g5, 64, %%g5 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + stda %%f48, [%%o4 + %%g1] %3 + bne,pt %%xcc, 5b + ldda [%%o3] %3, %%f16 + + ldda [%%o2] %3, %%f32 + fxor %%f0, %%f16, %%f48 + fxor %%f2, %%f18, %%f50 + fxor %%f4, %%f20, %%f52 + fxor %%f6, %%f22, %%f54 + fxor %%f8, %%f24, %%f56 + fxor %%f10, %%f26, %%f58 + fxor %%f12, %%f28, %%f60 + fxor %%f14, %%f30, %%f62 + ldda [%%o0] %3, %%f16 + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + ldda [%%o1] %3, %%f32 + fxor %%f48, %%f16, %%f48 + fxor %%f50, %%f18, %%f50 + fxor %%f52, %%f20, %%f52 + fxor %%f54, %%f22, %%f54 + fxor %%f56, %%f24, %%f56 + fxor %%f58, %%f26, %%f58 + fxor %%f60, %%f28, %%f60 + fxor %%f62, %%f30, %%f62 + membar #Sync + fxor %%f48, %%f32, %%f48 + fxor %%f50, %%f34, %%f50 + fxor %%f52, %%f36, %%f52 + fxor %%f54, %%f38, %%f54 + fxor %%f56, %%f40, %%f56 + fxor %%f58, %%f42, %%f58 + fxor %%f60, %%f44, %%f60 + fxor %%f62, %%f46, %%f62 + stda %%f48, [%%o4] %3 + membar #Sync|#StoreStore|#StoreLoad + retl + wr %%g0, 0, %%fprs + " : : + "i" (&((struct buffer_head *)0)->b_data), + "i" (&((struct buffer_head *)0)->b_data), + "i" (FPRS_FEF|FPRS_DU), "i" (ASI_BLK_P), + "i" (FPRS_FEF), "i" (VISenter)); +} +#endif /* __sparc_v9__ */ + +#if defined(__sparc__) && !defined(__sparc_v9__) +/* + * High speed xor_block operation for RAID4/5 utilizing the + * ldd/std SPARC instructions. + * + * Copyright (C) 1999 Jakub Jelinek (jj@ultra.linux.cz) + * + */ + +XORBLOCK_TEMPLATE(SPARC) +{ + int size = bh_ptr[0]->b_size; + int lines = size / (sizeof (long)) / 8, i; + long *destp = (long *) bh_ptr[0]->b_data; + long *source1 = (long *) bh_ptr[1]->b_data; + long *source2, *source3, *source4; + + switch (count) { + case 2: + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (source1) : "g2", "g3", "g4", "g5", "o0", + "o1", "o2", "o3", "o4", "o5", "l0", "l1", "l2", "l3", "l4", "l5"); + destp += 8; + source1 += 8; + } + break; + case 3: + source2 = (long *) bh_ptr[2]->b_data; + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%2 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%2 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%2 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%2 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (source1), "r" (source2) + : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", + "l0", "l1", "l2", "l3", "l4", "l5"); + destp += 8; + source1 += 8; + source2 += 8; + } + break; + case 4: + source2 = (long *) bh_ptr[2]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%2 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%2 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%2 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%2 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%3 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%3 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%3 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%3 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (source1), "r" (source2), "r" (source3) + : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", + "l0", "l1", "l2", "l3", "l4", "l5"); + destp += 8; + source1 += 8; + source2 += 8; + source3 += 8; + } + break; + case 5: + source2 = (long *) bh_ptr[2]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + source4 = (long *) bh_ptr[4]->b_data; + for (i = lines; i > 0; i--) { + __asm__ __volatile__(" + ldd [%0 + 0x00], %%g2 + ldd [%0 + 0x08], %%g4 + ldd [%0 + 0x10], %%o0 + ldd [%0 + 0x18], %%o2 + ldd [%1 + 0x00], %%o4 + ldd [%1 + 0x08], %%l0 + ldd [%1 + 0x10], %%l2 + ldd [%1 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%2 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%2 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%2 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%2 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%3 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%3 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%3 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%3 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + ldd [%4 + 0x00], %%o4 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + ldd [%4 + 0x08], %%l0 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + ldd [%4 + 0x10], %%l2 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + ldd [%4 + 0x18], %%l4 + xor %%g2, %%o4, %%g2 + xor %%g3, %%o5, %%g3 + xor %%g4, %%l0, %%g4 + xor %%g5, %%l1, %%g5 + xor %%o0, %%l2, %%o0 + xor %%o1, %%l3, %%o1 + xor %%o2, %%l4, %%o2 + xor %%o3, %%l5, %%o3 + std %%g2, [%0 + 0x00] + std %%g4, [%0 + 0x08] + std %%o0, [%0 + 0x10] + std %%o2, [%0 + 0x18] + " : : "r" (destp), "r" (source1), "r" (source2), "r" (source3), "r" (source4) + : "g2", "g3", "g4", "g5", "o0", "o1", "o2", "o3", "o4", "o5", + "l0", "l1", "l2", "l3", "l4", "l5"); + destp += 8; + source1 += 8; + source2 += 8; + source3 += 8; + source4 += 8; + } + break; + } +} +#endif /* __sparc_v[78]__ */ + +#ifndef __sparc_v9__ + +/* + * this one works reasonably on any x86 CPU + * (send me an assembly version for inclusion if you can make it faster) + * + * this one is just as fast as written in pure assembly on x86. + * the reason for this separate version is that the + * fast open-coded xor routine "32reg" produces suboptimal code + * on x86, due to lack of registers. + */ +XORBLOCK_TEMPLATE(8regs) +{ + int len = bh_ptr[0]->b_size; + long *destp = (long *) bh_ptr[0]->b_data; + long *source1, *source2, *source3, *source4; + long lines = len / (sizeof (long)) / 8, i; + + switch(count) { + case 2: + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 7) ^= *(source1 + 7); + source1 += 8; + destp += 8; + } + break; + case 3: + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + source1 += 8; + source2 += 8; + destp += 8; + } + break; + case 4: + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 0) ^= *(source3 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 1) ^= *(source3 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 2) ^= *(source3 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 3) ^= *(source3 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 4) ^= *(source3 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 5) ^= *(source3 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 6) ^= *(source3 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + *(destp + 7) ^= *(source3 + 7); + source1 += 8; + source2 += 8; + source3 += 8; + destp += 8; + } + break; + case 5: + source4 = (long *) bh_ptr[4]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + *(destp + 0) ^= *(source1 + 0); + *(destp + 0) ^= *(source2 + 0); + *(destp + 0) ^= *(source3 + 0); + *(destp + 0) ^= *(source4 + 0); + *(destp + 1) ^= *(source1 + 1); + *(destp + 1) ^= *(source2 + 1); + *(destp + 1) ^= *(source3 + 1); + *(destp + 1) ^= *(source4 + 1); + *(destp + 2) ^= *(source1 + 2); + *(destp + 2) ^= *(source2 + 2); + *(destp + 2) ^= *(source3 + 2); + *(destp + 2) ^= *(source4 + 2); + *(destp + 3) ^= *(source1 + 3); + *(destp + 3) ^= *(source2 + 3); + *(destp + 3) ^= *(source3 + 3); + *(destp + 3) ^= *(source4 + 3); + *(destp + 4) ^= *(source1 + 4); + *(destp + 4) ^= *(source2 + 4); + *(destp + 4) ^= *(source3 + 4); + *(destp + 4) ^= *(source4 + 4); + *(destp + 5) ^= *(source1 + 5); + *(destp + 5) ^= *(source2 + 5); + *(destp + 5) ^= *(source3 + 5); + *(destp + 5) ^= *(source4 + 5); + *(destp + 6) ^= *(source1 + 6); + *(destp + 6) ^= *(source2 + 6); + *(destp + 6) ^= *(source3 + 6); + *(destp + 6) ^= *(source4 + 6); + *(destp + 7) ^= *(source1 + 7); + *(destp + 7) ^= *(source2 + 7); + *(destp + 7) ^= *(source3 + 7); + *(destp + 7) ^= *(source4 + 7); + source1 += 8; + source2 += 8; + source3 += 8; + source4 += 8; + destp += 8; + } + break; + } +} + +/* + * platform independent RAID5 checksum calculation, this should + * be very fast on any platform that has a decent amount of + * registers. (32 or more) + */ +XORBLOCK_TEMPLATE(32regs) +{ + int size = bh_ptr[0]->b_size; + int lines = size / (sizeof (long)) / 8, i; + long *destp = (long *) bh_ptr[0]->b_data; + long *source1, *source2, *source3, *source4; + + /* LOTS of registers available... + We do explicite loop-unrolling here for code which + favours RISC machines. In fact this is almoast direct + RISC assembly on Alpha and SPARC :-) */ + + + switch(count) { + case 2: + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + destp += 8; + } + break; + case 3: + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + destp += 8; + } + break; + case 4: + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + d0 ^= source3[0]; + d1 ^= source3[1]; + d2 ^= source3[2]; + d3 ^= source3[3]; + d4 ^= source3[4]; + d5 ^= source3[5]; + d6 ^= source3[6]; + d7 ^= source3[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + source3 += 8; + destp += 8; + } + break; + case 5: + source4 = (long *) bh_ptr[4]->b_data; + source3 = (long *) bh_ptr[3]->b_data; + source2 = (long *) bh_ptr[2]->b_data; + source1 = (long *) bh_ptr[1]->b_data; + for (i = lines; i > 0; i--) { + register long d0, d1, d2, d3, d4, d5, d6, d7; + d0 = destp[0]; /* Pull the stuff into registers */ + d1 = destp[1]; /* ... in bursts, if possible. */ + d2 = destp[2]; + d3 = destp[3]; + d4 = destp[4]; + d5 = destp[5]; + d6 = destp[6]; + d7 = destp[7]; + d0 ^= source1[0]; + d1 ^= source1[1]; + d2 ^= source1[2]; + d3 ^= source1[3]; + d4 ^= source1[4]; + d5 ^= source1[5]; + d6 ^= source1[6]; + d7 ^= source1[7]; + d0 ^= source2[0]; + d1 ^= source2[1]; + d2 ^= source2[2]; + d3 ^= source2[3]; + d4 ^= source2[4]; + d5 ^= source2[5]; + d6 ^= source2[6]; + d7 ^= source2[7]; + d0 ^= source3[0]; + d1 ^= source3[1]; + d2 ^= source3[2]; + d3 ^= source3[3]; + d4 ^= source3[4]; + d5 ^= source3[5]; + d6 ^= source3[6]; + d7 ^= source3[7]; + d0 ^= source4[0]; + d1 ^= source4[1]; + d2 ^= source4[2]; + d3 ^= source4[3]; + d4 ^= source4[4]; + d5 ^= source4[5]; + d6 ^= source4[6]; + d7 ^= source4[7]; + destp[0] = d0; /* Store the result (in burts) */ + destp[1] = d1; + destp[2] = d2; + destp[3] = d3; + destp[4] = d4; /* Store the result (in burts) */ + destp[5] = d5; + destp[6] = d6; + destp[7] = d7; + source1 += 8; + source2 += 8; + source3 += 8; + source4 += 8; + destp += 8; + } + break; + } +} + +/* + * (the -6*32 shift factor colors the cache) + */ +#define SIZE (PAGE_SIZE-6*32) + +static void xor_speed ( struct xor_block_template * func, + struct buffer_head *b1, struct buffer_head *b2) +{ + int speed; + unsigned long now; + int i, count, max; + struct buffer_head *bh_ptr[6]; + + func->next = xor_functions; + xor_functions = func; + bh_ptr[0] = b1; + bh_ptr[1] = b2; + + /* + * count the number of XORs done during a whole jiffy. + * calculate the speed of checksumming from this. + * (we use a 2-page allocation to have guaranteed + * color L1-cache layout) + */ + max = 0; + for (i = 0; i < 5; i++) { + now = jiffies; + count = 0; + while (jiffies == now) { + mb(); + func->xor_block(2,bh_ptr); + mb(); + count++; + mb(); + } + if (count > max) + max = count; + } + + speed = max * (HZ*SIZE/1024); + func->speed = speed; + + printk( " %-10s: %5d.%03d MB/sec\n", func->name, + speed / 1000, speed % 1000); +} + +static inline void pick_fastest_function(void) +{ + struct xor_block_template *f, *fastest; + + fastest = xor_functions; + for (f = fastest; f; f = f->next) { + if (f->speed > fastest->speed) + fastest = f; + } +#ifdef CONFIG_X86_XMM + if (boot_cpu_data.mmu_cr4_features & X86_CR4_OSXMMEXCPT) { + fastest = &t_xor_block_pIII_kni; + } +#endif + xor_block = fastest->xor_block; + printk( "using fastest function: %s (%d.%03d MB/sec)\n", fastest->name, + fastest->speed / 1000, fastest->speed % 1000); +} + +static struct buffer_head b1, b2; + +void calibrate_xor_block(void) +{ + memset(&b1,0,sizeof(b1)); + b2 = b1; + + b1.b_data = (char *) md__get_free_pages(GFP_KERNEL,2); + if (!b1.b_data) { + pick_fastest_function(); + return; + } + b2.b_data = b1.b_data + 2*PAGE_SIZE + SIZE; + + b1.b_size = SIZE; + + printk(KERN_INFO "raid5: measuring checksumming speed\n"); + + sti(); /* should be safe */ + +#if defined(__sparc__) && !defined(__sparc_v9__) + printk(KERN_INFO "raid5: trying high-speed SPARC checksum routine\n"); + xor_speed(&t_xor_block_SPARC,&b1,&b2); +#endif + +#ifdef CONFIG_X86_XMM + if (boot_cpu_data.mmu_cr4_features & X86_CR4_OSXMMEXCPT) { + printk(KERN_INFO + "raid5: KNI detected, trying cache-avoiding KNI checksum routine\n"); + /* we force the use of the KNI xor block because it + can write around l2. we may also be able + to load into the l1 only depending on how + the cpu deals with a load to a line that is + being prefetched. + */ + xor_speed(&t_xor_block_pIII_kni,&b1,&b2); + } +#endif /* CONFIG_X86_XMM */ + +#ifdef __i386__ + + if (md_cpu_has_mmx()) { + printk(KERN_INFO + "raid5: MMX detected, trying high-speed MMX checksum routines\n"); + xor_speed(&t_xor_block_pII_mmx,&b1,&b2); + xor_speed(&t_xor_block_p5_mmx,&b1,&b2); + } + +#endif /* __i386__ */ + + + xor_speed(&t_xor_block_8regs,&b1,&b2); + xor_speed(&t_xor_block_32regs,&b1,&b2); + + free_pages((unsigned long)b1.b_data,2); + pick_fastest_function(); +} + +#else /* __sparc_v9__ */ + +void calibrate_xor_block(void) +{ + printk(KERN_INFO "raid5: using high-speed VIS checksum routine\n"); + xor_block = xor_block_VIS; +} + +#endif /* __sparc_v9__ */ + +MD_EXPORT_SYMBOL(xor_block); + diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index d2aa95921..48047a637 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c @@ -1,12 +1,12 @@ #undef BLOCKMOVE #define Z_WAKE static char rcsid[] = -"$Revision: 2.3.2.4 $$Date: 2000/01/17 09:19:40 $"; +"$Revision: 2.3.2.6 $$Date: 2000/05/05 13:56:05 $"; /* * linux/drivers/char/cyclades.c * - * This file contains the driver for the Cyclades Cyclom-Y multiport + * This file contains the driver for the Cyclades async multiport * serial boards. * * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>. @@ -23,14 +23,22 @@ static char rcsid[] = * * This version supports shared IRQ's (only for PCI boards). * - * This module exports the following rs232 io functions: - * int cy_init(void); - * int cy_open(struct tty_struct *tty, struct file *filp); - * and the following functions for modularization. - * int init_module(void); - * void cleanup_module(void); - * * $Log: cyclades.c,v $ + * Revision 2.3.2.6 2000/05/05 13:56:05 ivan + * Driver now reports physical instead of virtual memory addresses. + * Masks were added to some Cyclades-Z read accesses. + * Implemented workaround for PLX9050 bug that would cause a system lockup + * in certain systems, depending on the MMIO addresses allocated to the + * board. + * Changed the Tx interrupt programming in the CD1400 chips to boost up + * performance (Cyclom-Y only). + * Code is now compliant with the new module interface (module_[init|exit]). + * Make use of the PCI helper functions to access PCI resources. + * Did some code "housekeeping". + * + * Revision 2.3.2.5 2000/01/19 14:35:33 ivan + * Fixed bug in cy_set_termios on CRTSCTS flag turnoff. + * * Revision 2.3.2.4 2000/01/17 09:19:40 ivan * Fixed SMP locking in Cyclom-Y interrupt handler. * @@ -695,7 +703,7 @@ cy_get_user(unsigned long *addr) #ifndef SERIAL_XMIT_SIZE #define SERIAL_XMIT_SIZE (MIN(PAGE_SIZE, 4096)) #endif -#define WAKEUP_CHARS (SERIAL_XMIT_SIZE-256) +#define WAKEUP_CHARS 256 #define STD_COM_FLAGS (0) @@ -706,7 +714,7 @@ static DECLARE_TASK_QUEUE(tq_cyclades); static struct tty_driver cy_serial_driver, cy_callout_driver; static int serial_refcount; -#ifndef CONFIG_COBALT_27 +#ifdef CONFIG_ISA /* This is the address lookup table. The driver will probe for Cyclom-Y/ISA boards at all addresses in here. If you want the driver to probe addresses at a different address, add it to @@ -737,7 +745,7 @@ MODULE_PARM(maddr, "1-" __MODULE_STRING(NR_CARDS) "l"); MODULE_PARM(irq, "1-" __MODULE_STRING(NR_CARDS) "i"); #endif -#endif /* CONFIG_COBALT_27 */ +#endif /* CONFIG_ISA */ /* This is the per-card data structure containing address, irq, number of channels, etc. This driver supports a maximum of NR_CARDS cards. @@ -861,12 +869,9 @@ static unsigned short cy_pci_dev_id[] = { static void cy_start(struct tty_struct *); static void set_line_char(struct cyclades_port *); static int cyz_issue_cmd(struct cyclades_card *, uclong, ucchar, uclong); -#ifndef CONFIG_COBALT_27 +#ifdef CONFIG_ISA static unsigned detect_isa_irq (volatile ucchar *); -#endif /* CONFIG_COBALT_27 */ -#ifdef CYCLOM_SHOW_STATUS -static void show_status(int); -#endif +#endif /* CONFIG_ISA */ static int cyclades_get_proc_info(char *, char **, off_t , int , int *, void *); @@ -877,23 +882,15 @@ static void cyz_poll(unsigned long); static long cyz_polling_cycle = CZ_DEF_POLL; static int cyz_timeron = 0; -static struct timer_list cyz_timerlist = { - function: cyz_poll +static struct timer_list +cyz_timerlist = { + NULL, NULL, 0, 0, cyz_poll }; #else /* CONFIG_CYZ_INTR */ static void cyz_rx_restart(unsigned long); static struct timer_list cyz_rx_full_timer[NR_PORTS]; #endif /* CONFIG_CYZ_INTR */ -/************************************************** -error = verify_area(VERIFY_WRITE, (void *) arg, sizeof(unsigned long)); -copy_to_user (to, from, count); -*************************************************************** -error = verify_area(VERIFY_READ, (void *) arg, sizeof(unsigned long *)); -copy_from_user(to, from, count); -**************************************************/ - - static inline int serial_paranoia_check(struct cyclades_port *info, kdev_t device, const char *routine) @@ -1047,7 +1044,8 @@ cyy_issue_cmd(volatile ucchar *base_addr, u_char cmd, int index) return(0); } /* cyy_issue_cmd */ -#ifndef CONFIG_COBALT_27 /* ISA interrupt detection code */ +#ifdef CONFIG_ISA +/* ISA interrupt detection code */ static unsigned detect_isa_irq (volatile ucchar *address) { @@ -1074,7 +1072,7 @@ detect_isa_irq (volatile ucchar *address) cy_writeb((u_long)address + (CyCAR<<index), 0); cy_writeb((u_long)address + (CySRER<<index), - cy_readb(address + (CySRER<<index)) | CyTxMpty); + cy_readb(address + (CySRER<<index)) | CyTxRdy); restore_flags(flags); /* Wait ... */ @@ -1088,7 +1086,7 @@ detect_isa_irq (volatile ucchar *address) save_car = cy_readb(address + (CyCAR<<index)); cy_writeb((u_long)address + (CyCAR<<index), (save_xir & 0x3)); cy_writeb((u_long)address + (CySRER<<index), - cy_readb(address + (CySRER<<index)) & ~CyTxMpty); + cy_readb(address + (CySRER<<index)) & ~CyTxRdy); cy_writeb((u_long)address + (CyTIR<<index), (save_xir & 0x3f)); cy_writeb((u_long)address + (CyCAR<<index), (save_car)); cy_writeb((u_long)address + (Cy_ClrIntr<<index), 0); @@ -1096,7 +1094,7 @@ detect_isa_irq (volatile ucchar *address) return (irq > 0)? irq : 0; } -#endif /* CONFIG_COBALT_27 */ +#endif /* CONFIG_ISA */ /* The real interrupt service routine is called whenever the card wants its hand held--chars @@ -1319,14 +1317,14 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) /* validate the port# (as configured and open) */ if( (i < 0) || (NR_PORTS <= i) ){ cy_writeb((u_long)base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty); + cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy); goto txend; } info = &cy_port[i]; info->last_active = jiffies; if(info->tty == 0){ cy_writeb((u_long)base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty); + cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy); goto txdone; } @@ -1360,19 +1358,19 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) if (!info->xmit_cnt){ cy_writeb((u_long)base_addr+(CySRER<<index), cy_readb(base_addr+(CySRER<<index)) & - ~CyTxMpty); + ~CyTxRdy); goto txdone; } if (info->xmit_buf == 0){ cy_writeb((u_long)base_addr+(CySRER<<index), cy_readb(base_addr+(CySRER<<index)) & - ~CyTxMpty); + ~CyTxRdy); goto txdone; } if (info->tty->stopped || info->tty->hw_stopped){ cy_writeb((u_long)base_addr+(CySRER<<index), cy_readb(base_addr+(CySRER<<index)) & - ~CyTxMpty); + ~CyTxRdy); goto txdone; } /* Because the Embedded Transmit Commands have @@ -1470,7 +1468,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) info->tty->hw_stopped = 0; cy_writeb((u_long)base_addr+(CySRER<<index), cy_readb(base_addr+(CySRER<<index)) | - CyTxMpty); + CyTxRdy); cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); } @@ -1481,7 +1479,7 @@ cyy_interrupt(int irq, void *dev_id, struct pt_regs *regs) info->tty->hw_stopped = 1; cy_writeb((u_long)base_addr+(CySRER<<index), cy_readb(base_addr+(CySRER<<index)) & - ~CyTxMpty); + ~CyTxRdy); } } } @@ -1526,7 +1524,8 @@ cyz_fetch_msg( struct cyclades_card *cinfo, return (-1); } zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; loc_doorbell = cy_readl(&((struct RUNTIME_9060 *) @@ -1557,7 +1556,8 @@ cyz_issue_cmd( struct cyclades_card *cinfo, return (-1); } zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; index = 0; @@ -1774,7 +1774,8 @@ cyz_handle_cmd(struct cyclades_card *cinfo) firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &(zfw_ctrl->board_ctrl); fw_ver = cy_readl(&board_ctrl->fw_version); hw_ver = cy_readl(&((struct RUNTIME_9060 *)(cinfo->ctl_addr))->mail_box_0); @@ -1951,7 +1952,8 @@ cyz_poll(unsigned long arg) firm_id = (struct FIRM_ID *)(cinfo->base_addr + ID_ADDRESS); zfw_ctrl = (struct ZFW_CTRL *) - (cinfo->base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cinfo->base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &(zfw_ctrl->board_ctrl); /* Skip first polling cycle to avoid racing conditions with the FW */ @@ -2091,9 +2093,9 @@ startup(struct cyclades_port * info) return -ENODEV; } - zfw_ctrl = - (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + zfw_ctrl = (struct ZFW_CTRL *) + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -2201,7 +2203,7 @@ start_xmit( struct cyclades_port *info ) CY_LOCK(info, flags); cy_writeb((u_long)base_addr+(CyCAR<<index), channel); cy_writeb((u_long)base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) | CyTxMpty); + cy_readb(base_addr+(CySRER<<index)) | CyTxRdy); CY_UNLOCK(info, flags); } else { #ifdef CONFIG_CYZ_INTR @@ -2299,9 +2301,9 @@ shutdown(struct cyclades_port * info) return; } - zfw_ctrl = - (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + zfw_ctrl = (struct ZFW_CTRL *) + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &(zfw_ctrl->board_ctrl); ch_ctrl = zfw_ctrl->ch_ctrl; @@ -2499,9 +2501,8 @@ block_til_ready(struct tty_struct *tty, struct file * filp, return -EINVAL; } - zfw_ctrl = - (struct ZFW_CTRL *) - (base_addr + cy_readl(&firm_id->zfwctrl_addr)); + zfw_ctrl = (struct ZFW_CTRL *) + (base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -2758,7 +2759,7 @@ cy_wait_until_sent(struct tty_struct *tty, int timeout) index = cy_card[card].bus_index; base_addr = (unsigned char *) (cy_card[card].base_addr + (cy_chip_offset[chip]<<index)); - while (cy_readb(base_addr+(CySRER<<index)) & CyTxMpty) { + while (cy_readb(base_addr+(CySRER<<index)) & CyTxRdy) { #ifdef CY_DEBUG_WAIT_UNTIL_SENT printk("Not clean (jiff=%lu)...", jiffies); #endif @@ -2882,8 +2883,8 @@ cy_close(struct tty_struct *tty, struct file *filp) unsigned char *base_addr = (unsigned char *) cy_card[info->card].base_addr; struct FIRM_ID *firm_id = (struct FIRM_ID *) (base_addr + ID_ADDRESS); - struct ZFW_CTRL *zfw_ctrl = - (struct ZFW_CTRL *) (base_addr + cy_readl(&firm_id->zfwctrl_addr)); + struct ZFW_CTRL *zfw_ctrl = (struct ZFW_CTRL *) + (base_addr + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); struct CH_CTRL *ch_ctrl = zfw_ctrl->ch_ctrl; int channel = info->line - cy_card[info->card].first_line; int retval; @@ -3136,8 +3137,9 @@ cy_chars_in_buffer(struct tty_struct *tty) volatile uclong tx_put, tx_get, tx_bufsize; firm_id = (struct FIRM_ID *)(cy_card[card].base_addr + ID_ADDRESS); - zfw_ctrl = (struct ZFW_CTRL *) (cy_card[card].base_addr + - cy_readl(&firm_id->zfwctrl_addr)); + zfw_ctrl = (struct ZFW_CTRL *) + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &(zfw_ctrl->buf_ctrl[channel]); @@ -3427,7 +3429,8 @@ set_line_char(struct cyclades_port * info) } zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; @@ -3660,7 +3663,8 @@ get_modem_info(struct cyclades_port * info, unsigned int *value) (cy_card[card].base_addr + ID_ADDRESS); if (ISZLOADED(cy_card[card])) { zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; lstatus = cy_readl(&ch_ctrl[channel].rs_status); @@ -3825,7 +3829,8 @@ set_modem_info(struct cyclades_port * info, unsigned int cmd, (cy_card[card].base_addr + ID_ADDRESS); if (ISZLOADED(cy_card[card])) { zfw_ctrl = (struct ZFW_CTRL *) - (cy_card[card].base_addr + cy_readl(&firm_id->zfwctrl_addr)); + (cy_card[card].base_addr + + (cy_readl(&firm_id->zfwctrl_addr) & 0xfffff)); board_ctrl = &zfw_ctrl->board_ctrl; ch_ctrl = zfw_ctrl->ch_ctrl; @@ -4337,7 +4342,7 @@ cy_set_termios(struct tty_struct *tty, struct termios * old_termios) if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) { - tty->stopped = 0; + tty->hw_stopped = 0; cy_start(tty); } #if 0 @@ -4502,7 +4507,7 @@ cy_stop(struct tty_struct *tty) cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)(channel & 0x0003)); /* index channel */ cy_writeb((u_long)base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) & ~CyTxMpty); + cy_readb(base_addr+(CySRER<<index)) & ~CyTxRdy); CY_UNLOCK(info, flags); } else { // Nothing to do! @@ -4542,7 +4547,7 @@ cy_start(struct tty_struct *tty) cy_writeb((u_long)base_addr+(CyCAR<<index), (u_char)(channel & 0x0003)); /* index channel */ cy_writeb((u_long)base_addr+(CySRER<<index), - cy_readb(base_addr+(CySRER<<index)) | CyTxMpty); + cy_readb(base_addr+(CySRER<<index)) | CyTxRdy); CY_UNLOCK(info, flags); } else { // Nothing to do! @@ -4707,7 +4712,6 @@ cyy_init_card(volatile ucchar *true_base_addr,int index) return chip_number; } /* cyy_init_card */ -#ifndef CONFIG_COBALT_27 /* * --------------------------------------------------------------------- * cy_detect_isa() - Probe for Cyclom-Y/ISA boards. @@ -4717,6 +4721,7 @@ cyy_init_card(volatile ucchar *true_base_addr,int index) static int __init cy_detect_isa(void) { +#ifdef CONFIG_ISA unsigned short cy_isa_irq,nboard; volatile ucchar *cy_isa_address; unsigned short i,j,cy_isa_nchan; @@ -4746,7 +4751,6 @@ cy_detect_isa(void) } /* probe for CD1400... */ - #if !defined(__alpha__) cy_isa_address = ioremap((ulong)cy_isa_address, CyISA_Ywin); #endif @@ -4819,9 +4823,10 @@ cy_detect_isa(void) cy_next_channel += cy_isa_nchan; } return(nboard); - +#else + return(0); +#endif /* CONFIG_ISA */ } /* cy_detect_isa */ -#endif /* CONFIG_COBALT_27 */ static void plx_init(uclong addr, uclong initctl) @@ -4851,11 +4856,13 @@ cy_detect_pci(void) struct pci_dev *pdev = NULL; unsigned char cyy_rev_id; unsigned char cy_pci_irq = 0; - uclong cy_pci_addr0, cy_pci_addr1, cy_pci_addr2; + uclong cy_pci_phys0, cy_pci_phys2; + uclong cy_pci_addr0, cy_pci_addr2; unsigned short i,j,cy_pci_nchan, plx_ver; unsigned short device_id,dev_index = 0; uclong mailbox; uclong Ze_addr0[NR_CARDS], Ze_addr2[NR_CARDS], ZeIndex = 0; + uclong Ze_phys0[NR_CARDS], Ze_phys2[NR_CARDS]; unsigned char Ze_irq[NR_CARDS]; for (i = 0; i < NR_CARDS; i++) { @@ -4877,10 +4884,9 @@ cy_detect_pci(void) /* read PCI configuration area */ cy_pci_irq = pdev->irq; - cy_pci_addr0 = pci_resource_start(pdev, 0); - cy_pci_addr1 = pci_resource_start(pdev, 1); - cy_pci_addr2 = pci_resource_start(pdev, 2); - pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); + cy_pci_phys0 = pci_resource_start(pdev, 0); + cy_pci_phys2 = pci_resource_start(pdev, 2); + pci_read_config_byte(pdev, PCI_REVISION_ID, &cyy_rev_id); device_id &= ~PCI_DEVICE_ID_MASK; @@ -4892,13 +4898,13 @@ cy_detect_pci(void) printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); #endif - if (pdev->resource[2].flags & ~PCI_BASE_ADDRESS_IO_MASK) { + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { printk(" Warning: PCI I/O bit incorrectly set. " "Ignoring it...\n"); - pdev->resource[2].flags &= PCI_BASE_ADDRESS_IO_MASK; + pdev->resource[2].flags &= ~IORESOURCE_IO; } #if defined(__alpha__) @@ -4908,15 +4914,15 @@ cy_detect_pci(void) printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclom-Y/PCI:found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); printk("Cyclom-Y/PCI not supported for low addresses in " "Alpha systems.\n"); i--; continue; } #else - cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Yctl); - cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ywin); + cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Yctl); + cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ywin); #endif #ifdef CY_PCI_DEBUG @@ -4928,13 +4934,13 @@ cy_detect_pci(void) if(cy_pci_nchan == 0) { printk("Cyclom-Y PCI host card with "); printk("no Serial-Modules at 0x%lx.\n", - (ulong) cy_pci_addr2); + (ulong) cy_pci_phys2); i--; continue; } if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_addr2); + (ulong) cy_pci_phys2); printk("but no channels are available.\n"); printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); return(i); @@ -4945,7 +4951,7 @@ cy_detect_pci(void) } if (j == NR_CARDS) { /* no more cy_cards available */ printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_addr2); + (ulong) cy_pci_phys2); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); return(i); @@ -4956,13 +4962,15 @@ cy_detect_pci(void) SA_SHIRQ, "Cyclom-Y", &cy_card[j])) { printk("Cyclom-Y/PCI found at 0x%lx ", - (ulong) cy_pci_addr2); + (ulong) cy_pci_phys2); printk("but could not allocate IRQ%d.\n", cy_pci_irq); return(i); } /* set cy_card */ + cy_card[j].base_phys = (ulong)cy_pci_phys2; + cy_card[j].ctl_phys = (ulong)cy_pci_phys0; cy_card[j].base_addr = (ulong)cy_pci_addr2; cy_card[j].ctl_addr = (ulong)cy_pci_addr0; cy_card[j].irq = (int) cy_pci_irq; @@ -4975,10 +4983,7 @@ cy_detect_pci(void) switch (plx_ver) { case PLX_9050: - plx_init(cy_pci_addr0, 0x50); - - cy_writew(cy_pci_addr0+0x4c, - cy_readw(cy_pci_addr0+0x4c)|0x0040); + cy_writeb(cy_pci_addr0+0x4c, 0x43); break; case PLX_9060: @@ -5000,8 +5005,8 @@ cy_detect_pci(void) /* print message */ printk("Cyclom-Y/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", j+1, - (ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Ywin - 1), + (ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Ywin - 1), (int)cy_pci_irq); printk("%d channels starting from port %d.\n", cy_pci_nchan, cy_next_channel); @@ -5014,7 +5019,7 @@ cy_detect_pci(void) printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); printk("Cyclades-Z/PCI not supported for low addresses\n"); break; }else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi){ @@ -5024,10 +5029,10 @@ cy_detect_pci(void) printk("rev_id=%d) IRQ%d\n", cyy_rev_id, (int)cy_pci_irq); printk("Cyclades-Z/PCI: found winaddr=0x%lx ctladdr=0x%lx\n", - (ulong)cy_pci_addr2, (ulong)cy_pci_addr0); + (ulong)cy_pci_phys2, (ulong)cy_pci_phys0); #endif #if !defined(__alpha__) - cy_pci_addr0 = (ulong)ioremap(cy_pci_addr0, CyPCI_Zctl); + cy_pci_addr0 = (ulong)ioremap(cy_pci_phys0, CyPCI_Zctl); #endif /* Disable interrupts on the PLX before resetting it */ @@ -5044,21 +5049,23 @@ cy_detect_pci(void) mailbox = (uclong)cy_readl(&((struct RUNTIME_9060 *) cy_pci_addr0)->mail_box_0); - if (pdev->resource[2].flags & ~PCI_BASE_ADDRESS_IO_MASK) { + if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) { printk(" Warning: PCI I/O bit incorrectly set. " "Ignoring it...\n"); - pdev->resource[2].flags &= PCI_BASE_ADDRESS_IO_MASK; + pdev->resource[2].flags &= ~IORESOURCE_IO; } if (mailbox == ZE_V1) { #if !defined(__alpha__) - cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Ze_win); + cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Ze_win); #endif if (ZeIndex == NR_CARDS) { printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); } else { + Ze_phys0[ZeIndex] = cy_pci_phys0; + Ze_phys2[ZeIndex] = cy_pci_phys2; Ze_addr0[ZeIndex] = cy_pci_addr0; Ze_addr2[ZeIndex] = cy_pci_addr2; Ze_irq[ZeIndex] = cy_pci_irq; @@ -5068,7 +5075,7 @@ cy_detect_pci(void) continue; } else { #if !defined(__alpha__) - cy_pci_addr2 = (ulong)ioremap(cy_pci_addr2, CyPCI_Zwin); + cy_pci_addr2 = (ulong)ioremap(cy_pci_phys2, CyPCI_Zwin); #endif } @@ -5105,7 +5112,7 @@ cy_detect_pci(void) if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { printk("Cyclades-8Zo/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no channels are available.\n"); printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); return(i); @@ -5117,7 +5124,7 @@ cy_detect_pci(void) } if (j == NR_CARDS) { /* no more cy_cards available */ printk("Cyclades-8Zo/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); return(i); @@ -5129,10 +5136,10 @@ cy_detect_pci(void) if(request_irq(cy_pci_irq, cyz_interrupt, SA_SHIRQ, "Cyclades-Z", &cy_card[j])) { - printk("Could not allocate IRQ%d ", + printk("Cyclom-8Zo/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but could not allocate IRQ%d.\n", cy_pci_irq); - printk("for Cyclades-8Zo/PCI at 0x%lx.\n", - (ulong)cy_pci_addr2); return(i); } } @@ -5140,6 +5147,8 @@ cy_detect_pci(void) /* set cy_card */ + cy_card[j].base_phys = cy_pci_phys2; + cy_card[j].ctl_phys = cy_pci_phys0; cy_card[j].base_addr = cy_pci_addr2; cy_card[j].ctl_addr = cy_pci_addr0; cy_card[j].irq = (int) cy_pci_irq; @@ -5152,14 +5161,14 @@ cy_detect_pci(void) /* don't report IRQ if board is no IRQ */ if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1,(ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Zwin - 1), + j+1,(ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1), (int)cy_pci_irq); else #endif /* CONFIG_CYZ_INTR */ printk("Cyclades-8Zo/PCI #%d: 0x%lx-0x%lx, ", - j+1,(ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Zwin - 1)); + j+1,(ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Zwin - 1)); printk("%d channels starting from port %d.\n", cy_pci_nchan,cy_next_channel); @@ -5168,10 +5177,14 @@ cy_detect_pci(void) } for (; ZeIndex != 0 && i < NR_CARDS; i++) { + cy_pci_phys0 = Ze_phys0[0]; + cy_pci_phys2 = Ze_phys2[0]; cy_pci_addr0 = Ze_addr0[0]; cy_pci_addr2 = Ze_addr2[0]; cy_pci_irq = Ze_irq[0]; for (j = 0 ; j < ZeIndex-1 ; j++) { + Ze_phys0[j] = Ze_phys0[j+1]; + Ze_phys2[j] = Ze_phys2[j+1]; Ze_addr0[j] = Ze_addr0[j+1]; Ze_addr2[j] = Ze_addr2[j+1]; Ze_irq[j] = Ze_irq[j+1]; @@ -5190,7 +5203,7 @@ cy_detect_pci(void) if((cy_next_channel+cy_pci_nchan) > NR_PORTS) { printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no channels are available.\n"); printk("Change NR_PORTS in cyclades.c and recompile kernel.\n"); return(i); @@ -5202,7 +5215,7 @@ cy_detect_pci(void) } if (j == NR_CARDS) { /* no more cy_cards available */ printk("Cyclades-Ze/PCI found at 0x%lx ", - (ulong)cy_pci_addr2); + (ulong)cy_pci_phys2); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); return(i); @@ -5214,16 +5227,18 @@ cy_detect_pci(void) if(request_irq(cy_pci_irq, cyz_interrupt, SA_SHIRQ, "Cyclades-Z", &cy_card[j])) { - printk("Could not allocate IRQ%d ", + printk("Cyclom-Ze/PCI found at 0x%lx ", + (ulong) cy_pci_phys2); + printk("but could not allocate IRQ%d.\n", cy_pci_irq); - printk("for Cyclades-Ze/PCI at 0x%lx.\n", - (ulong) cy_pci_addr2); return(i); } } #endif /* CONFIG_CYZ_INTR */ /* set cy_card */ + cy_card[j].base_phys = cy_pci_phys2; + cy_card[j].ctl_phys = cy_pci_phys0; cy_card[j].base_addr = cy_pci_addr2; cy_card[j].ctl_addr = cy_pci_addr0; cy_card[j].irq = (int) cy_pci_irq; @@ -5236,14 +5251,14 @@ cy_detect_pci(void) /* don't report IRQ if board is no IRQ */ if( (cy_pci_irq != 0) && (cy_pci_irq != 255) ) printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, IRQ%d, ", - j+1,(ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1), + j+1,(ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1), (int)cy_pci_irq); else #endif /* CONFIG_CYZ_INTR */ printk("Cyclades-Ze/PCI #%d: 0x%lx-0x%lx, ", - j+1,(ulong)cy_pci_addr2, - (ulong)(cy_pci_addr2 + CyPCI_Ze_win - 1)); + j+1,(ulong)cy_pci_phys2, + (ulong)(cy_pci_phys2 + CyPCI_Ze_win - 1)); printk("%d channels starting from port %d.\n", cy_pci_nchan,cy_next_channel); @@ -5251,7 +5266,7 @@ cy_detect_pci(void) } if (ZeIndex != 0) { printk("Cyclades-Ze/PCI found at 0x%x ", - (unsigned int) Ze_addr2[0]); + (unsigned int) Ze_phys2[0]); printk("but no more cards can be used.\n"); printk("Change NR_CARDS in cyclades.c and recompile kernel.\n"); } @@ -5438,10 +5453,8 @@ cy_init(void) availability of cy_card and cy_port data structures and updating the cy_next_channel. */ -#ifndef CONFIG_COBALT_27 /* look for isa boards */ cy_isa_nboard = cy_detect_isa(); -#endif /* CONFIG_COBALT_27 */ /* look for pci boards */ cy_pci_nboard = cy_detect_pci(); @@ -5568,9 +5581,10 @@ cy_init(void) info->icount.frame = info->icount.parity = 0; info->icount.overrun = info->icount.brk = 0; chip_number = (port - cinfo->first_line) / 4; - if ((info->chip_rev = cy_readb(cinfo->base_addr + - (cy_chip_offset[chip_number]<<index) + - (CyGFRCR<<index))) >= CD1400_REV_J) { + if ((info->chip_rev = + cy_readb(cinfo->base_addr + + (cy_chip_offset[chip_number]<<index) + + (CyGFRCR<<index))) >= CD1400_REV_J) { /* It is a CD1400 rev. J or later */ info->tbpr = baud_bpr_60[13]; /* Tx BPR */ info->tco = baud_co_60[13]; /* Tx CO */ @@ -5628,16 +5642,8 @@ cy_init(void) } /* cy_init */ #ifdef MODULE -/* See linux/drivers/char/riscom.c for ideas on how to - pass additional base addresses to the driver!!! */ -int -init_module(void) -{ - return(cy_init()); -} /* init_module */ - void -cleanup_module(void) +cy_cleanup_module(void) { int i; int e1, e2; @@ -5679,13 +5685,18 @@ cleanup_module(void) free_page((unsigned long) tmp_buf); tmp_buf = NULL; } -} /* cleanup_module */ -#else +} /* cy_cleanup_module */ + +/* Module entry-points */ +module_init(cy_init); +module_exit(cy_cleanup_module); + +#else /* MODULE */ /* called by linux/init/main.c to parse command line options */ void cy_setup(char *str, int *ints) { -#ifndef CONFIG_COBALT_27 +#ifdef CONFIG_ISA int i, j; for (i = 0 ; i < NR_ISA_ADDRS ; i++) { @@ -5696,110 +5707,7 @@ cy_setup(char *str, int *ints) cy_isa_addresses[i++] = (unsigned char *)(ints[j]); } } -#endif /* CONFIG_COBALT_27 */ - +#endif /* CONFIG_ISA */ } /* cy_setup */ -#endif - - -#ifdef CYCLOM_SHOW_STATUS -static void -show_status(int line_num) -{ - unsigned char *base_addr; - int card,chip,channel,index; - struct cyclades_port * info; - unsigned long flags; - - info = &cy_port[line_num]; - card = info->card; - index = cy_card[card].bus_index; - channel = (info->line) - (cy_card[card].first_line); - chip = channel>>2; - channel &= 0x03; - printk(" card %d, chip %d, channel %d\n", card, chip, channel);/**/ - - printk(" cy_card\n"); - printk(" irq base_addr num_chips first_line = %d %lx %d %d\n", - cy_card[card].irq, (long)cy_card[card].base_addr, - cy_card[card].num_chips, cy_card[card].first_line); - - printk(" cy_port\n"); - printk(" card line flags = %d %d %x\n", - info->card, info->line, info->flags); - printk(" *tty read_status_mask timeout xmit_fifo_size ", - printk("= %lx %x %x %x\n", - (long)info->tty, info->read_status_mask, - info->timeout, info->xmit_fifo_size); - printk(" cor1,cor2,cor3,cor4,cor5 = %x %x %x %x %x\n", - info->cor1, info->cor2, info->cor3, info->cor4, info->cor5); - printk(" tbpr,tco,rbpr,rco = %d %d %d %d\n", - info->tbpr, info->tco, info->rbpr, info->rco); - printk(" close_delay event count = %d %d %d\n", - info->close_delay, info->event, info->count); - printk(" x_char blocked_open = %x %x\n", - info->x_char, info->blocked_open); - printk(" session pgrp open_wait = %lx %lx %lx\n", - info->session, info->pgrp, (long)info->open_wait); - - CY_LOCK(info, flags); - - base_addr = (unsigned char*) - (cy_card[card].base_addr - + (cy_chip_offset[chip]<<index)); - -/* Global Registers */ - - printk(" CyGFRCR %x\n", cy_readb(base_addr + CyGFRCR<<index)); - printk(" CyCAR %x\n", cy_readb(base_addr + CyCAR<<index)); - printk(" CyGCR %x\n", cy_readb(base_addr + CyGCR<<index)); - printk(" CySVRR %x\n", cy_readb(base_addr + CySVRR<<index)); - printk(" CyRICR %x\n", cy_readb(base_addr + CyRICR<<index)); - printk(" CyTICR %x\n", cy_readb(base_addr + CyTICR<<index)); - printk(" CyMICR %x\n", cy_readb(base_addr + CyMICR<<index)); - printk(" CyRIR %x\n", cy_readb(base_addr + CyRIR<<index)); - printk(" CyTIR %x\n", cy_readb(base_addr + CyTIR<<index)); - printk(" CyMIR %x\n", cy_readb(base_addr + CyMIR<<index)); - printk(" CyPPR %x\n", cy_readb(base_addr + CyPPR<<index)); - - cy_writeb(base_addr + CyCAR<<index, (u_char)channel); - -/* Virtual Registers */ - - printk(" CyRIVR %x\n", cy_readb(base_addr + CyRIVR<<index)); - printk(" CyTIVR %x\n", cy_readb(base_addr + CyTIVR<<index)); - printk(" CyMIVR %x\n", cy_readb(base_addr + CyMIVR<<index)); - printk(" CyMISR %x\n", cy_readb(base_addr + CyMISR<<index)); - -/* Channel Registers */ - - printk(" CyCCR %x\n", cy_readb(base_addr + CyCCR<<index)); - printk(" CySRER %x\n", cy_readb(base_addr + CySRER<<index)); - printk(" CyCOR1 %x\n", cy_readb(base_addr + CyCOR1<<index)); - printk(" CyCOR2 %x\n", cy_readb(base_addr + CyCOR2<<index)); - printk(" CyCOR3 %x\n", cy_readb(base_addr + CyCOR3<<index)); - printk(" CyCOR4 %x\n", cy_readb(base_addr + CyCOR4<<index)); - printk(" CyCOR5 %x\n", cy_readb(base_addr + CyCOR5<<index)); - printk(" CyCCSR %x\n", cy_readb(base_addr + CyCCSR<<index)); - printk(" CyRDCR %x\n", cy_readb(base_addr + CyRDCR<<index)); - printk(" CySCHR1 %x\n", cy_readb(base_addr + CySCHR1<<index)); - printk(" CySCHR2 %x\n", cy_readb(base_addr + CySCHR2<<index)); - printk(" CySCHR3 %x\n", cy_readb(base_addr + CySCHR3<<index)); - printk(" CySCHR4 %x\n", cy_readb(base_addr + CySCHR4<<index)); - printk(" CySCRL %x\n", cy_readb(base_addr + CySCRL<<index)); - printk(" CySCRH %x\n", cy_readb(base_addr + CySCRH<<index)); - printk(" CyLNC %x\n", cy_readb(base_addr + CyLNC<<index)); - printk(" CyMCOR1 %x\n", cy_readb(base_addr + CyMCOR1<<index)); - printk(" CyMCOR2 %x\n", cy_readb(base_addr + CyMCOR2<<index)); - printk(" CyRTPR %x\n", cy_readb(base_addr + CyRTPR<<index)); - printk(" CyMSVR1 %x\n", cy_readb(base_addr + CyMSVR1<<index)); - printk(" CyMSVR2 %x\n", cy_readb(base_addr + CyMSVR2<<index)); - printk(" CyRBPR %x\n", cy_readb(base_addr + CyRBPR<<index)); - printk(" CyRCOR %x\n", cy_readb(base_addr + CyRCOR<<index)); - printk(" CyTBPR %x\n", cy_readb(base_addr + CyTBPR<<index)); - printk(" CyTCOR %x\n", cy_readb(base_addr + CyTCOR<<index)); - - CY_UNLOCK(info, flags); -} /* show_status */ -#endif +#endif /* MODULE */ diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index 986b728db..34d996582 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c @@ -22,14 +22,14 @@ #define __NWBUTTON_C /* Tell the header file who we are */ #include "nwbutton.h" -static int button_press_count = 0; /* The count of button presses */ +static int button_press_count; /* The count of button presses */ static struct timer_list button_timer; /* Times for the end of a sequence */ static DECLARE_WAIT_QUEUE_HEAD(button_wait_queue); /* Used for blocking read */ static char button_output_buffer[32]; /* Stores data to write out of device */ -static int bcount = 0; /* The number of bytes in the buffer */ +static int bcount; /* The number of bytes in the buffer */ static int bdelay = BUTTON_DELAY; /* The delay, in jiffies */ static struct button_callback button_callback_list[32]; /* The callback list */ -static int callback_count = 0; /* The number of callbacks registered */ +static int callback_count; /* The number of callbacks registered */ static int reboot_count = NUM_PRESSES_REBOOT; /* Number of presses to reboot */ /* diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index cbe0ec79f..579e970d4 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c @@ -50,10 +50,10 @@ static long long flash_llseek(struct file *file, long long offset, int orig); #define KFLASH_ID 0x89A6 //Intel flash #define KFLASH_ID4 0xB0D4 //Intel flash 4Meg -static int flashdebug = 0; //if set - we will display progress msgs +static int flashdebug; //if set - we will display progress msgs -static int gbWriteEnable = 0; -static int gbWriteBase64Enable = 0; +static int gbWriteEnable; +static int gbWriteBase64Enable; MSTATIC int gbFlashSize = KFLASH_SIZE; extern spinlock_t gpio_lock; diff --git a/drivers/net/Config.in b/drivers/net/Config.in index 00c9fc7f3..7aaeb9398 100644 --- a/drivers/net/Config.in +++ b/drivers/net/Config.in @@ -218,7 +218,7 @@ if [ ! "$CONFIG_PPP" = "n" ]; then dep_tristate ' PPP support for async serial ports' CONFIG_PPP_ASYNC $CONFIG_PPP dep_tristate ' PPP support for sync tty ports' CONFIG_PPP_SYNC_TTY $CONFIG_PPP dep_tristate ' PPP Deflate compression' CONFIG_PPP_DEFLATE $CONFIG_PPP - dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP m + dep_tristate ' PPP BSD-Compress compression' CONFIG_PPP_BSDCOMP if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' PPP over Ethernet (EXPERIMENTAL)' CONFIG_PPPOE $CONFIG_PPP fi diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 77a2c7298..3490fd92f 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -204,29 +204,12 @@ obj-$(CONFIG_ES3210) += es3210.o 8390.o obj-$(CONFIG_LNE390) += lne390.o 8390.o obj-$(CONFIG_NE3210) += ne3210.o 8390.o -# bsd_comp.o is *always* a module, for some documented reason -# (licensing). -ifeq ($(CONFIG_PPP),y) - obj-y += ppp_generic.o slhc.o - obj-$(CONFIG_PPP_ASYNC) += ppp_async.o - obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o - obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o - ifeq ($(CONFIG_PPP_BSDCOMP),m) - obj-m += bsd_comp.o - endif - obj-$(CONFIG_PPPOE) += pppox.o pppoe.o -else - ifeq ($(CONFIG_PPP),m) - obj-m += ppp_generic.o slhc.o - obj-$(CONFIG_PPP_ASYNC) += ppp_async.o - obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o - obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o - obj-$(CONFIG_PPPOE) += pppox.o pppoe.o - ifeq ($(CONFIG_PPP_BSDCOMP),m) - obj-m += bsd_comp.o - endif - endif -endif +obj-$(CONFIG_PPP) += ppp_generic.o slhc.o +obj-$(CONFIG_PPP_ASYNC) += ppp_async.o +obj-$(CONFIG_PPP_SYNC_TTY) += ppp_synctty.o +obj-$(CONFIG_PPP_DEFLATE) += ppp_deflate.o +obj-$(CONFIG_PPP_BSDCOMP) += bsd_comp.o +obj-$(CONFIG_PPPOE) += pppox.o pppoe.o obj-$(CONFIG_SLIP) += slip.o ifeq ($(CONFIG_SLIP),y) diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index 8fa454af9..7d53e1260 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -29,6 +29,7 @@ * infrastructure and Sparc support * Pierrick Pinasseau (CERN): For lending me an Ultra 5 to test the * driver under Linux/Sparc64 + * Matt Domsch <Matt_Domsch@dell.com>: Detect 1000baseT cards */ #include <linux/config.h> @@ -70,7 +71,10 @@ #ifndef PCI_VENDOR_ID_ALTEON #define PCI_VENDOR_ID_ALTEON 0x12ae -#define PCI_DEVICE_ID_ALTEON_ACENIC 0x0001 +#endif +#ifndef PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE +#define PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE 0x0001 +#define PCI_DEVICE_ID_ALTEON_ACENIC_COPPER 0x0002 #endif #ifndef PCI_DEVICE_ID_3COM_3C985 #define PCI_DEVICE_ID_3COM_3C985 0x0001 @@ -105,6 +109,12 @@ #endif +#if (LINUX_VERSION_CODE < 0x02030d) +#define pci_resource_start(dev, bar) dev->base_address[bar] +#elif (LINUX_VERSION_CODE < 0x02032c) +#define pci_resource_start(dev, bar) dev->resource[bar].start +#endif + #if (LINUX_VERSION_CODE < 0x02030e) #define net_device device #endif @@ -379,7 +389,7 @@ static int tx_ratio[ACE_MAX_MOD_PARMS] = {0, }; static int dis_pci_mem_inval[ACE_MAX_MOD_PARMS] = {1, 1, 1, 1, 1, 1, 1, 1}; static const char __initdata *version = - "acenic.c: v0.42 03/02/2000 Jes Sorensen, linux-acenic@SunSITE.auc.dk\n" + "acenic.c: v0.44 05/11/2000 Jes Sorensen, linux-acenic@SunSITE.auc.dk\n" " http://home.cern.ch/~jes/gige/acenic.html\n"; static struct net_device *root_dev = NULL; @@ -414,7 +424,8 @@ int __init acenic_probe (struct net_device *dev) while ((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET<<8, pdev))) { if (!((pdev->vendor == PCI_VENDOR_ID_ALTEON) && - (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC)) && + ((pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_FIBRE) || + (pdev->device == PCI_DEVICE_ID_ALTEON_ACENIC_COPPER)) ) && !((pdev->vendor == PCI_VENDOR_ID_3COM) && (pdev->device == PCI_DEVICE_ID_3COM_3C985)) && !((pdev->vendor == PCI_VENDOR_ID_NETGEAR) && @@ -494,11 +505,7 @@ int __init acenic_probe (struct net_device *dev) * dev->base_addr since it was means for I/O port * addresses but who gives a damn. */ -#if (LINUX_VERSION_CODE < 0x02030d) - dev->base_addr = pdev->base_address[0]; -#else - dev->base_addr = pdev->resource[0].start; -#endif + dev->base_addr = pci_resource_start(pdev, 0); ap->regs = (struct ace_regs *)ioremap(dev->base_addr, 0x4000); if (!ap->regs) { printk(KERN_ERR "%s: Unable to map I/O register, " @@ -717,10 +724,7 @@ void cleanup_module(void) { ace_module_cleanup(); } -#endif - - -#if (LINUX_VERSION_CODE >= 0x02032a) +#else module_init(ace_module_init); module_exit(ace_module_cleanup); #endif @@ -1087,11 +1091,17 @@ static int __init ace_init(struct net_device *dev) #endif writel(tmp, ®s->PciState); +#if 0 + /* + * I have received reports from people having problems when this + * bit is enabled. + */ if (!(ap->pci_command & PCI_COMMAND_FAST_BACK)) { printk(KERN_INFO " Enabling PCI Fast Back to Back\n"); ap->pci_command |= PCI_COMMAND_FAST_BACK; pci_write_config_word(ap->pdev, PCI_COMMAND, ap->pci_command); } +#endif /* * Initialize the generic info block and the command+event rings @@ -1760,16 +1770,23 @@ static u32 ace_handle_event(struct net_device *dev, u32 evtcsm, u32 evtprd) case E_LNK_STATE: { u16 code = ap->evt_ring[evtcsm].code; - if (code == E_C_LINK_UP) { + switch (code) { + case E_C_LINK_UP: printk(KERN_WARNING "%s: Optical link UP\n", dev->name); - } - else if (code == E_C_LINK_DOWN) + break; + case E_C_LINK_DOWN: printk(KERN_WARNING "%s: Optical link DOWN\n", dev->name); - else + break; + case E_C_LINK_10_100: + printk(KERN_WARNING "%s: 10/100BaseT link " + "UP\n", dev->name); + break; + default: printk(KERN_ERR "%s: Unknown optical link " "state %02x\n", dev->name, code); + } break; } case E_ERROR: @@ -2949,6 +2966,6 @@ static int __init read_eeprom_byte(struct net_device *dev, /* * Local variables: - * compile-command: "gcc -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" + * compile-command: "gcc -D__SMP__ -D__KERNEL__ -DMODULE -I../../include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -pipe -fno-strength-reduce -DMODVERSIONS -include ../../include/linux/modversions.h -c -o acenic.o acenic.c" * End: */ diff --git a/drivers/net/acenic.h b/drivers/net/acenic.h index 958561a69..b74368cae 100644 --- a/drivers/net/acenic.h +++ b/drivers/net/acenic.h @@ -324,7 +324,7 @@ struct event { #define E_LNK_STATE 0x06 #define E_C_LINK_UP 0x01 #define E_C_LINK_DOWN 0x02 -#define E_C_LINK_UP_FAST 0x03 +#define E_C_LINK_10_100 0x03 #define E_ERROR 0x07 #define E_C_ERR_INVAL_CMD 0x01 diff --git a/drivers/net/acenic_firmware.h b/drivers/net/acenic_firmware.h index 729eac664..cb2441285 100644 --- a/drivers/net/acenic_firmware.h +++ b/drivers/net/acenic_firmware.h @@ -5,17 +5,17 @@ */ #define tigonFwReleaseMajor 0xc #define tigonFwReleaseMinor 0x4 -#define tigonFwReleaseFix 0x5 +#define tigonFwReleaseFix 0xb #define tigonFwStartAddr 0x00004000 #define tigonFwTextAddr 0x00004000 -#define tigonFwTextLen 0x11190 -#define tigonFwRodataAddr 0x00015190 +#define tigonFwTextLen 0x11140 +#define tigonFwRodataAddr 0x00015140 #define tigonFwRodataLen 0xac0 -#define tigonFwDataAddr 0x00015c80 +#define tigonFwDataAddr 0x00015c20 #define tigonFwDataLen 0x170 -#define tigonFwSbssAddr 0x00015df0 -#define tigonFwSbssLen 0x34 -#define tigonFwBssAddr 0x00015e30 +#define tigonFwSbssAddr 0x00015d90 +#define tigonFwSbssLen 0x38 +#define tigonFwBssAddr 0x00015dd0 #define tigonFwBssLen 0x2080 u32 tigonFwText[]; u32 tigonFwData[]; @@ -25,16 +25,16 @@ u32 tigonFwRodata[]; u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x10000003, 0x0, 0xd, 0xd, 0x3c1d0001, -0x8fbd5cb4, 0x3a0f021, 0x3c100000, 0x26104000, +0x8fbd5c54, 0x3a0f021, 0x3c100000, 0x26104000, 0xc00100c, 0x0, 0xd, 0x27bdffd8, 0x3c1cc000, 0x3c1b0013, 0x377bd800, 0xd021, 0x3c170013, 0x36f75418, 0x2e02021, 0x340583e8, 0xafbf0024, 0xc002488, 0xafb00020, 0xc0023e8, -0x0, 0x3c040001, 0x248451f4, 0x24050001, -0x2e03021, 0x3821, 0x3c100001, 0x26107eb0, +0x0, 0x3c040001, 0x248451a4, 0x24050001, +0x2e03021, 0x3821, 0x3c100001, 0x26107e50, 0xafb00010, 0xc002403, 0xafbb0014, 0x3c02000f, 0x3442ffff, 0x2021024, 0x362102b, 0x10400009, -0x24050003, 0x3c040001, 0x24845200, 0x2003021, +0x24050003, 0x3c040001, 0x248451b0, 0x2003021, 0x3603821, 0x3c020010, 0xafa20010, 0xc002403, 0xafa00014, 0x2021, 0x3405c000, 0x3c010001, 0x370821, 0xa02083b0, 0x3c010001, 0x370821, @@ -72,7 +72,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x8ee20450, 0x8ee30454, 0xaee304fc, 0x8ee204fc, 0x2442e000, 0x2c422001, 0x1440000d, 0x26e40030, 0x8ee20450, 0x8ee30454, 0x3c040001, -0x2484520c, 0x3c050001, 0xafa00010, 0xafa00014, +0x248451bc, 0x3c050001, 0xafa00010, 0xafa00014, 0x8ee704fc, 0x34a5f000, 0xc002403, 0x603021, 0x26e40030, 0xc002488, 0x24050400, 0x27440080, 0xc002488, 0x24050080, 0x26e4777c, 0xc002488, @@ -82,7 +82,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x3442ca00, 0x2021, 0x24030002, 0xaee30074, 0xaee30070, 0xaee2006c, 0x240203e8, 0xaee20104, 0x24020001, 0xaee30100, 0xaee2010c, 0x3c030001, -0x641821, 0x90635c80, 0x2e41021, 0x24840001, +0x641821, 0x90635c20, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 0xa062009c, 0x2e41021, 0xa040009c, @@ -128,7 +128,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, -0xaee90608, 0x3c040001, 0x24845218, 0xafa00010, +0xaee90608, 0x3c040001, 0x248451c8, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x8001223, 0x0, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, @@ -154,21 +154,21 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14c0001b, 0x0, -0x3c040001, 0x24845220, 0xafa00010, 0xafa00014, +0x3c040001, 0x248451d0, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, -0x8001223, 0x8ee201b0, 0x3c040001, 0x2484522c, +0x8001223, 0x8ee201b0, 0x3c040001, 0x248451dc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20160, 0x3c040001, -0x24845238, 0x3405f001, 0x24420001, 0xaee20160, +0x248451e8, 0x3405f001, 0x24420001, 0xaee20160, 0x8ee20160, 0x3021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, 0x8001238, 0x0, 0x3c020001, 0x2442f5a8, 0x21100, 0x21182, 0x431025, 0x3c010001, 0xac221278, 0x96e2045a, 0x30420003, 0x10400025, 0x3c050fff, 0x8ee204c8, 0x34a5ffff, 0x34420a00, 0xaee204c8, 0x8ee304c8, -0x3c040001, 0x24845244, 0x24020001, 0xa2e204ec, +0x3c040001, 0x248451f4, 0x24020001, 0xa2e204ec, 0xa2e204ed, 0x3c020002, 0x621825, 0x3c020001, 0x2442a390, 0x451024, 0x21082, 0xaee304c8, 0x3c030800, 0x431025, 0x3c010001, 0xac221220, @@ -211,7 +211,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, 0xaee90608, 0x3c040001, -0x24845218, 0xafa00010, 0xafa00014, 0x8ee60608, +0x248451c8, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x800136d, 0x0, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, @@ -236,17 +236,17 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, -0x14c0001b, 0x0, 0x3c040001, 0x24845220, +0x14c0001b, 0x0, 0x3c040001, 0x248451d0, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, 0x800136d, 0x8ee201b0, -0x3c040001, 0x2484522c, 0xafa00014, 0x8ee60608, +0x3c040001, 0x248451dc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, -0x8ee20160, 0x3c040001, 0x24845238, 0x3405f002, +0x8ee20160, 0x3c040001, 0x248451e8, 0x3405f002, 0x24420001, 0xaee20160, 0x8ee20160, 0x3021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, -0x96e6047a, 0x96e7046a, 0x3c040001, 0x24845250, +0x96e6047a, 0x96e7046a, 0x3c040001, 0x24845200, 0x24050012, 0xafa00010, 0xc002403, 0xafa00014, 0xc004500, 0x0, 0xc002318, 0x0, 0x3c060001, 0x34c63800, 0xaee00608, 0xaf400228, @@ -289,7 +289,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x54c0000c, 0xaee90608, 0x3c040001, -0x24845218, 0xafa00010, 0xafa00014, 0x8ee60608, +0x248451c8, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x80014a5, 0x0, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, 0x27663000, @@ -314,11 +314,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, -0x14c0001b, 0x0, 0x3c040001, 0x24845220, +0x14c0001b, 0x0, 0x3c040001, 0x248451d0, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, 0x80014a5, 0x8ee201b0, -0x3c040001, 0x2484522c, 0xafa00014, 0x8ee60608, +0x3c040001, 0x248451dc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20154, 0x24420001, 0xaee20154, 0xc0014dc, @@ -340,7 +340,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee07b8c, 0xaee07b84, 0x3c010001, 0x370821, 0xac2083bc, 0x3c010001, 0x370821, 0x3e00008, 0xa02083b9, 0x27bdffd8, 0xafbf0024, 0xafb00020, -0x8f820054, 0x3c030001, 0x8c635d38, 0x24420067, +0x8f820054, 0x3c030001, 0x8c635cd8, 0x24420067, 0x1060000d, 0xaf820058, 0x3c020001, 0x571021, 0x904283b8, 0x10400005, 0x3c030200, 0x3c010001, 0x370821, 0x8001503, 0xa02083b8, 0x8ee20000, @@ -358,7 +358,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x3c030001, 0x771821, 0x8c6383d4, 0x8f8200b4, 0x1462007c, 0x0, 0x3c070001, 0xf73821, 0x8ce783d0, 0x8f8200b0, 0x3c040001, -0x248452c0, 0xafa00014, 0xafa20010, 0x8f8600b0, +0x24845270, 0xafa00014, 0xafa20010, 0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0xaf830104, 0x8f830120, @@ -386,10 +386,10 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xac820000, 0x24020001, 0xac820004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201e4, 0x3c070001, 0xf73821, 0x8ce783d0, 0x24420001, -0xaee201e4, 0x8ee201e4, 0x3c040001, 0x248452cc, +0xaee201e4, 0x8ee201e4, 0x3c040001, 0x2484527c, 0x80015bd, 0xafa00010, 0x8f820104, 0x3c010001, 0x370821, 0xac2283d0, 0x8f8200b4, 0x3c070001, -0xf73821, 0x8ce783d0, 0x3c040001, 0x248452d4, +0xf73821, 0x8ce783d0, 0x3c040001, 0x24845284, 0x3c010001, 0x370821, 0xac2283d4, 0xafa00010, 0xafa00014, 0x8f8600b0, 0x3c050005, 0xc002403, 0x34a50900, 0x80015cc, 0x0, 0x8f820104, @@ -422,7 +422,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, 0x24100001, -0x8ee204e4, 0x3c040001, 0x248452dc, 0xafa00014, +0x8ee204e4, 0x3c040001, 0x2484528c, 0xafa00014, 0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f006, 0x16000003, 0x24020001, 0x8001650, 0xa2e204f4, 0x8ee20170, 0x24420001, @@ -452,7 +452,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, 0x24100001, 0x8ee2724c, 0x3c040001, -0x248452e8, 0xafa00014, 0xafa20010, 0x8ee6724c, +0x24845298, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x56000001, 0xaee00e1c, 0x8ee20174, 0x24420001, 0xaee20174, 0x8ee20174, 0x8ee24e24, 0x10400019, @@ -563,11 +563,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x14620003, 0x3c050009, 0x800197c, 0x24100001, 0x3c040001, -0x248452f4, 0xafa00010, 0xafa00014, 0x8f860120, +0x248452a4, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x800187b, 0x34a5f011, 0x3c040001, -0x24845300, 0xafa00010, 0xafa00014, 0x8f860120, +0x248452b0, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x34a5f010, 0xc002403, 0x8021, -0x800197c, 0x0, 0x3c040001, 0x2484530c, +0x800197c, 0x0, 0x3c040001, 0x248452bc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0x8001975, 0x34a5f00f, 0x8ee20608, 0x8f430228, 0x24420001, 0x304900ff, 0x512300e2, 0xafa00010, @@ -598,7 +598,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x5600000c, 0xaee90608, -0x3c040001, 0x24845318, 0xafa00010, 0xafa00014, +0x3c040001, 0x248452c8, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x800197c, 0x0, 0x8f830120, 0x27623800, 0x24660020, 0xc2102b, 0x50400001, @@ -624,10 +624,10 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600001d, 0x24100001, 0x3c040001, -0x24845320, 0xafa00010, 0xafa00014, 0x8ee60608, +0x248452d0, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, 0x800197c, -0x8ee201b0, 0x3c040001, 0x2484532c, 0xafa00014, +0x8ee201b0, 0x3c040001, 0x248452dc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f005, 0xc002403, 0x0, 0x8ee201ac, 0x8021, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x1200000c, @@ -635,7 +635,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f420238, 0x8ee30158, 0x24630001, 0xaee30158, 0x8ee30158, 0x800198c, 0xaee27278, 0x24020001, 0x3c010001, 0x370821, 0xa02283b0, 0x3c020001, -0x8c425d38, 0x10400187, 0x0, 0x8ee27b84, +0x8c425cd8, 0x10400187, 0x0, 0x8ee27b84, 0x24430001, 0x284200c9, 0x144001a4, 0xaee37b84, 0x8ee204d4, 0x30420002, 0x14400119, 0xaee07b84, 0x8ee204d4, 0x3c030600, 0x34631000, 0x34420002, @@ -699,12 +699,12 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x56000006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022, 0x0, 0x3c040001, -0x248452f4, 0xafa00010, 0xafa00014, 0x8f860120, +0x248452a4, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, -0x8001aad, 0x0, 0x3c040001, 0x24845300, +0x8001aad, 0x0, 0x3c040001, 0x248452b0, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x8001aad, 0x0, -0x3c040001, 0x2484530c, 0xafa00014, 0x8ee60608, +0x3c040001, 0x248452bc, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c, @@ -741,7 +741,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaf820044, 0x8f820044, 0x34420040, 0xaf820044, 0x8ee27b88, 0x24430001, 0x28421389, 0x14400005, 0xaee37b88, 0x8f820044, 0x38420020, 0xaf820044, -0xaee07b88, 0xc0045f4, 0x0, 0x8fbf0024, +0xaee07b88, 0xc004603, 0x0, 0x8fbf0024, 0x8fb00020, 0x3e00008, 0x27bd0028, 0x27bdffb8, 0xafbf0044, 0xafb60040, 0xafb5003c, 0xafb40038, 0xafb30034, 0xafb20030, 0xafb1002c, 0xafb00028, @@ -751,18 +751,18 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee2016c, 0x80022f4, 0x8ee2016c, 0x32c20001, 0x10400004, 0x24020001, 0xaf820064, 0x80022f4, 0x0, 0x32c20002, 0x1440000c, 0x3c050003, -0x3c040001, 0x248453a4, 0x34a50001, 0x2c03021, +0x3c040001, 0x24845354, 0x34a50001, 0x2c03021, 0x3821, 0xafa00010, 0xc002403, 0xafa00014, 0x2402fff8, 0x80022f4, 0xaf820064, 0x8f43022c, 0x8f42010c, 0x5062000c, 0xafa00010, 0x8f42022c, 0x21080, 0x5a1021, 0x8c420300, 0xafa20020, 0x8f42022c, 0x24070001, 0x24420001, 0x3042003f, -0x8001b80, 0xaf42022c, 0x3c040001, 0x248453b0, +0x8001b80, 0xaf42022c, 0x3c040001, 0x24845360, 0xafa00014, 0x8f46022c, 0x8f47010c, 0x3c050003, 0xc002403, 0x34a5f01f, 0x3821, 0x14e00003, 0x0, 0x80022ed, 0xaf960064, 0x93a20020, 0x2443ffff, 0x2c620011, 0x10400658, 0x31080, -0x3c010001, 0x220821, 0x8c225468, 0x400008, +0x3c010001, 0x220821, 0x8c225418, 0x400008, 0x0, 0x8fa20020, 0x30420fff, 0xaee20e0c, 0x8f820060, 0x34420200, 0xaf820060, 0x8ee20118, 0x24420001, 0xaee20118, 0x80022e8, 0x8ee20118, @@ -778,7 +778,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f840054, 0x41442, 0x41c82, 0x431021, 0x41cc2, 0x431023, 0x41d02, 0x431021, 0x41d42, 0x431023, 0x8001bd0, 0xaee20078, -0x3c040001, 0x248453bc, 0xafa00014, 0x8fa60020, +0x3c040001, 0x2484536c, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a50004, 0x8ee20110, 0x24420001, 0xaee20110, 0x80022e8, 0x8ee20110, 0x27440212, 0xc0022fe, 0x24050006, 0x3049001f, @@ -794,7 +794,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2c820080, 0x1440fff8, 0x410c0, 0x4c10010, 0x618c0, 0x610c0, 0x571821, 0x8c63737c, 0x571021, 0xafa30010, 0x8c427380, 0x3c040001, -0x248453c8, 0xafa20014, 0x8f470214, 0x3c050003, +0x24845378, 0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a50013, 0x8001c90, 0x3c020800, 0x97440212, 0x771021, 0xa444737e, 0x8f440214, 0x771021, 0x2e31821, 0xac447380, 0x34028000, @@ -812,7 +812,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24840001, 0x2c820080, 0x1440fff8, 0x410c0, 0x4c10023, 0x618c0, 0x910c0, 0x571821, 0x8c63727c, 0x571021, 0xafa30010, 0x8c427280, -0x3c040001, 0x248453d4, 0xafa20014, 0x8f470214, +0x3c040001, 0x24845384, 0xafa20014, 0x8f470214, 0x3c050003, 0xc002403, 0x34a5f017, 0x8001c90, 0x3c020800, 0x8f430210, 0xb71021, 0xac43777c, 0x8f430214, 0xb71021, 0xac437780, 0x3c020001, @@ -887,13 +887,13 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, -0x10620022, 0x0, 0x3c040001, 0x248453e0, +0x10620022, 0x0, 0x3c040001, 0x24845390, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001da0, -0x0, 0x3c040001, 0x248453ec, 0xafa00014, +0x0, 0x3c040001, 0x2484539c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x8001da0, 0x0, 0x3c040001, -0x248453f8, 0xafa00014, 0x8ee60608, 0x8f470228, +0x248453a8, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20124, 0x24420001, 0xaee20124, 0x8001f97, 0x8ee20124, @@ -908,7 +908,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1221004, 0x21027, 0x621824, 0xaf830228, 0x910c0, 0x2e21821, 0x3402c000, 0x8001e4e, 0xa462727c, 0x8f420214, 0xafa20010, 0x910c0, -0x571021, 0x8c42727c, 0x3c040001, 0x24845404, +0x571021, 0x8c42727c, 0x3c040001, 0x248453b4, 0x3c050003, 0xafa20014, 0x8f470210, 0x34a5f01c, 0xc002403, 0x1203021, 0x8001e83, 0x3c020800, 0xb71021, 0x9443727e, 0x97420212, 0x14620019, @@ -936,7 +936,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x910c0, 0x2e41821, 0x3402c000, 0x15000015, 0xa462737c, 0x910c0, 0x2e21821, 0x34028000, 0x8001e4e, 0xa462727c, 0x571021, 0x8c42727c, -0x3c040001, 0x24845410, 0x3c050003, 0xafa20010, +0x3c040001, 0x248453c0, 0x3c050003, 0xafa20010, 0x710c0, 0x571021, 0x8c42737c, 0x34a5001e, 0x1203021, 0xc002403, 0xafa20014, 0x8001e83, 0x3c020800, 0x2021, 0x428c0, 0xb71021, @@ -1012,12 +1012,12 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x10620022, -0x0, 0x3c040001, 0x248453e0, 0xafa00010, +0x0, 0x3c040001, 0x24845390, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x8001f93, 0x0, -0x3c040001, 0x248453ec, 0xafa00014, 0x8f860120, +0x3c040001, 0x2484539c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, -0x8001f93, 0x0, 0x3c040001, 0x248453f8, +0x8001f93, 0x0, 0x3c040001, 0x248453a8, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20128, 0x24420001, @@ -1029,7 +1029,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f820228, 0xaee204dc, 0x2402ffff, 0xaf820228, 0x24020001, 0x8001fbe, 0xa2e204d8, 0x92e204d8, 0x5040000c, 0xa2e004d8, 0x8ee204dc, 0xaf820228, -0x8001fbe, 0xa2e004d8, 0x3c040001, 0x24845418, +0x8001fbe, 0xa2e004d8, 0x3c040001, 0x248453c8, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f009, 0x8ee2013c, 0x24420001, 0xaee2013c, 0x80022e8, 0x8ee2013c, 0x8fa20020, 0x21200, @@ -1040,7 +1040,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x370821, 0xa02283b2, 0x8001fea, 0xaee40108, 0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024, 0xaf820220, 0x3c010001, 0x370821, 0xa02083b2, -0x8001fea, 0xaee40108, 0x3c040001, 0x24845424, +0x8001fea, 0xaee40108, 0x3c040001, 0x248453d4, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00a, 0x8ee2012c, 0x24420001, 0xaee2012c, 0x80022e8, 0x8ee2012c, 0x8fa20020, 0x21200, @@ -1052,13 +1052,13 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x571021, 0x904283b2, 0x3c010001, 0x370821, 0x1440000e, 0xa02083b3, 0x8f820220, 0x3c0308ff, 0x3463fff7, 0x431024, 0x8002018, 0xaf820220, -0x3c040001, 0x24845430, 0xafa00014, 0x8fa60020, +0x3c040001, 0x248453e0, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00b, 0x8ee20114, 0x24420001, 0xaee20114, 0x80022e8, 0x8ee20114, 0x27840208, 0x27450200, 0xc00249a, 0x24060008, 0x26e40094, 0x27450200, 0xc00249a, 0x24060008, 0x8ee20134, 0x24420001, 0xaee20134, 0x80022e8, -0x8ee20134, 0x8f460248, 0x2021, 0xc0050e0, +0x8ee20134, 0x8f460248, 0x2021, 0xc005108, 0x24050004, 0x8ee20130, 0x24420001, 0xaee20130, 0x80022e8, 0x8ee20130, 0x8ef301cc, 0x8ef401d0, 0x8ef501d8, 0x8ee20140, 0x26e40030, 0x24420001, @@ -1072,7 +1072,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee20104, 0xaee40100, 0xaee3010c, 0x8f820220, 0x30420008, 0x10400004, 0x0, 0xaee30108, 0x8002061, 0x2021, 0xaee40108, 0x2021, -0x3c030001, 0x641821, 0x90635c90, 0x2e41021, +0x3c030001, 0x641821, 0x90635c30, 0x2e41021, 0x24840001, 0xa043009c, 0x2c82000f, 0x1440fff8, 0x0, 0x8f820040, 0x2e41821, 0x24840001, 0x21702, 0x24420030, 0xa062009c, 0x2e41021, @@ -1152,13 +1152,13 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2e22021, 0xac8a0000, 0xac8c0004, 0x54e00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, -0x10620022, 0x0, 0x3c040001, 0x248453e0, +0x10620022, 0x0, 0x3c040001, 0x24845390, 0xafa00010, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x80021c4, -0x0, 0x3c040001, 0x248453ec, 0xafa00014, +0x0, 0x3c040001, 0x2484539c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80021c4, 0x0, 0x3c040001, -0x248453f8, 0xafa00014, 0x8ee60608, 0x8f470228, +0x248453a8, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20120, 0x24420001, 0xaee20120, 0x8ee20120, 0x8ee20168, @@ -1168,7 +1168,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f820220, 0x30420008, 0x14400002, 0x24020001, 0x24020002, 0xaee20108, 0x8ee2011c, 0x24420001, 0xaee2011c, 0x80022e8, 0x8ee2011c, 0x3c040001, -0x2484543c, 0xafa00010, 0xafa00014, 0x8fa60020, +0x248453ec, 0xafa00010, 0xafa00014, 0x8fa60020, 0x3c050003, 0xc002403, 0x34a5f00f, 0x93a20020, 0x3c030700, 0x34631000, 0x431025, 0xafa20018, 0x8ee20608, 0x8f430228, 0x24420001, 0x304900ff, @@ -1199,7 +1199,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, -0x54e0000c, 0xaee90608, 0x3c040001, 0x24845444, +0x54e0000c, 0xaee90608, 0x3c040001, 0x248453f4, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f000, 0x80022e0, 0x0, 0x8f830120, 0x27623800, 0x24660020, @@ -1225,11 +1225,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x14e0001b, -0x0, 0x3c040001, 0x2484544c, 0xafa00010, +0x0, 0x3c040001, 0x248453fc, 0xafa00010, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f001, 0x8ee201b0, 0x24420001, 0xaee201b0, 0x80022e0, 0x8ee201b0, 0x3c040001, -0x24845458, 0xafa00014, 0x8ee60608, 0x8f470228, +0x24845408, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f005, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee20150, 0x24420001, 0xaee20150, 0x8ee20150, 0x8ee20160, @@ -1256,7 +1256,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaf82011c, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0xafbf0018, 0x8f820104, 0xafa20010, 0x8f820100, 0x3c050002, 0xafa20014, 0x8f8600b0, -0x8f87011c, 0x3c040001, 0x24845510, 0xc002403, +0x8f87011c, 0x3c040001, 0x248454c0, 0xc002403, 0x34a5f000, 0x8f8300b0, 0x3c027f00, 0x621824, 0x3c020400, 0x10620029, 0x43102b, 0x14400008, 0x3c022000, 0x3c020100, 0x10620024, 0x3c020200, @@ -1273,7 +1273,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x27bd0020, 0x27bdffe0, 0xafbf001c, 0xafb00018, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c050001, 0xafa20014, 0x8f8600a0, 0x8f87011c, 0x3c040001, -0x2484551c, 0xc002403, 0x34a5f000, 0x8f8300a0, +0x248454cc, 0xc002403, 0x34a5f000, 0x8f8300a0, 0x3c027f00, 0x621824, 0x3c020400, 0x10620053, 0x8021, 0x43102b, 0x14400008, 0x3c042000, 0x3c020100, 0x1062004d, 0x3c020200, 0x1062003a, @@ -1298,43 +1298,43 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee2019c, 0x80023e3, 0x8ee2019c, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x0, 0x3c020001, -0x8c425cb8, 0x27bdffe8, 0xafbf0014, 0x14400012, -0xafb00010, 0x3c100001, 0x26105e30, 0x2002021, +0x8c425c58, 0x27bdffe8, 0xafbf0014, 0x14400012, +0xafb00010, 0x3c100001, 0x26105dd0, 0x2002021, 0xc002488, 0x24052000, 0x26021fe0, 0x3c010001, -0xac225df4, 0x3c010001, 0xac225df0, 0xaf420250, +0xac225d94, 0x3c010001, 0xac225d90, 0xaf420250, 0x24022000, 0xaf500254, 0xaf420258, 0x24020001, -0x3c010001, 0xac225cb8, 0x8fbf0014, 0x8fb00010, -0x3e00008, 0x27bd0018, 0x3c030001, 0x8c635df4, +0x3c010001, 0xac225c58, 0x8fbf0014, 0x8fb00010, +0x3e00008, 0x27bd0018, 0x3c030001, 0x8c635d94, 0x8c820000, 0x8fa80010, 0x8fa90014, 0xac620000, -0x3c020001, 0x8c425df4, 0x8c830004, 0xac430004, +0x3c020001, 0x8c425d94, 0x8c830004, 0xac430004, 0xac450008, 0x8f840054, 0x2443ffe0, 0xac460010, 0xac470014, 0xac480018, 0xac49001c, 0x3c010001, -0xac235df4, 0xac44000c, 0x3c020001, 0x24425e30, +0xac235d94, 0xac44000c, 0x3c020001, 0x24425dd0, 0x62182b, 0x10600005, 0x0, 0x3c020001, -0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001, -0x8c635df4, 0x3c020001, 0x8c425ca0, 0xac620000, -0x3c030001, 0x8c635df4, 0x3c020001, 0x8c425ca0, +0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001, +0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620000, +0x3c030001, 0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620004, 0x3e00008, 0xaf430250, 0x3c030001, -0x8c635df4, 0x3c020001, 0x8c425ca0, 0x27bdffd0, +0x8c635d94, 0x3c020001, 0x8c425c40, 0x27bdffd0, 0xafb40020, 0x8fb40040, 0xafb00010, 0x808021, 0xafb50024, 0x8fb50044, 0x8fa40048, 0xafb10014, 0xa08821, 0xafbf0028, 0xafb3001c, 0xafb20018, -0xac620000, 0x3c050001, 0x8ca55df4, 0x3c020001, -0x8c425ca0, 0xc09021, 0xe09821, 0x10800006, +0xac620000, 0x3c050001, 0x8ca55d94, 0x3c020001, +0x8c425c40, 0xc09021, 0xe09821, 0x10800006, 0xaca20004, 0x24a50008, 0xc002490, 0x24060018, 0x800244e, 0x0, 0x24a40008, 0xc002488, -0x24050018, 0x3c020001, 0x8c425df4, 0x3c050001, -0x24a55e30, 0x2442ffe0, 0x3c010001, 0xac225df4, +0x24050018, 0x3c020001, 0x8c425d94, 0x3c050001, +0x24a55dd0, 0x2442ffe0, 0x3c010001, 0xac225d94, 0x45102b, 0x10400005, 0x0, 0x3c020001, -0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001, -0x8c635df4, 0x8e020000, 0xac620000, 0x3c030001, -0x8c635df4, 0x8e020004, 0xac620004, 0xac710008, -0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225df4, +0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001, +0x8c635d94, 0x8e020000, 0xac620000, 0x3c030001, +0x8c635d94, 0x8e020004, 0xac620004, 0xac710008, +0x8f840054, 0x2462ffe0, 0x3c010001, 0xac225d94, 0x45102b, 0xac720010, 0xac730014, 0xac740018, 0xac75001c, 0x10400005, 0xac64000c, 0x3c020001, -0x8c425df0, 0x3c010001, 0xac225df4, 0x3c030001, -0x8c635df4, 0x3c020001, 0x8c425ca0, 0xac620000, -0x3c030001, 0x8c635df4, 0x3c020001, 0x8c425ca0, +0x8c425d90, 0x3c010001, 0xac225d94, 0x3c030001, +0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620000, +0x3c030001, 0x8c635d94, 0x3c020001, 0x8c425c40, 0xac620004, 0xaf430250, 0x8fbf0028, 0x8fb50024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 0x10a00005, @@ -1380,7 +1380,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, 0x8ee27264, 0x3c040001, -0x24845780, 0x3c050004, 0xafa20014, 0x8ee604e4, +0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f114, 0x8ee27264, 0x34843800, 0x3641821, 0x24420010, 0x43102b, 0x14400073, 0x0, 0x8ee27264, 0x24480010, 0x3641021, @@ -1409,7 +1409,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010, 0x8ee27264, 0x3c040001, -0x24845780, 0x3c050004, 0xafa20014, 0x8ee604e4, +0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f125, 0x34028100, 0xa5020000, 0x9582000e, 0x800261d, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, 0xc2102b, 0x50400001, @@ -1436,7 +1436,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x34028100, 0xafab0010, 0x8ee27264, -0x3c040001, 0x24845780, 0x3c050004, 0xafa20014, +0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f015, 0x8ee37264, 0xa462000c, 0x8ee37264, 0x9582000e, 0xa462000e, 0x8002681, 0x24e70004, 0x8f840100, 0x27623000, @@ -1462,7 +1462,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x15200009, 0x3c050004, -0xafab0010, 0x8ee27264, 0x3c040001, 0x24845780, +0xafab0010, 0x8ee27264, 0x3c040001, 0x24845730, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f004, 0x8ee2725c, 0x30e7ffff, 0x471021, 0xaee2725c, 0x8ee204e4, 0x8ee304fc, 0x8ee47258, 0x21100, @@ -1482,7 +1482,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f8200f0, 0x24090001, 0x8fa30018, 0x8fa4001c, 0xac430000, 0xac440004, 0xaf8700f0, 0x15200012, 0xd1142, 0x8f8200f0, 0xafa20010, 0x8f8200f4, -0x3c040001, 0x2484578c, 0xafa20014, 0x8fa60018, +0x3c040001, 0x2484573c, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050004, 0xc002403, 0x34a5f005, 0x8ee20088, 0x24420001, 0xaee20088, 0x8ee20088, 0x80028d3, 0xaee0725c, 0x30430003, 0x24020002, @@ -1524,7 +1524,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x3c040001, 0xafab0010, -0x8ee27264, 0x3c040001, 0x24845780, 0x3c050004, +0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f014, 0x8ee27264, 0x34843800, 0x3641821, 0x24420010, 0x43102b, 0x14400073, 0x0, 0x8ee27264, @@ -1553,7 +1553,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x2508fffc, 0xafab0010, -0x8ee27264, 0x3c040001, 0x24845780, 0x3c050004, +0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f015, 0x34028100, 0xa5020000, 0x9582000e, 0x800285f, 0xa5020002, 0x8f850100, 0x27623000, 0x24a60020, @@ -1580,7 +1580,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000a, 0x34028100, -0xafab0010, 0x8ee27264, 0x3c040001, 0x24845780, +0xafab0010, 0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x80028be, 0x34a5f016, 0x8ee37264, 0xa462000c, 0x8ee37264, 0x9582000e, 0xa462000e, 0x80028c2, 0x24e70004, @@ -1606,7 +1606,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1520000b, 0x3c050004, 0x3c040001, -0x24845798, 0xafab0010, 0xafa00014, 0x8ee604e4, +0x24845748, 0xafab0010, 0xafa00014, 0x8ee604e4, 0x34a5f017, 0xc002403, 0x30e7ffff, 0x80028e1, 0x0, 0x8ee27264, 0x3c050001, 0x30e4ffff, 0x441021, 0xaee27264, 0x8ee2725c, 0x8ee37264, @@ -1672,7 +1672,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1540000a, 0x24020001, -0xafa90010, 0x8ee27264, 0x3c040001, 0x24845780, +0xafa90010, 0x8ee27264, 0x3c040001, 0x24845730, 0x3c050004, 0xafa20014, 0x8ee604e4, 0x8002a4f, 0x34a5f204, 0xa2e204ed, 0x8ee204e8, 0x8ee304fc, 0x8ee47258, 0x3c060001, 0x34c63800, 0x3c010001, @@ -1706,7 +1706,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e28, 0x8ee24e28, 0x210c0, 0x24424e38, 0x2e22021, 0x24020005, 0xac820000, 0x24020001, 0xac820004, 0x1540000c, 0x30e5ffff, 0x3c040001, -0x24845798, 0x3c050004, 0xafa90010, 0xafa00014, +0x24845748, 0x3c050004, 0xafa90010, 0xafa00014, 0x8ee604e4, 0x34a5f237, 0xc002403, 0x30e7ffff, 0x8002a72, 0x0, 0x8ee27264, 0x451021, 0xaee27264, 0x8ee2726c, 0x8ee37264, 0x3c040001, @@ -1730,7 +1730,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f830108, 0x21140, 0x621821, 0xaf830108, 0xac800000, 0x8cc20018, 0x2443fffe, 0x2c620013, 0x104000c1, 0x31080, 0x3c010001, 0x220821, -0x8c2257c0, 0x400008, 0x0, 0x8ee204f0, +0x8c225770, 0x400008, 0x0, 0x8ee204f0, 0x471021, 0xaee204f0, 0x8ee204f0, 0x8f43023c, 0x43102b, 0x144000be, 0x0, 0x8ee304e4, 0x8ee204f8, 0x506200ba, 0xa2e004f4, 0x8f830120, @@ -1757,7 +1757,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0xac820000, 0x24020001, 0xac820004, 0x5600000b, 0x24100001, 0x8ee204e4, -0x3c040001, 0x248457a4, 0xafa00014, 0xafa20010, +0x3c040001, 0x24845754, 0xafa00014, 0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f006, 0x16000003, 0x24020001, 0x8002b71, 0xa2e204f4, 0x8ee20170, 0x24420001, 0xaee20170, @@ -1778,7 +1778,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8002b71, 0xaee20000, 0x8ee2014c, 0x3c010001, 0x370821, 0xa02083e0, 0x24420001, 0xaee2014c, 0x8002b71, 0x8ee2014c, 0x94c7000e, 0x8cc2001c, -0x3c040001, 0x248457b0, 0xafa60014, 0xafa20010, +0x3c040001, 0x24845760, 0xafa60014, 0xafa20010, 0x8cc60018, 0x3c050008, 0xc002403, 0x34a50910, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x27bdff98, 0xafbf0060, 0xafbe005c, 0xafb60058, @@ -1787,7 +1787,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa00024, 0x106203e7, 0xafa0002c, 0x3c1e0001, 0x37de3800, 0x3c0bffff, 0x8f930108, 0x8e620018, 0x8f830104, 0x2443fffe, 0x2c620014, 0x104003cf, -0x31080, 0x3c010001, 0x220821, 0x8c225810, +0x31080, 0x3c010001, 0x220821, 0x8c2257c0, 0x400008, 0x0, 0x9663000e, 0x8ee2725c, 0x8ee404f0, 0x431021, 0xaee2725c, 0x8e63001c, 0x96e20458, 0x24840001, 0xaee404f0, 0x24630001, @@ -1816,7 +1816,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 0xac8c0004, 0x5600000d, 0x24100001, 0x8ee204e4, -0x3c040001, 0x248457a4, 0xafa00014, 0xafa20010, +0x3c040001, 0x24845754, 0xafa00014, 0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038, 0x1200030a, 0x240c0001, 0x8002f19, 0x0, 0x966c001c, @@ -2010,7 +2010,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020012, 0x240c0001, 0xac820000, 0xac8c0004, 0x5600000d, 0x24100001, -0x8ee204e4, 0x3c040001, 0x248457a4, 0xafa00014, +0x8ee204e4, 0x3c040001, 0x24845754, 0xafa00014, 0xafa20010, 0x8ee60608, 0x8f470228, 0x3c050009, 0x34a5f006, 0xc002403, 0xafab0038, 0x8fab0038, 0x16000003, 0x240c0001, 0x8002f5c, 0xa2ec04f4, @@ -2065,7 +2065,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8821, 0x8f8200e4, 0x24110001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x1620000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, 0x8f8200c8, -0x3c040001, 0x248458c0, 0xafa20014, 0x8f8600e0, +0x3c040001, 0x24845870, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000, 0x80034cc, 0x0, 0x8fa3001c, 0x8fb20018, 0x3074ffff, 0x2694fffc, 0x621024, 0x10400058, @@ -2163,11 +2163,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, -0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c8, +0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845878, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403, 0x34a5f003, 0x80034cc, 0x0, 0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001, -0x248458d4, 0xafa20014, 0x8ee60e10, 0x8ee70e18, +0x24845884, 0xafa20014, 0x8ee60e10, 0x8ee70e18, 0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8ee20000, 0x8ee301c0, 0x2403ffbf, 0x431024, 0x8003470, 0xaee20000, @@ -2219,7 +2219,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x50550003, 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0xac960000, 0xac9e0004, 0x16200018, -0x3c050006, 0x8e020018, 0x3c040001, 0x248458e0, +0x3c050006, 0x8e020018, 0x3c040001, 0x24845890, 0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc002403, 0xafa30014, 0x93a20037, 0x10400216, 0x340f8100, 0x8e420004, 0x8e430008, @@ -2252,7 +2252,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x210c0, 0x24425038, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620000d, 0x0, 0xa60c000a, 0xa60a000e, 0x8f820100, 0xafa20010, 0x8f820104, -0x3c040001, 0x248458ec, 0x3c050006, 0xafa20014, +0x3c040001, 0x2484589c, 0x3c050006, 0xafa20014, 0x8ee6724c, 0x800343b, 0x34a5f00b, 0x3c010001, 0x370821, 0xa02083c0, 0xadab0000, 0x8ee201d8, 0x8ee3724c, 0x2442ffff, 0xaee201d8, 0x8ee201d8, @@ -2284,7 +2284,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x5620000d, 0x24110001, -0x8ee2724c, 0x3c040001, 0x248458f8, 0xafa00014, +0x8ee2724c, 0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048, 0x56200001, 0xaee00e1c, 0x8ee20188, 0x24420001, @@ -2311,7 +2311,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0xac8e0000, 0xac9e0004, 0x1620000d, 0x0, 0x8ee2724c, -0x3c040001, 0x248458f8, 0xafa00014, 0xafa20010, +0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0x34a5f008, 0xc002403, 0xafae0048, 0x8fae0048, 0x8ee20174, 0x24420001, 0xaee20174, 0x8ee20174, 0x800346e, @@ -2341,7 +2341,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0xac960000, 0xac9e0004, 0x1620001d, 0x0, 0xa60c000a, 0x8f820100, 0xafa20010, 0x8f820104, -0x3c040001, 0x248458ec, 0x3c050006, 0xafa20014, +0x3c040001, 0x2484589c, 0x3c050006, 0xafa20014, 0x8ee6724c, 0x34a5f00d, 0xc002403, 0x2003821, 0x93a20037, 0x10400031, 0x340f8100, 0x8e420004, 0x8e430008, 0x8e44000c, 0xa64f000c, 0xae420000, @@ -2403,7 +2403,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x10430007, 0x4821, 0x8f8200e4, 0x24090001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x1520000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, -0x8f8200c8, 0x3c040001, 0x248458c0, 0xafa20014, +0x8f8200c8, 0x3c040001, 0x24845870, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f000, 0x8003850, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024, @@ -2501,15 +2501,15 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, -0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c8, +0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845878, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403, 0x34a5f003, 0x8003850, 0x0, 0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001, -0x248458d4, 0xafa20014, 0x8ee60e10, 0x8ee70e18, +0x24845884, 0xafa20014, 0x8ee60e10, 0x8ee70e18, 0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8ee20000, 0x8ee301c0, 0x2403ffbf, 0x431024, 0x80037f8, 0xaee20000, 0x8ee25240, -0xafa20010, 0x8ee25244, 0x3c040001, 0x248458d4, +0xafa20010, 0x8ee25244, 0x3c040001, 0x24845884, 0xafa20014, 0x8ee60e10, 0x8ee70e18, 0x3c050006, 0xc002403, 0x34a5f002, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x80037f8, 0x8ee201c0, 0x96e20468, @@ -2568,7 +2568,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x15200018, 0x3c050006, -0x8e020018, 0x3c040001, 0x248458e0, 0xafa20010, +0x8e020018, 0x3c040001, 0x24845890, 0xafa20010, 0x8e020000, 0x8e030004, 0x34a5f009, 0x2003021, 0xc002403, 0xafa30014, 0x32c200ff, 0x1040002b, 0x34028100, 0x8e430004, 0x8e440008, 0x8e45000c, @@ -2628,7 +2628,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x10430007, 0x3821, 0x8f8200e4, 0x24070001, 0x8c430000, 0x8c440004, 0xafa30018, 0xafa4001c, 0x14e0000e, 0x3c02ffff, 0x8f8200c4, 0xafa20010, -0x8f8200c8, 0x3c040001, 0x24845904, 0xafa20014, +0x8f8200c8, 0x3c040001, 0x248458b4, 0xafa20014, 0x8f8600e0, 0x8f8700e4, 0x3c050006, 0xc002403, 0x34a5f200, 0x8003c5b, 0x0, 0x8fa3001c, 0x8fb20018, 0x3073ffff, 0x2673fffc, 0x621024, @@ -2726,11 +2726,11 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x862021, 0xaee400c0, 0xaee500c4, 0x8ee20058, 0x24420001, 0xaee20058, 0x8ee20058, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x8f8200e0, -0xafa20010, 0x8f8200e4, 0x3c040001, 0x24845910, +0xafa20010, 0x8f8200e4, 0x3c040001, 0x248458c0, 0xafa20014, 0x8fa60018, 0x8fa7001c, 0x3c050006, 0xc002403, 0x34a5f203, 0x8003c5b, 0x0, 0x8ee25240, 0xafa20010, 0x8ee25244, 0x3c040001, -0x2484591c, 0xafa20014, 0x8ee60e10, 0x8ee70e18, +0x248458cc, 0xafa20014, 0x8ee60e10, 0x8ee70e18, 0x3c050006, 0xc002403, 0x34a5f202, 0x8ee201c0, 0x24420001, 0xaee201c0, 0x8003c02, 0x8ee201c0, 0x96e20468, 0x53102b, 0x54400001, 0x3c168000, @@ -2826,7 +2826,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, -0x14e00019, 0x3c050006, 0x3c040001, 0x248458e0, +0x14e00019, 0x3c050006, 0x3c040001, 0x24845890, 0x8e220018, 0x34a5f209, 0xafa20010, 0x8e220000, 0x8e230004, 0x2203021, 0x1603821, 0xc002403, 0xafa30014, 0x93a2002f, 0x1040002a, 0x34028100, @@ -2890,7 +2890,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24020001, 0xac620004, 0x1480000e, 0x24030040, 0x8ee20e14, 0xafa20010, 0x8ee20e18, 0x3c050007, 0xafa20014, 0x8ee60e0c, 0x8ee70e10, 0x3c040001, -0x24845924, 0xc002403, 0x34a5f001, 0x8003cdd, +0x248458d4, 0xc002403, 0x34a5f001, 0x8003cdd, 0x0, 0x8ee20500, 0x24420001, 0x50430003, 0x1021, 0x8ee20500, 0x24420001, 0xaee20500, 0x8ee20500, 0x21080, 0x571021, 0xac490508, @@ -2922,7 +2922,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24020003, 0xac620000, 0x24020001, 0xac620004, 0x1480000e, 0x24030040, 0x8ee2523c, 0xafa20010, 0x8ee25244, 0x3c050007, 0xafa20014, 0x8ee65238, -0x8ee75240, 0x3c040001, 0x24845930, 0xc002403, +0x8ee75240, 0x3c040001, 0x248458e0, 0xc002403, 0x34a5f010, 0x8003d5f, 0x0, 0x8ee20500, 0x24420001, 0x50430003, 0x1021, 0x8ee20500, 0x24420001, 0xaee20500, 0x8ee20500, 0x21080, @@ -2942,7 +2942,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f830128, 0x21140, 0x621821, 0xaf830128, 0xaca00000, 0x8cc20018, 0x2443fffe, 0x2c620012, 0x10400008, 0x31080, 0x3c010001, 0x220821, -0x8c225940, 0x400008, 0x0, 0x24020001, +0x8c2258f0, 0x400008, 0x0, 0x24020001, 0xaee24e24, 0x3e00008, 0x0, 0x27bdffc8, 0xafbf0030, 0xafb5002c, 0xafb40028, 0xafb30024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f830128, @@ -2951,7 +2951,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24140040, 0x8f8c0128, 0x8f820128, 0x24420020, 0xaf820128, 0x9182001b, 0x8f830128, 0x2443fffe, 0x2c620012, 0x1040029c, 0x31080, 0x3c010001, -0x220821, 0x8c225998, 0x400008, 0x0, +0x220821, 0x8c225948, 0x400008, 0x0, 0x8f420218, 0x30420100, 0x10400007, 0x0, 0x95830016, 0x95820018, 0x621823, 0x31402, 0x431021, 0xa5820016, 0x8d82001c, 0x3c038000, @@ -3052,7 +3052,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020007, 0xac820000, 0x24020001, 0xac820004, 0x1600000d, 0x0, -0x8f820120, 0x3c040001, 0x24845988, 0xafa00014, +0x8f820120, 0x3c040001, 0x24845938, 0xafa00014, 0xafa20010, 0x8d86001c, 0x8f870124, 0x3c050008, 0xc002403, 0x34a50001, 0x8004057, 0x0, 0x8ee2724c, 0x24420001, 0x304207ff, 0x11a00006, @@ -3087,7 +3087,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x5600000b, 0x24100001, 0x8ee2724c, -0x3c040001, 0x248458f8, 0xafa00014, 0xafa20010, +0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x56000001, 0xaee00e1c, 0x8ee20188, 0x24420001, 0xaee20188, 0x8004050, 0x8ee20188, @@ -3113,7 +3113,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1021, 0x8ee24e30, 0x24420001, 0xaee24e30, 0x8ee24e30, 0x210c0, 0x24425038, 0x2e22021, 0x24020001, 0xac950000, 0xac820004, 0x1600000b, -0x0, 0x8ee2724c, 0x3c040001, 0x248458f8, +0x0, 0x8ee2724c, 0x3c040001, 0x248458a8, 0xafa00014, 0xafa20010, 0x8ee6724c, 0x8f470280, 0x3c050009, 0xc002403, 0x34a5f008, 0x8ee20174, 0x24420001, 0xaee20174, 0x8004057, 0x8ee20174, @@ -3125,16 +3125,16 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xc00249a, 0xafb00010, 0x2021, 0x24100001, 0x2402241f, 0xaf900210, 0xaf900200, 0xaf800204, 0xaf820214, 0x8f460248, 0x24030004, 0x3c020040, -0x3c010001, 0xac235d24, 0x3c010001, 0xac235d28, -0x3c010001, 0xac205dfc, 0x3c010001, 0xac225d20, -0x3c010001, 0xac235d28, 0xc0050e0, 0x24050004, -0xc0047fc, 0x0, 0x8ee20000, 0x3c03feff, +0x3c010001, 0xac235cc4, 0x3c010001, 0xac235cc8, +0x3c010001, 0xac205d9c, 0x3c010001, 0xac225cc0, +0x3c010001, 0xac235cc8, 0xc005108, 0x24050004, +0xc004822, 0x0, 0x8ee20000, 0x3c03feff, 0x3463fffd, 0x431024, 0xaee20000, 0x3c023c00, 0xaf82021c, 0x3c010001, 0x370821, 0xac3083ac, 0x8fbf0014, 0x8fb00010, 0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c050008, 0x34a50400, 0xafbf0018, 0xafa00010, 0xafa00014, 0x8f860200, 0x3c040001, -0x24845a40, 0xc002403, 0x3821, 0x8ee20280, +0x248459f0, 0xc002403, 0x3821, 0x8ee20280, 0x24420001, 0xaee20280, 0x8ee20280, 0x8f830200, 0x3c023f00, 0x621824, 0x8fbf0018, 0x3c020400, 0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020, @@ -3146,16 +3146,16 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaee20218, 0x8ee20218, 0x80040c6, 0x3c03fdff, 0x8ee2021c, 0x24420001, 0xaee2021c, 0x8ee2021c, 0x3c03fdff, 0x3463ffff, 0x3c0808ff, 0x3508ffff, -0x8ee20000, 0x3c040001, 0x24845a4c, 0x3c050008, +0x8ee20000, 0x3c040001, 0x248459fc, 0x3c050008, 0x2003021, 0x431024, 0xaee20000, 0x8f820220, 0x3821, 0x3c030300, 0x481024, 0x431025, 0xaf820220, 0xafa00010, 0xc002403, 0xafa00014, 0x8004296, 0x0, 0x2111024, 0x1040001f, 0x3c024000, 0x8f830224, 0x24021402, 0x1462000b, -0x3c03fdff, 0x3c040001, 0x24845a58, 0x3c050008, +0x3c03fdff, 0x3c040001, 0x24845a08, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860224, 0x34a5ffff, 0xc002403, 0x3821, 0x3c03fdff, 0x8ee20000, -0x3463ffff, 0x2002021, 0x431024, 0xc004e2c, +0x3463ffff, 0x2002021, 0x431024, 0xc004e54, 0xaee20000, 0x8ee20220, 0x24420001, 0xaee20220, 0x8ee20220, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x8004295, 0x511025, 0x2021024, @@ -3226,7 +3226,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x431025, 0xaf820220, 0x8f8600e0, 0x8f8400e4, 0x10c4002a, 0x0, 0x8ee2007c, 0x24420001, 0xaee2007c, 0x8ee2007c, 0x24c2fff8, 0xaf8200e0, -0x3c020001, 0x8c427e90, 0x3c030008, 0x8f8600e0, +0x3c020001, 0x8c427e30, 0x3c030008, 0x8f8600e0, 0x431024, 0x1040001d, 0x0, 0x10c4001b, 0x240dfff8, 0x3c0a000a, 0x354af000, 0x3c0c0080, 0x24850008, 0x27622800, 0x50a20001, 0x27651800, @@ -3262,12 +3262,12 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820220, 0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, -0x3e00008, 0x27bd0028, 0x3c020001, 0x8c425d38, +0x3e00008, 0x27bd0028, 0x3c020001, 0x8c425cd8, 0x27bdffd8, 0x10400012, 0xafbf0020, 0x3c040001, -0x24845a64, 0x3c050008, 0x24020001, 0x3c010001, +0x24845a14, 0x3c050008, 0x24020001, 0x3c010001, 0x370821, 0xac2283ac, 0xafa00010, 0xafa00014, -0x8f860220, 0x34a50498, 0x3c010001, 0xac205d38, -0x3c010001, 0xac225d2c, 0xc002403, 0x3821, +0x8f860220, 0x34a50498, 0x3c010001, 0xac205cd8, +0x3c010001, 0xac225ccc, 0xc002403, 0x3821, 0x8f420268, 0x3c037fff, 0x3463ffff, 0x431024, 0xaf420268, 0x8ee204d0, 0x8ee404d4, 0x2403fffe, 0x431024, 0x30840002, 0x1080011e, 0xaee204d0, @@ -3333,24 +3333,24 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x54a00006, 0x240b0001, 0x8f820054, 0x1221023, 0x2c420033, 0x1440ffa6, 0x0, 0x316300ff, 0x24020001, 0x54620003, 0xafa00010, 0x80043d6, -0x0, 0x3c040001, 0x24845a70, 0xafa00014, +0x0, 0x3c040001, 0x24845a20, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f011, 0x80043d6, 0x0, 0x3c040001, -0x24845a7c, 0xafa00014, 0x8f860120, 0x8f870124, +0x24845a2c, 0xafa00014, 0x8f860120, 0x8f870124, 0x3c050009, 0xc002403, 0x34a5f010, 0x80043d6, -0x0, 0x3c040001, 0x24845a88, 0xafa00014, +0x0, 0x3c040001, 0x24845a38, 0xafa00014, 0x8ee60608, 0x8f470228, 0x3c050009, 0xc002403, 0x34a5f00f, 0x8ee201ac, 0x24420001, 0xaee201ac, 0x8ee201ac, 0x8ee2015c, 0x24420001, 0xaee2015c, 0x8ee2015c, 0x8fbf0020, 0x3e00008, 0x27bd0028, -0x3c020001, 0x8c425d38, 0x27bdffe0, 0x1440000d, -0xafbf0018, 0x3c040001, 0x24845a94, 0x3c050008, +0x3c020001, 0x8c425cd8, 0x27bdffe0, 0x1440000d, +0xafbf0018, 0x3c040001, 0x24845a44, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50499, -0x24020001, 0x3c010001, 0xac225d38, 0xc002403, +0x24020001, 0x3c010001, 0xac225cd8, 0xc002403, 0x3821, 0x8ee204d0, 0x3c030001, 0x771821, 0x946383b2, 0x34420001, 0x10600007, 0xaee204d0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, -0x34420008, 0xaf820220, 0x2021, 0xc005276, +0x34420008, 0xaf820220, 0x2021, 0xc0052a2, 0x24050004, 0xaf420268, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -3368,7 +3368,7 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3c120001, -0x26521200, 0x3c140001, 0x8e945cb0, 0x3c100001, +0x26521200, 0x3c140001, 0x8e945c50, 0x3c100001, 0x26101120, 0x3c15c000, 0x36b50060, 0x8e8a0000, 0x8eb30000, 0x26a400b, 0x248000a, 0x200f821, 0x0, 0xd, 0x0, 0x0, @@ -3429,978 +3429,973 @@ u32 tigonFwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1062000c, 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x8004539, 0x0, 0x10620004, 0x24020800, 0x8004539, -0x0, 0x24020700, 0x3c010001, 0xac225d3c, -0x3e00008, 0x0, 0x27bdffd0, 0xafbf0028, -0x8f830054, 0x8f820054, 0x3c010001, 0xac205d24, -0x8004544, 0x24630064, 0x8f820054, 0x621023, -0x2c420065, 0x1440fffc, 0x0, 0xc004d49, -0x0, 0x24040001, 0x2821, 0x27a60020, -0x34028000, 0xc004966, 0xa7a20020, 0x8f830054, -0x8f820054, 0x8004555, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x24040001, -0x24050001, 0xc004924, 0x27a60020, 0x8f830054, -0x8f820054, 0x8004561, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x24040001, -0x24050001, 0xc004924, 0x27a60020, 0x8f830054, -0x8f820054, 0x800456d, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x24040001, -0x24050002, 0xc004924, 0x27a60018, 0x8f830054, -0x8f820054, 0x8004579, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x24040001, -0x24050003, 0xc004924, 0x27a6001a, 0x3c040001, -0x24845b00, 0x97a60020, 0x97a70018, 0x97a2001a, -0x3c05000d, 0x34a50100, 0xafa00014, 0xc002403, -0xafa20010, 0x97a20020, 0x10400045, 0x24036040, -0x97a2001a, 0x3042fff0, 0x14430009, 0x24020020, -0x97a30018, 0x54620008, 0x24027830, 0x24020003, -0x3c010001, 0xac225d24, 0x80045a4, 0x24020005, -0x97a30018, 0x24027830, 0x1462000e, 0x24030010, -0x97a2001a, 0x3042fff0, 0x1443000a, 0x24020003, -0x3c010001, 0xac225d24, 0x24020006, 0x3c010001, -0xac225e0c, 0x3c010001, 0xac225e18, 0x80045da, -0x3c09fff0, 0x3c020001, 0x8c425d24, 0x97a30018, -0x34420001, 0x3c010001, 0xac225d24, 0x24020015, -0x1462000e, 0x0, 0x97a2001a, 0x3042fff0, -0x3843f420, 0x2c630001, 0x3842f430, 0x2c420001, -0x621825, 0x10600005, 0x24020003, 0x3c010001, -0xac225e18, 0x80045da, 0x3c09fff0, 0x97a30018, -0x24027810, 0x1462000a, 0x24020002, 0x97a2001a, +0x0, 0x24020700, 0x3c010001, 0xac225cdc, +0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, +0xafb00020, 0x8f830054, 0x8f820054, 0x3c010001, +0xac205cc4, 0x8004545, 0x24630064, 0x8f820054, +0x621023, 0x2c420065, 0x1440fffc, 0x0, +0xc004d71, 0x0, 0x24040001, 0x2821, +0x27a60018, 0x34028000, 0xc00498e, 0xa7a20018, +0x8f830054, 0x8f820054, 0x8004556, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, +0x24040001, 0x24050001, 0xc00494c, 0x27a60018, +0x8f830054, 0x8f820054, 0x8004562, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, +0x24040001, 0x24050001, 0xc00494c, 0x27a60018, +0x8f830054, 0x8f820054, 0x800456e, 0x24630064, +0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, +0x24040001, 0x3c060001, 0x24c65da0, 0xc00494c, +0x24050002, 0x8f830054, 0x8f820054, 0x800457b, +0x24630064, 0x8f820054, 0x621023, 0x2c420065, +0x1440fffc, 0x24040001, 0x24050003, 0x3c100001, +0x26105da2, 0xc00494c, 0x2003021, 0x97a60018, +0x3c070001, 0x94e75da0, 0x3c040001, 0x24845ab0, +0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100, +0xc002403, 0xafa20010, 0x97a20018, 0x1040004c, +0x24036040, 0x96020000, 0x3042fff0, 0x1443000a, +0x24020020, 0x3c030001, 0x94635da0, 0x54620009, +0x24027830, 0x24020003, 0x3c010001, 0xac225cc4, +0x80045ac, 0x24020005, 0x3c030001, 0x94635da0, +0x24027830, 0x1462000f, 0x24030010, 0x3c020001, +0x94425da2, 0x3042fff0, 0x1443000a, 0x24020003, +0x3c010001, 0xac225cc4, 0x24020006, 0x3c010001, +0xac225db0, 0x3c010001, 0xac225dbc, 0x80045e6, +0x3c09fff0, 0x3c020001, 0x8c425cc4, 0x3c030001, +0x94635da0, 0x34420001, 0x3c010001, 0xac225cc4, +0x24020015, 0x1462000f, 0x0, 0x3c020001, +0x94425da2, 0x3042fff0, 0x3843f420, 0x2c630001, +0x3842f430, 0x2c420001, 0x621825, 0x10600005, +0x24020003, 0x3c010001, 0xac225dbc, 0x80045e6, +0x3c09fff0, 0x3c030001, 0x94635da0, 0x24027810, +0x1462000b, 0x24020002, 0x3c020001, 0x94425da2, 0x3042fff0, 0x14400006, 0x24020002, 0x24020004, -0x3c010001, 0xac225e18, 0x80045da, 0x3c09fff0, -0x3c010001, 0xac225e18, 0x80045da, 0x3c09fff0, -0x3c020001, 0x8c425d24, 0x24030001, 0x3c010001, -0xac235e18, 0x34420004, 0x3c010001, 0xac225d24, -0x3c09fff0, 0x3529bdc0, 0x8f830054, 0x3c060001, -0x8cc65d24, 0x3c070001, 0x8ce75e18, 0x97a80018, -0x3c040001, 0x24845b00, 0x24020001, 0x3c010001, -0xac225d2c, 0xafa80010, 0x97a2001a, 0x3c05000d, -0x34a50100, 0x3c010001, 0xac205d28, 0x691821, -0x3c010001, 0xac235e08, 0xc002403, 0xafa20014, -0x8fbf0028, 0x3e00008, 0x27bd0030, 0x27bdffe8, -0x3c050001, 0x8ca55d28, 0x24060004, 0x24020001, -0x14a20014, 0xafbf0010, 0x3c020001, 0x8c427e9c, -0x30428000, 0x10400005, 0x3c04000f, 0x3c030001, -0x8c635e18, 0x8004608, 0x34844240, 0x3c040004, -0x3c030001, 0x8c635e18, 0x348493e0, 0x24020005, -0x14620016, 0x0, 0x3c04003d, 0x8004620, -0x34840900, 0x3c020001, 0x8c427e98, 0x30428000, -0x10400005, 0x3c04001e, 0x3c030001, 0x8c635e18, -0x800461b, 0x34848480, 0x3c04000f, 0x3c030001, -0x8c635e18, 0x34844240, 0x24020005, 0x14620003, -0x0, 0x3c04007a, 0x34841200, 0x3c020001, -0x8c425e08, 0x8f830054, 0x441021, 0x431023, -0x44102b, 0x14400037, 0x0, 0x3c020001, -0x8c425d30, 0x14400033, 0x0, 0x3c010001, -0x10c00025, 0xac205d40, 0x3c090001, 0x8d295d24, -0x24070001, 0x3c044000, 0x3c080001, 0x25087e9c, -0x250afffc, 0x52842, 0x14a00002, 0x24c6ffff, -0x24050008, 0xa91024, 0x10400010, 0x0, -0x14a70008, 0x0, 0x8d020000, 0x441024, -0x1040000a, 0x0, 0x3c010001, 0x800464c, -0xac255d40, 0x8d420000, 0x441024, 0x10400003, -0x0, 0x3c010001, 0xac275d40, 0x3c020001, -0x8c425d40, 0x6182b, 0x2c420001, 0x431024, -0x5440ffe5, 0x52842, 0x8f820054, 0x3c030001, -0x8c635d40, 0x3c010001, 0xac225e08, 0x1060002a, -0x24020001, 0x3c010001, 0xac255d28, 0x3c010001, -0xac225d2c, 0x3c020001, 0x8c425d40, 0x10400022, -0x0, 0x3c020001, 0x8c425d2c, 0x1040000a, -0x24020001, 0x3c010001, 0xac205d2c, 0x3c010001, -0x370821, 0xac2283ac, 0x3c010001, 0xac205dac, -0x3c010001, 0xac225d64, 0x3c030001, 0x771821, -0x8c6383ac, 0x24020008, 0x10620005, 0x24020001, -0xc004686, 0x0, 0x8004683, 0x0, -0x3c030001, 0x8c635d28, 0x10620007, 0x2402000e, -0x3c030001, 0x8c637e30, 0x10620003, 0x0, -0xc004e2c, 0x8f840220, 0x8fbf0010, 0x3e00008, -0x27bd0018, 0x27bdffe0, 0x3c02fdff, 0xafbf001c, -0xafb00018, 0x8ee30000, 0x3c050001, 0x8ca55d28, -0x3c040001, 0x8c845d50, 0x3442ffff, 0x621824, -0x14a40008, 0xaee30000, 0x3c030001, 0x771821, -0x8c6383ac, 0x3c020001, 0x8c425d54, 0x10620008, -0x0, 0x3c020001, 0x571021, 0x8c4283ac, -0x3c010001, 0xac255d50, 0x3c010001, 0xac225d54, -0x3c030001, 0x8c635d28, 0x24020002, 0x10620150, -0x2c620003, 0x10400005, 0x24020001, 0x10620008, -0x0, 0x80047f5, 0x0, 0x24020004, -0x10620098, 0x24020001, 0x80047f6, 0x0, -0x3c020001, 0x571021, 0x8c4283ac, 0x2443ffff, -0x2c620008, 0x10400141, 0x31080, 0x3c010001, -0x220821, 0x8c225b18, 0x400008, 0x0, -0x3c030001, 0x8c635e18, 0x24020005, 0x14620014, -0x0, 0x3c020001, 0x8c425d34, 0x1040000a, -0x24020003, 0xc0047fc, 0x0, 0x24020002, +0x3c010001, 0xac225dbc, 0x80045e6, 0x3c09fff0, +0x3c010001, 0xac225dbc, 0x80045e6, 0x3c09fff0, +0x3c020001, 0x8c425cc4, 0x24030001, 0x3c010001, +0xac235dbc, 0x34420004, 0x3c010001, 0xac225cc4, +0x3c09fff0, 0x3529bdc0, 0x3c060001, 0x8cc65cc4, +0x3c040001, 0x24845ab0, 0x24020001, 0x3c010001, +0xac225ccc, 0x8f820054, 0x3c070001, 0x8ce75dbc, +0x3c030001, 0x94635da0, 0x3c080001, 0x95085da2, +0x3c05000d, 0x34a50100, 0x3c010001, 0xac205cc8, +0x491021, 0x3c010001, 0xac225dac, 0xafa30010, +0xc002403, 0xafa80014, 0x8fbf0024, 0x8fb00020, +0x3e00008, 0x27bd0028, 0x27bdffe8, 0x3c050001, +0x8ca55cc8, 0x24060004, 0x24020001, 0x14a20014, +0xafbf0010, 0x3c020001, 0x8c427e3c, 0x30428000, +0x10400005, 0x3c04000f, 0x3c030001, 0x8c635dbc, +0x8004617, 0x34844240, 0x3c040004, 0x3c030001, +0x8c635dbc, 0x348493e0, 0x24020005, 0x14620016, +0x0, 0x3c04003d, 0x800462f, 0x34840900, +0x3c020001, 0x8c427e38, 0x30428000, 0x10400005, +0x3c04001e, 0x3c030001, 0x8c635dbc, 0x800462a, +0x34848480, 0x3c04000f, 0x3c030001, 0x8c635dbc, +0x34844240, 0x24020005, 0x14620003, 0x0, +0x3c04007a, 0x34841200, 0x3c020001, 0x8c425dac, +0x8f830054, 0x441021, 0x431023, 0x44102b, +0x14400037, 0x0, 0x3c020001, 0x8c425cd0, +0x14400033, 0x0, 0x3c010001, 0x10c00025, +0xac205ce0, 0x3c090001, 0x8d295cc4, 0x24070001, +0x3c044000, 0x3c080001, 0x25087e3c, 0x250afffc, +0x52842, 0x14a00002, 0x24c6ffff, 0x24050008, +0xa91024, 0x10400010, 0x0, 0x14a70008, +0x0, 0x8d020000, 0x441024, 0x1040000a, +0x0, 0x3c010001, 0x800465b, 0xac255ce0, +0x8d420000, 0x441024, 0x10400003, 0x0, +0x3c010001, 0xac275ce0, 0x3c020001, 0x8c425ce0, +0x6182b, 0x2c420001, 0x431024, 0x5440ffe5, +0x52842, 0x8f820054, 0x3c030001, 0x8c635ce0, +0x3c010001, 0xac225dac, 0x1060002a, 0x24020001, +0x3c010001, 0xac255cc8, 0x3c010001, 0xac225ccc, +0x3c020001, 0x8c425ce0, 0x10400022, 0x0, +0x3c020001, 0x8c425ccc, 0x1040000a, 0x24020001, +0x3c010001, 0xac205ccc, 0x3c010001, 0x370821, +0xac2283ac, 0x3c010001, 0xac205d4c, 0x3c010001, +0xac225d04, 0x3c030001, 0x771821, 0x8c6383ac, +0x24020008, 0x10620005, 0x24020001, 0xc004695, +0x0, 0x8004692, 0x0, 0x3c030001, +0x8c635cc8, 0x10620007, 0x2402000e, 0x3c030001, +0x8c637dd0, 0x10620003, 0x0, 0xc004e54, +0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, +0x27bdffe0, 0x3c02fdff, 0xafbf0018, 0x8ee30000, +0x3c050001, 0x8ca55cc8, 0x3c040001, 0x8c845cf0, +0x3442ffff, 0x621824, 0x14a40008, 0xaee30000, +0x3c030001, 0x771821, 0x8c6383ac, 0x3c020001, +0x8c425cf4, 0x10620008, 0x0, 0x3c020001, +0x571021, 0x8c4283ac, 0x3c010001, 0xac255cf0, +0x3c010001, 0xac225cf4, 0x3c030001, 0x8c635cc8, +0x24020002, 0x10620169, 0x2c620003, 0x10400005, +0x24020001, 0x10620008, 0x0, 0x800481c, +0x0, 0x24020004, 0x106200b1, 0x24020001, +0x800481d, 0x0, 0x3c020001, 0x571021, +0x8c4283ac, 0x2443ffff, 0x2c620008, 0x1040015a, +0x31080, 0x3c010001, 0x220821, 0x8c225ac8, +0x400008, 0x0, 0x3c030001, 0x8c635dbc, +0x24020005, 0x14620014, 0x0, 0x3c020001, +0x8c425cd4, 0x1040000a, 0x24020003, 0xc004822, +0x0, 0x24020002, 0x3c010001, 0x370821, +0xac2283ac, 0x3c010001, 0x80046e0, 0xac205cd4, 0x3c010001, 0x370821, 0xac2283ac, 0x3c010001, -0x80046d2, 0xac205d34, 0x3c010001, 0x370821, -0xac2283ac, 0x3c010001, 0x80047f8, 0xac205cc0, -0xc0047fc, 0x0, 0x3c020001, 0x8c425d34, -0x3c010001, 0xac205cc0, 0x104000c4, 0x24020002, +0x800481f, 0xac205c60, 0xc004822, 0x0, +0x3c020001, 0x8c425cd4, 0x3c010001, 0xac205c60, +0x104000dd, 0x24020002, 0x3c010001, 0x370821, +0xac2283ac, 0x3c010001, 0x800481f, 0xac205cd4, +0x3c030001, 0x8c635dbc, 0x24020005, 0x14620003, +0x24020001, 0x3c010001, 0xac225d00, 0xc0049cf, +0x0, 0x3c030001, 0x8c635d00, 0x800478e, +0x24020011, 0x3c050001, 0x8ca55cc8, 0x3c060001, +0x8cc67e3c, 0xc005108, 0x2021, 0x24020005, +0x3c010001, 0xac205cd4, 0x3c010001, 0x370821, +0x800481f, 0xac2283ac, 0x3c040001, 0x24845abc, +0x3c05000f, 0x34a50100, 0x3021, 0x3821, +0xafa00010, 0xc002403, 0xafa00014, 0x800481f, +0x0, 0x8f820220, 0x3c03f700, 0x431025, +0x80047b7, 0xaf820220, 0x8f820220, 0x3c030004, +0x431024, 0x144000a9, 0x24020007, 0x8f830054, +0x3c020001, 0x8c425da4, 0x2463d8f0, 0x431023, +0x2c422710, 0x144000f8, 0x24020001, 0x800481d, +0x0, 0x3c050001, 0x8ca55cc8, 0xc0052a2, +0x2021, 0xc005386, 0x2021, 0x3c030001, +0x8c637e34, 0x46100ea, 0x24020001, 0x3c020008, +0x621024, 0x10400006, 0x0, 0x8f820214, +0x3c03ffff, 0x431024, 0x8004741, 0x3442251f, +0x8f820214, 0x3c03ffff, 0x431024, 0x3442241f, +0xaf820214, 0x8ee20000, 0x3c030200, 0x431025, +0xaee20000, 0x8f820220, 0x2403fffb, 0x431024, +0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, +0x24020008, 0x3c010001, 0x370821, 0xac2283ac, +0x8f820220, 0x3c030004, 0x431024, 0x14400005, +0x0, 0x8f820220, 0x3c03f700, 0x431025, +0xaf820220, 0x3c030001, 0x8c635dbc, 0x24020005, +0x1462000a, 0x0, 0x3c020001, 0x94425da2, +0x24429fbc, 0x2c420004, 0x10400004, 0x24040018, +0x24050002, 0xc004d93, 0x24060020, 0xc0043dd, +0x0, 0x3c010001, 0x800481f, 0xac205d50, +0x3c020001, 0x571021, 0x8c4283ac, 0x2443ffff, +0x2c620008, 0x104000ac, 0x31080, 0x3c010001, +0x220821, 0x8c225ae8, 0x400008, 0x0, +0xc00429b, 0x0, 0x3c010001, 0xac205ccc, +0xaf800204, 0x3c010001, 0xc004822, 0xac207e20, +0x24020001, 0x3c010001, 0xac225ce4, 0x24020002, +0x3c010001, 0x370821, 0x800481f, 0xac2283ac, +0xc00489f, 0x0, 0x3c030001, 0x8c635ce4, +0x24020009, 0x14620090, 0x24020003, 0x3c010001, +0x370821, 0x800481f, 0xac2283ac, 0x3c020001, +0x8c427e38, 0x30424000, 0x10400005, 0x0, +0x8f820044, 0x3c03ffff, 0x800479f, 0x34637fff, +0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044, +0x8f830054, 0x80047b9, 0x24020004, 0x8f830054, +0x3c020001, 0x8c425da4, 0x2463d8f0, 0x431023, +0x2c422710, 0x14400074, 0x24020005, 0x3c010001, +0x370821, 0x800481f, 0xac2283ac, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, +0x3c010001, 0xac207e20, 0x8f830054, 0x24020006, 0x3c010001, 0x370821, 0xac2283ac, 0x3c010001, -0x80047f8, 0xac205d34, 0x24020001, 0x3c010001, -0xc0049a7, 0xac225d60, 0x3c030001, 0x8c635d60, -0x8004767, 0x24020011, 0x3c020001, 0x8c425e18, -0x24100005, 0x10500007, 0x0, 0x3c050001, -0x8ca55d28, 0x3c060001, 0x8cc67e9c, 0xc0050e0, -0x2021, 0x3c010001, 0xac205d34, 0x3c010001, -0x370821, 0x80047f8, 0xac3083ac, 0x3c040001, -0x24845b0c, 0x3c05000f, 0x34a50100, 0x3021, -0x3821, 0xafa00010, 0xc002403, 0xafa00014, -0x80047f8, 0x0, 0x8f820220, 0x3c03f700, -0x431025, 0x8004790, 0xaf820220, 0x8f820220, -0x3c030004, 0x431024, 0x14400091, 0x24020007, -0x8f830054, 0x3c020001, 0x8c425e00, 0x2463d8f0, -0x431023, 0x2c422710, 0x144000e0, 0x24020001, -0x80047f6, 0x0, 0x3c050001, 0x8ca55d28, -0xc005276, 0x2021, 0xc005397, 0x2021, -0x3c030001, 0x8c637e94, 0x46100d2, 0x24020001, -0x3c020008, 0x621024, 0x10400006, 0x0, -0x8f820214, 0x3c03ffff, 0x431024, 0x8004732, -0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, -0x3442241f, 0xaf820214, 0x8ee20000, 0x3c030200, -0x431025, 0xaee20000, 0x8f820220, 0x2403fffb, -0x431024, 0xaf820220, 0x8f820220, 0x34420002, -0xaf820220, 0x24020008, 0x3c010001, 0x370821, -0xc0043dd, 0xac2283ac, 0x3c010001, 0x80047f8, -0xac205db0, 0x3c020001, 0x571021, 0x8c4283ac, -0x2443ffff, 0x2c620008, 0x104000ac, 0x31080, -0x3c010001, 0x220821, 0x8c225b38, 0x400008, -0x0, 0xc00429b, 0x0, 0x3c010001, -0xac205d2c, 0xaf800204, 0x3c010001, 0xc0047fc, -0xac207e80, 0x24020001, 0x3c010001, 0xac225d44, -0x24020002, 0x3c010001, 0x370821, 0x80047f8, -0xac2283ac, 0xc004879, 0x0, 0x3c030001, -0x8c635d44, 0x24020009, 0x14620090, 0x24020003, -0x3c010001, 0x370821, 0x80047f8, 0xac2283ac, -0x3c020001, 0x8c427e98, 0x30424000, 0x10400005, -0x0, 0x8f820044, 0x3c03ffff, 0x8004778, -0x34637fff, 0x8f820044, 0x2403ff7f, 0x431024, -0xaf820044, 0x8f830054, 0x8004792, 0x24020004, -0x8f830054, 0x3c020001, 0x8c425e00, 0x2463d8f0, -0x431023, 0x2c422710, 0x14400074, 0x24020005, -0x3c010001, 0x370821, 0x80047f8, 0xac2283ac, +0x800481f, 0xac235da4, 0x8f830054, 0x3c020001, +0x8c425da4, 0x2463fff6, 0x431023, 0x2c42000a, +0x14400059, 0x0, 0x24020007, 0x3c010001, +0x370821, 0x800481f, 0xac2283ac, 0x8f820220, +0x3c04f700, 0x441025, 0xaf820220, 0x8f820220, +0x3c030300, 0x431024, 0x14400005, 0x1821, +0x8f820220, 0x24030001, 0x441025, 0xaf820220, +0x10600043, 0x24020001, 0x8f820214, 0x3c03ffff, +0x3c040001, 0x8c845d98, 0x431024, 0x3442251f, +0xaf820214, 0x24020008, 0x3c010001, 0x370821, +0x1080000b, 0xac2283ac, 0x3c020001, 0x8c425d74, +0x14400007, 0x24020001, 0x3c010001, 0xac227dd0, +0xc004e54, 0x8f840220, 0x800480c, 0x0, +0x8f820220, 0x3c030008, 0x431024, 0x14400017, +0x2402000e, 0x3c010001, 0xac227dd0, 0x8ee20000, +0x2021, 0x3c030200, 0x431025, 0xc005386, +0xaee20000, 0x8f820220, 0x2403fffb, 0x431024, +0xaf820220, 0x8f820220, 0x34420002, 0xc0043dd, +0xaf820220, 0x3c050001, 0x8ca55cc8, 0xc0052a2, +0x2021, 0x800481f, 0x0, 0x3c020001, +0x8c425d74, 0x10400010, 0x0, 0x3c020001, +0x8c425d70, 0x2442ffff, 0x3c010001, 0xac225d70, +0x14400009, 0x24020002, 0x3c010001, 0xac205d74, +0x3c010001, 0x800481f, 0xac225d70, 0x24020001, +0x3c010001, 0xac225ccc, 0x8fbf0018, 0x3e00008, +0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, +0x34420004, 0xaf820220, 0x8f820200, 0x3c060001, +0x8cc65cc8, 0x34420004, 0xaf820200, 0x24020002, +0x10c2003a, 0x2cc20003, 0x10400005, 0x24020001, +0x10c20008, 0x0, 0x8004868, 0x0, +0x24020004, 0x10c20013, 0x24020001, 0x8004868, +0x0, 0x3c030001, 0x8c635cb8, 0x3c020001, +0x8c425cc0, 0x3c040001, 0x8c845cdc, 0x3c050001, +0x8ca55cbc, 0xaf860200, 0xaf860220, 0x34630022, +0x441025, 0x451025, 0x34420002, 0x8004867, +0xaf830200, 0x3c030001, 0x8c635d98, 0xaf820200, +0x10600009, 0xaf820220, 0x3c020001, 0x8c425d74, +0x14400005, 0x3c033f00, 0x3c020001, 0x8c425cb0, +0x800485b, 0x346300e0, 0x3c020001, 0x8c425cb0, +0x3c033f00, 0x346300e2, 0x431025, 0xaf820200, +0x3c030001, 0x8c635cb4, 0x3c04f700, 0x3c020001, +0x8c425cc0, 0x3c050001, 0x8ca55cdc, 0x641825, +0x431025, 0x451025, 0xaf820220, 0x3e00008, +0x0, 0x8f820220, 0x3c030001, 0x8c635cc8, +0x34420004, 0xaf820220, 0x24020001, 0x1062000f, +0x0, 0x8f830054, 0x8f820054, 0x24630002, +0x621023, 0x2c420003, 0x10400011, 0x0, +0x8f820054, 0x621023, 0x2c420003, 0x1040000c, +0x0, 0x8004879, 0x0, 0x8f830054, +0x8f820054, 0x8004885, 0x24630007, 0x8f820054, +0x621023, 0x2c420008, 0x1440fffc, 0x0, +0x8f8400e0, 0x30820007, 0x1040000d, 0x0, +0x8f820054, 0x8f8300e0, 0x14830009, 0x24450032, +0x8f820054, 0xa21023, 0x2c420033, 0x10400004, +0x0, 0x8f8200e0, 0x1082fff9, 0x0, +0x8f820220, 0x2403fffd, 0x431024, 0xaf820220, +0x3e00008, 0x0, 0x3c030001, 0x8c635ce4, +0x3c020001, 0x8c425ce8, 0x50620004, 0x2463ffff, +0x3c010001, 0xac235ce8, 0x2463ffff, 0x2c620009, +0x1040009d, 0x31080, 0x3c010001, 0x220821, +0x8c225b08, 0x400008, 0x0, 0x8f820044, +0x34428080, 0xaf820044, 0x8f830054, 0x8004938, +0x24020002, 0x8f830054, 0x3c020001, 0x8c425da8, +0x2463d8f0, 0x431023, 0x2c422710, 0x1440008a, +0x24020003, 0x8004945, 0x0, 0x8f820044, +0x3c03ffff, 0x34637fff, 0x431024, 0xaf820044, +0x8f830054, 0x8004938, 0x24020004, 0x8f830054, +0x3c020001, 0x8c425da8, 0x2463fff6, 0x431023, +0x2c42000a, 0x14400078, 0x24020005, 0x8004945, +0x0, 0x8f820220, 0x3c03f700, 0x431025, +0xaf820220, 0x8f820220, 0x2403fffb, 0x431024, +0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, +0x3c023f00, 0x344200e0, 0xaf820200, 0x8f820200, +0x2403fffd, 0x431024, 0xaf820200, 0x24040001, +0x3405ffff, 0xaf840204, 0x8f830054, 0x8f820054, +0x80048ec, 0x24630001, 0x8f820054, 0x621023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820224, +0x42040, 0xa4102b, 0x1040fff2, 0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, -0xaf800204, 0x3c010001, 0xac207e80, 0x8f830054, -0x24020006, 0x3c010001, 0x370821, 0xac2283ac, -0x3c010001, 0x80047f8, 0xac235e00, 0x8f830054, -0x3c020001, 0x8c425e00, 0x2463fff6, 0x431023, -0x2c42000a, 0x14400059, 0x0, 0x24020007, -0x3c010001, 0x370821, 0x80047f8, 0xac2283ac, -0x8f820220, 0x3c04f700, 0x441025, 0xaf820220, -0x8f820220, 0x3c030300, 0x431024, 0x14400005, -0x1821, 0x8f820220, 0x24030001, 0x441025, -0xaf820220, 0x10600043, 0x24020001, 0x8f820214, -0x3c03ffff, 0x3c040001, 0x8c845df8, 0x431024, -0x3442251f, 0xaf820214, 0x24020008, 0x3c010001, -0x370821, 0x1080000b, 0xac2283ac, 0x3c020001, -0x8c425dd4, 0x14400007, 0x24020001, 0x3c010001, -0xac227e30, 0xc004e2c, 0x8f840220, 0x80047e5, -0x0, 0x8f820220, 0x3c030008, 0x431024, -0x14400017, 0x2402000e, 0x3c010001, 0xac227e30, -0x8ee20000, 0x2021, 0x3c030200, 0x431025, -0xc005397, 0xaee20000, 0x8f820220, 0x2403fffb, -0x431024, 0xaf820220, 0x8f820220, 0x34420002, -0xc0043dd, 0xaf820220, 0x3c050001, 0x8ca55d28, -0xc005276, 0x2021, 0x80047f8, 0x0, -0x3c020001, 0x8c425dd4, 0x10400010, 0x0, -0x3c020001, 0x8c425dd0, 0x2442ffff, 0x3c010001, -0xac225dd0, 0x14400009, 0x24020002, 0x3c010001, -0xac205dd4, 0x3c010001, 0x80047f8, 0xac225dd0, -0x24020001, 0x3c010001, 0xac225d2c, 0x8fbf001c, -0x8fb00018, 0x3e00008, 0x27bd0020, 0x8f820200, -0x8f820220, 0x8f820220, 0x34420004, 0xaf820220, -0x8f820200, 0x3c060001, 0x8cc65d28, 0x34420004, -0xaf820200, 0x24020002, 0x10c2003a, 0x2cc20003, -0x10400005, 0x24020001, 0x10c20008, 0x0, -0x8004842, 0x0, 0x24020004, 0x10c20013, -0x24020001, 0x8004842, 0x0, 0x3c030001, -0x8c635d18, 0x3c020001, 0x8c425d20, 0x3c040001, -0x8c845d3c, 0x3c050001, 0x8ca55d1c, 0xaf860200, -0xaf860220, 0x34630022, 0x441025, 0x451025, -0x34420002, 0x8004841, 0xaf830200, 0x3c030001, -0x8c635df8, 0xaf820200, 0x10600009, 0xaf820220, -0x3c020001, 0x8c425dd4, 0x14400005, 0x3c033f00, -0x3c020001, 0x8c425d10, 0x8004835, 0x346300e0, -0x3c020001, 0x8c425d10, 0x3c033f00, 0x346300e2, -0x431025, 0xaf820200, 0x3c030001, 0x8c635d14, -0x3c04f700, 0x3c020001, 0x8c425d20, 0x3c050001, -0x8ca55d3c, 0x641825, 0x431025, 0x451025, -0xaf820220, 0x3e00008, 0x0, 0x8f820220, -0x3c030001, 0x8c635d28, 0x34420004, 0xaf820220, -0x24020001, 0x1062000f, 0x0, 0x8f830054, -0x8f820054, 0x24630002, 0x621023, 0x2c420003, -0x10400011, 0x0, 0x8f820054, 0x621023, -0x2c420003, 0x1040000c, 0x0, 0x8004853, -0x0, 0x8f830054, 0x8f820054, 0x800485f, -0x24630007, 0x8f820054, 0x621023, 0x2c420008, -0x1440fffc, 0x0, 0x8f8400e0, 0x30820007, -0x1040000d, 0x0, 0x8f820054, 0x8f8300e0, -0x14830009, 0x24450032, 0x8f820054, 0xa21023, -0x2c420033, 0x10400004, 0x0, 0x8f8200e0, -0x1082fff9, 0x0, 0x8f820220, 0x2403fffd, -0x431024, 0xaf820220, 0x3e00008, 0x0, -0x3c030001, 0x8c635d44, 0x3c020001, 0x8c425d48, -0x50620004, 0x2463ffff, 0x3c010001, 0xac235d48, -0x2463ffff, 0x2c620009, 0x1040009d, 0x31080, -0x3c010001, 0x220821, 0x8c225b58, 0x400008, -0x0, 0x8f820044, 0x34428080, 0xaf820044, -0x8f830054, 0x8004912, 0x24020002, 0x8f830054, -0x3c020001, 0x8c425e04, 0x2463d8f0, 0x431023, -0x2c422710, 0x1440008a, 0x24020003, 0x800491f, -0x0, 0x8f820044, 0x3c03ffff, 0x34637fff, -0x431024, 0xaf820044, 0x8f830054, 0x8004912, -0x24020004, 0x8f830054, 0x3c020001, 0x8c425e04, -0x2463fff6, 0x431023, 0x2c42000a, 0x14400078, -0x24020005, 0x800491f, 0x0, 0x8f820220, -0x3c03f700, 0x431025, 0xaf820220, 0x8f820220, -0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, -0x34420002, 0xaf820220, 0x3c023f00, 0x344200e0, -0xaf820200, 0x8f820200, 0x2403fffd, 0x431024, -0xaf820200, 0x24040001, 0x3405ffff, 0xaf840204, -0x8f830054, 0x8f820054, 0x80048c6, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820224, 0x42040, 0xa4102b, -0x1040fff2, 0x0, 0x8f820220, 0x3c03f700, -0x431025, 0xaf820220, 0x8f820214, 0x3c03ffff, -0x431024, 0x3442251f, 0xaf820214, 0x8f820220, -0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, -0x3c04f700, 0x34840008, 0x34420002, 0xaf820220, -0x8f820220, 0x3c033f00, 0x346300e2, 0x441025, -0xaf820220, 0xaf830200, 0x8f8400f0, 0x276217f8, -0x14820002, 0x24850008, 0x27651000, 0x8f8200f4, -0x10a20007, 0x3c038000, 0x34630040, 0x3c020001, -0x24425cd0, 0xac820000, 0xac830004, 0xaf8500f0, -0x8f830054, 0x8004912, 0x24020006, 0x8f830054, -0x3c020001, 0x8c425e04, 0x2463fff6, 0x431023, -0x2c42000a, 0x14400022, 0x24020007, 0x800491f, -0x0, 0x8f8200e0, 0xaf8200e4, 0x8f8200e0, -0xaf8200e8, 0x8f820220, 0x34420004, 0xaf820220, -0x8f820220, 0x2403fff7, 0x431024, 0xaf820220, -0x8f820044, 0x34428080, 0xaf820044, 0x8f830054, -0x24020008, 0x3c010001, 0xac225d44, 0x3c010001, -0x8004921, 0xac235e04, 0x8f830054, 0x3c020001, -0x8c425e04, 0x2463d8f0, 0x431023, 0x2c422710, -0x14400003, 0x24020009, 0x3c010001, 0xac225d44, -0x3e00008, 0x0, 0x0, 0x27bdffd8, +0x8f820214, 0x3c03ffff, 0x431024, 0x3442251f, +0xaf820214, 0x8f820220, 0x2403fffb, 0x431024, +0xaf820220, 0x8f820220, 0x3c04f700, 0x34840008, +0x34420002, 0xaf820220, 0x8f820220, 0x3c033f00, +0x346300e2, 0x441025, 0xaf820220, 0xaf830200, +0x8f8400f0, 0x276217f8, 0x14820002, 0x24850008, +0x27651000, 0x8f8200f4, 0x10a20007, 0x3c038000, +0x34630040, 0x3c020001, 0x24425c70, 0xac820000, +0xac830004, 0xaf8500f0, 0x8f830054, 0x8004938, +0x24020006, 0x8f830054, 0x3c020001, 0x8c425da8, +0x2463fff6, 0x431023, 0x2c42000a, 0x14400022, +0x24020007, 0x8004945, 0x0, 0x8f8200e0, +0xaf8200e4, 0x8f8200e0, 0xaf8200e8, 0x8f820220, +0x34420004, 0xaf820220, 0x8f820220, 0x2403fff7, +0x431024, 0xaf820220, 0x8f820044, 0x34428080, +0xaf820044, 0x8f830054, 0x24020008, 0x3c010001, +0xac225ce4, 0x3c010001, 0x8004947, 0xac235da8, +0x8f830054, 0x3c020001, 0x8c425da8, 0x2463d8f0, +0x431023, 0x2c422710, 0x14400003, 0x24020009, +0x3c010001, 0xac225ce4, 0x3e00008, 0x0, +0x0, 0x0, 0x0, 0x27bdffd8, 0xafb20018, 0x809021, 0xafb3001c, 0xa09821, 0xafb10014, 0xc08821, 0xafb00010, 0x8021, -0xafbf0020, 0xa6200000, 0xc004d23, 0x24040001, +0xafbf0020, 0xa6200000, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004d23, 0x2021, 0xc004d23, 0x24040001, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x24100010, 0x2501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fffa, +0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x2501024, 0x24100010, 0x2701024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fffa, 0x2701024, 0xc004d49, 0x34108000, -0xc004d49, 0x0, 0xc004d03, 0x0, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fffa, 0x2701024, 0xc004d71, 0x34108000, +0xc004d71, 0x0, 0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004d49, 0x0, 0x8fbf0020, 0x8fb3001c, +0xc004d71, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, -0xafb00010, 0x8021, 0xafbf0020, 0xc004d23, +0xafb00010, 0x8021, 0xafbf0020, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x2301024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x2301024, 0x24100010, 0x2501024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x2501024, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x2501024, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96620000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fff8, -0x0, 0xc004d49, 0x0, 0x8fbf0020, +0x24040001, 0xc004d4b, 0x108042, 0x1600fff8, +0x0, 0xc004d71, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, -0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635d60, -0x3c020001, 0x8c425da8, 0x27bdffd8, 0xafbf0020, +0x3e00008, 0x27bd0028, 0x3c030001, 0x8c635d00, +0x3c020001, 0x8c425d48, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0x10620003, 0xafb00018, 0x3c010001, -0xac235da8, 0x2463ffff, 0x2c620013, 0x10400349, -0x31080, 0x3c010001, 0x220821, 0x8c225b80, -0x400008, 0x0, 0xc004d49, 0x8021, -0x34028000, 0xa7a20010, 0x27b10010, 0xc004d23, +0xac235d48, 0x2463ffff, 0x2c620013, 0x10400349, +0x31080, 0x3c010001, 0x220821, 0x8c225b30, +0x400008, 0x0, 0xc004d71, 0x8021, +0x34028000, 0xa7a20010, 0x27b10010, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0xc004d23, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0xc004d4b, 0x2021, 0x108042, 0x1600fffc, 0x0, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8004cfc, 0x24020002, 0x27b10010, 0xa7a00010, -0x8021, 0xc004d23, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004d23, -0x2021, 0xc004d23, 0x24040001, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x24100010, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8004d24, 0x24020002, 0x27b10010, 0xa7a00010, +0x8021, 0xc004d4b, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d4b, +0x2021, 0xc004d4b, 0x24040001, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0xc004d23, 0x2021, 0x108042, -0x1600fffc, 0x0, 0xc004d49, 0x34108000, -0xc004d49, 0x0, 0xc004d03, 0x0, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0xc004d4b, 0x2021, 0x108042, +0x1600fffc, 0x0, 0xc004d71, 0x34108000, +0xc004d71, 0x0, 0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004d49, 0x0, 0x97a20010, 0x30428000, -0x144002dc, 0x24020003, 0x8004cfc, 0x0, +0xc004d71, 0x0, 0x97a20010, 0x30428000, +0x144002dc, 0x24020003, 0x8004d24, 0x0, 0x24021200, 0xa7a20010, 0x27b10010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, -0xc004d23, 0x2021, 0x108042, 0x1600fffc, -0x0, 0xc004d23, 0x24040001, 0xc004d23, +0xc004d4b, 0x2021, 0x108042, 0x1600fffc, +0x0, 0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fff8, 0x0, 0xc004d49, -0x0, 0x8f830054, 0x8004cee, 0x24020004, -0x8f830054, 0x3c020001, 0x8c425e14, 0x2463ff9c, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fff8, 0x0, 0xc004d71, +0x0, 0x8f830054, 0x8004d16, 0x24020004, +0x8f830054, 0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, 0x24020002, -0x3c030001, 0x8c635e18, 0x10620297, 0x2c620003, +0x3c030001, 0x8c635dbc, 0x10620297, 0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, -0x24020004, 0x10620291, 0x2402000f, 0x8004cfc, -0x24020011, 0x8004cfc, 0x24020005, 0x24020014, -0xa7a20010, 0x27b10010, 0x8021, 0xc004d23, +0x24020004, 0x10620291, 0x2402000f, 0x8004d24, +0x24020011, 0x8004d24, 0x24020005, 0x24020014, +0xa7a20010, 0x27b10010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020012, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x32020012, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x32020012, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fff8, -0x0, 0xc004d49, 0x0, 0x8f830054, -0x8004cee, 0x24020006, 0x8f830054, 0x3c020001, -0x8c425e14, 0x2463ff9c, 0x431023, 0x2c420064, -0x14400250, 0x24020007, 0x8004cfc, 0x0, +0x24040001, 0xc004d4b, 0x108042, 0x1600fff8, +0x0, 0xc004d71, 0x0, 0x8f830054, +0x8004d16, 0x24020006, 0x8f830054, 0x3c020001, +0x8c425db8, 0x2463ff9c, 0x431023, 0x2c420064, +0x14400250, 0x24020007, 0x8004d24, 0x0, 0x24020006, 0xa7a20010, 0x27b10010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020013, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020013, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x24020008, 0x8f830054, -0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023, -0x2c420064, 0x1440020f, 0x24020009, 0x8004cfc, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x24020008, 0x8f830054, +0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, +0x2c420064, 0x1440020f, 0x24020009, 0x8004d24, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x24040001, -0xc004d23, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001, +0xc004d4b, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020018, -0xc004d49, 0x34108000, 0xc004d49, 0x0, -0xc004d03, 0x0, 0x50400005, 0x108042, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020018, +0xc004d71, 0x34108000, 0xc004d71, 0x0, +0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004d49, 0x8021, +0x1600fff7, 0x0, 0xc004d71, 0x8021, 0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020018, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020018, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x2402000a, 0x8f830054, -0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023, -0x2c420064, 0x1440019b, 0x2402000b, 0x8004cfc, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x2402000a, 0x8f830054, +0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, +0x2c420064, 0x1440019b, 0x2402000b, 0x8004d24, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x24040001, -0xc004d23, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001, +0xc004d4b, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020017, -0xc004d49, 0x34108000, 0xc004d49, 0x0, -0xc004d03, 0x0, 0x50400005, 0x108042, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020017, +0xc004d71, 0x34108000, 0xc004d71, 0x0, +0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004d49, 0x8021, +0x1600fff7, 0x0, 0xc004d71, 0x8021, 0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020017, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020017, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x2402000c, 0x8f830054, -0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023, -0x2c420064, 0x14400127, 0x24020012, 0x8004cfc, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x2402000c, 0x8f830054, +0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, +0x2c420064, 0x14400127, 0x24020012, 0x8004d24, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x24040001, -0xc004d23, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001, +0xc004d4b, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020014, -0xc004d49, 0x34108000, 0xc004d49, 0x0, -0xc004d03, 0x0, 0x50400005, 0x108042, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020014, +0xc004d71, 0x34108000, 0xc004d71, 0x0, +0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004d49, 0x8021, +0x1600fff7, 0x0, 0xc004d71, 0x8021, 0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020014, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020014, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x24020013, 0x8f830054, -0x3c020001, 0x8c425e14, 0x2463ff9c, 0x431023, -0x2c420064, 0x144000b3, 0x2402000d, 0x8004cfc, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x24020013, 0x8f830054, +0x3c020001, 0x8c425db8, 0x2463ff9c, 0x431023, +0x2c420064, 0x144000b3, 0x2402000d, 0x8004d24, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x24040001, -0xc004d23, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x24040001, +0xc004d4b, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020018, -0xc004d49, 0x34108000, 0xc004d49, 0x0, -0xc004d03, 0x0, 0x50400005, 0x108042, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020018, +0xc004d71, 0x34108000, 0xc004d71, 0x0, +0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004d49, 0x8021, +0x1600fff7, 0x0, 0xc004d71, 0x8021, 0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, -0xc004d23, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, -0xc004d23, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004d23, +0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, +0xc004d4b, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004d23, 0x108042, 0x1600fffa, 0x32020018, -0xc004d23, 0x24040001, 0xc004d23, 0x2021, +0xc004d4b, 0x108042, 0x1600fffa, 0x32020018, +0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, -0x1600fff8, 0x0, 0xc004d49, 0x0, -0x8f830054, 0x8004cee, 0x2402000e, 0x24020840, -0xa7a20010, 0x27b10010, 0x8021, 0xc004d23, +0x2021, 0x24040001, 0xc004d4b, 0x108042, +0x1600fff8, 0x0, 0xc004d71, 0x0, +0x8f830054, 0x8004d16, 0x2402000e, 0x24020840, +0xa7a20010, 0x27b10010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x32020013, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x32020013, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fff8, -0x0, 0xc004d49, 0x0, 0x8f830054, -0x24020010, 0x3c010001, 0xac225d60, 0x3c010001, -0x8004cfe, 0xac235e14, 0x8f830054, 0x3c020001, -0x8c425e14, 0x2463ff9c, 0x431023, 0x2c420064, +0x24040001, 0xc004d4b, 0x108042, 0x1600fff8, +0x0, 0xc004d71, 0x0, 0x8f830054, +0x24020010, 0x3c010001, 0xac225d00, 0x3c010001, +0x8004d26, 0xac235db8, 0x8f830054, 0x3c020001, +0x8c425db8, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, -0xac225d60, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, +0xac225d00, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, 0x8f820044, 0x3c030001, 0x431025, 0x3c030008, 0xaf820044, -0x8f840054, 0x8f820054, 0xa32824, 0x8004d0f, +0x8f840054, 0x8f820054, 0xa32824, 0x8004d37, 0x24840001, 0x8f820054, 0x821023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, -0x8f820054, 0x8004d1d, 0x24630001, 0x8f820054, +0x8f820054, 0x8004d45, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, 0x3c020002, 0x822025, 0x641825, 0xaf830044, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, -0x8f830054, 0x8f820054, 0x8004d36, 0x24630001, +0x8f830054, 0x8f820054, 0x8004d5e, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c030001, 0x431025, -0xaf820044, 0x8f830054, 0x8f820054, 0x8004d43, +0xaf820044, 0x8f830054, 0x8f820054, 0x8004d6b, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, 0x8f820044, 0x3c030001, 0x431025, -0xaf820044, 0x8f830054, 0x8f820054, 0x8004d57, +0xaf820044, 0x8f830054, 0x8f820054, 0x8004d7f, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, -0x8f820054, 0x8004d65, 0x24630001, 0x8f820054, +0x8f820054, 0x8004d8d, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, 0x0, 0x27bdffc8, 0xafb30024, 0x809821, 0xafb5002c, 0xa0a821, 0xafb20020, 0xc09021, 0x32a2ffff, 0xafbf0030, 0xafb40028, 0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010, -0x3271ffff, 0x27b20010, 0x8021, 0xc004d23, +0x3271ffff, 0x27b20010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x2301024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x2301024, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x2301024, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96420000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x12000075, -0x0, 0x8004da1, 0x0, 0x3274ffff, -0x27b10010, 0xa7a00010, 0x8021, 0xc004d23, +0x24040001, 0xc004d4b, 0x108042, 0x12000075, +0x0, 0x8004dc9, 0x0, 0x3274ffff, +0x27b10010, 0xa7a00010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x24040001, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x24040001, 0xc004d4b, 0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x2901024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x2901024, 0xc004d49, -0x34108000, 0xc004d49, 0x0, 0xc004d03, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x2901024, 0xc004d71, +0x34108000, 0xc004d71, 0x0, 0xc004d2b, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004d49, 0x0, 0x32a5ffff, +0x0, 0xc004d71, 0x0, 0x32a5ffff, 0x24020001, 0x54a20004, 0x24020002, 0x97a20010, -0x8004dec, 0x521025, 0x14a20006, 0x3271ffff, +0x8004e14, 0x521025, 0x14a20006, 0x3271ffff, 0x97a20010, 0x121827, 0x431024, 0xa7a20010, -0x3271ffff, 0x27b20010, 0x8021, 0xc004d23, +0x3271ffff, 0x27b20010, 0x8021, 0xc004d4b, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004d23, 0x2021, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0xc004d23, +0x0, 0xc004d4b, 0x2021, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0xc004d4b, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004d23, 0x108042, +0x2021, 0x24040001, 0xc004d4b, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x2301024, -0x10400002, 0x2021, 0x24040001, 0xc004d23, -0x108042, 0x1600fffa, 0x2301024, 0xc004d23, -0x24040001, 0xc004d23, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d4b, +0x108042, 0x1600fffa, 0x2301024, 0xc004d4b, +0x24040001, 0xc004d4b, 0x2021, 0x34108000, 0x96420000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004d23, 0x108042, 0x1600fff8, -0x0, 0xc004d49, 0x0, 0x8fbf0030, +0x24040001, 0xc004d4b, 0x108042, 0x1600fff8, +0x0, 0xc004d71, 0x0, 0x8fbf0030, 0x8fb5002c, 0x8fb40028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038, 0x0, 0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x3c030001, 0x771821, 0x8c6383ac, 0x24020008, 0x1462022c, 0x803021, 0x3c020001, -0x8c425df8, 0x14400033, 0x0, 0x8f850224, +0x8c425d98, 0x14400033, 0x0, 0x8f850224, 0x38a30020, 0x2c630001, 0x38a20010, 0x2c420001, 0x621825, 0x1460000d, 0x38a30030, 0x2c630001, 0x38a20400, 0x2c420001, 0x621825, 0x14600007, 0x38a30402, 0x2c630001, 0x38a20404, 0x2c420001, 0x621825, 0x10600005, 0x0, 0xc00429b, -0x0, 0x8004e65, 0x2402000e, 0xc0043dd, -0x0, 0x3c050001, 0x8ca55d28, 0xc005276, -0x2021, 0x3c030001, 0x8c635d28, 0x24020004, -0x14620005, 0x2403fffb, 0x3c020001, 0x8c425d24, -0x8004e61, 0x2403fff7, 0x3c020001, 0x8c425d24, -0x431024, 0x3c010001, 0xac225d24, 0x2402000e, -0x3c010001, 0xc00429b, 0xac227e30, 0x800505f, +0x0, 0x8004e8d, 0x2402000e, 0xc0043dd, +0x0, 0x3c050001, 0x8ca55cc8, 0xc0052a2, +0x2021, 0x3c030001, 0x8c635cc8, 0x24020004, +0x14620005, 0x2403fffb, 0x3c020001, 0x8c425cc4, +0x8004e89, 0x2403fff7, 0x3c020001, 0x8c425cc4, +0x431024, 0x3c010001, 0xac225cc4, 0x2402000e, +0x3c010001, 0xc00429b, 0xac227dd0, 0x8005087, 0x0, 0x8f820220, 0x3c030400, 0x431024, 0x10400027, 0x2403ffbf, 0x8f850224, 0x3c020001, -0x8c427e3c, 0xa32024, 0x431024, 0x1482000c, -0x0, 0x3c020001, 0x8c427e40, 0x24420001, -0x3c010001, 0xac227e40, 0x2c420002, 0x14400008, -0x24020001, 0x3c010001, 0x8004e85, 0xac227e60, -0x3c010001, 0xac207e40, 0x3c010001, 0xac207e60, -0x3c020001, 0x8c427e60, 0x10400006, 0x30a20040, -0x10400004, 0x24020001, 0x3c010001, 0x8004e90, -0xac227e64, 0x3c010001, 0xac207e64, 0x3c010001, -0xac257e3c, 0x3c010001, 0x8004ea0, 0xac207e70, -0x24020001, 0x3c010001, 0xac227e70, 0x3c010001, -0xac207e60, 0x3c010001, 0xac207e40, 0x3c010001, -0xac207e64, 0x3c010001, 0xac207e3c, 0x3c030001, -0x8c637e30, 0x3c020001, 0x8c427e34, 0x10620003, -0x3c020200, 0x3c010001, 0xac237e34, 0xc21024, +0x8c427ddc, 0xa32024, 0x431024, 0x1482000c, +0x0, 0x3c020001, 0x8c427de0, 0x24420001, +0x3c010001, 0xac227de0, 0x2c420002, 0x14400008, +0x24020001, 0x3c010001, 0x8004ead, 0xac227e00, +0x3c010001, 0xac207de0, 0x3c010001, 0xac207e00, +0x3c020001, 0x8c427e00, 0x10400006, 0x30a20040, +0x10400004, 0x24020001, 0x3c010001, 0x8004eb8, +0xac227e04, 0x3c010001, 0xac207e04, 0x3c010001, +0xac257ddc, 0x3c010001, 0x8004ec8, 0xac207e10, +0x24020001, 0x3c010001, 0xac227e10, 0x3c010001, +0xac207e00, 0x3c010001, 0xac207de0, 0x3c010001, +0xac207e04, 0x3c010001, 0xac207ddc, 0x3c030001, +0x8c637dd0, 0x3c020001, 0x8c427dd4, 0x10620003, +0x3c020200, 0x3c010001, 0xac237dd4, 0xc21024, 0x10400007, 0x2463ffff, 0x8f820220, 0x24030001, -0x3c010001, 0xac235d2c, 0x800505d, 0x3c03f700, +0x3c010001, 0xac235ccc, 0x8005085, 0x3c03f700, 0x2c62000e, 0x104001a8, 0x31080, 0x3c010001, -0x220821, 0x8c225bd0, 0x400008, 0x0, -0x3c010001, 0xac207e60, 0x3c010001, 0xac207e40, -0x3c010001, 0xac207e3c, 0x3c010001, 0xac207e64, -0x3c010001, 0xac207e58, 0x3c010001, 0xac207e50, -0xc004844, 0xaf800224, 0x24020002, 0x3c010001, -0xac227e30, 0x3c020001, 0x8c427e70, 0x14400056, +0x220821, 0x8c225b80, 0x400008, 0x0, +0x3c010001, 0xac207e00, 0x3c010001, 0xac207de0, +0x3c010001, 0xac207ddc, 0x3c010001, 0xac207e04, +0x3c010001, 0xac207df8, 0x3c010001, 0xac207df0, +0xc00486a, 0xaf800224, 0x24020002, 0x3c010001, +0xac227dd0, 0x3c020001, 0x8c427e10, 0x14400056, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024, 0xc00429b, 0xaee20000, 0xaf800204, 0x8f820200, 0x2403fffd, 0x431024, 0xaf820200, 0x3c010001, -0xac207e80, 0x8f830054, 0x3c020001, 0x8c427e58, -0x24040001, 0x3c010001, 0xac247e6c, 0x24420001, -0x3c010001, 0xac227e58, 0x2c420004, 0x3c010001, -0xac237e54, 0x14400006, 0x24020003, 0x3c010001, -0xac245d2c, 0x3c010001, 0x800505b, 0xac207e58, -0x3c010001, 0x800505b, 0xac227e30, 0x8f830054, -0x3c020001, 0x8c427e54, 0x2463d8f0, 0x431023, +0xac207e20, 0x8f830054, 0x3c020001, 0x8c427df8, +0x24040001, 0x3c010001, 0xac247e0c, 0x24420001, +0x3c010001, 0xac227df8, 0x2c420004, 0x3c010001, +0xac237df4, 0x14400006, 0x24020003, 0x3c010001, +0xac245ccc, 0x3c010001, 0x8005083, 0xac207df8, +0x3c010001, 0x8005083, 0xac227dd0, 0x8f830054, +0x3c020001, 0x8c427df4, 0x2463d8f0, 0x431023, 0x2c422710, 0x14400003, 0x24020004, 0x3c010001, -0xac227e30, 0x3c020001, 0x8c427e70, 0x14400026, +0xac227dd0, 0x3c020001, 0x8c427e10, 0x14400026, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024, -0x800505b, 0xaee20000, 0x3c040001, 0x8c845dfc, -0x3c010001, 0xc005062, 0xac207e48, 0x3c020001, -0x8c427e7c, 0xaf820204, 0x3c020001, 0x8c427e70, +0x8005083, 0xaee20000, 0x3c040001, 0x8c845d9c, +0x3c010001, 0xc00508a, 0xac207de8, 0x3c020001, +0x8c427e1c, 0xaf820204, 0x3c020001, 0x8c427e10, 0x14400015, 0x3c03fdff, 0x8ee20000, 0x3463ffff, 0x431024, 0xaee20000, 0x8f820204, 0x30420030, -0x1440013c, 0x24020002, 0x3c030001, 0x8c637e7c, -0x24020005, 0x3c010001, 0xac227e30, 0x3c010001, -0x800505b, 0xac237e80, 0x3c020001, 0x8c427e70, -0x10400010, 0x3c03fdff, 0x3c020001, 0x8c425dcc, -0x24420001, 0x3c010001, 0xac225dcc, 0x2c420002, -0x14400131, 0x24020001, 0x3c010001, 0xac225dd4, -0x3c010001, 0xac205dcc, 0x3c010001, 0x800505b, -0xac225d2c, 0x8ee20000, 0x3463ffff, 0x431024, -0xaee20000, 0x3c020001, 0x8c427e60, 0x10400122, -0x0, 0x3c020001, 0x8c427e3c, 0x1040011e, -0x0, 0x3c010001, 0xac227e68, 0x24020003, -0x3c010001, 0xac227e40, 0x8004ffc, 0x24020006, -0x3c010001, 0xac207e48, 0x8f820204, 0x34420040, -0xaf820204, 0x3c020001, 0x8c427e80, 0x24030007, -0x3c010001, 0xac237e30, 0x34420040, 0x3c010001, -0xac227e80, 0x3c020001, 0x8c427e60, 0x10400005, -0x0, 0x3c020001, 0x8c427e3c, 0x104000f9, -0x24020002, 0x3c050001, 0x24a57e40, 0x8ca20000, +0x1440013c, 0x24020002, 0x3c030001, 0x8c637e1c, +0x24020005, 0x3c010001, 0xac227dd0, 0x3c010001, +0x8005083, 0xac237e20, 0x3c020001, 0x8c427e10, +0x10400010, 0x3c03fdff, 0x3c020001, 0x8c425d6c, +0x24420001, 0x3c010001, 0xac225d6c, 0x2c420002, +0x14400131, 0x24020001, 0x3c010001, 0xac225d74, +0x3c010001, 0xac205d6c, 0x3c010001, 0x8005083, +0xac225ccc, 0x8ee20000, 0x3463ffff, 0x431024, +0xaee20000, 0x3c020001, 0x8c427e00, 0x10400122, +0x0, 0x3c020001, 0x8c427ddc, 0x1040011e, +0x0, 0x3c010001, 0xac227e08, 0x24020003, +0x3c010001, 0xac227de0, 0x8005024, 0x24020006, +0x3c010001, 0xac207de8, 0x8f820204, 0x34420040, +0xaf820204, 0x3c020001, 0x8c427e20, 0x24030007, +0x3c010001, 0xac237dd0, 0x34420040, 0x3c010001, +0xac227e20, 0x3c020001, 0x8c427e00, 0x10400005, +0x0, 0x3c020001, 0x8c427ddc, 0x104000f9, +0x24020002, 0x3c050001, 0x24a57de0, 0x8ca20000, 0x2c424e21, 0x104000f3, 0x24020002, 0x3c020001, -0x8c427e64, 0x104000f8, 0x2404ffbf, 0x3c020001, -0x8c427e3c, 0x3c030001, 0x8c637e68, 0x441024, +0x8c427e04, 0x104000f8, 0x2404ffbf, 0x3c020001, +0x8c427ddc, 0x3c030001, 0x8c637e08, 0x441024, 0x641824, 0x10430004, 0x24020001, 0x3c010001, -0x800505b, 0xac227e30, 0x24020003, 0xaca20000, -0x24020008, 0x3c010001, 0xac227e30, 0x3c020001, -0x8c427e6c, 0x1040000c, 0x24020001, 0x3c040001, -0xc00506f, 0x8c847e3c, 0x3c020001, 0x8c427e88, -0x14400005, 0x24020001, 0x3c020001, 0x8c427e84, -0x10400006, 0x24020001, 0x3c010001, 0xac225d2c, -0x3c010001, 0x800505b, 0xac207e58, 0x3c020001, -0x8c427e50, 0x3c030001, 0x8c637e3c, 0x2c420001, -0x210c0, 0x30630008, 0x3c010001, 0xac227e50, -0x3c010001, 0xac237e4c, 0x8f830054, 0x24020009, -0x3c010001, 0xac227e30, 0x3c010001, 0x800505b, -0xac237e54, 0x8f830054, 0x3c020001, 0x8c427e54, +0x8005083, 0xac227dd0, 0x24020003, 0xaca20000, +0x24020008, 0x3c010001, 0xac227dd0, 0x3c020001, +0x8c427e0c, 0x1040000c, 0x24020001, 0x3c040001, +0xc005097, 0x8c847ddc, 0x3c020001, 0x8c427e28, +0x14400005, 0x24020001, 0x3c020001, 0x8c427e24, +0x10400006, 0x24020001, 0x3c010001, 0xac225ccc, +0x3c010001, 0x8005083, 0xac207df8, 0x3c020001, +0x8c427df0, 0x3c030001, 0x8c637ddc, 0x2c420001, +0x210c0, 0x30630008, 0x3c010001, 0xac227df0, +0x3c010001, 0xac237dec, 0x8f830054, 0x24020009, +0x3c010001, 0xac227dd0, 0x3c010001, 0x8005083, +0xac237df4, 0x8f830054, 0x3c020001, 0x8c427df4, 0x2463d8f0, 0x431023, 0x2c422710, 0x144000a8, -0x0, 0x3c020001, 0x8c427e60, 0x10400005, -0x0, 0x3c020001, 0x8c427e3c, 0x104000a9, -0x24020002, 0x3c030001, 0x24637e40, 0x8c620000, +0x0, 0x3c020001, 0x8c427e00, 0x10400005, +0x0, 0x3c020001, 0x8c427ddc, 0x104000a9, +0x24020002, 0x3c030001, 0x24637de0, 0x8c620000, 0x2c424e21, 0x104000a3, 0x24020002, 0x3c020001, -0x8c427e6c, 0x1040000e, 0x0, 0x3c020001, -0x8c427e3c, 0x3c010001, 0xac207e6c, 0x30420080, +0x8c427e0c, 0x1040000e, 0x0, 0x3c020001, +0x8c427ddc, 0x3c010001, 0xac207e0c, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, -0x1440000c, 0x24020003, 0x8004fe9, 0x2402000c, -0x3c020001, 0x8c427e3c, 0x30420080, 0x14400005, +0x1440000c, 0x24020003, 0x8005011, 0x2402000c, +0x3c020001, 0x8c427ddc, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, 0x24020003, 0xac620000, 0x2402000a, 0x3c010001, -0xac227e30, 0x3c040001, 0x24847e78, 0x8c820000, -0x3c030001, 0x8c637e50, 0x431025, 0xaf820204, -0x8c830000, 0x3c040001, 0x8c847e50, 0x2402000b, -0x3c010001, 0xac227e30, 0x641825, 0x3c010001, -0xac237e80, 0x3c050001, 0x24a57e40, 0x8ca20000, +0xac227dd0, 0x3c040001, 0x24847e18, 0x8c820000, +0x3c030001, 0x8c637df0, 0x431025, 0xaf820204, +0x8c830000, 0x3c040001, 0x8c847df0, 0x2402000b, +0x3c010001, 0xac227dd0, 0x641825, 0x3c010001, +0xac237e20, 0x3c050001, 0x24a57de0, 0x8ca20000, 0x2c424e21, 0x1040006f, 0x24020002, 0x3c020001, -0x8c427e70, 0x10400005, 0x0, 0x2402000c, -0x3c010001, 0x800505b, 0xac227e30, 0x3c020001, -0x8c427e60, 0x1040006c, 0x0, 0x3c040001, -0x8c847e3c, 0x1080005e, 0x30820008, 0x3c030001, -0x8c637e4c, 0x10620064, 0x24020003, 0x3c010001, -0xac247e68, 0xaca20000, 0x24020006, 0x3c010001, -0x800505b, 0xac227e30, 0x8f820200, 0x34420002, +0x8c427e10, 0x10400005, 0x0, 0x2402000c, +0x3c010001, 0x8005083, 0xac227dd0, 0x3c020001, +0x8c427e00, 0x1040006c, 0x0, 0x3c040001, +0x8c847ddc, 0x1080005e, 0x30820008, 0x3c030001, +0x8c637dec, 0x10620064, 0x24020003, 0x3c010001, +0xac247e08, 0xaca20000, 0x24020006, 0x3c010001, +0x8005083, 0xac227dd0, 0x8f820200, 0x34420002, 0xaf820200, 0x8f830054, 0x2402000d, 0x3c010001, -0xac227e30, 0x3c010001, 0xac237e54, 0x8f830054, -0x3c020001, 0x8c427e54, 0x2463d8f0, 0x431023, +0xac227dd0, 0x3c010001, 0xac237df4, 0x8f830054, +0x3c020001, 0x8c427df4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440003a, 0x0, 0x3c020001, -0x8c427e70, 0x10400029, 0x2402000e, 0x3c030001, -0x8c637e84, 0x3c010001, 0x14600015, 0xac227e30, -0xc0043dd, 0x0, 0x3c050001, 0x8ca55d28, -0xc005276, 0x2021, 0x3c030001, 0x8c635d28, +0x8c427e10, 0x10400029, 0x2402000e, 0x3c030001, +0x8c637e24, 0x3c010001, 0x14600015, 0xac227dd0, +0xc0043dd, 0x0, 0x3c050001, 0x8ca55cc8, +0xc0052a2, 0x2021, 0x3c030001, 0x8c635cc8, 0x24020004, 0x14620005, 0x2403fffb, 0x3c020001, -0x8c425d24, 0x800502a, 0x2403fff7, 0x3c020001, -0x8c425d24, 0x431024, 0x3c010001, 0xac225d24, +0x8c425cc4, 0x8005052, 0x2403fff7, 0x3c020001, +0x8c425cc4, 0x431024, 0x3c010001, 0xac225cc4, 0x8ee20000, 0x3c030200, 0x431025, 0xaee20000, -0x8f820224, 0x3c010001, 0xac227e8c, 0x8f820220, +0x8f820224, 0x3c010001, 0xac227e2c, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, -0x34420002, 0x800505b, 0xaf820220, 0x3c020001, -0x8c427e60, 0x10400005, 0x0, 0x3c020001, -0x8c427e3c, 0x1040000f, 0x24020002, 0x3c020001, -0x8c427e40, 0x2c424e21, 0x1040000a, 0x24020002, -0x3c020001, 0x8c427e60, 0x1040000f, 0x0, -0x3c020001, 0x8c427e3c, 0x1440000b, 0x0, -0x24020002, 0x3c010001, 0x800505b, 0xac227e30, -0x3c020001, 0x8c427e60, 0x10400003, 0x0, +0x34420002, 0x8005083, 0xaf820220, 0x3c020001, +0x8c427e00, 0x10400005, 0x0, 0x3c020001, +0x8c427ddc, 0x1040000f, 0x24020002, 0x3c020001, +0x8c427de0, 0x2c424e21, 0x1040000a, 0x24020002, +0x3c020001, 0x8c427e00, 0x1040000f, 0x0, +0x3c020001, 0x8c427ddc, 0x1440000b, 0x0, +0x24020002, 0x3c010001, 0x8005083, 0xac227dd0, +0x3c020001, 0x8c427e00, 0x10400003, 0x0, 0xc00429b, 0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, -0x27bd0018, 0x3c030001, 0x24637e88, 0x8c620000, -0x10400005, 0x34422000, 0x3c010001, 0xac227e7c, -0x800506d, 0xac600000, 0x3c010001, 0xac247e7c, +0x27bd0018, 0x3c030001, 0x24637e28, 0x8c620000, +0x10400005, 0x34422000, 0x3c010001, 0xac227e1c, +0x8005095, 0xac600000, 0x3c010001, 0xac247e1c, 0x3e00008, 0x0, 0x27bdffe0, 0x30820030, -0xafbf0018, 0x3c010001, 0xac227e84, 0x14400067, +0xafbf0018, 0x3c010001, 0xac227e24, 0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030, 0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, 0x21200, 0x3c040001, -0x8c845dfc, 0x621825, 0x331c2, 0x3c030001, -0x24635dd8, 0x30828000, 0x21202, 0x30840001, +0x8c845d9c, 0x621825, 0x331c2, 0x3c030001, +0x24635d78, 0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2, 0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025, 0x0, 0x10600007, 0x24020002, 0x10620013, 0x24020003, 0x1062002c, 0x3c05000f, -0x80050d1, 0x0, 0x8f820200, 0x2403feff, +0x80050f9, 0x0, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x3c010001, -0xac207ea4, 0x3c010001, 0x80050dc, 0xac207eac, +0xac207e44, 0x3c010001, 0x8005104, 0xac207e4c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, -0x24020100, 0x3c010001, 0xac227ea4, 0x3c010001, -0x80050dc, 0xac207eac, 0x8f820200, 0x2403feff, +0x24020100, 0x3c010001, 0xac227e44, 0x3c010001, +0x8005104, 0xac207e4c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c030001, -0x431025, 0xaf820220, 0x3c010001, 0xac207ea4, -0x3c010001, 0x80050dc, 0xac237eac, 0x8f820200, +0x431025, 0xaf820220, 0x3c010001, 0xac207e44, +0x3c010001, 0x8005104, 0xac237e4c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, 0x24020100, 0x3c010001, -0xac227ea4, 0x3c010001, 0x80050dc, 0xac237eac, -0x34a5ffff, 0x3c040001, 0x24845c08, 0xafa30010, -0xc002403, 0xafa00014, 0x80050dc, 0x0, -0x24020030, 0x3c010001, 0xac227e88, 0x8fbf0018, +0xac227e44, 0x3c010001, 0x8005104, 0xac237e4c, +0x34a5ffff, 0x3c040001, 0x24845bb8, 0xafa30010, +0xc002403, 0xafa00014, 0x8005104, 0x0, +0x24020030, 0x3c010001, 0xac227e28, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x27bdffc8, 0xafb20028, 0x809021, 0xafb3002c, 0xa09821, -0xafb00020, 0xc08021, 0x3c040001, 0x24845c20, -0x3c050009, 0x3c020001, 0x8c425d28, 0x34a59001, +0xafb00020, 0xc08021, 0x3c040001, 0x24845bd0, +0x3c050009, 0x3c020001, 0x8c425cc8, 0x34a59001, 0x2403021, 0x2603821, 0xafbf0030, 0xafb10024, 0xa7a0001a, 0xafb00014, 0xc002403, 0xafa20010, -0x24020002, 0x1262007f, 0x2e620003, 0x10400005, -0x24020001, 0x1262000a, 0x0, 0x800526f, -0x0, 0x24020004, 0x126200f6, 0x24020008, -0x126200f5, 0x3c02ffec, 0x800526f, 0x0, -0x3c020001, 0x8c425d24, 0x30420002, 0x14400004, +0x24020002, 0x12620083, 0x2e620003, 0x10400005, +0x24020001, 0x1262000a, 0x0, 0x800529b, +0x0, 0x24020004, 0x126200fa, 0x24020008, +0x126200f9, 0x3c02ffec, 0x800529b, 0x0, +0x3c020001, 0x8c425cc4, 0x30420002, 0x14400004, 0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024, -0x3c010001, 0x310821, 0xac307e9c, 0x3c024000, -0x2021024, 0x1040004a, 0x1023c2, 0x30840030, -0x101382, 0x3042001c, 0x3c030001, 0x24635d68, +0x3c010001, 0x310821, 0xac307e3c, 0x3c024000, +0x2021024, 0x1040004e, 0x1023c2, 0x30840030, +0x101382, 0x3042001c, 0x3c030001, 0x24635d08, 0x431021, 0x823821, 0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010001, 0x310821, -0xac227ea0, 0x8005128, 0x3c020080, 0x3c010001, -0x310821, 0xac207ea0, 0x3c020080, 0x2021024, +0xac227e40, 0x8005150, 0x3c020080, 0x3c010001, +0x310821, 0xac207e40, 0x3c020080, 0x2021024, 0x10400006, 0x121940, 0x3c020001, 0x3c010001, -0x230821, 0x8005134, 0xac227ea8, 0x121140, -0x3c010001, 0x220821, 0xac207ea8, 0x94e30000, -0x32024000, 0x10400003, 0xa7a30018, 0x34624000, +0x230821, 0x800515c, 0xac227e48, 0x121140, +0x3c010001, 0x220821, 0xac207e48, 0x94e40000, +0x3c030001, 0x8c635dbc, 0x24020005, 0x10620010, +0xa7a40018, 0x32024000, 0x10400002, 0x34824000, 0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, -0x24e60002, 0x34420001, 0xc004966, 0xa4e20002, -0x24040001, 0x2821, 0xc004966, 0x27a60018, -0x3c020001, 0x8c425d28, 0x24110001, 0x3c010001, -0xac315d34, 0x14530004, 0x32028000, 0xc00429b, +0x24e60002, 0x34420001, 0xc00498e, 0xa4e20002, +0x24040001, 0x2821, 0xc00498e, 0x27a60018, +0x3c020001, 0x8c425cc8, 0x24110001, 0x3c010001, +0xac315cd4, 0x14530004, 0x32028000, 0xc00429b, 0x0, 0x32028000, 0x1040011f, 0x0, -0xc00429b, 0x0, 0x3c030001, 0x8c635e18, +0xc00429b, 0x0, 0x3c030001, 0x8c635dbc, 0x24020005, 0x10620118, 0x24020002, 0x3c010001, -0xac315d2c, 0x3c010001, 0x800526f, 0xac225d28, -0x24040001, 0x24050004, 0x27b0001a, 0xc004966, -0x2003021, 0x24040001, 0x2821, 0xc004966, -0x2003021, 0x3c020001, 0x511021, 0x8c427e94, -0x3c040001, 0x8c845d28, 0x3c03bfff, 0x3463ffff, -0x3c010001, 0xac335d34, 0x431024, 0x3c010001, -0x310821, 0x109300fa, 0xac227e94, 0x800526f, +0xac315ccc, 0x3c010001, 0x800529b, 0xac225cc8, +0x24040001, 0x24050004, 0x27b0001a, 0xc00498e, +0x2003021, 0x24040001, 0x2821, 0xc00498e, +0x2003021, 0x3c020001, 0x511021, 0x8c427e34, +0x3c040001, 0x8c845cc8, 0x3c03bfff, 0x3463ffff, +0x3c010001, 0xac335cd4, 0x431024, 0x3c010001, +0x310821, 0x109300fa, 0xac227e34, 0x800529b, 0x0, 0x3c022000, 0x2021024, 0x10400005, -0x24020001, 0x3c010001, 0xac225df8, 0x8005181, -0x128940, 0x3c010001, 0xac205df8, 0x128940, -0x3c010001, 0x310821, 0xac307e98, 0x3c024000, +0x24020001, 0x3c010001, 0xac225d98, 0x80051ad, +0x128940, 0x3c010001, 0xac205d98, 0x128940, +0x3c010001, 0x310821, 0xac307e38, 0x3c024000, 0x2021024, 0x14400016, 0x0, 0x3c020001, -0x8c425df8, 0x10400008, 0x24040004, 0x24050001, -0xc004d6b, 0x24062000, 0x24020001, 0x3c010001, +0x8c425d98, 0x10400008, 0x24040004, 0x24050001, +0xc004d93, 0x24062000, 0x24020001, 0x3c010001, 0x370821, 0xac2283ac, 0x3c020001, 0x511021, -0x8c427e90, 0x3c03bfff, 0x3463ffff, 0x431024, -0x3c010001, 0x310821, 0x800526d, 0xac227e90, -0x3c020001, 0x8c425df8, 0x10400028, 0x3c0300a0, +0x8c427e30, 0x3c03bfff, 0x3463ffff, 0x431024, +0x3c010001, 0x310821, 0x8005299, 0xac227e30, +0x3c020001, 0x8c425d98, 0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d, 0x3c020020, 0x3c020001, -0x8c425dfc, 0x24030100, 0x3c010001, 0x310821, -0xac237ea4, 0x3c030001, 0x3c010001, 0x310821, -0xac237eac, 0x80051c4, 0x34420400, 0x2021024, -0x10400008, 0x24030100, 0x3c020001, 0x8c425dfc, -0x3c010001, 0x310821, 0xac237ea4, 0x80051c4, +0x8c425d9c, 0x24030100, 0x3c010001, 0x310821, +0xac237e44, 0x3c030001, 0x3c010001, 0x310821, +0xac237e4c, 0x80051f0, 0x34420400, 0x2021024, +0x10400008, 0x24030100, 0x3c020001, 0x8c425d9c, +0x3c010001, 0x310821, 0xac237e44, 0x80051f0, 0x34420800, 0x3c020080, 0x2021024, 0x1040002e, -0x3c030001, 0x3c020001, 0x8c425dfc, 0x3c010001, -0x310821, 0xac237eac, 0x34420c00, 0x3c010001, -0xac225dfc, 0x80051ec, 0x24040001, 0x3c020020, +0x3c030001, 0x3c020001, 0x8c425d9c, 0x3c010001, +0x310821, 0xac237e4c, 0x34420c00, 0x3c010001, +0xac225d9c, 0x8005218, 0x24040001, 0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010001, -0x310821, 0xac227ea4, 0x80051d5, 0x3c020080, -0x3c010001, 0x310821, 0xac207ea4, 0x3c020080, +0x310821, 0xac227e44, 0x8005201, 0x3c020080, +0x3c010001, 0x310821, 0xac207e44, 0x3c020080, 0x2021024, 0x10400007, 0x121940, 0x3c020001, -0x3c010001, 0x230821, 0xac227eac, 0x80051e3, +0x3c010001, 0x230821, 0xac227e4c, 0x800520f, 0x24040001, 0x121140, 0x3c010001, 0x220821, -0xac207eac, 0x24040001, 0x2821, 0x27b0001e, -0xc004924, 0x2003021, 0x24040001, 0x2821, -0xc004924, 0x2003021, 0x24040001, 0x24050001, -0x27b0001c, 0xc004924, 0x2003021, 0x24040001, -0x24050001, 0xc004924, 0x2003021, 0x800526d, +0xac207e4c, 0x24040001, 0x2821, 0x27b0001e, +0xc00494c, 0x2003021, 0x24040001, 0x2821, +0xc00494c, 0x2003021, 0x24040001, 0x24050001, +0x27b0001c, 0xc00494c, 0x2003021, 0x24040001, +0x24050001, 0xc00494c, 0x2003021, 0x8005299, 0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008, 0x2028025, 0x121140, 0x3c010001, -0x220821, 0xac307e98, 0x3c022000, 0x2021024, -0x10400009, 0x0, 0x3c020001, 0x8c425dd4, -0x14400005, 0x24020001, 0x3c010001, 0xac225df8, -0x800520e, 0x3c024000, 0x3c010001, 0xac205df8, +0x220821, 0xac307e38, 0x3c022000, 0x2021024, +0x10400009, 0x0, 0x3c020001, 0x8c425d74, +0x14400005, 0x24020001, 0x3c010001, 0xac225d98, +0x800523a, 0x3c024000, 0x3c010001, 0xac205d98, 0x3c024000, 0x2021024, 0x1440001e, 0x0, -0x3c020001, 0x8c425df8, 0x3c010001, 0xac205d40, -0x10400007, 0x24022020, 0x3c010001, 0xac225dfc, +0x3c020001, 0x8c425d98, 0x3c010001, 0xac205ce0, +0x10400007, 0x24022020, 0x3c010001, 0xac225d9c, 0x24020001, 0x3c010001, 0x370821, 0xac2283ac, 0x3c04bfff, 0x121940, 0x3c020001, 0x431021, -0x8c427e90, 0x3c050001, 0x8ca55d28, 0x3484ffff, -0x441024, 0x3c010001, 0x230821, 0xac227e90, -0x24020001, 0x10a20044, 0x0, 0x800526d, -0x0, 0x3c020001, 0x8c425df8, 0x1040001c, -0x24022000, 0x3c010001, 0xac225dfc, 0x3c0300a0, +0x8c427e30, 0x3c050001, 0x8ca55cc8, 0x3484ffff, +0x441024, 0x3c010001, 0x230821, 0xac227e30, +0x24020001, 0x10a20044, 0x0, 0x8005299, +0x0, 0x3c020001, 0x8c425d98, 0x1040001c, +0x24022000, 0x3c010001, 0xac225d9c, 0x3c0300a0, 0x2031024, 0x14430005, 0x121140, 0x3402a000, -0x3c010001, 0x8005268, 0xac225dfc, 0x3c030001, -0x621821, 0x8c637e98, 0x3c020020, 0x621024, -0x10400004, 0x24022001, 0x3c010001, 0x8005268, -0xac225dfc, 0x3c020080, 0x621024, 0x1040001f, -0x3402a001, 0x3c010001, 0x8005268, 0xac225dfc, +0x3c010001, 0x8005294, 0xac225d9c, 0x3c030001, +0x621821, 0x8c637e38, 0x3c020020, 0x621024, +0x10400004, 0x24022001, 0x3c010001, 0x8005294, +0xac225d9c, 0x3c020080, 0x621024, 0x1040001f, +0x3402a001, 0x3c010001, 0x8005294, 0xac225d9c, 0x3c020020, 0x2021024, 0x10400007, 0x121940, -0x24020100, 0x3c010001, 0x230821, 0xac227ea4, -0x800525c, 0x3c020080, 0x121140, 0x3c010001, -0x220821, 0xac207ea4, 0x3c020080, 0x2021024, +0x24020100, 0x3c010001, 0x230821, 0xac227e44, +0x8005288, 0x3c020080, 0x121140, 0x3c010001, +0x220821, 0xac207e44, 0x3c020080, 0x2021024, 0x10400006, 0x121940, 0x3c020001, 0x3c010001, -0x230821, 0x8005268, 0xac227eac, 0x121140, -0x3c010001, 0x220821, 0xac207eac, 0x3c030001, -0x8c635d28, 0x24020001, 0x10620003, 0x0, +0x230821, 0x8005294, 0xac227e4c, 0x121140, +0x3c010001, 0x220821, 0xac207e4c, 0x3c030001, +0x8c635cc8, 0x24020001, 0x10620003, 0x0, 0xc00429b, 0x0, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, -0x27bd0038, 0x27bdffc0, 0xafb40038, 0x80a021, -0xafb20030, 0x9021, 0xafb1002c, 0x8821, -0x24020002, 0xafbf003c, 0xafb30034, 0xafb00028, -0xa7a00020, 0xa7a00018, 0xa7a0001a, 0xa7a0001c, -0x10a20108, 0xa7a0001e, 0x2ca20003, 0x10400005, -0x24020001, 0x10a2000a, 0x149940, 0x800538f, -0x2201021, 0x24020004, 0x10a200b2, 0x24020008, -0x10a200b1, 0x142940, 0x800538f, 0x2201021, -0x3c030001, 0x731821, 0x8c637e9c, 0x3c024000, -0x621024, 0x14400009, 0x24040001, 0x3c027fff, -0x3442ffff, 0x628824, 0x3c010001, 0x330821, -0xac317e94, 0x800538f, 0x2201021, 0x2821, -0xc004924, 0x27a60018, 0x24040001, 0x2821, -0xc004924, 0x27a60018, 0x24040001, 0x24050001, -0x27b0001a, 0xc004924, 0x2003021, 0x24040001, -0x24050001, 0xc004924, 0x2003021, 0x24040001, -0x24050004, 0x27b0001c, 0xc004924, 0x2003021, -0x24040001, 0x24050004, 0xc004924, 0x2003021, -0x24040001, 0x24050005, 0x27b0001e, 0xc004924, -0x2003021, 0x24040001, 0x24050005, 0xc004924, -0x2003021, 0x24040001, 0x24050009, 0xc004924, -0x2003021, 0x24040001, 0x24050009, 0xc004924, -0x2003021, 0x24040001, 0x24050001, 0xc004924, -0x27a60018, 0x24040001, 0x24050001, 0xc004924, -0x27a60018, 0x97a20018, 0x30420004, 0x10400034, -0x3c114000, 0x3c020001, 0x8c425e18, 0x2443ffff, -0x2c620006, 0x10400034, 0x31080, 0x3c010001, -0x220821, 0x8c225c38, 0x400008, 0x0, -0x24040001, 0x24050011, 0x27b00020, 0xc004924, -0x2003021, 0x24040001, 0x24050011, 0xc004924, -0x2003021, 0x97a40020, 0x30824000, 0x10400002, -0x3c030010, 0x3c030008, 0x3c120001, 0x8005306, -0x30828000, 0x24040001, 0x24050014, 0x27b00020, -0xc004924, 0x2003021, 0x24040001, 0x24050014, -0xc004924, 0x2003021, 0x97a40020, 0x30821000, -0x10400002, 0x3c030010, 0x3c030008, 0x3c120001, -0x30820800, 0x54400001, 0x3c120002, 0x3c028000, -0x2221025, 0x2431825, 0x8005313, 0x438825, -0x3c110001, 0x2338821, 0x8e317e9c, 0x3c027fff, -0x3442ffff, 0x2228824, 0x3c020001, 0x8c425d38, -0x1040001c, 0x0, 0x3c020001, 0x8c425df8, -0x10400002, 0x3c022000, 0x2228825, 0x141140, -0x3c010001, 0x220821, 0x8c227ea0, 0x10400003, -0x3c020020, 0x8005327, 0x2228825, 0x3c02ffdf, -0x3442ffff, 0x2228824, 0x141140, 0x3c010001, -0x220821, 0x8c227ea8, 0x10400003, 0x3c020080, -0x8005332, 0x2228825, 0x3c02ff7f, 0x3442ffff, -0x2228824, 0x3c040001, 0x24845c2c, 0x3c05000c, -0x34a50326, 0x3c070001, 0x8ce75d28, 0x3021, -0x141140, 0x3c010001, 0x220821, 0xac317e94, -0xafb20010, 0xc002403, 0xafb10014, 0x800538f, -0x2201021, 0x142940, 0x3c030001, 0x651821, -0x8c637e98, 0x3c024000, 0x621024, 0x14400008, -0x3c027fff, 0x3442ffff, 0x628824, 0x3c010001, -0x250821, 0xac317e90, 0x800538f, 0x2201021, -0x3c020001, 0x8c425d38, 0x10400033, 0x3c11c00c, -0x3c020001, 0x8c425dd4, 0x3c04c00c, 0x34842000, -0x3c030001, 0x8c635df8, 0x2102b, 0x21023, -0x441024, 0x10600003, 0x518825, 0x3c022000, -0x2228825, 0x3c020001, 0x451021, 0x8c427ea4, -0x10400003, 0x3c020020, 0x800536c, 0x2228825, -0x3c02ffdf, 0x3442ffff, 0x2228824, 0x141140, -0x3c010001, 0x220821, 0x8c227eac, 0x10400003, -0x3c020080, 0x8005377, 0x2228825, 0x3c02ff7f, -0x3442ffff, 0x2228824, 0x3c020001, 0x8c425dc0, -0x10400002, 0x3c020800, 0x2228825, 0x3c020001, -0x8c425dc4, 0x10400002, 0x3c020400, 0x2228825, -0x3c020001, 0x8c425dc8, 0x10400006, 0x3c020100, -0x800538a, 0x2228825, 0x3c027fff, 0x3442ffff, -0x628824, 0x141140, 0x3c010001, 0x220821, -0xac317e90, 0x2201021, 0x8fbf003c, 0x8fb40038, -0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, -0x3e00008, 0x27bd0040, 0x27bdffd8, 0xafb40020, -0x80a021, 0xafbf0024, 0xafb3001c, 0xafb20018, -0xafb10014, 0xafb00010, 0x8f900200, 0x3c030001, -0x8c635d28, 0x8f930220, 0x24020002, 0x10620063, -0x2c620003, 0x10400005, 0x24020001, 0x1062000a, -0x141940, 0x8005459, 0x0, 0x24020004, -0x1062005a, 0x24020008, 0x10620059, 0x149140, -0x8005459, 0x0, 0x3c040001, 0x832021, -0x8c847e9c, 0x3c110001, 0x2238821, 0x8e317e94, -0x3c024000, 0x821024, 0x1040003e, 0x3c020008, -0x2221024, 0x10400020, 0x36100002, 0x3c020001, -0x431021, 0x8c427ea0, 0x10400005, 0x36100020, -0x36100100, 0x3c020020, 0x80053ce, 0x2228825, -0x2402feff, 0x2028024, 0x3c02ffdf, 0x3442ffff, +0x27bd0038, 0x27bdffd8, 0xafb20020, 0x809021, +0xafb1001c, 0x8821, 0x24020002, 0xafbf0024, +0xafb00018, 0xa7a00012, 0x10a200d3, 0xa7a00010, +0x2ca20003, 0x10400005, 0x24020001, 0x10a2000a, +0x128140, 0x8005380, 0x2201021, 0x24020004, +0x10a2007d, 0x24020008, 0x10a2007c, 0x122940, +0x8005380, 0x2201021, 0x3c030001, 0x701821, +0x8c637e3c, 0x3c024000, 0x621024, 0x14400009, +0x24040001, 0x3c027fff, 0x3442ffff, 0x628824, +0x3c010001, 0x300821, 0xac317e34, 0x8005380, +0x2201021, 0x24050001, 0xc00494c, 0x27a60010, +0x24040001, 0x24050001, 0xc00494c, 0x27a60010, +0x97a20010, 0x30420004, 0x10400034, 0x3c114000, +0x3c020001, 0x8c425dbc, 0x2443ffff, 0x2c620006, +0x10400034, 0x31080, 0x3c010001, 0x220821, +0x8c225be0, 0x400008, 0x0, 0x24040001, +0x24050011, 0x27b00012, 0xc00494c, 0x2003021, +0x24040001, 0x24050011, 0xc00494c, 0x2003021, +0x97a50012, 0x30a24000, 0x10400002, 0x3c040010, +0x3c040008, 0x3c030001, 0x8005301, 0x30a28000, +0x24040001, 0x24050014, 0x27b00012, 0xc00494c, +0x2003021, 0x24040001, 0x24050014, 0xc00494c, +0x2003021, 0x97a50012, 0x30a21000, 0x10400002, +0x3c040010, 0x3c040008, 0x3c030001, 0x30a20800, +0x54400001, 0x3c030002, 0x3c028000, 0x2221025, +0x641825, 0x800530e, 0x438825, 0x3c110001, +0x2308821, 0x8e317e3c, 0x3c027fff, 0x3442ffff, +0x2228824, 0x3c020001, 0x8c425cd8, 0x1040001d, +0x121140, 0x3c020001, 0x8c425d98, 0x10400002, +0x3c022000, 0x2228825, 0x121140, 0x3c010001, +0x220821, 0x8c227e40, 0x10400003, 0x3c020020, +0x8005322, 0x2228825, 0x3c02ffdf, 0x3442ffff, +0x2228824, 0x121140, 0x3c010001, 0x220821, +0x8c227e48, 0x10400003, 0x3c020080, 0x800532d, +0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824, +0x121140, 0x3c010001, 0x220821, 0xac317e34, +0x8005380, 0x2201021, 0x122940, 0x3c030001, +0x651821, 0x8c637e38, 0x3c024000, 0x621024, +0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, +0x3c010001, 0x250821, 0xac317e30, 0x8005380, +0x2201021, 0x3c020001, 0x8c425cd8, 0x10400033, +0x3c11c00c, 0x3c020001, 0x8c425d74, 0x3c04c00c, +0x34842000, 0x3c030001, 0x8c635d98, 0x2102b, +0x21023, 0x441024, 0x10600003, 0x518825, +0x3c022000, 0x2228825, 0x3c020001, 0x451021, +0x8c427e44, 0x10400003, 0x3c020020, 0x800535d, +0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, +0x121140, 0x3c010001, 0x220821, 0x8c227e4c, +0x10400003, 0x3c020080, 0x8005368, 0x2228825, +0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c020001, +0x8c425d60, 0x10400002, 0x3c020800, 0x2228825, +0x3c020001, 0x8c425d64, 0x10400002, 0x3c020400, +0x2228825, 0x3c020001, 0x8c425d68, 0x10400006, +0x3c020100, 0x800537b, 0x2228825, 0x3c027fff, +0x3442ffff, 0x628824, 0x121140, 0x3c010001, +0x220821, 0xac317e30, 0x2201021, 0x8fbf0024, +0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, +0x27bd0028, 0x27bdffd8, 0xafb40020, 0x80a021, +0xafbf0024, 0xafb3001c, 0xafb20018, 0xafb10014, +0xafb00010, 0x8f900200, 0x3c030001, 0x8c635cc8, +0x8f930220, 0x24020002, 0x10620063, 0x2c620003, +0x10400005, 0x24020001, 0x1062000a, 0x141940, +0x8005448, 0x0, 0x24020004, 0x1062005a, +0x24020008, 0x10620059, 0x149140, 0x8005448, +0x0, 0x3c040001, 0x832021, 0x8c847e3c, +0x3c110001, 0x2238821, 0x8e317e34, 0x3c024000, +0x821024, 0x1040003e, 0x3c020008, 0x2221024, +0x10400020, 0x36100002, 0x3c020001, 0x431021, +0x8c427e40, 0x10400005, 0x36100020, 0x36100100, +0x3c020020, 0x80053bd, 0x2228825, 0x2402feff, +0x2028024, 0x3c02ffdf, 0x3442ffff, 0x2228824, +0x141140, 0x3c010001, 0x220821, 0x8c227e48, +0x10400005, 0x3c020001, 0x2629825, 0x3c020080, +0x80053dc, 0x2228825, 0x3c02fffe, 0x3442ffff, +0x2629824, 0x3c02ff7f, 0x3442ffff, 0x80053dc, +0x2228824, 0x2402fedf, 0x2028024, 0x3c02fffe, +0x3442ffff, 0x2629824, 0x3c02ff5f, 0x3442ffff, +0x2228824, 0x3c010001, 0x230821, 0xac207e40, +0x3c010001, 0x230821, 0xac207e48, 0xc00486a, +0x0, 0xaf900200, 0xaf930220, 0x8f820220, +0x2403fffb, 0x431024, 0xaf820220, 0x8f820220, +0x34420002, 0xaf820220, 0x80053f3, 0x141140, +0x8f820200, 0x2403fffd, 0x431024, 0xc00486a, +0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc00429b, 0x2228824, 0x141140, 0x3c010001, 0x220821, -0x8c227ea8, 0x10400005, 0x3c020001, 0x2629825, -0x3c020080, 0x80053ed, 0x2228825, 0x3c02fffe, -0x3442ffff, 0x2629824, 0x3c02ff7f, 0x3442ffff, -0x80053ed, 0x2228824, 0x2402fedf, 0x2028024, -0x3c02fffe, 0x3442ffff, 0x2629824, 0x3c02ff5f, -0x3442ffff, 0x2228824, 0x3c010001, 0x230821, -0xac207ea0, 0x3c010001, 0x230821, 0xac207ea8, -0xc004844, 0x0, 0xaf900200, 0xaf930220, +0x8005448, 0xac317e34, 0x149140, 0x3c040001, +0x922021, 0x8c847e38, 0x3c110001, 0x2328821, +0x8e317e30, 0x3c024000, 0x821024, 0x14400011, +0x0, 0x3c020001, 0x8c425d98, 0x14400006, +0x3c02bfff, 0x8f820200, 0x34420002, 0xc00486a, +0xaf820200, 0x3c02bfff, 0x3442ffff, 0xc00429b, +0x2228824, 0x3c010001, 0x320821, 0x8005448, +0xac317e30, 0x3c020001, 0x8c425d98, 0x10400005, +0x3c020020, 0x3c020001, 0x8c425d74, 0x1040002b, +0x3c020020, 0x821024, 0x10400007, 0x36100020, +0x24020100, 0x3c010001, 0x320821, 0xac227e44, +0x8005428, 0x36100100, 0x3c010001, 0x320821, +0xac207e44, 0x2402feff, 0x2028024, 0x3c020080, +0x821024, 0x10400007, 0x141940, 0x3c020001, +0x3c010001, 0x230821, 0xac227e4c, 0x8005439, +0x2629825, 0x141140, 0x3c010001, 0x220821, +0xac207e4c, 0x3c02fffe, 0x3442ffff, 0x2629824, +0xc00486a, 0x0, 0xaf900200, 0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, 0xaf820220, -0x8f820220, 0x34420002, 0xaf820220, 0x8005404, -0x141140, 0x8f820200, 0x2403fffd, 0x431024, -0xc004844, 0xaf820200, 0x3c02bfff, 0x3442ffff, -0xc00429b, 0x2228824, 0x141140, 0x3c010001, -0x220821, 0x8005459, 0xac317e94, 0x149140, -0x3c040001, 0x922021, 0x8c847e98, 0x3c110001, -0x2328821, 0x8e317e90, 0x3c024000, 0x821024, -0x14400011, 0x0, 0x3c020001, 0x8c425df8, -0x14400006, 0x3c02bfff, 0x8f820200, 0x34420002, -0xc004844, 0xaf820200, 0x3c02bfff, 0x3442ffff, -0xc00429b, 0x2228824, 0x3c010001, 0x320821, -0x8005459, 0xac317e90, 0x3c020001, 0x8c425df8, -0x10400005, 0x3c020020, 0x3c020001, 0x8c425dd4, -0x1040002b, 0x3c020020, 0x821024, 0x10400007, -0x36100020, 0x24020100, 0x3c010001, 0x320821, -0xac227ea4, 0x8005439, 0x36100100, 0x3c010001, -0x320821, 0xac207ea4, 0x2402feff, 0x2028024, -0x3c020080, 0x821024, 0x10400007, 0x141940, -0x3c020001, 0x3c010001, 0x230821, 0xac227eac, -0x800544a, 0x2629825, 0x141140, 0x3c010001, -0x220821, 0xac207eac, 0x3c02fffe, 0x3442ffff, -0x2629824, 0xc004844, 0x0, 0xaf900200, -0xaf930220, 0x8f820220, 0x2403fffb, 0x431024, -0xaf820220, 0x8f820220, 0x34420002, 0xaf820220, -0x141140, 0x3c010001, 0x220821, 0xac317e90, -0x8fbf0024, 0x8fb40020, 0x8fb3001c, 0x8fb20018, -0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, -0x0, 0x0, 0x0, 0x0 }; +0x8f820220, 0x34420002, 0xaf820220, 0x141140, +0x3c010001, 0x220821, 0xac317e30, 0x8fbf0024, +0x8fb40020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, +0x8fb00010, 0x3e00008, 0x27bd0028, 0x0 }; u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, @@ -4473,10 +4468,10 @@ u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x32203139, 0x39382f30, 0x342f3237, 0x2032323a, 0x31333a34, 0x30207368, 0x75616e67, 0x20457870, 0x20240000, 0x46575f56, 0x45525349, 0x4f4e3a20, -0x23312053, 0x61742044, 0x65632031, 0x31203136, -0x3a30333a, 0x31392050, 0x53542031, 0x39393900, +0x23312046, 0x72692041, 0x70722037, 0x2031373a, +0x35353a34, 0x38205044, 0x54203230, 0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54, 0x494d453a, -0x2031363a, 0x30333a31, 0x39000000, 0x46575f43, +0x2031373a, 0x35353a34, 0x38000000, 0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, 0x0, @@ -4554,27 +4549,27 @@ u32 tigonFwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x2e322031, 0x3939382f, 0x30342f32, 0x37203232, 0x3a31333a, 0x33392073, 0x6875616e, 0x67204578, 0x70202400, 0x50726f62, 0x65506879, 0x0, -0x6c6e6b41, 0x53535254, 0x0, 0x11af4, -0x11b8c, 0x11bac, 0x11bf0, 0x11c1c, -0x11c30, 0x11c6c, 0x11fe0, 0x11d48, -0x11d88, 0x11db4, 0x11df4, 0x11e24, -0x11e60, 0x11e94, 0x11fe0, 0x12228, -0x12240, 0x12268, 0x12288, 0x122b0, -0x123e0, 0x12408, 0x1245c, 0x12484, -0x0, 0x126ec, 0x127bc, 0x12894, -0x12964, 0x129c0, 0x12a9c, 0x12ac4, -0x12ba0, 0x12bc8, 0x12d70, 0x12d98, -0x12f40, 0x13138, 0x133cc, 0x132e0, -0x133cc, 0x133f8, 0x12f68, 0x13110, -0x0, 0x13ae4, 0x13b28, 0x13bc0, -0x13c0c, 0x13c7c, 0x13d14, 0x13d48, -0x13dd0, 0x13e68, 0x13f38, 0x13f78, -0x13ffc, 0x14020, 0x14154, 0x646f4261, +0x6c6e6b41, 0x53535254, 0x0, 0x11b2c, +0x11bc4, 0x11bf8, 0x11c2c, 0x11c58, +0x11c6c, 0x11ca8, 0x1207c, 0x11de4, +0x11e24, 0x11e50, 0x11e90, 0x11ec0, +0x11efc, 0x11f30, 0x1207c, 0x122c0, +0x122d8, 0x12300, 0x12320, 0x12348, +0x12478, 0x124a0, 0x124f4, 0x1251c, +0x0, 0x1278c, 0x1285c, 0x12934, +0x12a04, 0x12a60, 0x12b3c, 0x12b64, +0x12c40, 0x12c68, 0x12e10, 0x12e38, +0x12fe0, 0x131d8, 0x1346c, 0x13380, +0x1346c, 0x13498, 0x13008, 0x131b0, +0x0, 0x13b84, 0x13bc8, 0x13c60, +0x13cac, 0x13d1c, 0x13db4, 0x13de8, +0x13e70, 0x13f08, 0x13fd8, 0x14018, +0x1409c, 0x140c0, 0x141f4, 0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0, 0x73746d61, 0x634c4e4b, 0x0, -0x6765746d, 0x636c6e6b, 0x0, 0x14c4c, -0x14c4c, 0x14b94, 0x14bd8, 0x14c4c, -0x14c4c, 0x0 }; +0x0, 0x14c38, 0x14c38, 0x14b80, +0x14bc4, 0x14c38, 0x14c38, 0x0, +0x0, 0x0 }; u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = { 0x416c7465, 0x6f6e2041, 0x63654e49, 0x43205600, 0x416c7465, @@ -4604,25 +4599,25 @@ u32 tigonFwData[(MAX_DATA_LEN/4) + 1] __initdata = { /* Generated by genfw.c */ #define tigon2FwReleaseMajor 0xc #define tigon2FwReleaseMinor 0x4 -#define tigon2FwReleaseFix 0x5 +#define tigon2FwReleaseFix 0xb #define tigon2FwStartAddr 0x00004000 #define tigon2FwTextAddr 0x00004000 -#define tigon2FwTextLen 0x11c50 -#define tigon2FwRodataAddr 0x00015c50 -#define tigon2FwRodataLen 0x10c0 -#define tigon2FwDataAddr 0x00016d40 +#define tigon2FwTextLen 0x11bc0 +#define tigon2FwRodataAddr 0x00015bc0 +#define tigon2FwRodataLen 0x10d0 +#define tigon2FwDataAddr 0x00016cc0 #define tigon2FwDataLen 0x1c0 -#define tigon2FwSbssAddr 0x00016f00 -#define tigon2FwSbssLen 0xc4 -#define tigon2FwBssAddr 0x00016fd0 +#define tigon2FwSbssAddr 0x00016e80 +#define tigon2FwSbssLen 0xcc +#define tigon2FwBssAddr 0x00016f50 #define tigon2FwBssLen 0x20c0 u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x10000003, 0x0, 0xd, 0xd, -0x3c1d0001, 0x8fbd6da0, 0x3a0f021, 0x3c100000, +0x3c1d0001, 0x8fbd6d20, 0x3a0f021, 0x3c100000, 0x26104000, 0xc0010c0, 0x0, 0xd, -0x3c1d0001, 0x8fbd6da4, 0x3a0f021, 0x3c100000, -0x26104000, 0xc0017c8, 0x0, 0xd, +0x3c1d0001, 0x8fbd6d24, 0x3a0f021, 0x3c100000, +0x26104000, 0xc0017e0, 0x0, 0xd, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -4634,22 +4629,22 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2000008, -0x0, 0x8001717, 0x3c0a0001, 0x8001717, -0x3c0a0002, 0x8001717, 0x0, 0x8002c68, -0x0, 0x8002c0b, 0x0, 0x8001717, -0x3c0a0004, 0x8003272, 0x0, 0x8001a3a, -0x0, 0x8003925, 0x0, 0x80038cc, -0x0, 0x8001717, 0x3c0a0006, 0x8003993, -0x3c0a0007, 0x8001717, 0x3c0a0008, 0x8001717, -0x3c0a0009, 0x80039eb, 0x0, 0x8002e62, -0x0, 0x8001717, 0x3c0a000b, 0x8001717, -0x3c0a000c, 0x8001717, 0x3c0a000d, 0x80028d7, -0x0, 0x800286c, 0x0, 0x8001717, -0x3c0a000e, 0x8002074, 0x0, 0x800194c, -0x0, 0x80019ec, 0x0, 0x8003c7e, -0x0, 0x8003c6c, 0x0, 0x8001717, -0x0, 0x8001902, 0x0, 0x8001717, -0x0, 0x8001717, 0x3c0a0013, 0x8001717, +0x0, 0x800172f, 0x3c0a0001, 0x800172f, +0x3c0a0002, 0x800172f, 0x0, 0x8002cac, +0x0, 0x8002c4f, 0x0, 0x800172f, +0x3c0a0004, 0x800328a, 0x0, 0x8001a52, +0x0, 0x800394d, 0x0, 0x80038f4, +0x0, 0x800172f, 0x3c0a0006, 0x80039bb, +0x3c0a0007, 0x800172f, 0x3c0a0008, 0x800172f, +0x3c0a0009, 0x8003a13, 0x0, 0x8002ea6, +0x0, 0x800172f, 0x3c0a000b, 0x800172f, +0x3c0a000c, 0x800172f, 0x3c0a000d, 0x80028fb, +0x0, 0x8002890, 0x0, 0x800172f, +0x3c0a000e, 0x800208c, 0x0, 0x8001964, +0x0, 0x8001a04, 0x0, 0x8003ca6, +0x0, 0x8003c94, 0x0, 0x800172f, +0x0, 0x800191a, 0x0, 0x800172f, +0x0, 0x800172f, 0x3c0a0013, 0x800172f, 0x3c0a0014, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -4667,335 +4662,341 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x27bdffe0, 0x3c1cc000, 0xafbf001c, 0xafb00018, 0x8f820140, -0x24030003, 0xaf8300ec, 0x34420004, 0xc002afc, -0xaf820140, 0x3c0100c0, 0xc00174b, 0xac203ffc, -0x403021, 0x3c020008, 0x3c010001, 0xac266f18, -0x50c2000d, 0x24020008, 0x3c100010, 0x10d00009, -0x24050100, 0x3c040001, 0x24845d04, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x3c010001, -0xac306f18, 0x24020008, 0x3c010001, 0xac226f30, -0x2402001f, 0x3c010001, 0xac226f40, 0x24020016, -0x3c010001, 0xac226f14, 0x3c05fffe, 0x34a56f08, -0x3c020001, 0x8c426f18, 0x3c030002, 0x24639090, -0x3c040001, 0x8c846d44, 0x431023, 0x14800002, -0x458021, 0x2610fa38, 0x2402f000, 0x2028024, -0xc00176d, 0x2002021, 0x2022823, 0x3c040020, -0x821823, 0x651823, 0x247bb000, 0x3c03fffe, -0x3463bf08, 0x363b821, 0x3c0600bf, 0x34c6f000, -0x3c070001, 0x8ce76d40, 0x3c0300bf, 0x3463e000, -0x852023, 0x3c010001, 0xac246f24, 0x822023, -0x3c010001, 0xac256f0c, 0x52842, 0x3c010001, -0xac226f00, 0x27620ffc, 0x3c010001, 0xac226da0, -0x27621ffc, 0xdb3023, 0x7b1823, 0x3c010001, -0xac246f04, 0x3c010001, 0xac256f28, 0x3c010001, -0xac226da4, 0xaf860150, 0x10e00011, 0xaf830250, -0x3c1d0001, 0x8fbd6d4c, 0x3a0f021, 0xc001731, -0x0, 0x3c020001, 0x8c426d50, 0x3c030001, -0x8c636d54, 0x2442fe00, 0x24630200, 0x3c010001, -0xac226d50, 0x3c010001, 0x10000004, 0xac236d54, -0x3c1d0001, 0x8fbd6da0, 0x3a0f021, 0x3c020001, -0x8c426d44, 0x1040000d, 0x26fafa38, 0x3c020001, -0x8c426d50, 0x3c030001, 0x8c636d54, 0x3c1a0001, -0x8f5a6d54, 0x2442fa38, 0x246305c8, 0x3c010001, -0xac226d50, 0x3c010001, 0xac236d54, 0x3c020001, -0x8c426d48, 0x14400003, 0x0, 0x3c010001, -0xac206d50, 0xc00114c, 0x0, 0x8fbf001c, -0x8fb00018, 0x3e00008, 0x27bd0020, 0x3c020001, -0x8c426d50, 0x3c030001, 0x8c636d54, 0x27bdffa0, -0xafb00040, 0x3c100001, 0x8e106748, 0x3c040001, -0x24845d10, 0xafbf0058, 0xafbe0054, 0xafb50050, -0xafb3004c, 0xafb20048, 0xafb10044, 0xafa20034, -0xafa30030, 0xafa00010, 0xafa00014, 0x8f860040, -0x24050200, 0xc002b17, 0x2003821, 0x8f830040, -0x3c02f000, 0x621824, 0x3c026000, 0x1062000b, -0xa3a0003f, 0x240e0001, 0x3c040001, 0x24845d18, -0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f860040, -0x24050300, 0xc002b17, 0x2003821, 0x8f820240, -0x3c030001, 0x431025, 0xaf820240, 0xaf800048, -0x8f820048, 0x14400005, 0x0, 0xaf800048, -0x8f820048, 0x10400004, 0x0, 0xaf800048, -0x10000003, 0x2e02021, 0xaf80004c, 0x2e02021, -0x3c050001, 0xc002b84, 0x34a540f8, 0x3402021, -0xc002b84, 0x240505c8, 0x3c020001, 0x8c426f24, -0x3c0d0001, 0x8dad6f04, 0x3c030001, 0x8c636f00, -0x3c080001, 0x8d086f0c, 0x3c090001, 0x8d296f28, -0x3c0a0001, 0x8d4a6f30, 0x3c0b0001, 0x8d6b6f40, -0x3c0c0001, 0x8d8c6f14, 0x3c040001, 0x24845d24, -0x24050400, 0xaf42013c, 0x8f42013c, 0x24060001, -0x24070001, 0xaf400000, 0xaf4d0138, 0xaf430144, -0xaf480148, 0xaf49014c, 0xaf4a0150, 0xaf4b0154, -0xaf4c0158, 0x2442ff80, 0xaf420140, 0x24020001, -0xafa20010, 0xc002b17, 0xafa00014, 0x8f420138, -0xafa20010, 0x8f42013c, 0xafa20014, 0x8f460144, -0x8f470148, 0x3c040001, 0x24845d30, 0xc002b17, -0x24050500, 0xafb70010, 0xafba0014, 0x8f46014c, -0x8f470150, 0x3c040001, 0x24845d3c, 0xc002b17, -0x24050600, 0x3c020001, 0x8c426f18, 0x3603821, -0x3c060002, 0x24c69090, 0x2448ffff, 0x1061824, -0xe81024, 0x43102b, 0x10400006, 0x24050900, -0x3c040001, 0x24845d48, 0xafa80010, 0xc002b17, -0xafa00014, 0x8f82000c, 0xafa20010, 0x8f82003c, -0xafa20014, 0x8f860000, 0x8f870004, 0x3c040001, -0x24845d54, 0xc002b17, 0x24051000, 0x8c020220, -0x8c030224, 0x8c060218, 0x8c07021c, 0x3c040001, -0x24845d5c, 0x24051100, 0xafa20010, 0xc002b17, -0xafa30014, 0xaf800054, 0xaf80011c, 0x8c020218, -0x30420002, 0x10400009, 0x0, 0x8c020220, -0x3c030002, 0x34630004, 0x431025, 0xaf42000c, -0x8c02021c, 0x10000008, 0x34420004, 0x8c020220, -0x3c030002, 0x34630006, 0x431025, 0xaf42000c, -0x8c02021c, 0x34420006, 0xaf420014, 0x8c020218, -0x30420010, 0x1040000a, 0x0, 0x8c02021c, -0x34420004, 0xaf420010, 0x8c020220, 0x3c03000a, -0x34630004, 0x431025, 0x10000009, 0xaf420008, -0x8c020220, 0x3c03000a, 0x34630006, 0x431025, -0xaf420008, 0x8c02021c, 0x34420006, 0xaf420010, -0x24020001, 0xaf8200a0, 0xaf8200b0, 0x8f830054, -0x8f820054, 0x10000002, 0x24630064, 0x8f820054, -0x621023, 0x2c420065, 0x1440fffc, 0x0, -0x8c040208, 0x8c05020c, 0x26e20028, 0xaee20020, -0x24020490, 0xaee20010, 0xaee40008, 0xaee5000c, -0x26e40008, 0x8c820000, 0x8c830004, 0xaf820090, -0xaf830094, 0x8c820018, 0xaf8200b4, 0x9482000a, -0xaf82009c, 0x8f420014, 0xaf8200b0, 0x8f8200b0, -0x30420004, 0x1440fffd, 0x0, 0x8f8200b0, -0x3c03ef00, 0x431024, 0x10400021, 0x0, -0x8f8200b4, 0xafa20010, 0x8f820090, 0x8f830094, -0x3c040001, 0x24845d64, 0xafa30014, 0x8f8600b0, -0x8f87009c, 0x3c050001, 0xc002b17, 0x34a5200d, -0x3c040001, 0x24845d70, 0x240203ac, 0xafa20010, -0xafa00014, 0x8f860144, 0x3c070001, 0x24e75d78, -0xc002b17, 0x3405dead, 0x8f82011c, 0x34420002, -0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, -0x8f820140, 0x3c030001, 0x431025, 0xaf820140, -0x96e20472, 0x96e60452, 0x96e70462, 0xafa20010, -0x96e20482, 0x3c040001, 0x24845da4, 0x24051200, -0xc002b17, 0xafa20014, 0x96f00452, 0x32020001, -0x10400002, 0xb021, 0x24160001, 0x32020002, -0x54400001, 0x36d60002, 0x32020008, 0x54400001, -0x36d60004, 0x32020010, 0x54400001, 0x36d60008, -0x32020020, 0x54400001, 0x36d60010, 0x32020040, -0x54400001, 0x36d60020, 0x32020080, 0x54400001, -0x36d60040, 0x96e60482, 0x30c20200, 0x54400001, -0x36d64000, 0x96e30472, 0x30620200, 0x10400003, -0x30620100, 0x10000003, 0x36d62000, 0x54400001, -0x36d61000, 0x96f00462, 0x32c24000, 0x14400004, -0x3207009b, 0x30c2009b, 0x14e20007, 0x240e0001, -0x32c22000, 0x1440000d, 0x32020001, 0x3062009b, -0x10e20009, 0x240e0001, 0x3c040001, 0x24845db0, -0x24051300, 0x2003821, 0xa3ae003f, 0xafa30010, -0xc002b17, 0xafa00014, 0x32020001, 0x54400001, -0x36d60080, 0x32020002, 0x54400001, 0x36d60100, -0x32020008, 0x54400001, 0x36d60200, 0x32020010, -0x54400001, 0x36d60400, 0x32020080, 0x54400001, -0x36d60800, 0x8c020218, 0x30420200, 0x10400002, -0x3c020008, 0x2c2b025, 0x8c020218, 0x30420800, -0x10400002, 0x3c020080, 0x2c2b025, 0x8c020218, -0x30420400, 0x10400002, 0x3c020100, 0x2c2b025, -0x8c020218, 0x30420100, 0x10400002, 0x3c020200, -0x2c2b025, 0x8c020218, 0x30420080, 0x10400002, -0x3c020400, 0x2c2b025, 0x8c020218, 0x30422000, -0x10400002, 0x3c020010, 0x2c2b025, 0x8c020218, -0x30424000, 0x10400002, 0x3c020020, 0x2c2b025, -0x8c020218, 0x30421000, 0x10400002, 0x3c020040, -0x2c2b025, 0x8ee20498, 0x8ee3049c, 0xaf420160, -0xaf430164, 0x8ee204a0, 0x8ee304a4, 0xaf420168, -0xaf43016c, 0x8ee204a8, 0x8ee304ac, 0xaf420170, -0xaf430174, 0x8ee20428, 0x8ee3042c, 0xaf420178, -0xaf43017c, 0x8ee20448, 0x8ee3044c, 0xaf420180, -0xaf430184, 0x8ee20458, 0x8ee3045c, 0xaf420188, -0xaf43018c, 0x8ee20468, 0x8ee3046c, 0xaf420190, -0xaf430194, 0x8ee20478, 0x8ee3047c, 0xaf420198, -0xaf43019c, 0x8ee20488, 0x8ee3048c, 0xaf4201a0, -0xaf4301a4, 0x8ee204b0, 0x8ee304b4, 0x24040080, -0xaf4201a8, 0xaf4301ac, 0xc002b84, 0x24050080, -0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260, -0x24050200, 0x24060008, 0xc002b9b, 0xaf4201f8, -0x3c043b9a, 0x3484ca00, 0x3821, 0x24020006, -0x24030002, 0xaf4201f4, 0x240203e8, 0xaf430204, -0xaf430200, 0xaf4401fc, 0xaf420294, 0x24020001, -0xaf430290, 0xaf42029c, 0x3c030001, 0x671821, -0x90636d58, 0x3471021, 0x24e70001, 0xa043022c, -0x2ce2000f, 0x1440fff8, 0x3471821, 0x24e70001, -0x3c080001, 0x350840f8, 0x8f820040, 0x3c040001, -0x24845dbc, 0x24051400, 0x21702, 0x24420030, -0xa062022c, 0x3471021, 0xa040022c, 0x8c070218, -0x2c03021, 0x240205c8, 0xafa20010, 0xc002b17, -0xafa80014, 0x3c040001, 0x24845dc8, 0x3c050000, -0x24a55c20, 0x24060010, 0x27b10030, 0x2203821, -0x27b30034, 0xc00178b, 0xafb30010, 0x3c030001, -0x8c636d48, 0x1060000a, 0x408021, 0x8fa30030, -0x2405ff00, 0x8fa20034, 0x246400ff, 0x852024, -0x831823, 0x431023, 0xafa20034, 0xafa40030, -0xafb30010, 0x3c040001, 0x24845dd4, 0x3c050000, -0x24a54100, 0x24060108, 0xc00178b, 0x2203821, -0x409021, 0x32c20003, 0x50400045, 0x2203821, -0x8f820050, 0x3c030010, 0x431024, 0x10400016, -0x0, 0x8c020218, 0x30420040, 0x1040000f, -0x24020001, 0x8f820050, 0x8c030218, 0x240e0001, -0x3c040001, 0x24845de0, 0xa3ae003f, 0xafa20010, -0xafa30014, 0x8f870040, 0x24051500, 0xc002b17, -0x2c03021, 0x10000004, 0x0, 0x3c010001, -0x370821, 0xa02240f4, 0x3c040001, 0x24845dec, -0x3c050001, 0x24a55bd0, 0x3c060001, 0x24c65c3c, -0xc53023, 0x8f420010, 0x27b30030, 0x2603821, -0x27b10034, 0x34420a00, 0xaf420010, 0xc00178b, -0xafb10010, 0x3c040001, 0x24845e00, 0x3c050001, -0x24a5b604, 0x3c060001, 0x24c6b980, 0xc53023, -0x2603821, 0xaf420108, 0xc00178b, 0xafb10010, -0x3c040001, 0x24845e1c, 0x3c050001, 0x24a5bda0, -0x3c060001, 0x24c6c8a0, 0xc53023, 0x2603821, -0x3c010001, 0xac226f70, 0xc00178b, 0xafb10010, -0x3c040001, 0x24845e34, 0x10000024, 0x24051600, -0x3c040001, 0x24845e3c, 0x3c050001, 0x24a5a07c, -0x3c060001, 0x24c6a1a8, 0xc53023, 0xc00178b, -0xafb30010, 0x3c040001, 0x24845e4c, 0x3c050001, -0x24a5b1a0, 0x3c060001, 0x24c6b5fc, 0xc53023, -0x2203821, 0xaf420108, 0xc00178b, 0xafb30010, -0x3c040001, 0x24845e60, 0x3c050001, 0x24a5b988, -0x3c060001, 0x24c6bd98, 0xc53023, 0x2203821, -0x3c010001, 0xac226f70, 0xc00178b, 0xafb30010, -0x3c040001, 0x24845e74, 0x24051650, 0x2c03021, -0x3821, 0x3c010001, 0xac226f74, 0xafa00010, -0xc002b17, 0xafa00014, 0x32c20020, 0x10400021, -0x27a70030, 0x3c040001, 0x24845e80, 0x3c050001, -0x24a5b02c, 0x3c060001, 0x24c6b198, 0xc53023, -0x24022000, 0xaf42001c, 0x27a20034, 0xc00178b, -0xafa20010, 0x21900, 0x31982, 0x3c040800, -0x641825, 0xae430028, 0x24030010, 0xaf43003c, -0x96e30450, 0xaf430040, 0x8f430040, 0x3c040001, -0x24845e94, 0xafa00014, 0xafa30010, 0x8f47001c, -0x24051660, 0x3c010001, 0xac226f6c, 0x10000025, -0x32c60020, 0x8ee20448, 0x8ee3044c, 0xaf43001c, -0x8f42001c, 0x2442e000, 0x2c422001, 0x1440000a, -0x240e0001, 0x3c040001, 0x24845ea0, 0xa3ae003f, -0xafa00010, 0xafa00014, 0x8f46001c, 0x24051700, -0xc002b17, 0x3821, 0x3c020000, 0x24425c5c, -0x21100, 0x21182, 0x3c030800, 0x431025, -0xae420028, 0x24020008, 0xaf42003c, 0x96e20450, -0xaf420040, 0x8f420040, 0x3c040001, 0x24845eac, -0xafa00014, 0xafa20010, 0x8f47001c, 0x24051800, -0x32c60020, 0xc002b17, 0x0, 0x3c030001, -0x8c636f70, 0x3c050fff, 0x34a5ffff, 0x3c020001, -0x8c426f74, 0x3c040800, 0x651824, 0x31882, -0x641825, 0x451024, 0x21082, 0x441025, -0xae420080, 0x32c20180, 0x10400056, 0xae430020, -0x8f82005c, 0x3c030080, 0x431024, 0x1040000d, -0x0, 0x8f820050, 0xafa20010, 0x8f82005c, -0x240e0001, 0x3c040001, 0x24845eb8, 0xa3ae003f, -0xafa20014, 0x8f870040, 0x24051900, 0xc002b17, -0x2c03021, 0x8f820050, 0x3c030010, 0x431024, +0x24030003, 0xaf8300ec, 0x34420004, 0xc002b20, +0xaf820140, 0x3c0100c0, 0xc001763, 0xac203ffc, +0x401821, 0x3c020010, 0x3c010001, 0xac236e9c, +0x10620011, 0x43102b, 0x14400002, 0x3c020020, +0x3c020008, 0x1062000c, 0x24050100, 0x3c060001, +0x8cc66e9c, 0x3c040001, 0x24845c74, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020020, +0x3c010001, 0xac226e9c, 0x24020008, 0x3c010001, +0xac226eb4, 0x2402001f, 0x3c010001, 0xac226ec4, +0x24020016, 0x3c010001, 0xac226e98, 0x3c05fffe, +0x34a56f08, 0x3c020001, 0x8c426e9c, 0x3c030002, +0x24639010, 0x3c040001, 0x8c846cc4, 0x431023, +0x14800002, 0x458021, 0x2610fa38, 0x2402f000, +0x2028024, 0xc001785, 0x2002021, 0x2022823, +0x3c040020, 0x821823, 0x651823, 0x247bb000, +0x3c03fffe, 0x3463bf08, 0x363b821, 0x3c0600bf, +0x34c6f000, 0x3c070001, 0x8ce76cc0, 0x3c0300bf, +0x3463e000, 0x852023, 0x3c010001, 0xac246ea8, +0x822023, 0x3c010001, 0xac256e90, 0x52842, +0x3c010001, 0xac226e84, 0x27620ffc, 0x3c010001, +0xac226d20, 0x27621ffc, 0xdb3023, 0x7b1823, +0x3c010001, 0xac246e88, 0x3c010001, 0xac256eac, +0x3c010001, 0xac226d24, 0xaf860150, 0x10e00011, +0xaf830250, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021, +0xc001749, 0x0, 0x3c020001, 0x8c426cd0, +0x3c030001, 0x8c636cd4, 0x2442fe00, 0x24630200, +0x3c010001, 0xac226cd0, 0x3c010001, 0x10000004, +0xac236cd4, 0x3c1d0001, 0x8fbd6d20, 0x3a0f021, +0x3c020001, 0x8c426cc4, 0x1040000d, 0x26fafa38, +0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, +0x3c1a0001, 0x8f5a6cd4, 0x2442fa38, 0x246305c8, +0x3c010001, 0xac226cd0, 0x3c010001, 0xac236cd4, +0x3c020001, 0x8c426cc8, 0x14400003, 0x0, +0x3c010001, 0xac206cd0, 0xc001151, 0x0, +0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, +0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, +0x27bdff98, 0xafb00048, 0x3c100001, 0x8e1066b8, +0xafb20050, 0x3c120000, 0x26524100, 0xafbf0060, +0xafbe005c, 0xafb50058, 0xafb30054, 0xafb1004c, +0xafa20034, 0xafa30030, 0xafa00010, 0xafa00014, +0x8f860040, 0x3c040001, 0x24845c80, 0x24050200, +0x3c010001, 0xac326e80, 0xc002b3b, 0x2003821, +0x8f830040, 0x3c02f000, 0x621824, 0x3c026000, +0x1062000b, 0xa3a0003f, 0x240e0001, 0x3c040001, +0x24845c88, 0xa3ae003f, 0xafa00010, 0xafa00014, +0x8f860040, 0x24050300, 0xc002b3b, 0x2003821, +0x8f820240, 0x3c030001, 0x431025, 0xaf820240, +0xaf800048, 0x8f820048, 0x14400005, 0x0, +0xaf800048, 0x8f820048, 0x10400004, 0x0, +0xaf800048, 0x10000003, 0x2e02021, 0xaf80004c, +0x2e02021, 0x3c050001, 0xc002ba8, 0x34a540f8, +0x3402021, 0xc002ba8, 0x240505c8, 0x3c020001, +0x8c426ea8, 0x3c0d0001, 0x8dad6e88, 0x3c030001, +0x8c636e84, 0x3c080001, 0x8d086e90, 0x3c090001, +0x8d296eac, 0x3c0a0001, 0x8d4a6eb4, 0x3c0b0001, +0x8d6b6ec4, 0x3c0c0001, 0x8d8c6e98, 0x3c040001, +0x24845c94, 0x24050400, 0xaf42013c, 0x8f42013c, +0x24060001, 0x24070001, 0xaf400000, 0xaf4d0138, +0xaf430144, 0xaf480148, 0xaf49014c, 0xaf4a0150, +0xaf4b0154, 0xaf4c0158, 0x2442ff80, 0xaf420140, +0x24020001, 0xafa20010, 0xc002b3b, 0xafa00014, +0x8f420138, 0xafa20010, 0x8f42013c, 0xafa20014, +0x8f460144, 0x8f470148, 0x3c040001, 0x24845ca0, +0xc002b3b, 0x24050500, 0xafb70010, 0xafba0014, +0x8f46014c, 0x8f470150, 0x3c040001, 0x24845cac, +0xc002b3b, 0x24050600, 0x3c020001, 0x8c426e9c, +0x3603821, 0x3c060002, 0x24c69010, 0x2448ffff, +0x1061824, 0xe81024, 0x43102b, 0x10400006, +0x24050900, 0x3c040001, 0x24845cb8, 0xafa80010, +0xc002b3b, 0xafa00014, 0x8f82000c, 0xafa20010, +0x8f82003c, 0xafa20014, 0x8f860000, 0x8f870004, +0x3c040001, 0x24845cc4, 0xc002b3b, 0x24051000, +0x8c020220, 0x8c030224, 0x8c060218, 0x8c07021c, +0x3c040001, 0x24845ccc, 0x24051100, 0xafa20010, +0xc002b3b, 0xafa30014, 0xaf800054, 0xaf80011c, +0x8c020218, 0x30420002, 0x10400009, 0x0, +0x8c020220, 0x3c030002, 0x34630004, 0x431025, +0xaf42000c, 0x8c02021c, 0x10000008, 0x34420004, +0x8c020220, 0x3c030002, 0x34630006, 0x431025, +0xaf42000c, 0x8c02021c, 0x34420006, 0xaf420014, +0x8c020218, 0x30420010, 0x1040000a, 0x0, +0x8c02021c, 0x34420004, 0xaf420010, 0x8c020220, +0x3c03000a, 0x34630004, 0x431025, 0x10000009, +0xaf420008, 0x8c020220, 0x3c03000a, 0x34630006, +0x431025, 0xaf420008, 0x8c02021c, 0x34420006, +0xaf420010, 0x24020001, 0xaf8200a0, 0xaf8200b0, +0x8f830054, 0x8f820054, 0xaf8000d0, 0xaf8000c0, +0x10000002, 0x24630064, 0x8f820054, 0x621023, +0x2c420065, 0x1440fffc, 0x0, 0x8c040208, +0x8c05020c, 0x26e20028, 0xaee20020, 0x24020490, +0xaee20010, 0xaee40008, 0xaee5000c, 0x26e40008, +0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, +0x8c820018, 0xaf8200b4, 0x9482000a, 0xaf82009c, +0x8f420014, 0xaf8200b0, 0x8f8200b0, 0x30420004, +0x1440fffd, 0x0, 0x8f8200b0, 0x3c03ef00, +0x431024, 0x10400021, 0x0, 0x8f8200b4, +0xafa20010, 0x8f820090, 0x8f830094, 0x3c040001, +0x24845cd4, 0xafa30014, 0x8f8600b0, 0x8f87009c, +0x3c050001, 0xc002b3b, 0x34a5200d, 0x3c040001, +0x24845ce0, 0x240203c0, 0xafa20010, 0xafa00014, +0x8f860144, 0x3c070001, 0x24e75ce8, 0xc002b3b, +0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, +0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, +0x3c030001, 0x431025, 0xaf820140, 0x96e20472, +0x96e60452, 0x96e70462, 0xafa20010, 0x96e20482, +0x3c040001, 0x24845d14, 0x24051200, 0xc002b3b, +0xafa20014, 0x96f00452, 0x32020001, 0x10400002, +0xb021, 0x24160001, 0x32020002, 0x54400001, +0x36d60002, 0x32020008, 0x54400001, 0x36d60004, +0x32020010, 0x54400001, 0x36d60008, 0x32020020, +0x54400001, 0x36d60010, 0x32020040, 0x54400001, +0x36d60020, 0x32020080, 0x54400001, 0x36d60040, +0x96e60482, 0x30c20200, 0x54400001, 0x36d64000, +0x96e30472, 0x30620200, 0x10400003, 0x30620100, +0x10000003, 0x36d62000, 0x54400001, 0x36d61000, +0x96f00462, 0x32c24000, 0x14400004, 0x3207009b, +0x30c2009b, 0x14e20007, 0x240e0001, 0x32c22000, +0x1440000d, 0x32020001, 0x3062009b, 0x10e20009, +0x240e0001, 0x3c040001, 0x24845d20, 0x24051300, +0x2003821, 0xa3ae003f, 0xafa30010, 0xc002b3b, +0xafa00014, 0x32020001, 0x54400001, 0x36d60080, +0x32020002, 0x54400001, 0x36d60100, 0x32020008, +0x54400001, 0x36d60200, 0x32020010, 0x54400001, +0x36d60400, 0x32020080, 0x54400001, 0x36d60800, +0x8c020218, 0x30420200, 0x10400002, 0x3c020008, +0x2c2b025, 0x8c020218, 0x30420800, 0x10400002, +0x3c020080, 0x2c2b025, 0x8c020218, 0x30420400, +0x10400002, 0x3c020100, 0x2c2b025, 0x8c020218, +0x30420100, 0x10400002, 0x3c020200, 0x2c2b025, +0x8c020218, 0x30420080, 0x10400002, 0x3c020400, +0x2c2b025, 0x8c020218, 0x30422000, 0x10400002, +0x3c020010, 0x2c2b025, 0x8c020218, 0x30424000, +0x10400002, 0x3c020020, 0x2c2b025, 0x8c020218, +0x30421000, 0x10400002, 0x3c020040, 0x2c2b025, +0x8ee20498, 0x8ee3049c, 0xaf420160, 0xaf430164, +0x8ee204a0, 0x8ee304a4, 0xaf420168, 0xaf43016c, +0x8ee204a8, 0x8ee304ac, 0xaf420170, 0xaf430174, +0x8ee20428, 0x8ee3042c, 0xaf420178, 0xaf43017c, +0x8ee20448, 0x8ee3044c, 0xaf420180, 0xaf430184, +0x8ee20458, 0x8ee3045c, 0xaf420188, 0xaf43018c, +0x8ee20468, 0x8ee3046c, 0xaf420190, 0xaf430194, +0x8ee20478, 0x8ee3047c, 0xaf420198, 0xaf43019c, +0x8ee20488, 0x8ee3048c, 0xaf4201a0, 0xaf4301a4, +0x8ee204b0, 0x8ee304b4, 0x24040080, 0xaf4201a8, +0xaf4301ac, 0xc002ba8, 0x24050080, 0x8c02025c, +0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200, +0x24060008, 0xc002bbf, 0xaf4201f8, 0x3c043b9a, +0x3484ca00, 0x3821, 0x24020006, 0x24030002, +0xaf4201f4, 0x240203e8, 0xaf430204, 0xaf430200, +0xaf4401fc, 0xaf420294, 0x24020001, 0xaf430290, +0xaf42029c, 0x3c030001, 0x671821, 0x90636cd8, +0x3471021, 0x24e70001, 0xa043022c, 0x2ce2000f, +0x1440fff8, 0x3471821, 0x24e70001, 0x3c080001, +0x350840f8, 0x8f820040, 0x3c040001, 0x24845d2c, +0x24051400, 0x21702, 0x24420030, 0xa062022c, +0x3471021, 0xa040022c, 0x8c070218, 0x2c03021, +0x240205c8, 0xafa20010, 0xc002b3b, 0xafa80014, +0x3c040001, 0x24845d38, 0x3c050000, 0x24a55c80, +0x24060010, 0x27b10030, 0x2203821, 0x27b30034, +0xc0017a3, 0xafb30010, 0x3c030001, 0x8c636cc8, +0x1060000a, 0x408021, 0x8fa30030, 0x2405ff00, +0x8fa20034, 0x246400ff, 0x852024, 0x831823, +0x431023, 0xafa20034, 0xafa40030, 0x3c040001, +0x24845d44, 0x3c050000, 0x24a54100, 0x24060108, +0x2203821, 0xc0017a3, 0xafb30010, 0x409021, +0x32c20003, 0x3c010001, 0xac326e80, 0x10400045, +0x2203821, 0x8f820050, 0x3c030010, 0x431024, 0x10400016, 0x0, 0x8c020218, 0x30420040, 0x1040000f, 0x24020001, 0x8f820050, 0x8c030218, -0x240e0001, 0x3c040001, 0x24845de0, 0xa3ae003f, -0xafa20010, 0xafa30014, 0x8f870040, 0x24052000, -0xc002b17, 0x2c03021, 0x10000004, 0x0, +0x240e0001, 0x3c040001, 0x24845d50, 0xa3ae003f, +0xafa20010, 0xafa30014, 0x8f870040, 0x24051500, +0xc002b3b, 0x2c03021, 0x10000004, 0x0, +0x3c010001, 0x370821, 0xa02240f4, 0x3c040001, +0x24845d5c, 0x3c050001, 0x24a55b40, 0x3c060001, +0x24c65bac, 0xc53023, 0x8f420010, 0x27b30030, +0x2603821, 0x27b10034, 0x34420a00, 0xaf420010, +0xc0017a3, 0xafb10010, 0x3c040001, 0x24845d70, +0x3c050001, 0x24a5b714, 0x3c060001, 0x24c6ba90, +0xc53023, 0x2603821, 0xaf420108, 0xc0017a3, +0xafb10010, 0x3c040001, 0x24845d8c, 0x3c050001, +0x24a5be58, 0x3c060001, 0x24c6c900, 0xc53023, +0x2603821, 0x3c010001, 0xac226ef4, 0xc0017a3, +0xafb10010, 0x3c040001, 0x24845da4, 0x10000024, +0x24051600, 0x3c040001, 0x24845dac, 0x3c050001, +0x24a5a10c, 0x3c060001, 0x24c6a238, 0xc53023, +0xc0017a3, 0xafb30010, 0x3c040001, 0x24845dbc, +0x3c050001, 0x24a5b2b0, 0x3c060001, 0x24c6b70c, +0xc53023, 0x2203821, 0xaf420108, 0xc0017a3, +0xafb30010, 0x3c040001, 0x24845dd0, 0x3c050001, +0x24a5ba98, 0x3c060001, 0x24c6be50, 0xc53023, +0x2203821, 0x3c010001, 0xac226ef4, 0xc0017a3, +0xafb30010, 0x3c040001, 0x24845de4, 0x24051650, +0x2c03021, 0x3821, 0x3c010001, 0xac226ef8, +0xafa00010, 0xc002b3b, 0xafa00014, 0x32c20020, +0x10400021, 0x27a70030, 0x3c040001, 0x24845df0, +0x3c050001, 0x24a5b13c, 0x3c060001, 0x24c6b2a8, +0xc53023, 0x24022000, 0xaf42001c, 0x27a20034, +0xc0017a3, 0xafa20010, 0x21900, 0x31982, +0x3c040800, 0x641825, 0xae430028, 0x24030010, +0xaf43003c, 0x96e30450, 0xaf430040, 0x8f430040, +0x3c040001, 0x24845e04, 0xafa00014, 0xafa30010, +0x8f47001c, 0x24051660, 0x3c010001, 0xac226ef0, +0x10000025, 0x32c60020, 0x8ee20448, 0x8ee3044c, +0xaf43001c, 0x8f42001c, 0x2442e000, 0x2c422001, +0x1440000a, 0x240e0001, 0x3c040001, 0x24845e10, +0xa3ae003f, 0xafa00010, 0xafa00014, 0x8f46001c, +0x24051700, 0xc002b3b, 0x3821, 0x3c020000, +0x24425cbc, 0x21100, 0x21182, 0x3c030800, +0x431025, 0xae420028, 0x24020008, 0xaf42003c, +0x96e20450, 0xaf420040, 0x8f420040, 0x3c040001, +0x24845e1c, 0xafa00014, 0xafa20010, 0x8f47001c, +0x24051800, 0x32c60020, 0xc002b3b, 0x0, +0x3c050fff, 0x3c030001, 0x8c636ef4, 0x34a5ffff, +0x2403021, 0x3c020001, 0x8c426ef8, 0x3c040800, +0x651824, 0x31882, 0x641825, 0x451024, +0x21082, 0x441025, 0xacc20080, 0x32c20180, +0x10400056, 0xacc30020, 0x8f82005c, 0x3c030080, +0x431024, 0x1040000d, 0x0, 0x8f820050, +0xafa20010, 0x8f82005c, 0x240e0001, 0x3c040001, +0x24845e28, 0xa3ae003f, 0xafa20014, 0x8f870040, +0x24051900, 0xc002b3b, 0x2c03021, 0x8f820050, +0x3c030010, 0x431024, 0x10400016, 0x0, +0x8c020218, 0x30420040, 0x1040000f, 0x24020001, +0x8f820050, 0x8c030218, 0x240e0001, 0x3c040001, +0x24845d50, 0xa3ae003f, 0xafa20010, 0xafa30014, +0x8f870040, 0x24052000, 0xc002b3b, 0x2c03021, +0x10000004, 0x0, 0x3c010001, 0x370821, +0xa02240f4, 0x3c040001, 0x24845e34, 0x3c050001, +0x24a55ac0, 0x3c060001, 0x24c65b38, 0xc53023, +0x8f420008, 0x27b30030, 0x2603821, 0x27b10034, +0x34420e00, 0xaf420008, 0xc0017a3, 0xafb10010, +0x3c040001, 0x24845e4c, 0x3c050001, 0x24a5d8b4, +0x3c060001, 0x24c6e3c8, 0xc53023, 0x2603821, +0xaf42010c, 0xc0017a3, 0xafb10010, 0x3c040001, +0x24845e64, 0x3c050001, 0x24a5e9ac, 0x3c060001, +0x24c6f0f0, 0xc53023, 0x2603821, 0x3c010001, +0xac226f04, 0xc0017a3, 0xafb10010, 0x3c040001, +0x24845e7c, 0x10000027, 0x24052100, 0x3c040001, +0x24845e84, 0x3c050001, 0x24a59fc8, 0x3c060001, +0x24c6a104, 0xc53023, 0x27b10030, 0x2203821, +0x27b30034, 0xc0017a3, 0xafb30010, 0x3c040001, +0x24845e94, 0x3c050001, 0x24a5cad4, 0x3c060001, +0x24c6d8ac, 0xc53023, 0x2203821, 0xaf42010c, +0xc0017a3, 0xafb30010, 0x3c040001, 0x24845ea4, +0x3c050001, 0x24a5e84c, 0x3c060001, 0x24c6e9a4, +0xc53023, 0x2203821, 0x3c010001, 0xac226f04, +0xc0017a3, 0xafb30010, 0x3c040001, 0x24845eb8, +0x24052150, 0x2c03021, 0x3821, 0x3c010001, +0xac226f10, 0xafa00010, 0xc002b3b, 0xafa00014, +0x3c110fff, 0x3c030001, 0x8c636f04, 0x3631ffff, +0x2409821, 0x3c020001, 0x8c426f10, 0x3c0e0800, +0x711824, 0x31882, 0x6e1825, 0x511024, +0x21082, 0x4e1025, 0xae630038, 0xae620078, +0x8c020218, 0x30420040, 0x14400004, 0x24020001, 0x3c010001, 0x370821, 0xa02240f4, 0x3c040001, -0x24845ec4, 0x3c050001, 0x24a55b50, 0x3c060001, -0x24c65bc8, 0xc53023, 0x8f420008, 0x27b30030, -0x2603821, 0x27b10034, 0x34420e00, 0xaf420008, -0xc00178b, 0xafb10010, 0x3c040001, 0x24845edc, -0x3c050001, 0x24a5d814, 0x3c060001, 0x24c6e328, -0xc53023, 0x2603821, 0xaf42010c, 0xc00178b, -0xafb10010, 0x3c040001, 0x24845ef4, 0x3c050001, -0x24a5e90c, 0x3c060001, 0x24c6f050, 0xc53023, -0x2603821, 0x3c010001, 0xac226f80, 0xc00178b, -0xafb10010, 0x3c040001, 0x24845f0c, 0x10000027, -0x24052100, 0x3c040001, 0x24845f14, 0x3c050001, -0x24a59f38, 0x3c060001, 0x24c6a074, 0xc53023, -0x27b10030, 0x2203821, 0x27b30034, 0xc00178b, -0xafb30010, 0x3c040001, 0x24845f24, 0x3c050001, -0x24a5ca74, 0x3c060001, 0x24c6d80c, 0xc53023, -0x2203821, 0xaf42010c, 0xc00178b, 0xafb30010, -0x3c040001, 0x24845f34, 0x3c050001, 0x24a5e7ac, -0x3c060001, 0x24c6e904, 0xc53023, 0x2203821, -0x3c010001, 0xac226f80, 0xc00178b, 0xafb30010, -0x3c040001, 0x24845f48, 0x24052150, 0x2c03021, -0x3821, 0x3c010001, 0xac226f8c, 0xafa00010, -0xc002b17, 0xafa00014, 0x3c030001, 0x8c636f80, -0x3c110fff, 0x3631ffff, 0x3c020001, 0x8c426f8c, -0x3c1e0800, 0x711824, 0x31882, 0x7e1825, -0x511024, 0x21082, 0x5e1025, 0xae430038, -0xae420078, 0x8c020218, 0x30420040, 0x14400004, -0x24020001, 0x3c010001, 0x370821, 0xa02240f4, -0x3c040001, 0x24845f54, 0x3c050001, 0x24a5e330, -0x3c060001, 0x24c6e48c, 0xc53023, 0x27b50030, -0x2a03821, 0x27b30034, 0xc00178b, 0xafb30010, -0x3c010001, 0xac226f78, 0x511024, 0x21082, -0x5e1025, 0xae420050, 0x32c22000, 0x10400005, -0x2a03821, 0x3c020000, 0x24425c5c, 0x1000000d, -0x511024, 0x3c040001, 0x24845f68, 0x3c050001, -0x24a5e494, 0x3c060001, 0x24c6e644, 0xc53023, -0xc00178b, 0xafb30010, 0x3c010001, 0xac226f90, -0x511024, 0x21082, 0x5e1025, 0xae420048, -0x32c24000, 0x10400005, 0x27a70030, 0x3c020000, -0x24425c5c, 0x1000000e, 0x21100, 0x3c040001, -0x24845f80, 0x3c050001, 0x24a5e64c, 0x3c060001, -0x24c6e7a4, 0xc53023, 0x27a20034, 0xc00178b, -0xafa20010, 0x3c010001, 0xac226f84, 0x21100, -0x21182, 0x3c030800, 0x431025, 0xae420060, -0x3c040001, 0x24845f98, 0x3c050001, 0x24a581d0, -0x3c060001, 0x24c685f0, 0xc53023, 0x27b10030, -0x2203821, 0x27b30034, 0xc00178b, 0xafb30010, -0x3c1e0fff, 0x37deffff, 0x3c040001, 0x24845fa4, -0x3c050000, 0x24a56408, 0x3c060000, 0x24c66528, -0xc53023, 0x2203821, 0x3c010001, 0xac226f58, -0x5e1024, 0x21082, 0x3c150800, 0x551025, -0xae4200b8, 0xc00178b, 0xafb30010, 0x3c040001, -0x24845fb0, 0x3c050000, 0x24a56530, 0x3c060000, -0x24c667a8, 0xc53023, 0x2203821, 0x3c010001, -0xac226f4c, 0x5e1024, 0x21082, 0x551025, -0xae4200e8, 0xc00178b, 0xafb30010, 0x3c040001, -0x24845fc8, 0x3c050000, 0x24a567b0, 0x3c060000, -0x24c668e0, 0xc53023, 0x2203821, 0x3c010001, -0xac226f44, 0x5e1024, 0x21082, 0x551025, -0xae4200c0, 0xc00178b, 0xafb30010, 0x3c040001, -0x24845fe0, 0x3c050001, 0x24a5fa30, 0x3c060001, -0x24c6fb08, 0xc53023, 0x2203821, 0x3c010001, -0xac226f50, 0x5e1024, 0x21082, 0x551025, -0xae4200c8, 0xc00178b, 0xafb30010, 0x3c040001, -0x24845fec, 0x3c050001, 0x24a5c8dc, 0x3c060001, -0x24c6c9c0, 0xc53023, 0x2203821, 0xaf420110, -0xc00178b, 0xafb30010, 0x3c040001, 0x24845ffc, -0x3c050001, 0x24a5c8b0, 0x3c060001, 0x24c6c8d4, -0xc53023, 0x2203821, 0xaf420124, 0xc00178b, -0xafb30010, 0x3c040001, 0x2484600c, 0x3c050001, -0x24a55b10, 0x3c060001, 0x24c65b3c, 0xc53023, -0x2203821, 0xaf420120, 0xaf420114, 0xc00178b, -0xafb30010, 0x3c040001, 0x24846018, 0x3c050001, -0x24a5f1f8, 0x3c060001, 0x24c6f614, 0xc53023, -0x2203821, 0xaf420118, 0xc00178b, 0xafb30010, -0x3c010001, 0xac226f94, 0x5e1024, 0x21082, -0x551025, 0xc003f9b, 0xae4200d0, 0xc003c18, -0x0, 0xc002784, 0x0, 0xac000228, +0x24845ec4, 0x3c050001, 0x24a5e3d0, 0x3c060001, +0x24c6e52c, 0xc53023, 0x27be0030, 0x3c03821, +0x27b50034, 0xc0017a3, 0xafb50010, 0x3c010001, +0xac226efc, 0x511024, 0x21082, 0x3c0e0800, +0x4e1025, 0xae620050, 0x32c22000, 0x10400006, +0x3c03821, 0x3c020000, 0x24425cbc, 0x2221024, +0x1000000f, 0x21082, 0x3c040001, 0x24845ed8, +0x3c050001, 0x24a5e534, 0x3c060001, 0x24c6e6e4, +0xc53023, 0xc0017a3, 0xafb50010, 0x3c010001, +0xac226f14, 0x511024, 0x21082, 0x3c0e0800, +0x4e1025, 0xae620048, 0x32c24000, 0x10400005, +0x27a70030, 0x3c020000, 0x24425cbc, 0x1000000e, +0x21100, 0x3c040001, 0x24845ef0, 0x3c050001, +0x24a5e6ec, 0x3c060001, 0x24c6e844, 0xc53023, +0x27a20034, 0xc0017a3, 0xafa20010, 0x3c010001, +0xac226f08, 0x21100, 0x21182, 0x3c030800, +0x431025, 0xae420060, 0x3c040001, 0x24845f08, +0x3c050001, 0x24a58230, 0x3c060001, 0x24c68650, +0xc53023, 0x27b10030, 0x2203821, 0x27b30034, +0xc0017a3, 0xafb30010, 0x3c0e0fff, 0x35ceffff, +0x3c040001, 0x24845f14, 0x3c050000, 0x24a56468, +0x3c060000, 0x24c66588, 0xc53023, 0x2203821, +0x240f021, 0x3c010001, 0xac226edc, 0x4e1024, +0x21082, 0x3c150800, 0x551025, 0xafae0044, +0xafc200b8, 0xc0017a3, 0xafb30010, 0x3c040001, +0x24845f20, 0x3c050000, 0x24a56590, 0x3c060000, +0x24c66808, 0x8fae0044, 0xc53023, 0x2203821, +0x3c010001, 0xac226ed0, 0x4e1024, 0x21082, +0x551025, 0xafc200e8, 0xc0017a3, 0xafb30010, +0x3c040001, 0x24845f38, 0x3c050000, 0x24a56810, +0x3c060000, 0x24c66940, 0x8fae0044, 0xc53023, +0x2203821, 0x3c010001, 0xac226ec8, 0x4e1024, +0x21082, 0x551025, 0xafc200c0, 0xc0017a3, +0xafb30010, 0x3c040001, 0x24845f50, 0x3c050001, +0x24a5fad0, 0x3c060001, 0x24c6fba8, 0x8fae0044, +0xc53023, 0x2203821, 0x3c010001, 0xac226ed4, +0x4e1024, 0x21082, 0x551025, 0xafc200c8, +0xc0017a3, 0xafb30010, 0x3c040001, 0x24845f5c, +0x3c050001, 0x24a5c93c, 0x3c060001, 0x24c6ca20, +0xc53023, 0x2203821, 0xaf420110, 0xc0017a3, +0xafb30010, 0x3c040001, 0x24845f6c, 0x3c050001, +0x24a5c910, 0x3c060001, 0x24c6c934, 0xc53023, +0x2203821, 0xaf420124, 0xc0017a3, 0xafb30010, +0x3c040001, 0x24845f7c, 0x3c050001, 0x24a55a80, +0x3c060001, 0x24c65aac, 0xc53023, 0x2203821, +0xaf420120, 0xaf420114, 0xc0017a3, 0xafb30010, +0x3c040001, 0x24845f88, 0x3c050001, 0x24a5f298, +0x3c060001, 0x24c6f6b4, 0xc53023, 0x2203821, +0xaf420118, 0xc0017a3, 0xafb30010, 0x8fae0044, +0x3c010001, 0xac226f18, 0x4e1024, 0x21082, +0x551025, 0xc003fc3, 0xafc200d0, 0xc003c40, +0x0, 0xc0027a8, 0x0, 0xac000228, 0xac00022c, 0x96e20450, 0x2442ffff, 0xaf420038, 0x96e20460, 0xaf420080, 0x32c24000, 0x14400003, 0x0, 0x96e20480, 0xaf420084, 0x96e70490, 0x50e00001, 0x24070800, 0x24e2ffff, 0xaf420088, 0xaf42007c, 0x24020800, 0x10e2000f, 0x32c24000, 0x10400003, 0x24020400, 0x10e2000b, 0x0, -0x240e0001, 0x3c040001, 0x24846028, 0xa3ae003f, +0x240e0001, 0x3c040001, 0x24845f98, 0xa3ae003f, 0x96e60490, 0x24052170, 0x2c03821, 0xafa00010, -0xc002b17, 0xafa00014, 0x8f430138, 0x8f440138, +0xc002b3b, 0xafa00014, 0x8f430138, 0x8f440138, 0x24020001, 0xa34205c2, 0xaf430094, 0xaf440098, 0xafa00010, 0xafa00014, 0x8f460080, 0x8f470084, -0x3c040001, 0x24846034, 0xc002b17, 0x24052200, -0xc002480, 0x3c110800, 0x3c1433d8, 0x3694cb58, -0x3c020800, 0x34420080, 0x3c040001, 0x24846040, -0x3c050000, 0x24a55ca0, 0x3c060000, 0x24c65cbc, +0x3c040001, 0x24845fa4, 0xc002b3b, 0x24052200, +0xc0024a4, 0x3c110800, 0x3c1433d8, 0x3694cb58, +0x3c020800, 0x34420080, 0x3c040001, 0x24845fb0, +0x3c050000, 0x24a55d00, 0x3c060000, 0x24c65d1c, 0xc53023, 0x27a70030, 0xaf820060, 0x2402ffff, -0xaf820064, 0x27a20034, 0xc00178b, 0xafa20010, -0x3c010001, 0xac226f34, 0x21100, 0x21182, -0x511025, 0xc0018e4, 0xae420000, 0x8f820240, +0xaf820064, 0x27a20034, 0xc0017a3, 0xafa20010, +0x3c010001, 0xac226eb8, 0x21100, 0x21182, +0x511025, 0xc0018fc, 0xae420000, 0x8f820240, 0x3c030001, 0x431025, 0xaf820240, 0x3c020000, 0x24424034, 0xaf820244, 0xaf800240, 0x8f820060, 0x511024, 0x14400005, 0x3c030800, 0x8f820060, -0x431024, 0x1040fffd, 0x0, 0xc003c25, +0x431024, 0x1040fffd, 0x0, 0xc003c4d, 0x8821, 0x3c020100, 0xafa20020, 0x8f530018, 0x240200ff, 0x56620001, 0x26710001, 0x8c020228, 0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, -0x24845cb4, 0x3c050009, 0xafa00014, 0xafa20010, +0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, 0x8f45017c, 0x1021, @@ -5004,21 +5005,21 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x24070008, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001, -0x24845cbc, 0x3c050009, 0xafa20014, 0x8fa60020, +0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010, 0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400010, 0x0, 0x8f420340, 0x24420001, 0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, 0x8f820124, 0x3c040001, -0x24845cc4, 0x3c050009, 0xafa20014, 0x8fa60020, -0x34a50300, 0xc002b17, 0x2603821, 0x8f4202e4, +0x24845c34, 0x3c050009, 0xafa20014, 0x8fa60020, +0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202e4, 0x24420001, 0xaf4202e4, 0x8f4202e4, 0x93a2003f, 0x10400069, 0x3c020700, 0x34423000, 0xafa20028, 0x8f530018, 0x240200ff, 0x12620002, 0x8821, 0x26710001, 0x8c020228, 0x1622000e, 0x1330c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, -0x8c020228, 0x3c040001, 0x24845cb4, 0x3c050009, +0x8c020228, 0x3c040001, 0x24845c24, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60028, 0x1000003f, 0x34a50100, 0xd71021, 0x8fa30028, 0x8fa4002c, 0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, @@ -5027,18 +5028,18 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, -0x8f820124, 0x3c040001, 0x24845cbc, 0x3c050009, +0x8f820124, 0x3c040001, 0x24845c2c, 0x3c050009, 0xafa20014, 0x8fa60028, 0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c, 0xaf510018, 0x8f860120, 0x24020010, 0xafa20010, 0xafb10014, 0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400010, 0x0, 0x8f420340, 0x24420001, 0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, -0x8f820124, 0x3c040001, 0x24845cc4, 0x3c050009, -0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b17, +0x8f820124, 0x3c040001, 0x24845c34, 0x3c050009, +0xafa20014, 0x8fa60028, 0x34a50300, 0xc002b3b, 0x2603821, 0x8f4202f0, 0x24420001, 0xaf4202f0, -0x8f4202f0, 0x3c040001, 0x24846050, 0xafa00010, -0xafa00014, 0x8fa60028, 0x24052300, 0xc002b17, +0x8f4202f0, 0x3c040001, 0x24845fc0, 0xafa00010, +0xafa00014, 0x8fa60028, 0x24052300, 0xc002b3b, 0x3821, 0x10000004, 0x0, 0x8c020264, 0x10400005, 0x0, 0x8f8200a0, 0x30420004, 0x1440fffa, 0x0, 0x8f820044, 0x34420004, @@ -5049,31 +5050,31 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x431021, 0xaf420090, 0x24020001, 0xaf42008c, 0x32c20008, 0x10400006, 0x0, 0x8f820214, 0x3c038100, 0x3042ffff, 0x431025, 0xaf820214, -0x3c030001, 0x8c636e14, 0x30620002, 0x10400009, -0x30620001, 0x3c040001, 0x2484605c, 0x3c050000, -0x24a56cf0, 0x3c060000, 0x24c67168, 0x10000012, +0x3c030001, 0x8c636d94, 0x30620002, 0x10400009, +0x30620001, 0x3c040001, 0x24845fcc, 0x3c050000, +0x24a56d50, 0x3c060000, 0x24c671c8, 0x10000012, 0xc53023, 0x10400009, 0x0, 0x3c040001, -0x2484606c, 0x3c050000, 0x24a57170, 0x3c060000, -0x24c67618, 0x10000008, 0xc53023, 0x3c040001, -0x2484607c, 0x3c050000, 0x24a568e8, 0x3c060000, -0x24c66ce8, 0xc53023, 0x27a70030, 0x27a20034, -0xc00178b, 0xafa20010, 0x3c010001, 0xac226f48, -0x3c020001, 0x8c426f48, 0x3c030800, 0x21100, +0x24845fdc, 0x3c050000, 0x24a571d0, 0x3c060000, +0x24c67678, 0x10000008, 0xc53023, 0x3c040001, +0x24845fec, 0x3c050000, 0x24a56948, 0x3c060000, +0x24c66d48, 0xc53023, 0x27a70030, 0x27a20034, +0xc0017a3, 0xafa20010, 0x3c010001, 0xac226ecc, +0x3c020001, 0x8c426ecc, 0x3c030800, 0x21100, 0x21182, 0x431025, 0xae420040, 0x8f8200a0, 0xafa20010, 0x8f8200b0, 0xafa20014, 0x8f86005c, -0x8f87011c, 0x3c040001, 0x2484608c, 0x3c010001, -0xac366f20, 0x3c010001, 0xac206f10, 0x3c010001, -0xac3c6f08, 0x3c010001, 0xac3b6f38, 0x3c010001, -0xac376f3c, 0x3c010001, 0xac3a6f1c, 0xc002b17, +0x8f87011c, 0x3c040001, 0x24845ffc, 0x3c010001, +0xac366ea4, 0x3c010001, 0xac206e94, 0x3c010001, +0xac3c6e8c, 0x3c010001, 0xac3b6ebc, 0x3c010001, +0xac376ec0, 0x3c010001, 0xac3a6ea0, 0xc002b3b, 0x24052400, 0x8f820200, 0xafa20010, 0x8f820220, 0xafa20014, 0x8f860044, 0x8f870050, 0x3c040001, -0x24846098, 0xc002b17, 0x24052500, 0x8f830060, +0x24846008, 0xc002b3b, 0x24052500, 0x8f830060, 0x74100b, 0x242000a, 0x200f821, 0x0, -0xd, 0x8fbf0058, 0x8fbe0054, 0x8fb50050, -0x8fb3004c, 0x8fb20048, 0x8fb10044, 0x8fb00040, -0x3e00008, 0x27bd0060, 0x27bdffe0, 0x3c040001, -0x248460a4, 0x24052600, 0x3021, 0x3821, -0xafbf0018, 0xafa00010, 0xc002b17, 0xafa00014, +0xd, 0x8fbf0060, 0x8fbe005c, 0x8fb50058, +0x8fb30054, 0x8fb20050, 0x8fb1004c, 0x8fb00048, +0x3e00008, 0x27bd0068, 0x27bdffe0, 0x3c040001, +0x24846014, 0x24052600, 0x3021, 0x3821, +0xafbf0018, 0xafa00010, 0xc002b3b, 0xafa00014, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x3e00008, 0x0, 0x3e00008, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @@ -5083,15 +5084,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa40018, 0xa22823, 0xa32824, 0x8ca20000, 0x1044000a, 0x0, 0xafa50010, 0x8ca20000, 0xafa20014, 0x8f860150, 0x8f870250, 0x3c040001, -0x248460ac, 0xc002b17, 0x24052700, 0x8fbf0218, +0x2484601c, 0xc002b3b, 0x24052700, 0x8fbf0218, 0x3e00008, 0x27bd0220, 0x27bdffe0, 0x3c06abba, 0x34c6babe, 0xafb00018, 0x3c100004, 0x3c07007f, 0x34e7ffff, 0xafbf001c, 0x102840, 0x8e040000, 0x8ca30000, 0xaca00000, 0xae060000, 0x8ca20000, 0xaca30000, 0x10460005, 0xae040000, 0xa08021, 0xf0102b, 0x1040fff5, 0x102840, 0x3c040001, -0x248460b8, 0x24052800, 0x2003021, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x2001021, +0x24846028, 0x24052800, 0x2003021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x2001021, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x8c020224, 0x3047003f, 0x10e00010, 0x803021, 0x2821, 0x24030020, 0xe31024, 0x10400002, @@ -5106,84 +5107,84 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8ea20000, 0x2403fffc, 0xc38024, 0x50102b, 0x1440001b, 0xe08821, 0x8e330000, 0xafb00010, 0x8ea20000, 0xafa20014, 0x8e270000, 0x24053000, -0xc002b17, 0x2403021, 0x8e230000, 0x702021, +0xc002b3b, 0x2403021, 0x8e230000, 0x702021, 0x64102b, 0x10400007, 0x2402821, 0x8ca20000, 0xac620000, 0x24630004, 0x64102b, 0x1440fffb, 0x24a50004, 0x8ea20000, 0x501023, 0xaea20000, 0x8e220000, 0x501021, 0x1000000b, 0xae220000, 0x2402002d, 0xa0820000, 0xafb00010, 0x8ea20000, 0x2409821, 0xafa20014, 0x8e270000, 0x24053100, -0xc002b17, 0x2603021, 0x2601021, 0x8fbf002c, +0xc002b3b, 0x2603021, 0x2601021, 0x8fbf002c, 0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0030, 0x27bdffe8, -0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636f00, -0x3c040001, 0x8c846f0c, 0x34a5bf08, 0x24021ffc, -0x3c010001, 0xac226d50, 0x3c0200c0, 0x3c010001, -0xac226d54, 0x3c020020, 0xafbf0010, 0x3c0100c0, +0x3c1cc000, 0x3c05fffe, 0x3c030001, 0x8c636e84, +0x3c040001, 0x8c846e90, 0x34a5bf08, 0x24021ffc, +0x3c010001, 0xac226cd0, 0x3c0200c0, 0x3c010001, +0xac226cd4, 0x3c020020, 0xafbf0010, 0x3c0100c0, 0xac201ffc, 0x431023, 0x441023, 0x245bb000, -0x365b821, 0x3c1d0001, 0x8fbd6d4c, 0x3a0f021, +0x365b821, 0x3c1d0001, 0x8fbd6ccc, 0x3a0f021, 0x3c0400c0, 0x34840200, 0x3c1a00c0, 0x3c0300c0, -0x346307c8, 0x24021dfc, 0x3c010001, 0xac226d50, -0x24021834, 0x3c010001, 0xac246d54, 0x3c010001, -0xac226d50, 0x3c010001, 0xac236d54, 0xc0017f5, +0x346307c8, 0x24021dfc, 0x3c010001, 0xac226cd0, +0x24021834, 0x3c010001, 0xac246cd4, 0x3c010001, +0xac226cd0, 0x3c010001, 0xac236cd4, 0xc00180d, 0x375a0200, 0x8fbf0010, 0x3e00008, 0x27bd0018, -0x27bdffc8, 0x3c040001, 0x248460c4, 0x24053200, -0x3c020001, 0x8c426d50, 0x3c030001, 0x8c636d54, +0x27bdffc8, 0x3c040001, 0x24846034, 0x24053200, +0x3c020001, 0x8c426cd0, 0x3c030001, 0x8c636cd4, 0x3021, 0x3603821, 0xafbf0030, 0xafb3002c, 0xafb20028, 0xafb10024, 0xafb00020, 0xafa2001c, -0xafa30018, 0xafb70010, 0xc002b17, 0xafba0014, -0xc0018fe, 0x0, 0x8f820240, 0x34420004, +0xafa30018, 0xafb70010, 0xc002b3b, 0xafba0014, +0xc001916, 0x0, 0x8f820240, 0x34420004, 0xaf820240, 0x24020001, 0xaf420000, 0x3c020001, 0x571021, 0x904240f4, 0x10400092, 0x2403fffc, -0x3c100001, 0x2610abe3, 0x3c120001, 0x2652a7bc, +0x3c100001, 0x2610ac73, 0x3c120001, 0x2652a84c, 0x2121023, 0x438024, 0x8fa3001c, 0x3c040001, -0x248460d0, 0x70102b, 0x1440001a, 0x27b30018, +0x24846040, 0x70102b, 0x1440001a, 0x27b30018, 0x8fb10018, 0x24053000, 0x2403021, 0xafb00010, -0xafa30014, 0xc002b17, 0x2203821, 0x8fa30018, +0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018, 0x702021, 0x64102b, 0x10400007, 0x2403021, 0x8cc20000, 0xac620000, 0x24630004, 0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023, 0xafa2001c, 0x8e620000, 0x501021, 0x1000000a, 0xae620000, 0x2408821, 0x24053100, 0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021, 0x2402002d, -0xc002b17, 0xa0820000, 0x24070020, 0x8fa3001c, -0x3c040001, 0x248460ec, 0x24120020, 0x3c010001, -0xac316f2c, 0x2c620020, 0x1440001d, 0x27b10018, -0x8fb00018, 0x24053000, 0x3c060001, 0x24c66fd0, -0xafa70010, 0xafa30014, 0xc002b17, 0x2003821, -0x8fa30018, 0x3c040001, 0x24846fd0, 0x24650020, +0xc002b3b, 0xa0820000, 0x24070020, 0x8fa3001c, +0x3c040001, 0x2484605c, 0x24120020, 0x3c010001, +0xac316eb0, 0x2c620020, 0x1440001d, 0x27b10018, +0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f50, +0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821, +0x8fa30018, 0x3c040001, 0x24846f50, 0x24650020, 0x65102b, 0x10400007, 0x0, 0x8c820000, 0xac620000, 0x24630004, 0x65102b, 0x1440fffb, 0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c, 0x8e220000, 0x521021, 0x1000000b, 0xae220000, -0x3c100001, 0x26106fd0, 0x24053100, 0xafa70010, +0x3c100001, 0x26106f50, 0x24053100, 0xafa70010, 0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d, -0xc002b17, 0xa0820000, 0x24070020, 0x3c040001, -0x24846100, 0x8fa3001c, 0x24120020, 0x3c010001, -0xac306f60, 0x2c620020, 0x1440001d, 0x27b10018, -0x8fb00018, 0x24053000, 0x3c060001, 0x24c66ff0, -0xafa70010, 0xafa30014, 0xc002b17, 0x2003821, -0x8fa30018, 0x3c040001, 0x24846ff0, 0x24650020, +0xc002b3b, 0xa0820000, 0x24070020, 0x3c040001, +0x24846070, 0x8fa3001c, 0x24120020, 0x3c010001, +0xac306ee4, 0x2c620020, 0x1440001d, 0x27b10018, +0x8fb00018, 0x24053000, 0x3c060001, 0x24c66f70, +0xafa70010, 0xafa30014, 0xc002b3b, 0x2003821, +0x8fa30018, 0x3c040001, 0x24846f70, 0x24650020, 0x65102b, 0x10400007, 0x0, 0x8c820000, 0xac620000, 0x24630004, 0x65102b, 0x1440fffb, 0x24840004, 0x8fa2001c, 0x521023, 0xafa2001c, 0x8e220000, 0x521021, 0x1000000b, 0xae220000, -0x3c100001, 0x26106ff0, 0x24053100, 0xafa70010, +0x3c100001, 0x26106f70, 0x24053100, 0xafa70010, 0xafa30014, 0x8fa70018, 0x2003021, 0x2402002d, -0xc002b17, 0xa0820000, 0x3c010001, 0x10000031, -0xac306f5c, 0x3c100001, 0x261081bf, 0x3c120001, -0x2652803c, 0x2121023, 0x438024, 0x8fa3001c, -0x3c040001, 0x24846114, 0x70102b, 0x1440001a, +0xc002b3b, 0xa0820000, 0x3c010001, 0x10000031, +0xac306ee0, 0x3c100001, 0x2610821f, 0x3c120001, +0x2652809c, 0x2121023, 0x438024, 0x8fa3001c, +0x3c040001, 0x24846084, 0x70102b, 0x1440001a, 0x27b30018, 0x8fb10018, 0x24053000, 0x2403021, -0xafb00010, 0xafa30014, 0xc002b17, 0x2203821, +0xafb00010, 0xafa30014, 0xc002b3b, 0x2203821, 0x8fa30018, 0x702021, 0x64102b, 0x10400007, 0x2403021, 0x8cc20000, 0xac620000, 0x24630004, 0x64102b, 0x1440fffb, 0x24c60004, 0x8fa2001c, 0x501023, 0xafa2001c, 0x8e620000, 0x501021, 0x1000000a, 0xae620000, 0x2408821, 0x24053100, 0xafb00010, 0xafa30014, 0x8fa70018, 0x2203021, -0x2402002d, 0xc002b17, 0xa0820000, 0x3c010001, -0xac316f2c, 0x3c030001, 0x8c636f2c, 0x24020400, +0x2402002d, 0xc002b3b, 0xa0820000, 0x3c010001, +0xac316eb0, 0x3c030001, 0x8c636eb0, 0x24020400, 0x60f809, 0xaf820070, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0038, 0x0, 0x0, 0x8f820040, @@ -5197,21 +5198,21 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaf820078, 0x27bdffe8, 0xafbf0010, 0x8f820054, 0x244203e8, 0xaf820058, 0x3c020800, 0x2c21024, 0x10400004, 0x3c02f7ff, 0x3442ffff, 0x2c2b024, -0x36940040, 0x3c020001, 0x8c426e28, 0x10400017, -0x3c020200, 0x3c030001, 0x8c636f98, 0x10600016, -0x282a025, 0x3c020001, 0x8c426ec4, 0x14400012, -0x3c020200, 0x3c020001, 0x8c426e14, 0x30420003, +0x36940040, 0x3c020001, 0x8c426da8, 0x10400017, +0x3c020200, 0x3c030001, 0x8c636f1c, 0x10600016, +0x282a025, 0x3c020001, 0x8c426e44, 0x14400012, +0x3c020200, 0x3c020001, 0x8c426d94, 0x30420003, 0x1440000d, 0x3c020200, 0x8f830224, 0x3c020002, -0x8c42906c, 0x10620008, 0x3c020200, 0xc003d87, -0x0, 0x10000004, 0x3c020200, 0xc004161, +0x8c428fec, 0x10620008, 0x3c020200, 0xc003daf, +0x0, 0x10000004, 0x3c020200, 0xc004196, 0x0, 0x3c020200, 0x2c21024, 0x10400003, -0x0, 0xc001f33, 0x0, 0x8f4200d8, +0x0, 0xc001f4b, 0x0, 0x8f4200d8, 0x8f4300dc, 0x24420001, 0xaf4200d8, 0x43102b, 0x14400003, 0x0, 0xaf4000d8, 0x36940080, 0x8c030238, 0x1060000c, 0x0, 0x8f4201b0, 0x244203e8, 0xaf4201b0, 0x43102b, 0x14400006, 0x0, 0x934205c5, 0x14400003, 0x0, -0xc001d88, 0x0, 0x8fbf0010, 0x3e00008, +0xc001da0, 0x0, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0020, 0x8f43002c, 0x8f420038, 0x10620059, 0x0, 0x3c020001, 0x571021, 0x904240f0, @@ -5220,8 +5221,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f0, 0x8f820124, 0xafa20010, -0x8f820128, 0x3c040001, 0x248461b8, 0xafa20014, -0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b17, +0x8f820128, 0x3c040001, 0x24846128, 0xafa20014, +0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900, 0x1000005c, 0x0, 0x8f420300, 0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1, 0x10000027, 0xaf420038, 0x8f440170, @@ -5230,8 +5231,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, -0x248461c4, 0xafa20014, 0x8f46002c, 0x8f870120, -0x3c050009, 0xc002b17, 0x34a51100, 0x10000036, +0x24846134, 0xafa20014, 0x8f46002c, 0x8f870120, +0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036, 0x0, 0x8f420300, 0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, 0xaf430038, 0x3c010001, 0x370821, 0xa02040f1, @@ -5259,8 +5260,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f2, 0x8f820124, 0xafa20010, 0x8f820128, -0x3c040001, 0x248461cc, 0xafa20014, 0x8f460044, -0x8f870120, 0x3c050009, 0xc002b17, 0x34a51300, +0x3c040001, 0x2484613c, 0xafa20014, 0x8f460044, +0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000f, 0x0, 0x8f420304, 0x24420001, 0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2, 0x10000004, @@ -5272,20 +5273,20 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x431024, 0xaf820060, 0x8f420000, 0x10400003, 0x0, 0x10000002, 0xaf80004c, 0xaf800048, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008, -0x0, 0x3c020001, 0x8c426e28, 0x27bdffa8, +0x0, 0x3c020001, 0x8c426da8, 0x27bdffa8, 0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c, 0xafb00038, 0x104000d5, 0x8f900044, 0x8f4200d0, 0x24430001, 0x2842000b, 0x144000e4, 0xaf4300d0, 0x8f420004, 0x30420002, 0x1440009c, 0xaf4000d0, 0x8f420004, 0x3c030001, -0x8c636e18, 0x34420002, 0xaf420004, 0x24020001, +0x8c636d98, 0x34420002, 0xaf420004, 0x24020001, 0x14620003, 0x3c020600, 0x10000002, 0x34423000, 0x34421000, 0xafa20020, 0x8f4a0018, 0xafaa0034, 0x27aa0020, 0xafaa002c, 0x8faa0034, 0x240200ff, 0x11420002, 0x1821, 0x25430001, 0x8c020228, 0x609821, 0x1662000e, 0x3c050009, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, -0x8fa70034, 0x3c040001, 0x2484619c, 0xafa00014, +0x8fa70034, 0x3c040001, 0x2484610c, 0xafa00014, 0xafa20010, 0x8fa60020, 0x10000070, 0x34a50500, 0x8faa0034, 0xa38c0, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, @@ -5300,7 +5301,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x32a200ff, 0x54400018, 0xaf530018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034, 0xafa20010, 0x8f820124, -0x3c040001, 0x248461a8, 0xafa20014, 0x8d460000, +0x3c040001, 0x24846118, 0xafa20014, 0x8d460000, 0x3c050009, 0x10000035, 0x34a50600, 0x8f420308, 0x24150001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001e, 0x32a200ff, 0x8f830054, 0x8f820054, @@ -5313,8 +5314,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1440ffee, 0x0, 0x32a200ff, 0x14400011, 0x3c050009, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0x8fa70034, -0xafa20010, 0x8f820124, 0x3c040001, 0x248461b0, -0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17, +0xafa20010, 0x8f820124, 0x3c040001, 0x24846120, +0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 0x0, 0x8f4202ec, 0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001, 0x50400029, 0x36100040, 0x3c020400, 0x2c21024, 0x10400013, @@ -5337,19 +5338,19 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008, 0x0, 0x3c020001, -0x8c426e28, 0x27bdffb0, 0xafbf0048, 0xafbe0044, +0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 0x104000c7, 0xafb00030, 0x8f4200d0, 0x24430001, 0x2842000b, 0x144000da, 0xaf4300d0, 0x8f420004, 0x30420002, 0x14400097, 0xaf4000d0, 0x8f420004, -0x3c030001, 0x8c636e18, 0x34420002, 0xaf420004, +0x3c030001, 0x8c636d98, 0x34420002, 0xaf420004, 0x24020001, 0x14620003, 0x3c020600, 0x10000002, 0x34423000, 0x34421000, 0xafa20020, 0x1821, 0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, -0x2484619c, 0x3c050009, 0xafa00014, 0xafa20010, +0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, @@ -5363,7 +5364,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, -0x3c040001, 0x248461a8, 0x3c050009, 0xafa20014, +0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000035, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054, 0x8f820054, @@ -5376,43 +5377,43 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1440ffee, 0x0, 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, -0x8f820124, 0x3c040001, 0x248461b0, 0x3c050009, -0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17, +0x8f820124, 0x3c040001, 0x24846120, 0x3c050009, +0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001, 0x10400018, 0x24040001, 0x8f420250, 0x8f430254, 0x8f4501b4, -0x3c010001, 0x14650006, 0xa0246d71, 0x8f420270, +0x3c010001, 0x14650006, 0xa0246cf1, 0x8f420270, 0x8f430274, 0x8f4401b8, 0x10640021, 0x0, -0x8f420250, 0x8f430254, 0x3c040001, 0x90846d70, +0x8f420250, 0x8f430254, 0x3c040001, 0x90846cf0, 0x8f460270, 0x8f470274, 0x38840001, 0xaf4301b4, -0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246d70, -0x8f4200d4, 0x3c010001, 0xa0206d70, 0x24430001, +0xaf4701b8, 0x3c010001, 0x10000025, 0xa0246cf0, +0x8f4200d4, 0x3c010001, 0xa0206cf0, 0x24430001, 0x28420033, 0x1440001e, 0xaf4300d4, 0x3c020001, -0x90426d71, 0xaf4000d4, 0x10000017, 0x38420001, +0x90426cf1, 0xaf4000d4, 0x10000017, 0x38420001, 0x8f420004, 0x30420001, 0x10400008, 0x0, -0xc00567e, 0x2021, 0x3c010001, 0xa0206d71, -0x3c010001, 0x1000000e, 0xa0206d70, 0x8f4200d4, -0x3c010001, 0xa0206d70, 0x24430001, 0x284201f5, -0x14400007, 0xaf4300d4, 0x3c020001, 0x90426d71, -0xaf4000d4, 0x421026, 0x3c010001, 0xa0226d71, -0x3c030001, 0x8c636e18, 0x24020002, 0x1462000c, -0x3c030002, 0x3c030001, 0x90636d71, 0x24020001, -0x5462001f, 0x2021, 0x3c020001, 0x90426d70, +0xc00565a, 0x2021, 0x3c010001, 0xa0206cf1, +0x3c010001, 0x1000000e, 0xa0206cf0, 0x8f4200d4, +0x3c010001, 0xa0206cf0, 0x24430001, 0x284201f5, +0x14400007, 0xaf4300d4, 0x3c020001, 0x90426cf1, +0xaf4000d4, 0x421026, 0x3c010001, 0xa0226cf1, +0x3c030001, 0x8c636d98, 0x24020002, 0x1462000c, +0x3c030002, 0x3c030001, 0x90636cf1, 0x24020001, +0x5462001f, 0x2021, 0x3c020001, 0x90426cf0, 0x1443001b, 0x24040005, 0x10000019, 0x24040006, -0x3c020002, 0x8c429074, 0x431024, 0x1040000b, -0x24020001, 0x3c030001, 0x90636d71, 0x54620010, -0x2021, 0x3c020001, 0x90426d70, 0x1443000c, +0x3c020002, 0x8c428ff4, 0x431024, 0x1040000b, +0x24020001, 0x3c030001, 0x90636cf1, 0x54620010, +0x2021, 0x3c020001, 0x90426cf0, 0x1443000c, 0x24040003, 0x1000000a, 0x24040004, 0x3c030001, -0x90636d71, 0x14620006, 0x2021, 0x3c020001, -0x90426d70, 0x24040001, 0x50440001, 0x24040002, -0xc00567e, 0x0, 0x2402ff7f, 0x282a024, +0x90636cf1, 0x14620006, 0x2021, 0x3c020001, +0x90426cf0, 0x24040001, 0x50440001, 0x24040002, +0xc00565a, 0x0, 0x2402ff7f, 0x282a024, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, 0x3e00008, 0x0, 0x3c020001, -0x8c426e28, 0x27bdffb0, 0xafbf0048, 0xafbe0044, +0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 0x104000de, 0xafb00030, 0x8f4200d0, 0x3c040001, -0x8c846e18, 0x24430001, 0x2842000b, 0xaf4400e8, +0x8c846d98, 0x24430001, 0x2842000b, 0xaf4400e8, 0x144000fe, 0xaf4300d0, 0x8f420004, 0x30420002, 0x14400095, 0xaf4000d0, 0x8f420004, 0x34420002, 0xaf420004, 0x24020001, 0x14820003, 0x3c020600, @@ -5421,7 +5422,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, -0x3c040001, 0x2484619c, 0x3c050009, 0xafa00014, +0x3c040001, 0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, @@ -5435,7 +5436,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1440ffe9, 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, -0x8f820124, 0x3c040001, 0x248461a8, 0x3c050009, +0x8f820124, 0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000035, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff, 0x8f830054, @@ -5448,9 +5449,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2c4203e9, 0x1440ffee, 0x0, 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, -0xafa20010, 0x8f820124, 0x3c040001, 0x248461b0, +0xafa20010, 0x8f820124, 0x3c040001, 0x24846120, 0x3c050009, 0xafa20014, 0x8d460000, 0x34a50700, -0xc002b17, 0x3c03821, 0x8f4202ec, 0x24420001, +0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8f420004, 0x30420001, 0x10400033, 0x3c020400, 0x2c21024, 0x10400017, 0x0, 0x934205c0, 0x8f440250, 0x8f450254, @@ -5480,7 +5481,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f4300e8, 0x3042007f, 0xa34205c0, 0x24020001, 0x14620005, 0x0, 0x934405c0, 0x42102, 0x10000003, 0x348400f0, 0x934405c0, 0x3484000f, -0xc005664, 0x0, 0x2402ff7f, 0x282a024, +0xc005640, 0x0, 0x2402ff7f, 0x282a024, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, 0x3e00008, 0x0, 0x27bdffb0, @@ -5533,7 +5534,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, -0x2484619c, 0x3c050009, 0xafa00014, 0xafa20010, +0x2484610c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, @@ -5547,7 +5548,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, -0x3c040001, 0x248461a8, 0x3c050009, 0xafa20014, +0x3c040001, 0x24846118, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, @@ -5560,13 +5561,13 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x326200ff, 0x54400012, 0x24020001, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001, -0x248461b0, 0x3c050009, 0xafa20014, 0x8d460000, -0x34a50700, 0xc002b17, 0x3c03821, 0x1021, +0x24846120, 0x3c050009, 0xafa20014, 0x8d460000, +0x34a50700, 0xc002b3b, 0x3c03821, 0x1021, 0x1440005b, 0x24020001, 0x10000065, 0x0, 0x8f510018, 0x240200ff, 0x12220002, 0x8021, 0x26300001, 0x8c020228, 0x1602000e, 0x1130c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, -0x8c020228, 0x3c040001, 0x24846184, 0x3c050009, +0x8c020228, 0x3c040001, 0x248460f4, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, 0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, @@ -5575,15 +5576,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, -0x8f820124, 0x3c040001, 0x2484618c, 0x3c050009, +0x8f820124, 0x3c040001, 0x248460fc, 0x3c050009, 0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018, 0x8f860120, 0x24020010, 0xafa20010, 0xafb00014, 0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x54400011, 0x24020001, 0x8f420340, 0x24420001, 0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, -0x8f820124, 0x3c040001, 0x24846194, 0x3c050009, -0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b17, +0x8f820124, 0x3c040001, 0x24846104, 0x3c050009, +0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b, 0x2203821, 0x1021, 0x1040000d, 0x24020001, 0x8f4202e8, 0xa34005c6, 0xaf4001b0, 0x24420001, 0xaf4202e8, 0x8f4202e8, 0x8ee20150, 0x24420001, @@ -5603,11 +5604,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x14620005, 0x0, 0x8f430130, 0x8f8200b4, 0x10620010, 0x0, 0x8f820104, 0xaf420128, 0x8f8200b4, 0x8f430128, 0xaf420130, 0xafa30010, -0x8f420130, 0x3c040001, 0x248461d4, 0xafa20014, +0x8f420130, 0x3c040001, 0x24846144, 0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005, 0x10000031, 0x34a50900, 0x8f420128, 0xafa20010, 0x8f420130, -0x3c040001, 0x248461e0, 0xafa20014, 0x8f86011c, -0x8f8700b0, 0x3c050005, 0xc002b17, 0x34a51000, +0x3c040001, 0x24846150, 0xafa20014, 0x8f86011c, +0x8f8700b0, 0x3c050005, 0xc002b3b, 0x34a51000, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830104, 0x8f8200b0, 0x34420001, 0xaf8200b0, 0x24020008, 0xaf830104, 0xafa20010, 0xafa00014, 0x8f42000c, @@ -5615,9 +5616,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x26e60028, 0x40f809, 0x24070400, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f420128, -0xafa20010, 0x8f420130, 0x3c040001, 0x248461ec, +0xafa20010, 0x8f420130, 0x3c040001, 0x2484615c, 0xafa20014, 0x8f86011c, 0x8f8700b0, 0x3c050005, -0x34a51100, 0xc002b17, 0x0, 0x8f8200a0, +0x34a51100, 0xc002b3b, 0x0, 0x8f8200a0, 0x30420004, 0x10400069, 0x0, 0x8f43012c, 0x8f820124, 0x14620005, 0x0, 0x8f430134, 0x8f8200a4, 0x10620006, 0x0, 0x8f820124, @@ -5630,21 +5631,21 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x8f430134, 0x8f8200a4, 0x10620010, 0x0, 0x8f820124, 0xaf42012c, 0x8f8200a4, 0x8f43012c, 0xaf420134, 0xafa30010, 0x8f420134, -0x3c040001, 0x248461f8, 0xafa20014, 0x8f86011c, +0x3c040001, 0x24846168, 0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005, 0x10000032, 0x34a51200, 0x8f42012c, 0xafa20010, 0x8f420134, 0x3c040001, -0x24846204, 0xafa20014, 0x8f86011c, 0x8f8700a0, -0x3c050005, 0xc002b17, 0x34a51300, 0x8f82011c, +0x24846174, 0xafa20014, 0x8f86011c, 0x8f8700a0, +0x3c050005, 0xc002b3b, 0x34a51300, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f830124, 0x8f8200a0, 0x34420001, 0xaf8200a0, 0x24020080, 0xaf830124, 0xafa20010, 0xafa00014, 0x8f420014, 0x8c040208, 0x8c05020c, 0xafa20018, 0x8f420108, 0x3c060001, -0x24c66f54, 0x40f809, 0x24070004, 0x8f82011c, +0x24c66ed8, 0x40f809, 0x24070004, 0x8f82011c, 0x2403fffd, 0x431024, 0xaf82011c, 0x8ee201dc, 0x24420001, 0xaee201dc, 0x8ee201dc, 0x8f42012c, -0xafa20010, 0x8f420134, 0x3c040001, 0x24846210, +0xafa20010, 0x8f420134, 0x3c040001, 0x24846180, 0xafa20014, 0x8f86011c, 0x8f8700a0, 0x3c050005, -0x34a51400, 0xc002b17, 0x0, 0x8fbf0020, +0x34a51400, 0xc002b3b, 0x0, 0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3c081000, 0x24070001, 0x3c060080, 0x3c050100, 0x8f820070, 0x481024, 0x1040fffd, 0x0, 0x8f820054, 0x24420005, @@ -5712,8 +5713,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaf80004c, 0x1000006a, 0xaf800048, 0x30c20001, 0x10400004, 0x24020001, 0xaf820064, 0x10000064, 0x0, 0x30c20002, 0x1440000b, 0x3c050003, -0x3c040001, 0x248462d4, 0x34a50500, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x2402ffc0, +0x3c040001, 0x24846244, 0x34a50500, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x2402ffc0, 0x10000057, 0xaf820064, 0x8c05022c, 0x8c02010c, 0x10a20048, 0x51080, 0x8c460300, 0x24a20001, 0x3045003f, 0x24020003, 0xac05022c, 0x61e02, @@ -5732,7 +5733,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x34420100, 0xaf820060, 0x8f420000, 0x10400003, 0x0, 0x10000006, 0xaf80004c, -0x10000004, 0xaf800048, 0xc00217e, 0xc02021, +0x10000004, 0xaf800048, 0xc002196, 0xc02021, 0x402821, 0x8c02010c, 0x14a20002, 0x24020002, 0xaf820064, 0x8f820064, 0x30420002, 0x14400004, 0x0, 0x8c02010c, 0x14a2ffac, 0x0, @@ -5740,196 +5741,199 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x27bdffa0, 0xafb00040, 0x808021, 0x101602, 0x2442ffff, 0x304300ff, 0x2c620013, 0xafbf0058, 0xafbe0054, 0xafb50050, 0xafb3004c, -0xafb20048, 0xafb10044, 0x104001ec, 0xafa50034, -0x31080, 0x3c010001, 0x220821, 0x8c226318, +0xafb20048, 0xafb10044, 0x104001f3, 0xafa50034, +0x31080, 0x3c010001, 0x220821, 0x8c226288, 0x400008, 0x0, 0x101302, 0x30440fff, -0x24020001, 0x10820005, 0x24020002, 0x1082000a, -0x2402fffe, 0x10000021, 0x3c050003, 0x8f430004, -0x3c020001, 0x8c426f80, 0xaf440200, 0xaf440204, -0x10000007, 0x34630001, 0x8f430004, 0xaf440200, -0xaf440204, 0x621824, 0x3c020001, 0x2442c9c8, +0x24020001, 0x10820005, 0x24020002, 0x1082000c, +0x2402fffe, 0x10000024, 0x3c050003, 0x8f430004, +0x3c020001, 0x8c426f04, 0xaf440200, 0xaf440204, +0x3c040001, 0x8c846e80, 0x10000009, 0x34630001, +0x8f430004, 0xaf440200, 0xaf440204, 0x3c040001, +0x8c846e80, 0x621824, 0x3c020001, 0x2442ca28, 0x21100, 0x21182, 0xaf430004, 0x3c030800, -0x431025, 0x3c010000, 0xac224138, 0x8f840054, -0x41442, 0x41c82, 0x431021, 0x41cc2, -0x431023, 0x41d02, 0x431021, 0x41d42, -0x431023, 0x10000009, 0xaf420208, 0x3c040001, -0x248462e0, 0x34a51000, 0x2003021, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x8f4202a0, -0x24420001, 0xaf4202a0, 0x1000021b, 0x8f4202a0, -0x27b00028, 0x2002021, 0x24050210, 0xc002b9b, -0x24060008, 0xc0024f4, 0x2002021, 0x10000212, -0x0, 0x8faa0034, 0x27a40028, 0xa1880, -0x25420001, 0x3042003f, 0xafa20034, 0x8c650300, -0x8faa0034, 0x21080, 0x8c430300, 0x25420001, -0x3042003f, 0xafa20034, 0xac02022c, 0xafa50028, -0xc0024f4, 0xafa3002c, 0x100001ff, 0x0, -0x27b00028, 0x2002021, 0x24050210, 0xc002b9b, -0x24060008, 0xc002633, 0x2002021, 0x100001f6, -0x0, 0x8faa0034, 0x27a40028, 0xa1880, -0x25420001, 0x3042003f, 0xafa20034, 0x8c650300, -0x8faa0034, 0x21080, 0x8c430300, 0x25420001, -0x3042003f, 0xafa20034, 0xac02022c, 0xafa50028, -0xc002633, 0xafa3002c, 0x100001e3, 0x0, -0x101302, 0x30430fff, 0x24020001, 0x10620005, -0x24020002, 0x1062001e, 0x3c020002, 0x10000033, -0x3c050003, 0x3c030002, 0x2c31024, 0x54400037, -0x2c3b025, 0x8f820228, 0x3c010001, 0x370821, -0xac2238d8, 0x8f82022c, 0x3c010001, 0x370821, -0xac2238dc, 0x8f820230, 0x3c010001, 0x370821, -0xac2238e0, 0x8f820234, 0x3c010001, 0x370821, -0xac2238e4, 0x2402ffff, 0xaf820228, 0xaf82022c, -0xaf820230, 0xaf820234, 0x10000020, 0x2c3b025, -0x2c21024, 0x10400012, 0x3c02fffd, 0x3c020001, -0x571021, 0x8c4238d8, 0xaf820228, 0x3c020001, -0x571021, 0x8c4238dc, 0xaf82022c, 0x3c020001, -0x571021, 0x8c4238e0, 0xaf820230, 0x3c020001, -0x571021, 0x8c4238e4, 0xaf820234, 0x3c02fffd, -0x3442ffff, 0x10000009, 0x2c2b024, 0x3c040001, -0x248462ec, 0x34a51100, 0x2003021, 0x3821, -0xafa00010, 0xc002b17, 0xafa00014, 0x8f4202cc, -0x24420001, 0xaf4202cc, 0x1000019b, 0x8f4202cc, -0x101302, 0x30450fff, 0x24020001, 0x10a20005, -0x24020002, 0x10a2000d, 0x3c0408ff, 0x10000014, -0x3c050003, 0x3c0208ff, 0x3442ffff, 0x8f830220, -0x3c040004, 0x2c4b025, 0x621824, 0x34630008, -0xaf830220, 0x10000012, 0xaf450298, 0x3484fff7, -0x3c03fffb, 0x8f820220, 0x3463ffff, 0x2c3b024, -0x441024, 0xaf820220, 0x10000009, 0xaf450298, -0x3c040001, 0x248462f8, 0x34a51200, 0x2003021, -0x3821, 0xafa00010, 0xc002b17, 0xafa00014, -0x8f4202bc, 0x24420001, 0xaf4202bc, 0x10000172, -0x8f4202bc, 0x27840208, 0x24050200, 0xc002b9b, -0x24060008, 0x27440224, 0x24050200, 0xc002b9b, -0x24060008, 0x8f4202c4, 0x24420001, 0xaf4202c4, -0x10000165, 0x8f4202c4, 0x101302, 0x30430fff, -0x24020001, 0x10620011, 0x28620002, 0x50400005, -0x24020002, 0x10600007, 0x0, 0x10000017, -0x0, 0x1062000f, 0x0, 0x10000013, -0x0, 0x8c060248, 0x2021, 0xc005134, -0x24050004, 0x10000007, 0x0, 0x8c060248, -0x2021, 0xc005134, 0x24050004, 0x10000010, -0x0, 0x8c06024c, 0x2021, 0xc005134, -0x24050001, 0x1000000a, 0x0, 0x3c040001, -0x24846304, 0x3c050003, 0x34a51300, 0x2003021, -0x3821, 0xafa00010, 0xc002b17, 0xafa00014, -0x8f4202c0, 0x24420001, 0xaf4202c0, 0x10000136, -0x8f4202c0, 0xc002407, 0x0, 0x10000132, -0x0, 0x24020001, 0xa34205c5, 0x24100100, -0x8f4401a8, 0x8f4501ac, 0xafb00010, 0xafa00014, -0x8f420014, 0xafa20018, 0x8f420108, 0x26e60028, -0x40f809, 0x24070400, 0x1040fff5, 0x0, -0x10000121, 0x0, 0x3c02ffff, 0x34427fff, -0x2c2b024, 0x1821, 0x3c020900, 0xaf400058, -0xaf40005c, 0xaf400060, 0xaf400064, 0xaf400360, -0xafa20020, 0x8f5e0018, 0x27aa0020, 0x240200ff, -0x13c20002, 0xafaa003c, 0x27c30001, 0x8c020228, -0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, -0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, -0x3c040001, 0x2484629c, 0x3c050009, 0xafa00014, -0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500, -0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, -0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, -0x2021023, 0x2c4203e9, 0x1040001b, 0x9821, -0xe08821, 0x263504c0, 0x8f440178, 0x8f45017c, -0x2201821, 0x240a0004, 0xafaa0010, 0xafb20014, -0x8f48000c, 0x1021, 0x2f53021, 0xafa80018, -0x8f48010c, 0x24070008, 0xa32821, 0xa3482b, -0x822021, 0x100f809, 0x892021, 0x54400006, -0x24130001, 0x8f820054, 0x2021023, 0x2c4203e9, -0x1440ffe9, 0x0, 0x326200ff, 0x54400017, -0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, -0x8f420378, 0x8f820120, 0x8faa003c, 0xafa20010, -0x8f820124, 0x3c040001, 0x248462a8, 0x3c050009, -0xafa20014, 0x8d460000, 0x10000033, 0x34a50600, -0x8f420308, 0x24130001, 0x24420001, 0xaf420308, -0x8f420308, 0x1000001c, 0x326200ff, 0x8f830054, -0x8f820054, 0x247003e8, 0x2021023, 0x2c4203e9, -0x10400014, 0x9821, 0x24110010, 0x8f42000c, -0x8f440160, 0x8f450164, 0x8f860120, 0xafb10010, -0xafb20014, 0xafa20018, 0x8f42010c, 0x24070008, -0x40f809, 0x24c6001c, 0x1440ffe5, 0x0, -0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffef, -0x0, 0x326200ff, 0x14400011, 0x0, +0x431025, 0xac820038, 0x8f840054, 0x41442, +0x41c82, 0x431021, 0x41cc2, 0x431023, +0x41d02, 0x431021, 0x41d42, 0x431023, +0x10000009, 0xaf420208, 0x3c040001, 0x24846250, +0x34a51000, 0x2003021, 0x3821, 0xafa00010, +0xc002b3b, 0xafa00014, 0x8f4202a0, 0x24420001, +0xaf4202a0, 0x1000021f, 0x8f4202a0, 0x27b00028, +0x2002021, 0x24050210, 0xc002bbf, 0x24060008, +0xc002518, 0x2002021, 0x10000216, 0x0, +0x8faa0034, 0x27a40028, 0xa1880, 0x25420001, +0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034, +0x21080, 0x8c430300, 0x25420001, 0x3042003f, +0xafa20034, 0xac02022c, 0xafa50028, 0xc002518, +0xafa3002c, 0x10000203, 0x0, 0x27b00028, +0x2002021, 0x24050210, 0xc002bbf, 0x24060008, +0xc002657, 0x2002021, 0x100001fa, 0x0, +0x8faa0034, 0x27a40028, 0xa1880, 0x25420001, +0x3042003f, 0xafa20034, 0x8c650300, 0x8faa0034, +0x21080, 0x8c430300, 0x25420001, 0x3042003f, +0xafa20034, 0xac02022c, 0xafa50028, 0xc002657, +0xafa3002c, 0x100001e7, 0x0, 0x101302, +0x30430fff, 0x24020001, 0x10620005, 0x24020002, +0x1062001e, 0x3c020002, 0x10000033, 0x3c050003, +0x3c030002, 0x2c31024, 0x54400037, 0x2c3b025, +0x8f820228, 0x3c010001, 0x370821, 0xac2238d8, +0x8f82022c, 0x3c010001, 0x370821, 0xac2238dc, +0x8f820230, 0x3c010001, 0x370821, 0xac2238e0, +0x8f820234, 0x3c010001, 0x370821, 0xac2238e4, +0x2402ffff, 0xaf820228, 0xaf82022c, 0xaf820230, +0xaf820234, 0x10000020, 0x2c3b025, 0x2c21024, +0x10400012, 0x3c02fffd, 0x3c020001, 0x571021, +0x8c4238d8, 0xaf820228, 0x3c020001, 0x571021, +0x8c4238dc, 0xaf82022c, 0x3c020001, 0x571021, +0x8c4238e0, 0xaf820230, 0x3c020001, 0x571021, +0x8c4238e4, 0xaf820234, 0x3c02fffd, 0x3442ffff, +0x10000009, 0x2c2b024, 0x3c040001, 0x2484625c, +0x34a51100, 0x2003021, 0x3821, 0xafa00010, +0xc002b3b, 0xafa00014, 0x8f4202cc, 0x24420001, +0xaf4202cc, 0x1000019f, 0x8f4202cc, 0x101302, +0x30450fff, 0x24020001, 0x10a20005, 0x24020002, +0x10a2000d, 0x3c0408ff, 0x10000014, 0x3c050003, +0x3c0208ff, 0x3442ffff, 0x8f830220, 0x3c040004, +0x2c4b025, 0x621824, 0x34630008, 0xaf830220, +0x10000012, 0xaf450298, 0x3484fff7, 0x3c03fffb, +0x8f820220, 0x3463ffff, 0x2c3b024, 0x441024, +0xaf820220, 0x10000009, 0xaf450298, 0x3c040001, +0x24846268, 0x34a51200, 0x2003021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202bc, +0x24420001, 0xaf4202bc, 0x10000176, 0x8f4202bc, +0x27840208, 0x24050200, 0xc002bbf, 0x24060008, +0x27440224, 0x24050200, 0xc002bbf, 0x24060008, +0x8f4202c4, 0x24420001, 0xaf4202c4, 0x10000169, +0x8f4202c4, 0x101302, 0x30430fff, 0x24020001, +0x10620011, 0x28620002, 0x50400005, 0x24020002, +0x10600007, 0x0, 0x10000017, 0x0, +0x1062000f, 0x0, 0x10000013, 0x0, +0x8c060248, 0x2021, 0xc005104, 0x24050004, +0x10000007, 0x0, 0x8c060248, 0x2021, +0xc005104, 0x24050004, 0x10000010, 0x0, +0x8c06024c, 0x2021, 0xc005104, 0x24050001, +0x1000000a, 0x0, 0x3c040001, 0x24846274, +0x3c050003, 0x34a51300, 0x2003021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x8f4202c0, +0x24420001, 0xaf4202c0, 0x1000013a, 0x8f4202c0, +0xc002426, 0x0, 0x10000136, 0x0, +0x24020001, 0xa34205c5, 0x24100100, 0x8f4401a8, +0x8f4501ac, 0xafb00010, 0xafa00014, 0x8f420014, +0xafa20018, 0x8f420108, 0x26e60028, 0x40f809, +0x24070400, 0x1040fff5, 0x0, 0x10000125, +0x0, 0x3c03ffff, 0x34637fff, 0x8f420368, +0x8f440360, 0x2c3b024, 0x1821, 0xaf400058, +0xaf40005c, 0xaf400060, 0xaf400064, 0x441023, +0xaf420368, 0x3c020900, 0xaf400360, 0xafa20020, +0x8f5e0018, 0x27aa0020, 0x240200ff, 0x13c20002, +0xafaa003c, 0x27c30001, 0x8c020228, 0x609021, +0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, +0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, +0x2484620c, 0x3c050009, 0xafa00014, 0xafa20010, +0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, +0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, +0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, +0x2c4203e9, 0x1040001b, 0x9821, 0xe08821, +0x263504c0, 0x8f440178, 0x8f45017c, 0x2201821, +0x240a0004, 0xafaa0010, 0xafb20014, 0x8f48000c, +0x1021, 0x2f53021, 0xafa80018, 0x8f48010c, +0x24070008, 0xa32821, 0xa3482b, 0x822021, +0x100f809, 0x892021, 0x54400006, 0x24130001, +0x8f820054, 0x2021023, 0x2c4203e9, 0x1440ffe9, +0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa003c, 0xafa20010, 0x8f820124, -0x3c040001, 0x248462b0, 0x3c050009, 0xafa20014, -0x8d460000, 0x34a50700, 0xc002b17, 0x3c03821, -0x8f4202b0, 0x24420001, 0xaf4202b0, 0x8f4202b0, -0x8f4202f8, 0x24420001, 0xaf4202f8, 0x1000008a, -0x8f4202f8, 0x8c02025c, 0x27440224, 0xaf4201f0, -0x8c020260, 0x24050200, 0x24060008, 0xc002b9b, -0xaf4201f8, 0x8f820220, 0x30420008, 0x14400002, -0x24020001, 0x24020002, 0xaf420298, 0x8f4202ac, -0x24420001, 0xaf4202ac, 0x10000077, 0x8f4202ac, -0x3c0200ff, 0x3442ffff, 0x2021824, 0x32c20180, -0x14400006, 0x3402fffb, 0x43102b, 0x14400003, -0x0, 0x1000006c, 0xaf4300bc, 0x3c040001, -0x24846310, 0x3c050003, 0x34a51500, 0x2003021, -0x3821, 0xafa00010, 0xc002b17, 0xafa00014, -0x3c020700, 0x34421000, 0x101e02, 0x621825, -0xafa30020, 0x8f510018, 0x240200ff, 0x12220002, -0x8021, 0x26300001, 0x8c020228, 0x1602000e, -0x1130c0, 0x8f42033c, 0x24420001, 0xaf42033c, -0x8f42033c, 0x8c020228, 0x3c040001, 0x24846284, -0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, -0x1000003f, 0x34a50100, 0xd71021, 0x8fa30020, -0x8fa40024, 0xac4304c0, 0xac4404c4, 0xc01821, -0x8f440178, 0x8f45017c, 0x1021, 0x24070004, -0xafa70010, 0xafb00014, 0x8f48000c, 0x24c604c0, -0x2e63021, 0xafa80018, 0x8f48010c, 0x24070008, -0xa32821, 0xa3482b, 0x822021, 0x100f809, -0x892021, 0x1440000b, 0x24070008, 0x8f820120, -0xafa20010, 0x8f820124, 0x3c040001, 0x2484628c, -0x3c050009, 0xafa20014, 0x8fa60020, 0x1000001c, -0x34a50200, 0x8f440160, 0x8f450164, 0x8f43000c, -0xaf500018, 0x8f860120, 0x24020010, 0xafa20010, -0xafb00014, 0xafa30018, 0x8f42010c, 0x40f809, -0x24c6001c, 0x14400010, 0x0, 0x8f420340, -0x24420001, 0xaf420340, 0x8f420340, 0x8f820120, -0xafa20010, 0x8f820124, 0x3c040001, 0x24846294, -0x3c050009, 0xafa20014, 0x8fa60020, 0x34a50300, -0xc002b17, 0x2203821, 0x8f4202e0, 0x24420001, -0xaf4202e0, 0x8f4202e0, 0x8f4202f0, 0x24420001, -0xaf4202f0, 0x8f4202f0, 0x8fa20034, 0x8fbf0058, -0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048, -0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060, -0x27bdfff8, 0x2408ffff, 0x10a00014, 0x4821, -0x3c0aedb8, 0x354a8320, 0x90870000, 0x24840001, -0x3021, 0x1071026, 0x30420001, 0x10400002, -0x81842, 0x6a1826, 0x604021, 0x24c60001, -0x2cc20008, 0x1440fff7, 0x73842, 0x25290001, -0x125102b, 0x1440fff0, 0x0, 0x1001021, -0x3e00008, 0x27bd0008, 0x27bdffb8, 0xafbf0040, -0xafbe003c, 0xafb50038, 0xafb30034, 0xafb20030, -0xafb1002c, 0xafb00028, 0x8f870220, 0xafa7001c, -0x8f870200, 0xafa70024, 0x8f820220, 0x3c0308ff, -0x3463ffff, 0x431024, 0x34420004, 0xaf820220, -0x8f820200, 0x3c03c0ff, 0x3463ffff, 0x431024, -0x34420004, 0xaf820200, 0x8f53035c, 0x8f550360, -0x8f5e0364, 0x8f470368, 0xafa70014, 0x8f4202d0, -0x274401c0, 0x24420001, 0xaf4202d0, 0x8f5002d0, -0x8f510204, 0x8f520200, 0xc002b84, 0x24050400, -0xaf53035c, 0xaf550360, 0xaf5e0364, 0x8fa70014, -0xaf470368, 0xaf5002d0, 0xaf510204, 0xaf520200, +0x3c040001, 0x24846218, 0x3c050009, 0xafa20014, +0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, +0x24130001, 0x24420001, 0xaf420308, 0x8f420308, +0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, +0x247003e8, 0x2021023, 0x2c4203e9, 0x10400014, +0x9821, 0x24110010, 0x8f42000c, 0x8f440160, +0x8f450164, 0x8f860120, 0xafb10010, 0xafb20014, +0xafa20018, 0x8f42010c, 0x24070008, 0x40f809, +0x24c6001c, 0x1440ffe5, 0x0, 0x8f820054, +0x2021023, 0x2c4203e9, 0x1440ffef, 0x0, +0x326200ff, 0x14400011, 0x0, 0x8f420378, +0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, +0x8faa003c, 0xafa20010, 0x8f820124, 0x3c040001, +0x24846220, 0x3c050009, 0xafa20014, 0x8d460000, +0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b0, +0x24420001, 0xaf4202b0, 0x8f4202b0, 0x8f4202f8, +0x24420001, 0xaf4202f8, 0x1000008a, 0x8f4202f8, 0x8c02025c, 0x27440224, 0xaf4201f0, 0x8c020260, -0x24050200, 0x24060008, 0xaf4201f8, 0x24020006, -0xc002b9b, 0xaf4201f4, 0x3c023b9a, 0x3442ca00, -0xaf4201fc, 0x240203e8, 0x24040002, 0x24030001, -0xaf420294, 0xaf440290, 0xaf43029c, 0x8f820220, -0x30420008, 0x10400004, 0x0, 0xaf430298, -0x10000003, 0x3021, 0xaf440298, 0x3021, -0x3c030001, 0x661821, 0x90636d80, 0x3461021, -0x24c60001, 0xa043022c, 0x2cc2000f, 0x1440fff8, -0x3461821, 0x24c60001, 0x8f820040, 0x24040080, -0x24050080, 0x21702, 0x24420030, 0xa062022c, -0x3461021, 0xc002b84, 0xa040022c, 0x8fa7001c, -0x30e20004, 0x14400006, 0x0, 0x8f820220, -0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, -0x8fa70024, 0x30e20004, 0x14400006, 0x0, -0x8f820200, 0x3c03c0ff, 0x3463fffb, 0x431024, -0xaf820200, 0x8fbf0040, 0x8fbe003c, 0x8fb50038, -0x8fb30034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, -0x3e00008, 0x27bd0048, 0x0, 0xaf400104, +0x24050200, 0x24060008, 0xc002bbf, 0xaf4201f8, +0x8f820220, 0x30420008, 0x14400002, 0x24020001, +0x24020002, 0xaf420298, 0x8f4202ac, 0x24420001, +0xaf4202ac, 0x10000077, 0x8f4202ac, 0x3c0200ff, +0x3442ffff, 0x2021824, 0x32c20180, 0x14400006, +0x3402fffb, 0x43102b, 0x14400003, 0x0, +0x1000006c, 0xaf4300bc, 0x3c040001, 0x24846280, +0x3c050003, 0x34a51500, 0x2003021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x3c020700, +0x34421000, 0x101e02, 0x621825, 0xafa30020, +0x8f510018, 0x240200ff, 0x12220002, 0x8021, +0x26300001, 0x8c020228, 0x1602000e, 0x1130c0, +0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, +0x8c020228, 0x3c040001, 0x248461f4, 0x3c050009, +0xafa00014, 0xafa20010, 0x8fa60020, 0x1000003f, +0x34a50100, 0xd71021, 0x8fa30020, 0x8fa40024, +0xac4304c0, 0xac4404c4, 0xc01821, 0x8f440178, +0x8f45017c, 0x1021, 0x24070004, 0xafa70010, +0xafb00014, 0x8f48000c, 0x24c604c0, 0x2e63021, +0xafa80018, 0x8f48010c, 0x24070008, 0xa32821, +0xa3482b, 0x822021, 0x100f809, 0x892021, +0x1440000b, 0x24070008, 0x8f820120, 0xafa20010, +0x8f820124, 0x3c040001, 0x248461fc, 0x3c050009, +0xafa20014, 0x8fa60020, 0x1000001c, 0x34a50200, +0x8f440160, 0x8f450164, 0x8f43000c, 0xaf500018, +0x8f860120, 0x24020010, 0xafa20010, 0xafb00014, +0xafa30018, 0x8f42010c, 0x40f809, 0x24c6001c, +0x14400010, 0x0, 0x8f420340, 0x24420001, +0xaf420340, 0x8f420340, 0x8f820120, 0xafa20010, +0x8f820124, 0x3c040001, 0x24846204, 0x3c050009, +0xafa20014, 0x8fa60020, 0x34a50300, 0xc002b3b, +0x2203821, 0x8f4202e0, 0x24420001, 0xaf4202e0, +0x8f4202e0, 0x8f4202f0, 0x24420001, 0xaf4202f0, +0x8f4202f0, 0x8fa20034, 0x8fbf0058, 0x8fbe0054, +0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, +0x8fb00040, 0x3e00008, 0x27bd0060, 0x27bdfff8, +0x2408ffff, 0x10a00014, 0x4821, 0x3c0aedb8, +0x354a8320, 0x90870000, 0x24840001, 0x3021, +0x1071026, 0x30420001, 0x10400002, 0x81842, +0x6a1826, 0x604021, 0x24c60001, 0x2cc20008, +0x1440fff7, 0x73842, 0x25290001, 0x125102b, +0x1440fff0, 0x0, 0x1001021, 0x3e00008, +0x27bd0008, 0x27bdffb0, 0xafbf0048, 0xafbe0044, +0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, +0xafb00030, 0x8f870220, 0xafa70024, 0x8f870200, +0xafa7002c, 0x8f820220, 0x3c0308ff, 0x3463ffff, +0x431024, 0x34420004, 0xaf820220, 0x8f820200, +0x3c03c0ff, 0x3463ffff, 0x431024, 0x34420004, +0xaf820200, 0x8f530358, 0x8f55035c, 0x8f5e0360, +0x8f470364, 0xafa70014, 0x8f470368, 0xafa7001c, +0x8f4202d0, 0x274401c0, 0x24420001, 0xaf4202d0, +0x8f5002d0, 0x8f510204, 0x8f520200, 0xc002ba8, +0x24050400, 0xaf530358, 0xaf55035c, 0xaf5e0360, +0x8fa70014, 0xaf470364, 0x8fa7001c, 0xaf470368, +0xaf5002d0, 0xaf510204, 0xaf520200, 0x8c02025c, +0x27440224, 0xaf4201f0, 0x8c020260, 0x24050200, +0x24060008, 0xaf4201f8, 0x24020006, 0xc002bbf, +0xaf4201f4, 0x3c023b9a, 0x3442ca00, 0xaf4201fc, +0x240203e8, 0x24040002, 0x24030001, 0xaf420294, +0xaf440290, 0xaf43029c, 0x8f820220, 0x30420008, +0x10400004, 0x0, 0xaf430298, 0x10000003, +0x3021, 0xaf440298, 0x3021, 0x3c030001, +0x661821, 0x90636d00, 0x3461021, 0x24c60001, +0xa043022c, 0x2cc2000f, 0x1440fff8, 0x3461821, +0x24c60001, 0x8f820040, 0x24040080, 0x24050080, +0x21702, 0x24420030, 0xa062022c, 0x3461021, +0xc002ba8, 0xa040022c, 0x8fa70024, 0x30e20004, +0x14400006, 0x0, 0x8f820220, 0x3c0308ff, +0x3463fffb, 0x431024, 0xaf820220, 0x8fa7002c, +0x30e20004, 0x14400006, 0x0, 0x8f820200, +0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, +0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, +0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, +0x27bd0050, 0x0, 0x0, 0xaf400104, 0x24040001, 0x410c0, 0x2e21821, 0x24820001, 0x3c010001, 0x230821, 0xa42234d0, 0x402021, 0x2c820080, 0x1440fff8, 0x410c0, 0x24020001, @@ -5946,7 +5950,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2c450001, 0xa01021, 0x14400009, 0x24840008, 0x86102b, 0x1440fff0, 0x1021, 0x304200ff, 0x14400030, 0x24020001, 0x1000002e, 0x1021, -0x1000fffa, 0x24020001, 0x2002021, 0xc0023ed, +0x1000fffa, 0x24020001, 0x2002021, 0xc00240c, 0x24050006, 0x3042007f, 0x218c0, 0x2e31021, 0x3c010001, 0x220821, 0x942230d0, 0x1040fff2, 0x2e31021, 0x3c060001, 0xc23021, 0x94c630d0, @@ -5961,7 +5965,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x27bd0018, 0x3e00008, 0x0, 0x27bdffb0, 0x801021, 0xafb00030, 0x24500002, 0x2002021, 0x24050006, 0xafb10034, 0x408821, 0xafbf0048, -0xafbe0044, 0xafb50040, 0xafb3003c, 0xc0023ed, +0xafbe0044, 0xafb50040, 0xafb3003c, 0xc00240c, 0xafb20038, 0x3047007f, 0x710c0, 0x2e21021, 0x3c050001, 0xa22821, 0x94a530d0, 0x50a0001c, 0xa03021, 0x3c090001, 0x352934d2, 0x96280002, @@ -5974,15 +5978,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x10c00014, 0x610c0, 0x571821, 0x3c010001, 0x230821, 0x8c2334d0, 0x571021, 0xafa30010, 0x3c010001, 0x220821, 0x8c2234d4, 0x3c040001, -0x24846424, 0xafa20014, 0x8e260000, 0x8e270004, -0x3c050004, 0xc002b17, 0x34a50400, 0x10000063, +0x24846394, 0xafa20014, 0x8e260000, 0x8e270004, +0x3c050004, 0xc002b3b, 0x34a50400, 0x10000063, 0x3c020800, 0x8f450100, 0x10a00006, 0x510c0, 0x2e21021, 0x3c010001, 0x220821, 0x942234d0, 0xaf420100, 0xa03021, 0x14c00011, 0x628c0, 0x710c0, 0x2e21021, 0xafa70010, 0x3c010001, -0x220821, 0x942230d0, 0x3c040001, 0x24846430, +0x220821, 0x942230d0, 0x3c040001, 0x248463a0, 0xafa20014, 0x8e260000, 0x8e270004, 0x3c050004, -0xc002b17, 0x34a50500, 0x10000048, 0x3c020800, +0xc002b3b, 0x34a50500, 0x10000048, 0x3c020800, 0xb71821, 0x3c020001, 0x96040000, 0x344234d2, 0x621821, 0xa4640000, 0x8e020002, 0x720c0, 0xac620002, 0x2e41021, 0x3c030001, 0x621821, @@ -6005,7 +6009,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x240200ff, 0x13c20002, 0xafaa002c, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, -0x8c020228, 0x3c040001, 0x248463ec, 0x3c050009, +0x8c020228, 0x3c040001, 0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, @@ -6019,7 +6023,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, -0xafa20010, 0x8f820124, 0x3c040001, 0x248463f8, +0xafa20010, 0x8f820124, 0x3c040001, 0x24846368, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000033, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff, @@ -6032,8 +6036,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1440ffef, 0x0, 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, -0x8f820124, 0x3c040001, 0x24846400, 0x3c050009, -0xafa20014, 0x8d460000, 0x34a50700, 0xc002b17, +0x8f820124, 0x3c040001, 0x24846370, 0x3c050009, +0xafa20014, 0x8d460000, 0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b4, 0x24420001, 0xaf4202b4, 0x8f4202b4, 0x8f4202f4, 0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, @@ -6041,7 +6045,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x3e00008, 0x27bd0050, 0x27bdffa0, 0x801021, 0xafb00040, 0x24500002, 0x2002021, 0x24050006, 0xafb10044, 0x408821, 0xafbf0058, 0xafbe0054, -0xafb50050, 0xafb3004c, 0xc0023ed, 0xafb20048, +0xafb50050, 0xafb3004c, 0xc00240c, 0xafb20048, 0x3048007f, 0x810c0, 0x2e21021, 0x3c060001, 0xc23021, 0x94c630d0, 0x10c0001c, 0x3821, 0x3c0a0001, 0x354a34d2, 0x96290002, 0x610c0, @@ -6053,8 +6057,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x94c634d0, 0x14c0ffea, 0x610c0, 0x14c00011, 0xafa70028, 0x810c0, 0x2e21021, 0xafa80010, 0x3c010001, 0x220821, 0x942230d0, 0x3c040001, -0x2484643c, 0xafa20014, 0x8e260000, 0x8e270004, -0x3c050004, 0xc002b17, 0x34a50900, 0x10000075, +0x248463ac, 0xafa20014, 0x8e260000, 0x8e270004, +0x3c050004, 0xc002b3b, 0x34a50900, 0x10000075, 0x3c020800, 0x10e0000c, 0x610c0, 0x2e21021, 0x3c030001, 0x621821, 0x946334d0, 0x710c0, 0x2e21021, 0x3c010001, 0x220821, 0xa42334d0, @@ -6089,7 +6093,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafab0034, 0x27c30001, 0x8c020228, 0x609021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, 0x8c020228, 0x3c040001, -0x248463ec, 0x3c050009, 0xafa00014, 0xafa20010, +0x2484635c, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006b, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, 0x247003e8, 0x2021023, @@ -6103,7 +6107,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124, -0x3c040001, 0x248463f8, 0x3c050009, 0xafa20014, +0x3c040001, 0x24846368, 0x3c050009, 0xafa20014, 0x8d660000, 0x10000033, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001c, 0x326200ff, 0x8f830054, 0x8f820054, @@ -6116,14 +6120,14 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8fab0034, 0xafa20010, 0x8f820124, 0x3c040001, -0x24846400, 0x3c050009, 0xafa20014, 0x8d660000, -0x34a50700, 0xc002b17, 0x3c03821, 0x8f4202b8, +0x24846370, 0x3c050009, 0xafa20014, 0x8d660000, +0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202b8, 0x24420001, 0xaf4202b8, 0x8f4202b8, 0x8f4202f4, 0x24420001, 0xaf4202f4, 0x8f4202f4, 0x8fbf0058, 0x8fbe0054, 0x8fb50050, 0x8fb3004c, 0x8fb20048, 0x8fb10044, 0x8fb00040, 0x3e00008, 0x27bd0060, 0x0, 0x0, 0x0, 0x27bdffe0, -0x27644000, 0xafbf0018, 0xc002b84, 0x24051000, +0x27644000, 0xafbf0018, 0xc002ba8, 0x24051000, 0x3c030001, 0x34632cc0, 0x3c040001, 0x34842ec8, 0x24020020, 0xaf82011c, 0x2e31021, 0xaf800100, 0xaf800104, 0xaf800108, 0xaf800110, 0xaf800114, @@ -6132,15 +6136,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2e31021, 0xaf4200f0, 0x2e41021, 0xaf4200f4, 0x2e41021, 0xaf4200f8, 0x3c020001, 0x571021, 0x904240f4, 0x1440001c, 0x3c050001, 0x8f82011c, -0x3c040001, 0x24846500, 0x3c050001, 0x34420001, +0x3c040001, 0x24846470, 0x3c050001, 0x34420001, 0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c, -0x34a50100, 0xc002b17, 0x3821, 0x8c020218, +0x34a50100, 0xc002b3b, 0x3821, 0x8c020218, 0x30420040, 0x10400014, 0x0, 0x8f82011c, -0x3c040001, 0x2484650c, 0x3c050001, 0x34420004, +0x3c040001, 0x2484647c, 0x3c050001, 0x34420004, 0xaf82011c, 0xafa00010, 0xafa00014, 0x8f86011c, -0x10000007, 0x34a50200, 0x3c040001, 0x24846514, +0x10000007, 0x34a50200, 0x3c040001, 0x24846484, 0xafa00010, 0xafa00014, 0x8f86011c, 0x34a50300, -0xc002b17, 0x3821, 0x8fbf0018, 0x3e00008, +0xc002b3b, 0x3821, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x8fa90010, 0x8f83012c, 0x8faa0014, 0x8fab0018, 0x1060000a, 0x27624fe0, 0x14620002, 0x24680020, 0x27684800, 0x8f820128, 0x11020004, @@ -6181,55 +6185,55 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2e21021, 0x402021, 0x24020001, 0xaf4400ec, 0xac890000, 0xac820004, 0x24020001, 0x3e00008, 0x0, 0x3e00008, 0x0, 0x27bdffd8, -0x3c040001, 0x2484651c, 0x3c050001, 0xafbf0024, +0x3c040001, 0x2484648c, 0x3c050001, 0xafbf0024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900104, 0x8f9100b0, 0x8f92011c, 0x34a52500, 0x8f820100, -0x2403021, 0x2203821, 0xafa20010, 0xc002b17, +0x2403021, 0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c, -0x3c040001, 0x24846528, 0xafa20014, 0x8e060000, -0x8e070004, 0x3c050001, 0xc002b17, 0x34a52510, +0x3c040001, 0x24846498, 0xafa20014, 0x8e060000, +0x8e070004, 0x3c050001, 0xc002b3b, 0x34a52510, 0x8e020018, 0xafa20010, 0x8e02001c, 0x3c040001, -0x24846534, 0xafa20014, 0x8e060010, 0x8e070014, -0x3c050001, 0xc002b17, 0x34a52520, 0x3c027f00, +0x248464a4, 0xafa20014, 0x8e060010, 0x8e070014, +0x3c050001, 0xc002b3b, 0x34a52520, 0x3c027f00, 0x2221024, 0x3c030800, 0x54430016, 0x3c030200, 0x8f82009c, 0x3042ffff, 0x14400012, 0x3c030200, -0x3c040001, 0x24846540, 0x3c050002, 0x34a5f030, +0x3c040001, 0x248464b0, 0x3c050002, 0x34a5f030, 0x3021, 0x3821, 0x36420002, 0xaf82011c, 0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c, -0xafa00010, 0xc002b17, 0xafa00014, 0x10000024, +0xafa00010, 0xc002b3b, 0xafa00014, 0x10000024, 0x0, 0x2c31024, 0x1040000d, 0x2231024, 0x1040000b, 0x36420002, 0xaf82011c, 0x36220001, 0xaf8200b0, 0xaf900104, 0xaf92011c, 0x8f420330, 0x24420001, 0xaf420330, 0x10000015, 0x8f420330, -0x3c040001, 0x24846548, 0x240202a9, 0xafa20010, -0xafa00014, 0x8f860144, 0x3c070001, 0x24e76550, -0xc002b17, 0x3405dead, 0x8f82011c, 0x34420002, +0x3c040001, 0x248464b8, 0x240202a9, 0xafa20010, +0xafa00014, 0x8f860144, 0x3c070001, 0x24e764c0, +0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024, 0x8fb20020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0x3c040001, -0x24846578, 0x3c050001, 0xafbf0024, 0xafb20020, +0x248464e8, 0x3c050001, 0xafbf0024, 0xafb20020, 0xafb1001c, 0xafb00018, 0x8f900124, 0x8f9100a0, 0x8f92011c, 0x34a52600, 0x8f820120, 0x2403021, -0x2203821, 0xafa20010, 0xc002b17, 0xafb00014, +0x2203821, 0xafa20010, 0xc002b3b, 0xafb00014, 0x8e020008, 0xafa20010, 0x8e02000c, 0x3c040001, -0x24846584, 0xafa20014, 0x8e060000, 0x8e070004, -0x3c050001, 0xc002b17, 0x34a52610, 0x8e020018, -0xafa20010, 0x8e02001c, 0x3c040001, 0x24846590, +0x248464f4, 0xafa20014, 0x8e060000, 0x8e070004, +0x3c050001, 0xc002b3b, 0x34a52610, 0x8e020018, +0xafa20010, 0x8e02001c, 0x3c040001, 0x24846500, 0xafa20014, 0x8e060010, 0x8e070014, 0x3c050001, -0xc002b17, 0x34a52620, 0x3c027f00, 0x2221024, +0xc002b3b, 0x34a52620, 0x3c027f00, 0x2221024, 0x3c030800, 0x54430016, 0x3c030200, 0x8f8200ac, 0x3042ffff, 0x14400012, 0x3c030200, 0x3c040001, -0x2484659c, 0x3c050001, 0x34a5f030, 0x3021, +0x2484650c, 0x3c050001, 0x34a5f030, 0x3021, 0x3821, 0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0, 0xaf900124, 0xaf92011c, 0xafa00010, -0xc002b17, 0xafa00014, 0x10000024, 0x0, +0xc002b3b, 0xafa00014, 0x10000024, 0x0, 0x2c31024, 0x1040000d, 0x2231024, 0x1040000b, 0x36420002, 0xaf82011c, 0x36220001, 0xaf8200a0, 0xaf900124, 0xaf92011c, 0x8f42032c, 0x24420001, 0xaf42032c, 0x10000015, 0x8f42032c, 0x3c040001, -0x24846548, 0x240202e2, 0xafa20010, 0xafa00014, -0x8f860144, 0x3c070001, 0x24e76550, 0xc002b17, +0x248464b8, 0x240202e2, 0xafa20010, 0xafa00014, +0x8f860144, 0x3c070001, 0x24e764c0, 0xc002b3b, 0x3405dead, 0x8f82011c, 0x34420002, 0xaf82011c, 0x8f820220, 0x34420004, 0xaf820220, 0x8f820140, 0x3c030001, 0x431025, 0xaf820140, 0x8fbf0024, @@ -6238,24 +6242,24 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2821, 0x6821, 0x4821, 0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x1580002e, 0x8f8b011c, 0x11a00014, 0x31620800, 0x8f820120, -0x10460029, 0x0, 0x3c040001, 0x8c846f60, +0x10460029, 0x0, 0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, 0x10400017, 0x0, -0x3c040001, 0x8c846f60, 0x8d020000, 0x8d030004, +0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, 0xac820010, 0x8d020014, 0x240c0001, 0xc01821, 0xac820014, 0x27624fe0, 0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1540002f, 0x31620100, 0x11200014, 0x31628000, 0x8f820100, 0x1045002a, -0x31620100, 0x3c040001, 0x8c846f5c, 0x8ca20000, +0x31620100, 0x3c040001, 0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240a0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, 0x31620100, 0x3c040001, -0x8c846f5c, 0x8ce20000, 0x8ce30004, 0xac820000, +0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, 0x8ce20014, 0x240a0001, 0xa01821, 0xac820014, @@ -6264,7 +6268,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821, 0x11800011, 0x31621000, -0x3c040001, 0x8c846f60, 0x8c820000, 0x8c830004, +0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, 0x8c8f0014, 0x31621000, @@ -6273,7 +6277,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x3c020002, 0x1221024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x4821, 0x1140ff70, 0x0, -0x3c040001, 0x8c846f5c, 0x8c820000, 0x8c830004, +0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5021, 0xaf8200b0, 0x8c890010, 0x1000ff60, 0x8c8e0014, @@ -6282,11 +6286,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x7821, 0x7021, 0x8f880124, 0x8f870104, 0x3c180100, 0x1580002e, 0x8f89011c, 0x11a00014, 0x31220800, 0x8f820120, 0x10460029, 0x0, -0x3c040001, 0x8c846f60, 0x8cc20000, 0x8cc30004, +0x3c040001, 0x8c846ee4, 0x8cc20000, 0x8cc30004, 0xac820000, 0xac830004, 0x8cc20008, 0xac820008, 0x94c2000e, 0xa482000e, 0x8cc20010, 0x240c0001, 0xac820010, 0x8cc20014, 0x10000012, 0x24c60020, -0x10400017, 0x0, 0x3c040001, 0x8c846f60, +0x10400017, 0x0, 0x3c040001, 0x8c846ee4, 0x8d020000, 0x8d030004, 0xac820000, 0xac830004, 0x8d020008, 0xac820008, 0x9502000e, 0xa482000e, 0x8d020010, 0x25060020, 0xac820010, 0x8d020014, @@ -6294,11 +6298,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x43102b, 0x54400001, 0x27634800, 0x603021, 0x1560002f, 0x31220100, 0x11400014, 0x31228000, 0x8f820100, 0x1045002a, 0x31220100, 0x3c040001, -0x8c846f5c, 0x8ca20000, 0x8ca30004, 0xac820000, +0x8c846ee0, 0x8ca20000, 0x8ca30004, 0xac820000, 0xac830004, 0x8ca20008, 0xac820008, 0x94a2000e, 0xa482000e, 0x8ca20010, 0x240b0001, 0xac820010, 0x8ca20014, 0x10000012, 0x24a50020, 0x10400018, -0x31220100, 0x3c040001, 0x8c846f5c, 0x8ce20000, +0x31220100, 0x3c040001, 0x8c846ee0, 0x8ce20000, 0x8ce30004, 0xac820000, 0xac830004, 0x8ce20008, 0xac820008, 0x94e2000e, 0xa482000e, 0x8ce20010, 0x24e50020, 0xac820010, 0x8ce20014, 0x240b0001, @@ -6307,7 +6311,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x5440001d, 0x31221000, 0x11a00009, 0x31a20800, 0x10400004, 0x25020020, 0x8f8200a8, 0xa5e20000, 0x25020020, 0xaf820124, 0x8f880124, 0x6821, -0x11800011, 0x31221000, 0x3c040001, 0x8c846f60, +0x11800011, 0x31221000, 0x3c040001, 0x8c846ee4, 0x8c820000, 0x8c830004, 0xaf820080, 0xaf830084, 0x8c820008, 0xaf8200a4, 0x9482000e, 0xaf8200ac, 0x8c820010, 0x6021, 0xaf8200a0, 0x8c8d0010, @@ -6316,7 +6320,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f8200b8, 0xa5c20000, 0x3c020002, 0x1421024, 0x10400004, 0x24e20020, 0x8f8200b4, 0xaf8200d4, 0x24e20020, 0xaf820104, 0x8f870104, 0x5021, -0x11600010, 0x0, 0x3c040001, 0x8c846f5c, +0x11600010, 0x0, 0x3c040001, 0x8c846ee0, 0x8c820000, 0x8c830004, 0xaf820090, 0xaf830094, 0x8c820008, 0xaf8200b4, 0x9482000e, 0xaf82009c, 0x8c820010, 0x5821, 0xaf8200b0, 0x8c8a0010, @@ -6345,37 +6349,37 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f420000, 0x10400003, 0x0, 0x1000ff05, 0xaf80004c, 0x1000ff03, 0xaf800048, 0x3e00008, 0x0, 0x0, 0x0, 0x3c020001, -0x8c426da8, 0x27bdffe8, 0xafbf0014, 0x14400012, -0xafb00010, 0x3c100001, 0x26107010, 0x2002021, -0xc002b84, 0x24052000, 0x26021fe0, 0x3c010001, -0xac226f68, 0x3c010001, 0xac226f64, 0xac020250, +0x8c426d28, 0x27bdffe8, 0xafbf0014, 0x14400012, +0xafb00010, 0x3c100001, 0x26106f90, 0x2002021, +0xc002ba8, 0x24052000, 0x26021fe0, 0x3c010001, +0xac226eec, 0x3c010001, 0xac226ee8, 0xac020250, 0x24022000, 0xac100254, 0xac020258, 0x24020001, -0x3c010001, 0xac226da8, 0x8fbf0014, 0x8fb00010, -0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296f68, +0x3c010001, 0xac226d28, 0x8fbf0014, 0x8fb00010, +0x3e00008, 0x27bd0018, 0x3c090001, 0x8d296eec, 0x8c820000, 0x8fa30010, 0x8fa80014, 0xad220000, 0x8c820004, 0xad250008, 0xad220004, 0x8f820054, 0xad260010, 0xad270014, 0xad230018, 0xad28001c, -0xad22000c, 0x2529ffe0, 0x3c020001, 0x24427010, +0xad22000c, 0x2529ffe0, 0x3c020001, 0x24426f90, 0x122102b, 0x10400003, 0x0, 0x3c090001, -0x8d296f64, 0x3c020001, 0x8c426d90, 0xad220000, -0x3c020001, 0x8c426d90, 0x3c010001, 0xac296f68, +0x8d296ee8, 0x3c020001, 0x8c426d10, 0xad220000, +0x3c020001, 0x8c426d10, 0x3c010001, 0xac296eec, 0xad220004, 0xac090250, 0x3e00008, 0x0, -0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106f68, -0x3c020001, 0x8c426d90, 0xafb10014, 0x808821, +0x27bdffd0, 0xafb00010, 0x3c100001, 0x8e106eec, +0x3c020001, 0x8c426d10, 0xafb10014, 0x808821, 0xafbe0024, 0x8fbe0040, 0x8fa40048, 0xafb20018, 0xa09021, 0xafbf0028, 0xafb50020, 0xafb3001c, -0xae020000, 0x3c020001, 0x8c426d90, 0xc09821, +0xae020000, 0x3c020001, 0x8c426d10, 0xc09821, 0xe0a821, 0x10800006, 0xae020004, 0x26050008, -0xc002b8f, 0x24060018, 0x10000005, 0x2610ffe0, -0x26040008, 0xc002b84, 0x24050018, 0x2610ffe0, -0x3c030001, 0x24637010, 0x203102b, 0x10400003, -0x0, 0x3c100001, 0x8e106f64, 0x8e220000, +0xc002bb3, 0x24060018, 0x10000005, 0x2610ffe0, +0x26040008, 0xc002ba8, 0x24050018, 0x2610ffe0, +0x3c030001, 0x24636f90, 0x203102b, 0x10400003, +0x0, 0x3c100001, 0x8e106ee8, 0x8e220000, 0xae020000, 0x8e220004, 0xae120008, 0xae020004, 0x8f820054, 0xae130010, 0xae150014, 0xae1e0018, 0x8fa80044, 0xae08001c, 0xae02000c, 0x2610ffe0, 0x203102b, 0x10400003, 0x0, 0x3c100001, -0x8e106f64, 0x3c020001, 0x8c426d90, 0xae020000, -0x3c020001, 0x8c426d90, 0x3c010001, 0xac306f68, +0x8e106ee8, 0x3c020001, 0x8c426d10, 0xae020000, +0x3c020001, 0x8c426d10, 0x3c010001, 0xac306eec, 0xae020004, 0xac100250, 0x8fbf0028, 0x8fbe0024, 0x8fb50020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0030, 0x851821, @@ -6390,28 +6394,36 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x3e00008, 0x0, 0x63080, 0x861821, 0x83102b, 0x10400006, 0x0, 0xac850000, 0x24840004, 0x83102b, 0x5440fffd, 0xac850000, -0x3e00008, 0x0, 0x0, 0x3c0208ff, -0x3442ffff, 0x3c03c0ff, 0x8f850220, 0x3463ffff, -0x8f860200, 0xa21024, 0x34420004, 0xc31824, -0x34630004, 0xaf820220, 0xaf830200, 0x8c820214, -0xac020084, 0x8c820218, 0xac020088, 0x8c82021c, -0xac02008c, 0x8c820220, 0xac020090, 0x8c820224, -0xac020094, 0x8c820228, 0xac020098, 0x8c82022c, -0xac02009c, 0x8c820230, 0xac0200a0, 0x8c820234, -0xac0200a4, 0x8c820238, 0xac0200a8, 0x8c82023c, -0xac0200ac, 0x8c820240, 0xac0200b0, 0x8c820244, -0xac0200b4, 0x8c820248, 0xac0200b8, 0x8c82024c, -0xac0200bc, 0x8c82001c, 0xac020080, 0x8c820018, -0xac0200c0, 0x8c820020, 0xac0200cc, 0x8c820024, -0xac0200d0, 0x8c8201d0, 0xac0200e0, 0x8c8201d4, -0xac0200e4, 0x8c8201d8, 0xac0200e8, 0x8c8201dc, -0xac0200ec, 0x8c8201e0, 0xac0200f0, 0x8c820098, -0x8c83009c, 0xac0300fc, 0x8c8200a8, 0x8c8300ac, -0xac0300f4, 0x8c8200a0, 0x8c8300a4, 0x30a50004, -0xac0300f8, 0x14a00007, 0x30c20004, 0x8f820220, -0x3c0308ff, 0x3463fffb, 0x431024, 0xaf820220, -0x30c20004, 0x14400006, 0x0, 0x8f820200, -0x3c03c0ff, 0x3463fffb, 0x431024, 0xaf820200, +0x3e00008, 0x0, 0x0, 0x26e50028, +0xa03021, 0x274301c0, 0x8f4d0358, 0x8f47035c, +0x8f480360, 0x8f490364, 0x8f4a0368, 0x8f4b0204, +0x8f4c0200, 0x24640400, 0x64102b, 0x10400008, +0x3c0208ff, 0x8cc20000, 0xac620000, 0x24630004, +0x64102b, 0x1440fffb, 0x24c60004, 0x3c0208ff, +0x3442ffff, 0x3c03c0ff, 0xaf4d0358, 0xaf47035c, +0xaf480360, 0xaf490364, 0xaf4a0368, 0xaf4b0204, +0xaf4c0200, 0x8f840220, 0x3463ffff, 0x8f860200, +0x821024, 0x34420004, 0xc31824, 0x34630004, +0xaf820220, 0xaf830200, 0x8ca20214, 0xac020084, +0x8ca20218, 0xac020088, 0x8ca2021c, 0xac02008c, +0x8ca20220, 0xac020090, 0x8ca20224, 0xac020094, +0x8ca20228, 0xac020098, 0x8ca2022c, 0xac02009c, +0x8ca20230, 0xac0200a0, 0x8ca20234, 0xac0200a4, +0x8ca20238, 0xac0200a8, 0x8ca2023c, 0xac0200ac, +0x8ca20240, 0xac0200b0, 0x8ca20244, 0xac0200b4, +0x8ca20248, 0xac0200b8, 0x8ca2024c, 0xac0200bc, +0x8ca2001c, 0xac020080, 0x8ca20018, 0xac0200c0, +0x8ca20020, 0xac0200cc, 0x8ca20024, 0xac0200d0, +0x8ca201d0, 0xac0200e0, 0x8ca201d4, 0xac0200e4, +0x8ca201d8, 0xac0200e8, 0x8ca201dc, 0xac0200ec, +0x8ca201e0, 0xac0200f0, 0x8ca20098, 0x8ca3009c, +0xac0300fc, 0x8ca200a8, 0x8ca300ac, 0xac0300f4, +0x8ca200a0, 0x8ca300a4, 0x30840004, 0xac0300f8, +0x14800007, 0x30c20004, 0x8f820220, 0x3c0308ff, +0x3463fffb, 0x431024, 0xaf820220, 0x30c20004, +0x14400006, 0x0, 0x8f820200, 0x3c03c0ff, +0x3463fffb, 0x431024, 0xaf820200, 0x8f4202dc, +0xa34005c5, 0x24420001, 0xaf4202dc, 0x8f4202dc, 0x3e00008, 0x0, 0x27bdffd8, 0xafbf0024, 0xafb00020, 0x8f430024, 0x8f420020, 0x10620038, 0x0, 0x8f430020, 0x8f420024, 0x622023, @@ -6443,7 +6455,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8e040000, 0x8e050004, 0x96120008, 0x8f420090, 0x9611000a, 0x3246ffff, 0x46102a, 0x10400017, 0x0, 0x8f8200d8, 0x8f430098, 0x431023, -0x2442fff8, 0xaf420090, 0x8f420090, 0x2842fff9, +0x2442dcbe, 0xaf420090, 0x8f420090, 0x2842dcbf, 0x10400005, 0x0, 0x8f420090, 0x8f430144, 0x431021, 0xaf420090, 0x8f420090, 0x46102a, 0x10400006, 0x0, 0x8f420348, 0x24420001, @@ -6513,7 +6525,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8e040000, 0x8e050004, 0x96110008, 0x8f420090, 0x9607000a, 0x3226ffff, 0x46102a, 0x10400017, 0x0, 0x8f8200d8, 0x8f430098, 0x431023, -0x2442ff80, 0xaf420090, 0x8f420090, 0x2842ff81, +0x2442dc46, 0xaf420090, 0x8f420090, 0x2842dc47, 0x10400005, 0x0, 0x8f420090, 0x8f430144, 0x431021, 0xaf420090, 0x8f420090, 0x46102a, 0x10400006, 0x0, 0x8f420348, 0x24420001, @@ -6575,15 +6587,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x30a20001, 0x8c82001c, 0x8f430040, 0x8f440034, 0x24420001, 0x2463ffff, 0x431024, 0x862021, 0xaf42002c, 0x30a20030, 0x14400006, 0xaf440034, -0x8f420034, 0x8c03023c, 0x43102b, 0x144000ca, +0x8f420034, 0x8c03023c, 0x43102b, 0x144000b4, 0x0, 0x32c20010, 0x10400028, 0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f1, 0x8f820124, 0xafa20010, 0x8f820128, -0x3c040001, 0x24846854, 0xafa20014, 0x8f46002c, -0x8f870120, 0x3c050009, 0xc002b17, 0x34a51100, +0x3c040001, 0x248467c4, 0xafa20014, 0x8f46002c, +0x8f870120, 0x3c050009, 0xc002b3b, 0x34a51100, 0x10000036, 0x0, 0x8f420300, 0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170, @@ -6592,13 +6604,13 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, -0x24846848, 0xafa20014, 0x8f46002c, 0x8f870120, -0x3c050009, 0xc002b17, 0x34a50900, 0x1000000f, +0x248467b8, 0xafa20014, 0x8f46002c, 0x8f870120, +0x3c050009, 0xc002b3b, 0x34a50900, 0x1000000f, 0x0, 0x8f420300, 0x24420001, 0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1, 0xaf420038, 0x3c010001, 0x370821, 0xa02040f1, 0x3c010001, 0x370821, 0xa02040f0, 0xaf400034, 0x8f420314, -0x24420001, 0xaf420314, 0x1000006f, 0x8f420314, +0x24420001, 0xaf420314, 0x10000059, 0x8f420314, 0x10400022, 0x30a27000, 0x8c85001c, 0x8f420028, 0xa22023, 0x4810003, 0x0, 0x8f420040, 0x822021, 0x8f420358, 0x8f430000, 0xaf450028, @@ -6606,8 +6618,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f82004c, 0x1040fffd, 0x0, 0x10000005, 0x0, 0xaf800048, 0x8f820048, 0x1040fffd, 0x0, 0x8f820060, 0x34420008, 0xaf820060, -0x8f420000, 0x10400003, 0x0, 0x1000004e, -0xaf80004c, 0x1000004c, 0xaf800048, 0x1040002f, +0x8f420000, 0x10400003, 0x0, 0x10000038, +0xaf80004c, 0x10000036, 0xaf800048, 0x1040002f, 0x30a21000, 0x1040000c, 0x30a24000, 0x8c83001c, 0x8f420050, 0x622023, 0x4820001, 0x24840200, 0x8f42035c, 0x441021, 0xaf42035c, 0x8f420368, @@ -6618,190 +6630,179 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x3c020800, 0x8c83001c, 0x8f420060, 0x622023, 0x4820001, 0x24840100, 0x8f420360, 0x441021, 0xaf420360, 0x8f420368, 0xaf430060, 0x441021, -0xaf420368, 0x3c020800, 0x2c21024, 0x5040001e, -0x36940040, 0x1000001c, 0x0, 0x30a20100, -0x10400019, 0x0, 0x3c020001, 0x8c426d44, -0x1040000d, 0x274301c0, 0x24650400, 0x65102b, -0x10400007, 0x26e40028, 0x8c820000, 0xac620000, -0x24630004, 0x65102b, 0x1440fffb, 0x24840004, -0x10000002, 0x274401c0, 0x26e40028, 0xc002bb4, -0x0, 0x8f4202dc, 0xa34005c5, 0x24420001, -0xaf4202dc, 0x8f4202dc, 0x8fbf0020, 0x3e00008, -0x27bd0028, 0x3e00008, 0x0, 0x27bdffa8, -0xafbf0050, 0xafbe004c, 0xafb50048, 0xafb30044, -0xafb20040, 0xafb1003c, 0xafb00038, 0x8f910108, -0x26220020, 0xaf820108, 0x8e320018, 0xa821, -0x32420024, 0x104001ba, 0xf021, 0x8e26001c, -0x8f43001c, 0x61100, 0x621821, 0x8c70000c, -0x9604000c, 0x962d0016, 0x9473000a, 0x2c8305dd, -0x38828870, 0x2c420001, 0x621825, 0x10600015, -0x2821, 0x32c20040, 0x10400015, 0x24020800, -0x96030014, 0x14620012, 0x3402aaaa, 0x9603000e, -0x14620007, 0x2021, 0x96030010, 0x24020300, -0x14620004, 0x801021, 0x96020012, 0x2c440001, -0x801021, 0x54400006, 0x24050016, 0x10000004, -0x0, 0x24020800, 0x50820001, 0x2405000e, -0x934205c3, 0x14400008, 0x5821, 0x240b0001, -0x32620180, 0xaf4500a8, 0xaf5000a0, 0x10400002, -0xaf4600a4, 0xa34b05c3, 0x10a00085, 0x2054021, -0x91020000, 0x3821, 0x3042000f, 0x25080, -0x32c20002, 0x10400012, 0x10a1821, 0x32620002, -0x10400010, 0x32c20001, 0x1002021, 0x94820000, -0x24840002, 0xe23821, 0x83102b, 0x1440fffb, -0x30e2ffff, 0x71c02, 0x623821, 0x71c02, -0x30e2ffff, 0x623821, 0x71027, 0xa502000a, -0x32c20001, 0x1040006a, 0x32620001, 0x10400068, -0x0, 0x8f4200a8, 0x10400065, 0x0, -0x8f4200a0, 0x8f4300a8, 0x431021, 0x904c0009, -0x318900ff, 0x39230006, 0x3182b, 0x39220011, -0x2102b, 0x621824, 0x1060000c, 0x3c050006, -0x8f4200a4, 0x3c040001, 0x24846864, 0xafa20010, -0x8f4200a0, 0x34a54600, 0x1203821, 0xc002b17, -0xafa20014, 0x1000004e, 0x0, 0x32c20004, -0x14400013, 0x2821, 0x316200ff, 0x14400004, -0x0, 0x95020002, 0x1000000d, 0x4a2823, -0x9505000c, 0x9502000e, 0x95030010, 0xa22821, -0xa32821, 0x95030012, 0x91040009, 0x95020002, -0xa32821, 0xa42821, 0x4a1023, 0xa22821, -0x2002021, 0x94820000, 0x24840002, 0xe23821, -0x88102b, 0x1440fffb, 0x71c02, 0x30e2ffff, +0xaf420368, 0x3c020800, 0x2c21024, 0x50400008, +0x36940040, 0x10000006, 0x0, 0x30a20100, +0x10400003, 0x0, 0xc002bd8, 0x0, +0x8fbf0020, 0x3e00008, 0x27bd0028, 0x3e00008, +0x0, 0x27bdffa8, 0xafbf0050, 0xafbe004c, +0xafb50048, 0xafb30044, 0xafb20040, 0xafb1003c, +0xafb00038, 0x8f910108, 0x26220020, 0xaf820108, +0x8e320018, 0xa821, 0x32420024, 0x104001ba, +0xf021, 0x8e26001c, 0x8f43001c, 0x61100, +0x621821, 0x8c70000c, 0x9604000c, 0x962d0016, +0x9473000a, 0x2c8305dd, 0x38828870, 0x2c420001, +0x621825, 0x10600015, 0x2821, 0x32c20040, +0x10400015, 0x24020800, 0x96030014, 0x14620012, +0x3402aaaa, 0x9603000e, 0x14620007, 0x2021, +0x96030010, 0x24020300, 0x14620004, 0x801021, +0x96020012, 0x2c440001, 0x801021, 0x54400006, +0x24050016, 0x10000004, 0x0, 0x24020800, +0x50820001, 0x2405000e, 0x934205c3, 0x14400008, +0x5821, 0x240b0001, 0x32620180, 0xaf4500a8, +0xaf5000a0, 0x10400002, 0xaf4600a4, 0xa34b05c3, +0x10a00085, 0x2054021, 0x91020000, 0x3821, +0x3042000f, 0x25080, 0x32c20002, 0x10400012, +0x10a1821, 0x32620002, 0x10400010, 0x32c20001, +0x1002021, 0x94820000, 0x24840002, 0xe23821, +0x83102b, 0x1440fffb, 0x30e2ffff, 0x71c02, 0x623821, 0x71c02, 0x30e2ffff, 0x623821, -0x1a52821, 0x51c02, 0x30a2ffff, 0x622821, -0x51c02, 0x30a2ffff, 0x622821, 0xa72823, -0x51402, 0xa22821, 0x30a5ffff, 0x50a00001, -0x3405ffff, 0x316200ff, 0x14400008, 0x318300ff, -0x8f4300a0, 0x8f4200a8, 0x624021, 0x91020000, -0x3042000f, 0x25080, 0x318300ff, 0x24020006, -0x14620003, 0x10a1021, 0x10000002, 0x24440010, -0x24440006, 0x316200ff, 0x14400006, 0x0, -0x94820000, 0xa22821, 0x51c02, 0x30a2ffff, -0x622821, 0x934205c3, 0x10400003, 0x32620100, -0x50400003, 0xa4850000, 0x52827, 0xa4850000, -0x9622000e, 0x8f43009c, 0x621821, 0x32a200ff, -0x10400007, 0xaf43009c, 0x3c024000, 0x2021025, -0xafa20020, 0x8f42009c, 0x10000003, 0x5e1025, -0xafb00020, 0x8f42009c, 0xafa20024, 0x32620080, -0x10400010, 0x32620100, 0x8f4200b4, 0x24430001, -0x210c0, 0x571021, 0xaf4300b4, 0x8fa30020, -0x8fa40024, 0x3c010001, 0x220821, 0xac2338e8, -0x3c010001, 0x220821, 0xac2438ec, 0x100000a5, -0x32c20020, 0x10400064, 0x0, 0x8f4200b4, -0x24430001, 0x210c0, 0x571021, 0xaf4300b4, -0x8fa30020, 0x8fa40024, 0x3c010001, 0x220821, -0xac2338e8, 0x3c010001, 0x220821, 0xac2438ec, -0x8f4200b4, 0x10400051, 0x3821, 0x3c090001, -0x352938e8, 0x3c08001f, 0x3508ffff, 0x240bffff, -0x340affff, 0x710c0, 0x571021, 0x491021, -0x8c430000, 0x8c440004, 0xafa30028, 0xafa4002c, -0x8f8200fc, 0x8fa30028, 0x8fa4002c, 0xac430000, -0xac440004, 0x24420008, 0xaf8200f0, 0x8f42008c, -0x2442ffff, 0xaf42008c, 0x97a2002e, 0x8f440270, -0x8f450274, 0x401821, 0x1021, 0xa32821, -0xa3302b, 0x822021, 0x862021, 0xaf440270, -0xaf450274, 0x8fa20028, 0x481024, 0x90430000, -0x30630001, 0x1460000b, 0x402021, 0x8f420278, -0x8f43027c, 0x24630001, 0x2c640001, 0x441021, -0xaf420278, 0xaf43027c, 0x8f420278, 0x1000001a, -0x8f43027c, 0x8c820000, 0x144b000e, 0x0, -0x94820004, 0x144a000b, 0x0, 0x8f420288, -0x8f43028c, 0x24630001, 0x2c640001, 0x441021, -0xaf420288, 0xaf43028c, 0x8f420288, 0x1000000a, -0x8f43028c, 0x8f420280, 0x8f430284, 0x24630001, -0x2c640001, 0x441021, 0xaf420280, 0xaf430284, -0x8f420280, 0x8f430284, 0x8f4200b4, 0x24e70001, -0xe2102b, 0x1440ffb8, 0x710c0, 0xa34005c3, -0x1000003f, 0xaf4000b4, 0x8f8200fc, 0x8fa30020, -0x8fa40024, 0xac430000, 0xac440004, 0x24420008, -0xaf8200f0, 0x8f42009c, 0x8f46008c, 0x8f440270, -0x8f450274, 0x401821, 0x1021, 0x24c6ffff, -0xaf46008c, 0xa32821, 0xa3302b, 0x822021, -0x862021, 0xaf440270, 0xaf450274, 0x92020000, -0x30420001, 0x1440000c, 0x2402ffff, 0x8f420278, -0x8f43027c, 0x24630001, 0x2c640001, 0x441021, -0xaf420278, 0xaf43027c, 0x8f420278, 0x8f43027c, -0x1000001c, 0x32c20020, 0x8e030000, 0x1462000f, -0x3402ffff, 0x96030004, 0x1462000c, 0x0, -0x8f420288, 0x8f43028c, 0x24630001, 0x2c640001, -0x441021, 0xaf420288, 0xaf43028c, 0x8f420288, -0x8f43028c, 0x1000000b, 0x32c20020, 0x8f420280, +0x71027, 0xa502000a, 0x32c20001, 0x1040006a, +0x32620001, 0x10400068, 0x0, 0x8f4200a8, +0x10400065, 0x0, 0x8f4200a0, 0x8f4300a8, +0x431021, 0x904c0009, 0x318900ff, 0x39230006, +0x3182b, 0x39220011, 0x2102b, 0x621824, +0x1060000c, 0x3c050006, 0x8f4200a4, 0x3c040001, +0x248467d4, 0xafa20010, 0x8f4200a0, 0x34a54600, +0x1203821, 0xc002b3b, 0xafa20014, 0x1000004e, +0x0, 0x32c20004, 0x14400013, 0x2821, +0x316200ff, 0x14400004, 0x0, 0x95020002, +0x1000000d, 0x4a2823, 0x9505000c, 0x9502000e, +0x95030010, 0xa22821, 0xa32821, 0x95030012, +0x91040009, 0x95020002, 0xa32821, 0xa42821, +0x4a1023, 0xa22821, 0x2002021, 0x94820000, +0x24840002, 0xe23821, 0x88102b, 0x1440fffb, +0x71c02, 0x30e2ffff, 0x623821, 0x71c02, +0x30e2ffff, 0x623821, 0x1a52821, 0x51c02, +0x30a2ffff, 0x622821, 0x51c02, 0x30a2ffff, +0x622821, 0xa72823, 0x51402, 0xa22821, +0x30a5ffff, 0x50a00001, 0x3405ffff, 0x316200ff, +0x14400008, 0x318300ff, 0x8f4300a0, 0x8f4200a8, +0x624021, 0x91020000, 0x3042000f, 0x25080, +0x318300ff, 0x24020006, 0x14620003, 0x10a1021, +0x10000002, 0x24440010, 0x24440006, 0x316200ff, +0x14400006, 0x0, 0x94820000, 0xa22821, +0x51c02, 0x30a2ffff, 0x622821, 0x934205c3, +0x10400003, 0x32620100, 0x50400003, 0xa4850000, +0x52827, 0xa4850000, 0x9622000e, 0x8f43009c, +0x621821, 0x32a200ff, 0x10400007, 0xaf43009c, +0x3c024000, 0x2021025, 0xafa20020, 0x8f42009c, +0x10000003, 0x5e1025, 0xafb00020, 0x8f42009c, +0xafa20024, 0x32620080, 0x10400010, 0x32620100, +0x8f4200b4, 0x24430001, 0x210c0, 0x571021, +0xaf4300b4, 0x8fa30020, 0x8fa40024, 0x3c010001, +0x220821, 0xac2338e8, 0x3c010001, 0x220821, +0xac2438ec, 0x100000a5, 0x32c20020, 0x10400064, +0x0, 0x8f4200b4, 0x24430001, 0x210c0, +0x571021, 0xaf4300b4, 0x8fa30020, 0x8fa40024, +0x3c010001, 0x220821, 0xac2338e8, 0x3c010001, +0x220821, 0xac2438ec, 0x8f4200b4, 0x10400051, +0x3821, 0x3c090001, 0x352938e8, 0x3c08001f, +0x3508ffff, 0x240bffff, 0x340affff, 0x710c0, +0x571021, 0x491021, 0x8c430000, 0x8c440004, +0xafa30028, 0xafa4002c, 0x8f8200fc, 0x8fa30028, +0x8fa4002c, 0xac430000, 0xac440004, 0x24420008, +0xaf8200f0, 0x8f42008c, 0x2442ffff, 0xaf42008c, +0x97a2002e, 0x8f440270, 0x8f450274, 0x401821, +0x1021, 0xa32821, 0xa3302b, 0x822021, +0x862021, 0xaf440270, 0xaf450274, 0x8fa20028, +0x481024, 0x90430000, 0x30630001, 0x1460000b, +0x402021, 0x8f420278, 0x8f43027c, 0x24630001, +0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, +0x8f420278, 0x1000001a, 0x8f43027c, 0x8c820000, +0x144b000e, 0x0, 0x94820004, 0x144a000b, +0x0, 0x8f420288, 0x8f43028c, 0x24630001, +0x2c640001, 0x441021, 0xaf420288, 0xaf43028c, +0x8f420288, 0x1000000a, 0x8f43028c, 0x8f420280, 0x8f430284, 0x24630001, 0x2c640001, 0x441021, 0xaf420280, 0xaf430284, 0x8f420280, 0x8f430284, -0x32c20020, 0x10400005, 0xaf40009c, 0x8f420358, +0x8f4200b4, 0x24e70001, 0xe2102b, 0x1440ffb8, +0x710c0, 0xa34005c3, 0x1000003f, 0xaf4000b4, +0x8f8200fc, 0x8fa30020, 0x8fa40024, 0xac430000, +0xac440004, 0x24420008, 0xaf8200f0, 0x8f42009c, +0x8f46008c, 0x8f440270, 0x8f450274, 0x401821, +0x1021, 0x24c6ffff, 0xaf46008c, 0xa32821, +0xa3302b, 0x822021, 0x862021, 0xaf440270, +0xaf450274, 0x92020000, 0x30420001, 0x1440000c, +0x2402ffff, 0x8f420278, 0x8f43027c, 0x24630001, +0x2c640001, 0x441021, 0xaf420278, 0xaf43027c, +0x8f420278, 0x8f43027c, 0x1000001c, 0x32c20020, +0x8e030000, 0x1462000f, 0x3402ffff, 0x96030004, +0x1462000c, 0x0, 0x8f420288, 0x8f43028c, +0x24630001, 0x2c640001, 0x441021, 0xaf420288, +0xaf43028c, 0x8f420288, 0x8f43028c, 0x1000000b, +0x32c20020, 0x8f420280, 0x8f430284, 0x24630001, +0x2c640001, 0x441021, 0xaf420280, 0xaf430284, +0x8f420280, 0x8f430284, 0x32c20020, 0x10400005, +0xaf40009c, 0x8f420358, 0x2442ffff, 0xaf420358, +0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001, +0x2463ffff, 0x431024, 0xaf42002c, 0x32420060, +0x14400008, 0x32c20010, 0x8f420034, 0x24420001, +0xaf420034, 0x8c03023c, 0x43102b, 0x14400102, +0x32c20010, 0x10400018, 0x24070008, 0x8f440170, +0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, +0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, +0x8f42010c, 0x40f809, 0x24c6001c, 0x10400047, +0x24020001, 0x8f420300, 0x8f43002c, 0x24420001, +0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, +0x1000007c, 0xaf430038, 0x8f440170, 0x8f450174, +0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020, +0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, +0x40f809, 0x24c6001c, 0x10400057, 0x24020001, +0x10000065, 0x0, 0x32420012, 0x10400075, +0x32420001, 0x9622000e, 0x8f43009c, 0x621821, +0x32c20020, 0x10400005, 0xaf43009c, 0x8f420358, 0x2442ffff, 0xaf420358, 0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001, 0x2463ffff, 0x431024, -0xaf42002c, 0x32420060, 0x14400008, 0x32c20010, +0xaf42002c, 0x32420010, 0x14400008, 0x32c20010, 0x8f420034, 0x24420001, 0xaf420034, 0x8c03023c, -0x43102b, 0x14400118, 0x32c20010, 0x10400018, +0x43102b, 0x144000bc, 0x32c20010, 0x10400028, 0x24070008, 0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, -0x24c6001c, 0x10400047, 0x24020001, 0x8f420300, +0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, +0x370821, 0xa02240f1, 0x8f820124, 0xafa20010, +0x8f820128, 0x3c040001, 0x248467c4, 0xafa20014, +0x8f46002c, 0x8f870120, 0x3c050009, 0xc002b3b, +0x34a51100, 0x10000036, 0x0, 0x8f420300, 0x8f43002c, 0x24420001, 0xaf420300, 0x8f420300, -0x24020001, 0xa34205c1, 0x1000007c, 0xaf430038, +0x24020001, 0xa34205c1, 0x10000026, 0xaf430038, 0x8f440170, 0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020, 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, -0x10400057, 0x24020001, 0x10000065, 0x0, -0x32420012, 0x10400075, 0x32420001, 0x9622000e, -0x8f43009c, 0x621821, 0x32c20020, 0x10400005, -0xaf43009c, 0x8f420358, 0x2442ffff, 0xaf420358, -0x8f420358, 0x8e22001c, 0x8f430040, 0x24420001, -0x2463ffff, 0x431024, 0xaf42002c, 0x32420010, -0x14400008, 0x32c20010, 0x8f420034, 0x24420001, -0xaf420034, 0x8c03023c, 0x43102b, 0x144000d2, -0x32c20010, 0x10400028, 0x24070008, 0x8f440170, -0x8f450174, 0x8f43002c, 0x8f48000c, 0x8f860120, -0x24020080, 0xafa20010, 0xafa30014, 0xafa80018, -0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, -0x24020001, 0x3c010001, 0x370821, 0xa02240f1, -0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, -0x24846854, 0xafa20014, 0x8f46002c, 0x8f870120, -0x3c050009, 0xc002b17, 0x34a51100, 0x10000036, -0x0, 0x8f420300, 0x8f43002c, 0x24420001, -0xaf420300, 0x8f420300, 0x24020001, 0xa34205c1, -0x10000026, 0xaf430038, 0x8f440170, 0x8f450174, -0x8f43002c, 0x8f48000c, 0x8f860120, 0x24020020, -0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, -0x40f809, 0x24c6001c, 0x14400011, 0x24020001, -0x3c010001, 0x370821, 0xa02240f0, 0x8f820124, -0xafa20010, 0x8f820128, 0x3c040001, 0x24846848, -0xafa20014, 0x8f46002c, 0x8f870120, 0x3c050009, -0xc002b17, 0x34a50900, 0x1000000f, 0x0, -0x8f420300, 0x24420001, 0xaf420300, 0x8f420300, -0x8f42002c, 0xa34005c1, 0xaf420038, 0x3c010001, -0x370821, 0xa02040f1, 0x3c010001, 0x370821, -0xa02040f0, 0xaf400034, 0x8f420314, 0x24420001, -0xaf420314, 0x10000078, 0x8f420314, 0x10400022, -0x32427000, 0x8e25001c, 0x8f420028, 0xa22023, -0x4810003, 0x0, 0x8f420040, 0x822021, -0x8f420358, 0x8f430000, 0xaf450028, 0x441021, -0x10600007, 0xaf420358, 0xaf80004c, 0x8f82004c, -0x1040fffd, 0x0, 0x10000005, 0x0, -0xaf800048, 0x8f820048, 0x1040fffd, 0x0, -0x8f820060, 0x34420008, 0xaf820060, 0x8f420000, -0x10400003, 0x0, 0x10000057, 0xaf80004c, -0x10000055, 0xaf800048, 0x1040002f, 0x32421000, -0x1040000c, 0x32424000, 0x8e23001c, 0x8f420050, -0x622023, 0x4820001, 0x24840200, 0x8f42035c, -0x441021, 0xaf42035c, 0x8f420368, 0x1000001a, -0xaf430050, 0x1040000c, 0x32c28000, 0x8e23001c, -0x8f420070, 0x622023, 0x4820001, 0x24840400, -0x8f420364, 0x441021, 0xaf420364, 0x8f420368, -0x1000000d, 0xaf430070, 0x1040000e, 0x3c020800, -0x8e23001c, 0x8f420060, 0x622023, 0x4820001, -0x24840100, 0x8f420360, 0x441021, 0xaf420360, -0x8f420368, 0xaf430060, 0x441021, 0xaf420368, -0x3c020800, 0x2c21024, 0x50400027, 0x36940040, -0x10000025, 0x0, 0x32420048, 0x10400007, -0x24150001, 0x8e22001c, 0x3c03ffff, 0x43f024, -0x3042ffff, 0x1000fd75, 0xae22001c, 0x32420100, -0x10400019, 0x0, 0x3c020001, 0x8c426d44, -0x1040000d, 0x274301c0, 0x24650400, 0x65102b, -0x10400007, 0x26e40028, 0x8c820000, 0xac620000, -0x24630004, 0x65102b, 0x1440fffb, 0x24840004, -0x10000002, 0x274401c0, 0x26e40028, 0xc002bb4, -0x0, 0x8f4202dc, 0xa34005c5, 0x24420001, -0xaf4202dc, 0x8f4202dc, 0x8fbf0050, 0x8fbe004c, +0x14400011, 0x24020001, 0x3c010001, 0x370821, +0xa02240f0, 0x8f820124, 0xafa20010, 0x8f820128, +0x3c040001, 0x248467b8, 0xafa20014, 0x8f46002c, +0x8f870120, 0x3c050009, 0xc002b3b, 0x34a50900, +0x1000000f, 0x0, 0x8f420300, 0x24420001, +0xaf420300, 0x8f420300, 0x8f42002c, 0xa34005c1, +0xaf420038, 0x3c010001, 0x370821, 0xa02040f1, +0x3c010001, 0x370821, 0xa02040f0, 0xaf400034, +0x8f420314, 0x24420001, 0xaf420314, 0x10000062, +0x8f420314, 0x10400022, 0x32427000, 0x8e25001c, +0x8f420028, 0xa22023, 0x4810003, 0x0, +0x8f420040, 0x822021, 0x8f420358, 0x8f430000, +0xaf450028, 0x441021, 0x10600007, 0xaf420358, +0xaf80004c, 0x8f82004c, 0x1040fffd, 0x0, +0x10000005, 0x0, 0xaf800048, 0x8f820048, +0x1040fffd, 0x0, 0x8f820060, 0x34420008, +0xaf820060, 0x8f420000, 0x10400003, 0x0, +0x10000041, 0xaf80004c, 0x1000003f, 0xaf800048, +0x1040002f, 0x32421000, 0x1040000c, 0x32424000, +0x8e23001c, 0x8f420050, 0x622023, 0x4820001, +0x24840200, 0x8f42035c, 0x441021, 0xaf42035c, +0x8f420368, 0x1000001a, 0xaf430050, 0x1040000c, +0x32c28000, 0x8e23001c, 0x8f420070, 0x622023, +0x4820001, 0x24840400, 0x8f420364, 0x441021, +0xaf420364, 0x8f420368, 0x1000000d, 0xaf430070, +0x1040000e, 0x3c020800, 0x8e23001c, 0x8f420060, +0x622023, 0x4820001, 0x24840100, 0x8f420360, +0x441021, 0xaf420360, 0x8f420368, 0xaf430060, +0x441021, 0xaf420368, 0x3c020800, 0x2c21024, +0x50400011, 0x36940040, 0x1000000f, 0x0, +0x32420048, 0x10400007, 0x24150001, 0x8e22001c, +0x3c03ffff, 0x43f024, 0x3042ffff, 0x1000fd75, +0xae22001c, 0x32420100, 0x10400003, 0x0, +0xc002bd8, 0x0, 0x8fbf0050, 0x8fbe004c, 0x8fb50048, 0x8fb30044, 0x8fb20040, 0x8fb1003c, 0x8fb00038, 0x3e00008, 0x27bd0058, 0x3e00008, 0x0, 0x0, 0x0, 0x8f8300e4, @@ -6818,7 +6819,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x10400003, 0x0, 0x8f420148, 0x621821, 0x94a20006, 0x24420050, 0x62102b, 0x1440000f, 0xa01021, 0xafa40010, 0xafa30014, 0x8ca60000, -0x8ca70004, 0x3c040001, 0xc002b17, 0x24846924, +0x8ca70004, 0x3c040001, 0xc002b3b, 0x24846894, 0x8f42020c, 0x24420001, 0xaf42020c, 0x8f42020c, 0x1021, 0xaf9000e8, 0xaf9000e4, 0x8fbf001c, 0x8fb00018, 0x3e00008, 0x27bd0020, 0x3e00008, @@ -6840,15 +6841,15 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f4b00c4, 0xafab0064, 0x8f4a00c0, 0xafaa006c, 0x8f4b00cc, 0xafab0074, 0x8f4a00c8, 0x10000129, 0xafaa007c, 0x8f420114, 0x40f809, 0x0, -0x403021, 0x10c0033f, 0x0, 0x8cc20000, +0x403021, 0x10c0034f, 0x0, 0x8cc20000, 0x8cc30004, 0xafa20020, 0xafa30024, 0x8fab0024, 0x8faa0020, 0x3162ffff, 0x2442fffc, 0xafa2006c, 0x3c020006, 0x2c21024, 0xafab007c, 0x14400015, 0xafaa0064, 0x91420000, 0x30420001, 0x10400011, 0x2402ffff, 0x8d430000, 0x14620004, 0x3402ffff, -0x95430004, 0x1062000b, 0x0, 0xc002497, +0x95430004, 0x1062000b, 0x0, 0xc0024bb, 0x8fa40064, 0x304200ff, 0x14400006, 0x0, -0x8f420118, 0x40f809, 0x0, 0x1000031d, +0x8f420118, 0x40f809, 0x0, 0x1000032d, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, 0x431024, 0x3c03ffff, 0x431824, 0x14600003, 0xafa20024, 0x10000040, 0x1821, 0x3c020080, @@ -6871,13 +6872,13 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x4b102b, 0x10400014, 0x307000ff, 0x8f4201e8, 0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8faa007c, 0x8f8200e0, 0x354a0100, 0xafaa007c, 0xafa20010, -0x8f8200e4, 0x24100001, 0x3c040001, 0x24846930, +0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0, 0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007, -0xc002b17, 0x34a50800, 0x12000010, 0x3c020080, +0xc002b3b, 0x34a50800, 0x12000010, 0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400, 0x8fab007c, 0x3c020080, 0x34420100, 0x1621024, 0x10400005, 0x0, 0x8f42020c, 0x24420001, 0xaf42020c, -0x8f42020c, 0x100002a0, 0x8fa3006c, 0x32c20400, +0x8f42020c, 0x100002b0, 0x8fa3006c, 0x32c20400, 0x10400015, 0x34028100, 0x8faa0064, 0x9543000c, 0x14620012, 0x3c020100, 0x240b0200, 0xa7ab008e, 0x9542000e, 0x8d430008, 0x8d440004, 0x8d450000, @@ -6892,66 +6893,66 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x10400056, 0x32c28000, 0x1040005e, 0x240a0003, 0x32c21000, 0x1040005b, 0xafaa005c, 0x10000058, 0x240b0004, 0x8f420350, 0x2403ffbf, 0x283a024, -0x24420001, 0xaf420350, 0x1000023f, 0x8f420350, +0x24420001, 0xaf420350, 0x1000024f, 0x8f420350, 0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, -0x3c040001, 0x24846960, 0x26620001, 0xafa20014, +0x3c040001, 0x248468d0, 0x26620001, 0xafa20014, 0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007, -0xc002b17, 0x34a52250, 0x1000022f, 0x0, +0xc002b3b, 0x34a52250, 0x1000023f, 0x0, 0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, -0x3c040001, 0x24846960, 0x24020002, 0xafa20014, +0x3c040001, 0x248468d0, 0x24020002, 0xafa20014, 0xafa30010, 0x8f860120, 0x8f870124, 0x3c050007, -0xc002b17, 0x34a52450, 0x1000021f, 0x0, -0x8ea20000, 0x8ea30004, 0x3c040001, 0x24846978, +0xc002b3b, 0x34a52450, 0x1000022f, 0x0, +0x8ea20000, 0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010, 0xafbe0014, 0x8ea70018, 0x34a52800, -0xc002b17, 0x603021, 0x10000213, 0x0, -0xa6b1000a, 0x8f820124, 0x3c040001, 0x24846980, +0xc002b3b, 0x603021, 0x10000223, 0x0, +0xa6b1000a, 0x8f820124, 0x3c040001, 0x248468f0, 0xafbe0014, 0xafa20010, 0x8f460044, 0x8f870120, -0x3c050007, 0xc002b17, 0x34a53000, 0x10000206, +0x3c050007, 0xc002b3b, 0x34a53000, 0x10000216, 0x0, 0xa6b1000a, 0xa6b2000e, 0x8f820124, -0x3c040001, 0x2484698c, 0xafbe0014, 0xafa20010, -0x8f460044, 0x8f870120, 0x3c050007, 0xc002b17, -0x34a53200, 0x100001f8, 0x0, 0x8f420084, +0x3c040001, 0x248468fc, 0xafbe0014, 0xafa20010, +0x8f460044, 0x8f870120, 0x3c050007, 0xc002b3b, +0x34a53200, 0x10000208, 0x0, 0x8f420084, 0x8faa006c, 0x4a102b, 0x14400007, 0x3c020001, 0x2c21024, 0x10400004, 0x0, 0x240b0002, -0xafab005c, 0x8faa006c, 0x1140020b, 0x27ab0020, +0xafab005c, 0x8faa006c, 0x1140021b, 0x27ab0020, 0xafab00a4, 0x3c0a001f, 0x354affff, 0xafaa009c, -0x8fab005c, 0x240a0001, 0x156a0021, 0x24020002, +0x8fab005c, 0x240a0001, 0x556a0021, 0x240a0002, 0x8f430054, 0x8f420050, 0x1062000b, 0x274b0054, 0x8f5e0054, 0x3403ecc0, 0xafab004c, 0x27c20001, 0x304201ff, 0xafa20054, 0x1e1140, 0x431021, 0x1000006b, 0x2e2a821, 0x8f420044, 0x8faa006c, -0x3c040001, 0x2484693c, 0xafaa0014, 0xafa20010, -0x8f460054, 0x8f470050, 0x3c050007, 0xc002b17, +0x3c040001, 0x248468ac, 0xafaa0014, 0xafa20010, +0x8f460054, 0x8f470050, 0x3c050007, 0xc002b3b, 0x34a51300, 0x8f430350, 0x2402ffbf, 0x282a024, -0x24630001, 0xaf430350, 0x100001c3, 0x8f420350, -0x1562001d, 0x0, 0x8f430074, 0x8f420070, -0x1062000a, 0x274a0074, 0x8f5e0074, 0xafaa004c, +0x24630001, 0xaf430350, 0x100001d3, 0x8f420350, +0x156a001d, 0x0, 0x8f430074, 0x8f420070, +0x1062000a, 0x274b0074, 0x8f5e0074, 0xafab004c, 0x27c20001, 0x304203ff, 0xafa20054, 0x1e1140, 0x24426cc0, 0x1000004a, 0x2e2a821, 0x8f420044, -0x8fab006c, 0x3c040001, 0x24846948, 0x3c050007, -0xafab0014, 0xafa20010, 0x8f460074, 0x8f470070, -0x34a51500, 0x240a0001, 0xc002b17, 0xafaa005c, +0x8faa006c, 0x3c040001, 0x248468b8, 0x3c050007, +0xafaa0014, 0xafa20010, 0x8f460074, 0x8f470070, +0x34a51500, 0x240b0001, 0xc002b3b, 0xafab005c, 0x1000ffc3, 0x0, 0x8f430064, 0x8f420060, -0x1062001a, 0x274b0064, 0x8f5e0064, 0x8faa005c, -0xafab004c, 0x27c20001, 0x304200ff, 0xafa20054, -0x24020004, 0x1542000e, 0x1e1140, 0x1e1180, +0x1062001a, 0x274a0064, 0x8f5e0064, 0x8fab005c, +0xafaa004c, 0x27c20001, 0x304200ff, 0xafa20054, +0x24020004, 0x1562000e, 0x1e1140, 0x1e1180, 0x24420cc0, 0x2e21021, 0xafa20044, 0x9442002a, -0x8fab0044, 0x8faa006c, 0x4a102b, 0x10400024, -0x25750020, 0x240b0001, 0x10000021, 0xa3ab0097, +0x8faa0044, 0x8fab006c, 0x4b102b, 0x10400024, +0x25550020, 0x240a0001, 0x10000021, 0xa3aa0097, 0x24424cc0, 0x1000001e, 0x2e2a821, 0x8f420044, -0x8faa006c, 0x3c040001, 0x24846954, 0xafaa0014, +0x8fab006c, 0x3c040001, 0x248468c4, 0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060, 0x3c050007, -0xc002b17, 0x34a51800, 0x3c020008, 0x2c21024, -0x1440ff34, 0x0, 0x8f420370, 0x240b0001, -0xafab005c, 0x24420001, 0xaf420370, 0x1000ff90, +0xc002b3b, 0x34a51800, 0x3c020008, 0x2c21024, +0x1440ff34, 0x0, 0x8f420370, 0x240a0001, +0xafaa005c, 0x24420001, 0xaf420370, 0x1000ff90, 0x8f420370, 0x27a30036, 0x131040, 0x621821, 0x94620000, 0x441021, 0x10000020, 0xa4620000, -0x8faa0064, 0xaeaa0018, 0x93a20097, 0x10400072, -0x9821, 0x8fab0044, 0x8fa4006c, 0x8fa300a4, -0x25620020, 0xafa20028, 0x25620008, 0xafa20030, -0x25620010, 0xafab002c, 0xafa20034, 0x9562002a, -0xa7a20038, 0x95620018, 0xa7a2003a, 0x9562001a, -0xa7a2003c, 0x9562001c, 0xa7a2003e, 0x94620018, +0x8fab0064, 0xaeab0018, 0x93a20097, 0x10400072, +0x9821, 0x8faa0044, 0x8fa4006c, 0x8fa300a4, +0x25420020, 0xafa20028, 0x25420008, 0xafa20030, +0x25420010, 0xafaa002c, 0xafa20034, 0x9542002a, +0xa7a20038, 0x95420018, 0xa7a2003a, 0x9542001a, +0xa7a2003c, 0x9542001c, 0xa7a2003e, 0x94620018, 0x24630002, 0x822023, 0x1880ffde, 0x26730001, 0x2e620004, 0x1440fff9, 0x0, 0x8f4200fc, 0x26650001, 0xa2102a, 0x1440002b, 0x24030001, @@ -6960,20 +6961,20 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f820128, 0x431023, 0x21943, 0x58600001, 0x24630040, 0x64102a, 0x54400001, 0x602021, 0xaf4400fc, 0x8f4200fc, 0xa2102a, 0x10400011, -0x24030001, 0x10000015, 0x306200ff, 0x8faa0064, -0x96070018, 0xafaa0010, 0x8e220008, 0x3c040001, -0x2484696c, 0x8c430004, 0x8c420000, 0x34a52400, -0x2403021, 0xc002b17, 0xafa30014, 0x1000002b, +0x24030001, 0x10000015, 0x306200ff, 0x8fab0064, +0x96070018, 0xafab0010, 0x8e220008, 0x3c040001, +0x248468dc, 0x8c430004, 0x8c420000, 0x34a52400, +0x2403021, 0xc002b3b, 0xafa30014, 0x1000002b, 0x0, 0x8f420334, 0x1821, 0x24420001, 0xaf420334, 0x8f420334, 0x306200ff, 0x5040fedc, 0x3c020800, 0x12600021, 0x9021, 0x8fb100a4, 0x2208021, 0x8e220008, 0x96070018, 0x8fa60064, -0x8c440000, 0x8c450004, 0x240b0001, 0xafab0010, +0x8c440000, 0x8c450004, 0x240a0001, 0xafaa0010, 0xafbe0014, 0x8f420008, 0xafa20018, 0x8f42010c, 0x40f809, 0x0, 0x1040ffd8, 0x3c050007, -0x96020018, 0x8faa0064, 0x8fab009c, 0x1425021, -0x16a102b, 0x10400004, 0xafaa0064, 0x8f420148, -0x1425023, 0xafaa0064, 0x26100002, 0x26520001, +0x96020018, 0x8fab0064, 0x8faa009c, 0x1625821, +0x14b102b, 0x10400004, 0xafab0064, 0x8f420148, +0x1625823, 0xafab0064, 0x26100002, 0x26520001, 0x253102b, 0x1440ffe3, 0x26310004, 0x8fb0006c, 0x10000036, 0x97b10038, 0x8f4200fc, 0x24050002, 0xa2102a, 0x1440001b, 0x24030001, 0x8f83012c, @@ -6986,42 +6987,42 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f420334, 0x306200ff, 0x1040fea5, 0x3c020800, 0x96b1000a, 0x8fb0006c, 0x3223ffff, 0x70102b, 0x54400001, 0x608021, 0x8ea40000, 0x8ea50004, -0x240a0001, 0xafaa0010, 0xafbe0014, 0x8f420008, +0x240b0001, 0xafab0010, 0xafbe0014, 0x8f420008, 0x8fa60064, 0xafa20018, 0x8f42010c, 0x40f809, 0x2003821, 0x1040fea2, 0x3c050007, 0x96a3000e, -0x97ab008e, 0x11600007, 0x609021, 0x934205c4, -0x14400004, 0x0, 0x97aa0086, 0x6b1825, -0xa6aa0016, 0x8fab007c, 0x3c02ffff, 0x1621024, -0x10400003, 0xb1402, 0x34630400, 0xa6a20014, -0x8faa006c, 0x560a0072, 0xa6a3000e, 0x34620004, -0xa6a2000e, 0x8fab0074, 0x14b1021, 0xa6a2000a, +0x97aa008e, 0x11400007, 0x609021, 0x934205c4, +0x14400004, 0x0, 0x97ab0086, 0x6a1825, +0xa6ab0016, 0x8faa007c, 0x3c02ffff, 0x1421024, +0x10400003, 0xa1402, 0x34630400, 0xa6a20014, +0x8fab006c, 0x560b0072, 0xa6a3000e, 0x34620004, +0xa6a2000e, 0x8faa0074, 0x16a1021, 0xa6a2000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000, 0xafa20010, 0x8f420044, 0x2a03021, 0x24070020, 0xafa20014, 0x8f42000c, 0x31940, 0x604821, 0xafa20018, 0x8f42010c, 0x4021, 0xa92821, 0xa9182b, 0x882021, 0x40f809, 0x832021, 0x5040fe7f, 0xa6b2000e, 0x8f420368, 0xafa0006c, -0xa34005c4, 0x2442ffff, 0xaf420368, 0x8faa005c, -0x240b0001, 0x8f420368, 0x154b0006, 0x24020002, +0xa34005c4, 0x2442ffff, 0xaf420368, 0x8fab005c, +0x240a0001, 0x8f420368, 0x156a0006, 0x240a0002, 0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c, -0x8f42035c, 0x15420006, 0x0, 0x8f420364, +0x8f42035c, 0x156a0006, 0x0, 0x8f420364, 0x2442ffff, 0xaf420364, 0x10000005, 0x8f420364, 0x8f420360, 0x2442ffff, 0xaf420360, 0x8f420360, 0x8faa0054, 0x8fab004c, 0xad6a0000, 0x8f420044, 0x8f440088, 0x8f430078, 0x24420001, 0x441024, 0x24630001, 0xaf420044, 0xaf430078, 0x8c020240, -0x62182b, 0x14600065, 0x24070008, 0x8f440168, +0x62182b, 0x14600075, 0x24070008, 0x8f440168, 0x8f45016c, 0x8f430044, 0x8f48000c, 0x8f860120, 0x24020040, 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x240b0001, 0x3c010001, 0x370821, 0xa02b40f2, 0x8f820124, 0xafa20010, 0x8f820128, 0x3c040001, -0x2484691c, 0xafa20014, 0x8f460044, 0x8f870120, -0x3c050009, 0xc002b17, 0x34a51300, 0x1000000b, +0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120, +0x3c050009, 0xc002b3b, 0x34a51300, 0x1000000b, 0x0, 0x8f420304, 0x24420001, 0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2, 0xaf400078, 0x8f420318, -0x24420001, 0xaf420318, 0x10000038, 0x8f420318, +0x24420001, 0xaf420318, 0x10000048, 0x8f420318, 0xa6b0000a, 0x8f430044, 0x8f4401a0, 0x8f4501a4, 0x34028000, 0xafa20010, 0x8f420044, 0x2a03021, 0x24070020, 0xafa20014, 0x8f42000c, 0x31940, @@ -7031,12 +7032,16 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8fab006c, 0x8faa0064, 0x1705823, 0xafab006c, 0x8fab009c, 0x1505021, 0x16a102b, 0x10400004, 0xafaa0064, 0x8f420148, 0x1425023, 0xafaa0064, -0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420368, -0x8f42035c, 0x2442ffff, 0xaf42035c, 0x8fab0054, -0x8faa004c, 0x8f42035c, 0xad4b0000, 0x8f420044, +0x8f420368, 0x2442ffff, 0xaf420368, 0x8faa005c, +0x240b0001, 0x8f420368, 0x154b0006, 0x240b0002, +0x8f42035c, 0x2442ffff, 0xaf42035c, 0x1000000c, +0x8f42035c, 0x114b0006, 0x0, 0x8f420360, +0x2442ffff, 0xaf420360, 0x10000005, 0x8f420360, +0x8f420364, 0x2442ffff, 0xaf420364, 0x8f420364, +0x8fab0054, 0x8faa004c, 0xad4b0000, 0x8f420044, 0x8f440088, 0x8f430078, 0x24420001, 0x441024, 0x24630001, 0xaf420044, 0xaf430078, 0x8faa006c, -0x1540fe1b, 0x0, 0x8fab006c, 0x1160001e, +0x1540fe0b, 0x0, 0x8fab006c, 0x1160001e, 0x0, 0x934205c4, 0x10400009, 0x0, 0x8faa0064, 0xaf4a00c4, 0xaf4b00c0, 0x8fab007c, 0xaf4b00c8, 0x8faa0074, 0x1000000e, 0xaf4a00cc, @@ -7063,7 +7068,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa20064, 0x3c020006, 0x2c21024, 0x14400015, 0xafac006c, 0x93c20000, 0x30420001, 0x10400011, 0x2402ffff, 0x8fc30000, 0x14620004, 0x3402ffff, -0x97c30004, 0x1062000b, 0x0, 0xc002497, +0x97c30004, 0x1062000b, 0x0, 0xc0024bb, 0x3c02021, 0x304200ff, 0x14400006, 0x0, 0x8f420118, 0x40f809, 0x0, 0x10000280, 0x0, 0x8fa20024, 0x3c03ffbf, 0x3463ffff, @@ -7088,9 +7093,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x4b102b, 0x10400015, 0x320200ff, 0x8f4201e8, 0x24420001, 0xaf4201e8, 0x8f4201e8, 0x8fac006c, 0x8f8200e0, 0x358c0100, 0xafac006c, 0xafa20010, -0x8f8200e4, 0x24100001, 0x3c040001, 0x24846930, +0x8f8200e4, 0x24100001, 0x3c040001, 0x248468a0, 0xafa20014, 0x8fa60020, 0x8fa70024, 0x3c050007, -0xc002b17, 0x34a53600, 0x320200ff, 0x10400010, +0xc002b3b, 0x34a53600, 0x320200ff, 0x10400010, 0x3c020080, 0x2c21024, 0x1440000e, 0x32c20400, 0x8fab006c, 0x3c020080, 0x34420100, 0x1621024, 0x10400005, 0x0, 0x8f42020c, 0x24420001, @@ -7115,8 +7120,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2c420001, 0x621825, 0x10600004, 0x3c020100, 0x94820002, 0x453821, 0x3c020100, 0x2c21024, 0x5040000e, 0xafa70064, 0x8fac0064, 0x10ec0008, -0x3c050007, 0x3c040001, 0x24846998, 0x8fa60064, -0x34a54000, 0xafa00010, 0xc002b17, 0xafa00014, +0x3c050007, 0x3c040001, 0x24846908, 0x8fa60064, +0x34a54000, 0xafa00010, 0xc002b3b, 0xafa00014, 0x8fab0064, 0x256b0004, 0xafab0064, 0x8f420080, 0x8fac0064, 0x4c102b, 0x1040002c, 0x32c28000, 0x10400034, 0x240b0003, 0x32c21000, 0x10400031, @@ -7124,11 +7129,11 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2403ffbf, 0x283a024, 0x24420001, 0xaf420350, 0x10000173, 0x8f420350, 0x3c020800, 0x2c2b025, 0x2402ffbf, 0x282a024, 0x8f830128, 0x3c040001, -0x24846960, 0x26620001, 0xafa20014, 0xafa30010, -0x8f860120, 0x8f870124, 0x3c050007, 0xc002b17, +0x248468d0, 0x26620001, 0xafa20014, 0xafa30010, +0x8f860120, 0x8f870124, 0x3c050007, 0xc002b3b, 0x34a55300, 0x10000162, 0x0, 0x8ea20000, -0x8ea30004, 0x3c040001, 0x24846978, 0xafb00010, -0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b17, +0x8ea30004, 0x3c040001, 0x248468e8, 0xafb00010, +0xafb10014, 0x8ea70018, 0x34a55900, 0xc002b3b, 0x603021, 0x10000156, 0x0, 0x8f420084, 0x8fab0064, 0x4b102b, 0x14400007, 0x3c020001, 0x2c21024, 0x10400004, 0x0, 0x240c0002, @@ -7138,17 +7143,17 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x274b0054, 0x8f510054, 0x3403ecc0, 0xafab004c, 0x26220001, 0x304201ff, 0xafa20054, 0x111140, 0x431021, 0x1000006b, 0x2e2a821, 0x8f420044, -0x8fac0064, 0x3c040001, 0x2484693c, 0xafac0014, +0x8fac0064, 0x3c040001, 0x248468ac, 0xafac0014, 0xafa20010, 0x8f460054, 0x8f470050, 0x3c050007, -0xc002b17, 0x34a54300, 0x8f430350, 0x2402ffbf, +0xc002b3b, 0x34a54300, 0x8f430350, 0x2402ffbf, 0x282a024, 0x24630001, 0xaf430350, 0x10000124, 0x8f420350, 0x156c001d, 0x0, 0x8f430074, 0x8f420070, 0x1062000a, 0x274b0074, 0x8f510074, 0xafab004c, 0x26220001, 0x304203ff, 0xafa20054, 0x111140, 0x24426cc0, 0x1000004a, 0x2e2a821, -0x8f420044, 0x8fac0064, 0x3c040001, 0x24846948, +0x8f420044, 0x8fac0064, 0x3c040001, 0x248468b8, 0x3c050007, 0xafac0014, 0xafa20010, 0x8f460074, -0x8f470070, 0x34a54500, 0x240b0001, 0xc002b17, +0x8f470070, 0x34a54500, 0x240b0001, 0xc002b3b, 0xafab005c, 0x1000ffc3, 0x0, 0x8f430064, 0x8f420060, 0x1062001a, 0x274c0064, 0x8f510064, 0x8fab005c, 0xafac004c, 0x26220001, 0x304200ff, @@ -7157,9 +7162,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x9442002a, 0x8fac0044, 0x8fab0064, 0x4b102b, 0x10400024, 0x25950020, 0x240c0001, 0x10000021, 0xa3ac0087, 0x24424cc0, 0x1000001e, 0x2e2a821, -0x8f420044, 0x8fab0064, 0x3c040001, 0x24846954, +0x8f420044, 0x8fab0064, 0x3c040001, 0x248468c4, 0xafab0014, 0xafa20010, 0x8f460064, 0x8f470060, -0x3c050007, 0xc002b17, 0x34a54800, 0x3c020008, +0x3c050007, 0xc002b3b, 0x34a54800, 0x3c020008, 0x2c21024, 0x1440ff61, 0x0, 0x8f420370, 0x240c0001, 0xafac005c, 0x24420001, 0xaf420370, 0x1000ff90, 0x8f420370, 0x27a30036, 0x131040, @@ -7180,9 +7185,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x8f4200fc, 0x262102a, 0x10400016, 0x24030001, 0x1000001a, 0x306200ff, 0x8fac008c, 0x101040, 0x4c1021, 0x94470018, 0x101080, 0x4c1021, -0xafbe0010, 0x8c420008, 0x3c040001, 0x2484696c, +0xafbe0010, 0x8c420008, 0x3c040001, 0x248468dc, 0x3c050007, 0x8c430004, 0x8c420000, 0x34a55500, -0x2003021, 0xc002b17, 0xafa30014, 0x10000039, +0x2003021, 0xc002b3b, 0xafa30014, 0x10000039, 0x0, 0x8f420334, 0x1821, 0x24420001, 0xaf420334, 0x8f420334, 0x306200ff, 0x1040ff06, 0x8021, 0x8f430008, 0x2402fbff, 0x1260002d, @@ -7399,7 +7404,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x822023, 0x94820000, 0x2028021, 0x3c020100, 0x2c21024, 0x1040000e, 0x0, 0x8faa002c, 0x31420004, 0x1040000a, 0x0, 0x9504000e, -0x2642021, 0xc003ec4, 0x2484fffc, 0x3042ffff, +0x2642021, 0xc003eec, 0x2484fffc, 0x3042ffff, 0x2228821, 0x111c02, 0x3222ffff, 0x628821, 0x8faa0024, 0x1518823, 0x111402, 0x2228821, 0x2308821, 0x111402, 0x2228821, 0x3231ffff, @@ -7412,8 +7417,8 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa80018, 0x8f48010c, 0x1021, 0xa32821, 0xa3482b, 0x822021, 0x100f809, 0x892021, 0x1440000b, 0x0, 0x8f820128, 0x3c040001, -0x248469a4, 0xafbe0014, 0xafa20010, 0x8f860124, -0x8f870120, 0x3c050007, 0xc002b17, 0x34a59920, +0x24846914, 0xafbe0014, 0xafa20010, 0x8f860124, +0x8f870120, 0x3c050007, 0xc002b3b, 0x34a59920, 0x8f420368, 0x2442ffff, 0xaf420368, 0x8f420044, 0x8f430088, 0x24420001, 0x431024, 0xaf420044, 0x8faa0034, 0x8f440368, 0x24020001, 0x15420006, @@ -7430,9 +7435,9 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xafa20010, 0xafa30014, 0xafa80018, 0x8f42010c, 0x40f809, 0x24c6001c, 0x14400011, 0x24020001, 0x3c010001, 0x370821, 0xa02240f2, 0x8f820124, -0xafa20010, 0x8f820128, 0x3c040001, 0x2484691c, +0xafa20010, 0x8f820128, 0x3c040001, 0x2484688c, 0xafa20014, 0x8f460044, 0x8f870120, 0x3c050009, -0xc002b17, 0x34a51300, 0x1000000b, 0x0, +0xc002b3b, 0x34a51300, 0x1000000b, 0x0, 0x8f420304, 0x24420001, 0xaf420304, 0x8f420304, 0x8f420044, 0xaf42007c, 0x3c010001, 0x370821, 0xa02040f2, 0xaf400078, 0x8f420318, 0x24420001, @@ -7444,32 +7449,32 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaf8200c8, 0x8f420138, 0xaf8200d0, 0x8f420138, 0xaf8200d4, 0x8f420138, 0x3e00008, 0xaf8200d8, 0x27bdffe0, 0x27840208, 0x24050200, 0xafbf0018, -0xc002b9b, 0x24060008, 0x8c020204, 0xc003fea, -0xaf820210, 0x3c020001, 0x8c426e14, 0x30420002, +0xc002bbf, 0x24060008, 0x8c020204, 0xc004012, +0xaf820210, 0x3c020001, 0x8c426d94, 0x30420002, 0x1040000e, 0x2021, 0x8c060248, 0x24020002, -0x3c010001, 0xac226e18, 0xc005134, 0x24050002, +0x3c010001, 0xac226d98, 0xc005104, 0x24050002, 0x2021, 0x8c060248, 0x24020001, 0x3c010001, -0xac226e18, 0x10000011, 0x24050001, 0x8c060248, -0x24020004, 0x3c010001, 0xac226e18, 0xc005134, -0x24050004, 0x3c020001, 0x8c426e14, 0x30420001, -0x10400008, 0x24020001, 0x3c010001, 0xac226e18, -0x2021, 0x24050001, 0x3c06601b, 0xc005134, -0x0, 0x3c040001, 0x24846a60, 0x8f420150, +0xac226d98, 0x10000011, 0x24050001, 0x8c060248, +0x24020004, 0x3c010001, 0xac226d98, 0xc005104, +0x24050004, 0x3c020001, 0x8c426d94, 0x30420001, +0x10400008, 0x24020001, 0x3c010001, 0xac226d98, +0x2021, 0x24050001, 0x3c06601b, 0xc005104, +0x0, 0x3c040001, 0x248469d0, 0x8f420150, 0x8f430154, 0x3c050008, 0x8f460158, 0x21640, 0x31940, 0x34630403, 0x431025, 0x633c0, 0x461025, 0xaf82021c, 0xafa00010, 0xafa00014, -0x8f86021c, 0x34a50200, 0xc002b17, 0x3821, -0x3c010001, 0xac206e10, 0x3c010001, 0xac206e28, +0x8f86021c, 0x34a50200, 0xc002b3b, 0x3821, +0x3c010001, 0xac206d90, 0x3c010001, 0xac206da8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffe0, 0x3c050008, 0x34a50300, 0xafbf0018, 0xafa00010, -0xafa00014, 0x8f860200, 0x3c040001, 0x24846a6c, -0xc002b17, 0x3821, 0x8f420410, 0x24420001, +0xafa00014, 0x8f860200, 0x3c040001, 0x248469dc, +0xc002b3b, 0x3821, 0x8f420410, 0x24420001, 0xaf420410, 0x8f420410, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0xafb00018, 0x8f4203a4, 0x24420001, 0xaf4203a4, 0x8f4203a4, 0x8f900220, 0x8f8200e0, 0xafa20010, 0x8f8200e4, 0xafa20014, 0x8f8600c4, 0x8f8700c8, -0x3c040001, 0x24846a78, 0xc002b17, 0x2002821, +0x3c040001, 0x248469e8, 0xc002b3b, 0x2002821, 0x3c044000, 0x2041024, 0x504000b4, 0x3c040100, 0x8f4203bc, 0x24420001, 0xaf4203bc, 0x8f4203bc, 0x8f8700c4, 0x8f8300c8, 0x8f420148, 0x671823, @@ -7518,26 +7523,26 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0xaf4303cc, 0x10000039, 0x8f4203cc, 0x2041024, 0x1040000e, 0x3c110200, 0x8f4203a8, 0x24420001, 0xaf4203a8, 0x8f4203a8, 0x8f820220, 0x3c0308ff, -0x3463ffff, 0x431024, 0x441025, 0xc003d87, +0x3463ffff, 0x431024, 0x441025, 0xc003daf, 0xaf820220, 0x10000029, 0x0, 0x2111024, 0x50400008, 0x3c110400, 0x8f4203ac, 0x24420001, -0xaf4203ac, 0xc003d87, 0x8f4203ac, 0x10000019, +0xaf4203ac, 0xc003daf, 0x8f4203ac, 0x10000019, 0x0, 0x2111024, 0x1040001c, 0x0, 0x8f830224, 0x24021402, 0x14620009, 0x3c050008, -0x3c040001, 0x24846a84, 0xafa00010, 0xafa00014, -0x8f860224, 0x34a50500, 0xc002b17, 0x3821, +0x3c040001, 0x248469f4, 0xafa00010, 0xafa00014, +0x8f860224, 0x34a50500, 0xc002b3b, 0x3821, 0x8f4203b0, 0x24420001, 0xaf4203b0, 0x8f4203b0, -0x8f820220, 0x2002021, 0x34420002, 0xc004ecc, +0x8f820220, 0x2002021, 0x34420002, 0xc004e9c, 0xaf820220, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x511025, 0xaf820220, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0028, -0x3e00008, 0x0, 0x3c020001, 0x8c426e28, +0x3e00008, 0x0, 0x3c020001, 0x8c426da8, 0x27bdffb0, 0xafbf0048, 0xafbe0044, 0xafb50040, 0xafb3003c, 0xafb20038, 0xafb10034, 0x1040000f, -0xafb00030, 0x3c040001, 0x24846a90, 0x3c050008, +0xafb00030, 0x3c040001, 0x24846a00, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50600, -0x24020001, 0x3c010001, 0xac206e28, 0x3c010001, -0xac226e1c, 0xc002b17, 0x3821, 0x3c037fff, +0x24020001, 0x3c010001, 0xac206da8, 0x3c010001, +0xac226d9c, 0xc002b3b, 0x3821, 0x3c037fff, 0x8c020268, 0x3463ffff, 0x3c04fdff, 0x431024, 0xac020268, 0x8f420004, 0x3484ffff, 0x30420002, 0x10400092, 0x284a024, 0x3c040600, 0x34842000, @@ -7546,7 +7551,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x240200ff, 0x13c20002, 0xafaa002c, 0x27c50001, 0x8c020228, 0xa09021, 0x1642000e, 0x1e38c0, 0x8f42033c, 0x24420001, 0xaf42033c, 0x8f42033c, -0x8c020228, 0x3c040001, 0x24846a28, 0x3c050009, +0x8c020228, 0x3c040001, 0x24846998, 0x3c050009, 0xafa00014, 0xafa20010, 0x8fa60020, 0x1000006d, 0x34a50500, 0xf71021, 0x8fa30020, 0x8fa40024, 0xac4304c0, 0xac4404c4, 0x8f830054, 0x8f820054, @@ -7560,7 +7565,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x2c4203e9, 0x1440ffe9, 0x0, 0x326200ff, 0x54400017, 0xaf520018, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, -0xafa20010, 0x8f820124, 0x3c040001, 0x24846a34, +0xafa20010, 0x8f820124, 0x3c040001, 0x248469a4, 0x3c050009, 0xafa20014, 0x8d460000, 0x10000035, 0x34a50600, 0x8f420308, 0x24130001, 0x24420001, 0xaf420308, 0x8f420308, 0x1000001e, 0x326200ff, @@ -7574,21 +7579,21 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x326200ff, 0x14400011, 0x0, 0x8f420378, 0x24420001, 0xaf420378, 0x8f420378, 0x8f820120, 0x8faa002c, 0xafa20010, 0x8f820124, 0x3c040001, -0x24846a3c, 0x3c050009, 0xafa20014, 0x8d460000, -0x34a50700, 0xc002b17, 0x3c03821, 0x8f4202ec, +0x248469ac, 0x3c050009, 0xafa20014, 0x8d460000, +0x34a50700, 0xc002b3b, 0x3c03821, 0x8f4202ec, 0x24420001, 0xaf4202ec, 0x8f4202ec, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, 0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, 0x3e00008, 0x27bd0050, -0x3c020001, 0x8c426e28, 0x27bdffe0, 0x1440000d, -0xafbf0018, 0x3c040001, 0x24846a9c, 0x3c050008, +0x3c020001, 0x8c426da8, 0x27bdffe0, 0x1440000d, +0xafbf0018, 0x3c040001, 0x24846a0c, 0x3c050008, 0xafa00010, 0xafa00014, 0x8f860220, 0x34a50700, -0x24020001, 0x3c010001, 0xac226e28, 0xc002b17, +0x24020001, 0x3c010001, 0xac226da8, 0xc002b3b, 0x3821, 0x3c020004, 0x2c21024, 0x10400007, 0x0, 0x8f820220, 0x3c0308ff, 0x3463ffff, 0x431024, 0x34420008, 0xaf820220, 0x3c050001, -0x8ca56e18, 0x24020001, 0x14a20007, 0x2021, -0xc0052c7, 0x24050001, 0xac02026c, 0x8c03026c, -0x10000006, 0x3c020007, 0xc0052c7, 0x2021, +0x8ca56d98, 0x24020001, 0x14a20007, 0x2021, +0xc00529b, 0x24050001, 0xac02026c, 0x8c03026c, +0x10000006, 0x3c020007, 0xc00529b, 0x2021, 0xac020268, 0x8c030268, 0x3c020007, 0x621824, 0x3c020002, 0x5062000d, 0x3c0205f5, 0x43102b, 0x14400006, 0x3c020004, 0x3c020001, 0x10620009, @@ -7636,7 +7641,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x90a20000, 0x822021, 0x41c02, 0x3082ffff, 0x622021, 0x41c02, 0x3082ffff, 0x622021, 0x3e00008, 0x3082ffff, 0x0, 0x8f820220, -0x34420002, 0xaf820220, 0x3c020002, 0x8c429078, +0x34420002, 0xaf820220, 0x3c020002, 0x8c428ff8, 0x30424000, 0x10400054, 0x24040001, 0x8f820200, 0x24067fff, 0x8f830200, 0x30450002, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 0x8f830054, @@ -7683,1091 +7688,1069 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x43102b, 0x14400006, 0x3c026000, 0x3c024000, 0x10620008, 0x24020800, 0x10000008, 0x0, 0x10620004, 0x24020800, 0x10000004, 0x0, -0x24020700, 0x3c010001, 0xac226e2c, 0x3e00008, -0x0, 0x3c020001, 0x8c426e3c, 0x27bdffc8, -0xafbf0034, 0xafb20030, 0xafb1002c, 0xafb00028, -0x3c010001, 0x10400005, 0xac206e14, 0xc004dd1, -0x0, 0x3c010001, 0xac206e3c, 0x8f830054, +0x24020700, 0x3c010001, 0xac226dac, 0x3e00008, +0x0, 0x3c020001, 0x8c426dbc, 0x27bdffd0, +0xafbf002c, 0xafb20028, 0xafb10024, 0xafb00020, +0x3c010001, 0x10400005, 0xac206d94, 0xc004d9e, +0x0, 0x3c010001, 0xac206dbc, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, 0x0, -0xc004dec, 0x0, 0x24040001, 0x2821, -0x27a60020, 0x34028000, 0xc00450e, 0xa7a20020, +0xc004db9, 0x0, 0x24040001, 0x2821, +0x27a60018, 0x34028000, 0xc0045be, 0xa7a20018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, -0x24040001, 0x24050001, 0xc0044cc, 0x27a60020, +0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, -0x24040001, 0x24050001, 0xc0044cc, 0x27a60020, +0x24040001, 0x24050001, 0xc00457c, 0x27a60018, 0x8f830054, 0x8f820054, 0x10000002, 0x24630064, 0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, -0x24040001, 0x24050002, 0xc0044cc, 0x27a60018, -0x8f830054, 0x8f820054, 0x10000002, 0x24630064, -0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, -0x24040001, 0x24050003, 0xc0044cc, 0x27a6001a, -0x3c040001, 0x24846b70, 0x97a60020, 0x97a70018, -0x97a2001a, 0x3c05000d, 0x34a50100, 0xafa00014, -0xc002b17, 0xafa20010, 0x97a20020, 0x10400046, -0x24036040, 0x97a2001a, 0x3042fff0, 0x1443000b, -0x24020020, 0x97a30018, 0x1462000a, 0x24027830, -0x24020003, 0x3c010001, 0xac226e14, 0x24020005, -0x3c010001, 0x10000039, 0xac226fac, 0x97a30018, -0x24027830, 0x1462000b, 0x24030010, 0x97a2001a, -0x3042fff0, 0x14430007, 0x24020003, 0x3c010001, -0xac226e14, 0x24020006, 0x3c010001, 0x1000002b, -0xac226fac, 0x3c020001, 0x8c426e14, 0x97a30018, -0x34420001, 0x3c010001, 0xac226e14, 0x24020015, -0x1462000a, 0x0, 0x97a2001a, 0x3042fff0, -0x3843f420, 0x2c630001, 0x3842f430, 0x2c420001, -0x621825, 0x14600019, 0x24020003, 0x97a30018, -0x24027810, 0x14620015, 0x24020002, 0x97a2001a, -0x3042fff0, 0x14400011, 0x24020002, 0x1000000f, -0x24020004, 0x3c020001, 0x8c426e14, 0x34420008, -0x3c010001, 0xac226e14, 0x1000005e, 0x24020004, -0x3c020001, 0x8c426e14, 0x34420004, 0x3c010001, -0x100000af, 0xac226e14, 0x24020001, 0x3c010001, -0xac226fb8, 0x3c020001, 0x8c426e14, 0x30420002, -0x144000b2, 0x3c09fff0, 0x24020e00, 0xaf820238, -0x8f840054, 0x8f820054, 0x24030008, 0x3c010001, -0xac236e18, 0x10000002, 0x248401f4, 0x8f820054, -0x821023, 0x2c4201f5, 0x1440fffc, 0x3c0200c8, -0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, -0x10000002, 0x246301f4, 0x8f820054, 0x621023, -0x2c4201f5, 0x1440fffc, 0x8021, 0x24120001, -0x24110009, 0xc0043d3, 0x0, 0x3c010001, -0xac326e34, 0xc004498, 0x0, 0x3c020001, -0x8c426e34, 0x1451fffb, 0x3c0200c8, 0x344201f6, +0x24040001, 0x3c060001, 0x24c66f24, 0xc00457c, +0x24050002, 0x8f830054, 0x8f820054, 0x10000002, +0x24630064, 0x8f820054, 0x621023, 0x2c420065, +0x1440fffc, 0x24040001, 0x24050003, 0x3c100001, +0x26106f26, 0xc00457c, 0x2003021, 0x97a60018, +0x3c070001, 0x94e76f24, 0x3c040001, 0x24846ae0, +0xafa00014, 0x96020000, 0x3c05000d, 0x34a50100, +0xc002b3b, 0xafa20010, 0x97a20018, 0x1040004d, +0x24036040, 0x96020000, 0x3042fff0, 0x1443000c, +0x24020020, 0x3c030001, 0x94636f24, 0x1462000b, +0x24027830, 0x24020003, 0x3c010001, 0xac226d94, +0x24020005, 0x3c010001, 0x1000003f, 0xac226f34, +0x3c030001, 0x94636f24, 0x24027830, 0x1462000c, +0x24030010, 0x3c020001, 0x94426f26, 0x3042fff0, +0x14430007, 0x24020003, 0x3c010001, 0xac226d94, +0x24020006, 0x3c010001, 0x1000002f, 0xac226f34, +0x3c020001, 0x8c426d94, 0x3c030001, 0x94636f24, +0x34420001, 0x3c010001, 0xac226d94, 0x24020015, +0x1462000b, 0x0, 0x3c020001, 0x94426f26, +0x3042fff0, 0x3843f420, 0x2c630001, 0x3842f430, +0x2c420001, 0x621825, 0x1460001b, 0x24020003, +0x3c030001, 0x94636f24, 0x24027810, 0x14620016, +0x24020002, 0x3c020001, 0x94426f26, 0x3042fff0, +0x14400011, 0x24020002, 0x1000000f, 0x24020004, +0x3c020001, 0x8c426d94, 0x34420008, 0x3c010001, +0xac226d94, 0x1000005e, 0x24020004, 0x3c020001, +0x8c426d94, 0x34420004, 0x3c010001, 0x100000af, +0xac226d94, 0x24020001, 0x3c010001, 0xac226f40, +0x3c020001, 0x8c426d94, 0x30420002, 0x144000b2, +0x3c09fff0, 0x24020e00, 0xaf820238, 0x8f840054, +0x8f820054, 0x24030008, 0x3c010001, 0xac236d98, +0x10000002, 0x248401f4, 0x8f820054, 0x821023, +0x2c4201f5, 0x1440fffc, 0x3c0200c8, 0x344201fb, 0xaf820238, 0x8f830054, 0x8f820054, 0x10000002, -0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, -0x1440fffc, 0x0, 0x8f820220, 0x24040001, -0x34420002, 0xaf820220, 0x8f830200, 0x24057fff, -0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820224, 0x14440005, 0x34028000, -0x42040, 0xa4102b, 0x1040fff0, 0x34028000, -0x1082ffa0, 0x26100001, 0x2e020014, 0x1440ffcd, -0x24020004, 0x3c010001, 0xac226e18, 0x8021, -0x24120009, 0x3c11ffff, 0x36313f7f, 0xc0043d3, -0x0, 0x24020001, 0x3c010001, 0xac226e34, -0xc004498, 0x0, 0x3c020001, 0x8c426e34, -0x1452fffb, 0x0, 0x8f820044, 0x511024, -0x34425080, 0xaf820044, 0x8f830054, 0x8f820054, -0x10000002, 0x2463000a, 0x8f820054, 0x621023, -0x2c42000b, 0x1440fffc, 0x0, 0x8f820044, -0x511024, 0x3442f080, 0xaf820044, 0x8f830054, -0x8f820054, 0x10000002, 0x2463000a, 0x8f820054, -0x621023, 0x2c42000b, 0x1440fffc, 0x0, -0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, -0x8f830054, 0x8f820054, 0x10000002, 0x24630064, -0x8f820054, 0x621023, 0x2c420065, 0x1440fffc, +0x246301f4, 0x8f820054, 0x621023, 0x2c4201f5, +0x1440fffc, 0x8021, 0x24120001, 0x24110009, +0xc004482, 0x0, 0x3c010001, 0xac326db4, +0xc004547, 0x0, 0x3c020001, 0x8c426db4, +0x1451fffb, 0x3c0200c8, 0x344201f6, 0xaf820238, +0x8f830054, 0x8f820054, 0x10000002, 0x2463000a, +0x8f820054, 0x621023, 0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, 0x24040001, 0x34420002, 0xaf820220, 0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, 0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x8f820224, 0x14440005, 0x34028000, 0x42040, -0xa4102b, 0x1040fff0, 0x34028000, 0x1082ff50, -0x26100001, 0x2e020064, 0x1440ffb0, 0x0, -0x3c020001, 0x8c426e14, 0x30420004, 0x14400007, -0x3c09fff0, 0x8f820044, 0x3c03ffff, 0x34633f7f, -0x431024, 0xaf820044, 0x3c09fff0, 0x3529bdc0, -0x8f830054, 0x3c060001, 0x8cc66e14, 0x3c070001, -0x8ce76fb8, 0x97a80018, 0x3c040001, 0x24846b70, -0x24020001, 0x3c010001, 0xac226e1c, 0xafa80010, -0x97a2001a, 0x3c05000d, 0x34a50100, 0x3c010001, -0xac206e18, 0x691821, 0x3c010001, 0xac236fa8, -0xc002b17, 0xafa20014, 0x8fbf0034, 0x8fb20030, -0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038, -0x27bdffe8, 0x3c050001, 0x8ca56e18, 0x24060004, -0x24020001, 0x14a20014, 0xafbf0010, 0x3c020002, -0x8c42907c, 0x30428000, 0x10400005, 0x3c04000f, -0x3c030001, 0x8c636fb8, 0x10000005, 0x34844240, -0x3c040004, 0x3c030001, 0x8c636fb8, 0x348493e0, -0x24020005, 0x14620016, 0x0, 0x3c04003d, -0x10000013, 0x34840900, 0x3c020002, 0x8c429078, -0x30428000, 0x10400005, 0x3c04001e, 0x3c030001, -0x8c636fb8, 0x10000005, 0x34848480, 0x3c04000f, -0x3c030001, 0x8c636fb8, 0x34844240, 0x24020005, -0x14620003, 0x0, 0x3c04007a, 0x34841200, -0x3c020001, 0x8c426fa8, 0x8f830054, 0x441021, -0x431023, 0x44102b, 0x1440004b, 0x0, -0x3c020001, 0x8c426e20, 0x14400047, 0x0, -0x3c010001, 0x10c00025, 0xac206e30, 0x3c090001, -0x8d296e14, 0x24070001, 0x3c044000, 0x3c080002, -0x2508907c, 0x250afffc, 0x52842, 0x14a00002, -0x24c6ffff, 0x24050008, 0xa91024, 0x10400010, -0x0, 0x14a70008, 0x0, 0x8d020000, -0x441024, 0x1040000a, 0x0, 0x3c010001, -0x10000007, 0xac256e30, 0x8d420000, 0x441024, -0x10400003, 0x0, 0x3c010001, 0xac276e30, -0x3c020001, 0x8c426e30, 0x6182b, 0x2c420001, -0x431024, 0x5440ffe5, 0x52842, 0x8f820054, -0x3c030001, 0x8c636e30, 0x3c010001, 0xac226fa8, -0x1060003a, 0x24020005, 0x3c030001, 0x8c636fb8, -0x3c010001, 0xac256e18, 0x14620011, 0x24020001, -0x3c020002, 0x8c429078, 0x3c032000, 0x431024, -0x14400006, 0x24020001, 0x3c010001, 0xac206f98, -0x3c010001, 0xac226e18, 0x24020001, 0x3c010001, -0xac226ea4, 0x3c010001, 0xac226e24, 0x24020001, -0x3c010001, 0xac226e1c, 0x3c020001, 0x8c426e30, -0x1040001e, 0x0, 0x3c020001, 0x8c426e1c, -0x10400008, 0x24020001, 0x3c010001, 0xac206e1c, -0xaee204b8, 0x3c010001, 0xac206e9c, 0x3c010001, -0xac226e54, 0x8ee304b8, 0x24020008, 0x10620005, -0x24020001, 0xc004203, 0x0, 0x1000000b, -0x0, 0x3c030001, 0x8c636e18, 0x10620007, -0x2402000e, 0x3c030002, 0x8c639010, 0x10620003, -0x0, 0xc004ecc, 0x8f840220, 0x8fbf0010, -0x3e00008, 0x27bd0018, 0x27bdffe0, 0x3c03fdff, -0x3c040001, 0x8c846e18, 0x3c020001, 0x8c426e40, -0x3463ffff, 0x283a024, 0xafbf001c, 0x14820006, -0xafb00018, 0x8ee304b8, 0x3c020001, 0x8c426e44, -0x10620006, 0x0, 0x8ee204b8, 0x3c010001, -0xac246e40, 0x3c010001, 0xac226e44, 0x3c030001, -0x8c636e18, 0x24020002, 0x10620167, 0x2c620003, -0x10400005, 0x24020001, 0x1062000a, 0x0, -0x100001ab, 0x0, 0x24020004, 0x10620081, -0x24020008, 0x106200d5, 0x24020001, 0x100001a4, -0x0, 0x8ee204b8, 0x2443ffff, 0x2c620008, -0x104001a1, 0x31080, 0x3c010001, 0x220821, -0x8c226b88, 0x400008, 0x0, 0x3c030001, -0x8c636fb8, 0x24020005, 0x14620010, 0x0, -0x3c020001, 0x8c426e24, 0x10400008, 0x24020003, -0xc0043d3, 0x0, 0x24020002, 0xaee204b8, -0x3c010001, 0x10000002, 0xac206e24, 0xaee204b8, -0x3c010001, 0x10000188, 0xac206db0, 0xc0043d3, -0x0, 0x3c020001, 0x8c426e24, 0x3c010001, -0xac206db0, 0x14400145, 0x24020002, 0x10000163, -0x24020007, 0x24020001, 0x3c010001, 0xc00454f, -0xac226e50, 0x3c030001, 0x8c636e50, 0x10000144, -0x24020011, 0x3c020001, 0x8c426fb8, 0x24100005, -0x10500007, 0x0, 0x3c050001, 0x8ca56e18, -0x3c060002, 0x8cc6907c, 0xc005134, 0x2021, -0x3c010001, 0xac206e24, 0x10000167, 0xaef004b8, -0x3c040001, 0x24846b7c, 0x3c05000f, 0x34a50100, -0x3021, 0x3821, 0xafa00010, 0xc002b17, -0xafa00014, 0x1000015c, 0x0, 0x8f820220, -0x3c030004, 0x431024, 0x1440013c, 0x24020007, -0x8f830054, 0x3c020001, 0x8c426fa0, 0x2463d8f0, -0x431023, 0x2c422710, 0x1440014f, 0x24020001, -0x1000014b, 0x0, 0x3c050001, 0x8ca56e18, -0xc0052c7, 0x2021, 0xc00553d, 0x2021, -0x3c030002, 0x8c639074, 0x4610141, 0x24020001, -0x3c020008, 0x621024, 0x10400006, 0x0, -0x8f820214, 0x3c03ffff, 0x431024, 0x10000005, -0x3442251f, 0x8f820214, 0x3c03ffff, 0x431024, -0x3442241f, 0xaf820214, 0x8f820220, 0x3c030200, -0x283a025, 0x34420002, 0xaf820220, 0x24020008, -0xc003e45, 0xaee204b8, 0x3c010001, 0x1000012a, -0xac206ea0, 0x8ee204b8, 0x2443ffff, 0x2c620008, -0x10400125, 0x31080, 0x3c010001, 0x220821, -0x8c226ba8, 0x400008, 0x0, 0xc004498, -0x0, 0x3c030001, 0x8c636e34, 0x100000e8, -0x24020009, 0x3c020002, 0x8c429078, 0x30424000, -0x10400004, 0x0, 0x8f820044, 0x10000006, -0x3442f080, 0x8f820044, 0x3c03ffff, 0x34633f7f, -0x431024, 0x3442a080, 0xaf820044, 0x8f830054, -0x100000ea, 0x24020004, 0x8f830054, 0x3c020001, -0x8c426fa0, 0x2463d8f0, 0x431023, 0x2c422710, -0x14400101, 0x24020005, 0x100000d8, 0x0, +0xa4102b, 0x1040fff0, 0x34028000, 0x1082ffa0, +0x26100001, 0x2e020014, 0x1440ffcd, 0x24020004, +0x3c010001, 0xac226d98, 0x8021, 0x24120009, +0x3c11ffff, 0x36313f7f, 0xc004482, 0x0, +0x24020001, 0x3c010001, 0xac226db4, 0xc004547, +0x0, 0x3c020001, 0x8c426db4, 0x1452fffb, +0x0, 0x8f820044, 0x511024, 0x34425080, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, +0x2463000a, 0x8f820054, 0x621023, 0x2c42000b, +0x1440fffc, 0x0, 0x8f820044, 0x511024, +0x3442f080, 0xaf820044, 0x8f830054, 0x8f820054, +0x10000002, 0x2463000a, 0x8f820054, 0x621023, +0x2c42000b, 0x1440fffc, 0x0, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, +0x8f820054, 0x10000002, 0x24630064, 0x8f820054, +0x621023, 0x2c420065, 0x1440fffc, 0x0, +0x8f820220, 0x24040001, 0x34420002, 0xaf820220, +0x8f830200, 0x24057fff, 0x2402fffd, 0x621824, +0xaf830200, 0xaf840204, 0x8f830054, 0x8f820054, +0x10000002, 0x24630001, 0x8f820054, 0x621023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820224, +0x14440005, 0x34028000, 0x42040, 0xa4102b, +0x1040fff0, 0x34028000, 0x1082ff50, 0x26100001, +0x2e020064, 0x1440ffb0, 0x0, 0x3c020001, +0x8c426d94, 0x30420004, 0x14400007, 0x3c09fff0, +0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, +0xaf820044, 0x3c09fff0, 0x3529bdc0, 0x3c060001, +0x8cc66d94, 0x3c040001, 0x24846ae0, 0x24020001, +0x3c010001, 0xac226d9c, 0x8f820054, 0x3c070001, +0x8ce76f40, 0x3c030001, 0x94636f24, 0x3c080001, +0x95086f26, 0x3c05000d, 0x34a50100, 0x3c010001, +0xac206d98, 0x491021, 0x3c010001, 0xac226f30, +0xafa30010, 0xc002b3b, 0xafa80014, 0x8fbf002c, +0x8fb20028, 0x8fb10024, 0x8fb00020, 0x3e00008, +0x27bd0030, 0x27bdffe8, 0x3c050001, 0x8ca56d98, +0x24060004, 0x24020001, 0x14a20014, 0xafbf0010, +0x3c020002, 0x8c428ffc, 0x30428000, 0x10400005, +0x3c04000f, 0x3c030001, 0x8c636f40, 0x10000005, +0x34844240, 0x3c040004, 0x3c030001, 0x8c636f40, +0x348493e0, 0x24020005, 0x14620016, 0x0, +0x3c04003d, 0x10000013, 0x34840900, 0x3c020002, +0x8c428ff8, 0x30428000, 0x10400005, 0x3c04001e, +0x3c030001, 0x8c636f40, 0x10000005, 0x34848480, +0x3c04000f, 0x3c030001, 0x8c636f40, 0x34844240, +0x24020005, 0x14620003, 0x0, 0x3c04007a, +0x34841200, 0x3c020001, 0x8c426f30, 0x8f830054, +0x441021, 0x431023, 0x44102b, 0x1440004c, +0x0, 0x3c020001, 0x8c426da0, 0x14400048, +0x0, 0x3c010001, 0x10c00025, 0xac206db0, +0x3c090001, 0x8d296d94, 0x24070001, 0x3c044000, +0x3c080002, 0x25088ffc, 0x250afffc, 0x52842, +0x14a00002, 0x24c6ffff, 0x24050008, 0xa91024, +0x10400010, 0x0, 0x14a70008, 0x0, +0x8d020000, 0x441024, 0x1040000a, 0x0, +0x3c010001, 0x10000007, 0xac256db0, 0x8d420000, +0x441024, 0x10400003, 0x0, 0x3c010001, +0xac276db0, 0x3c020001, 0x8c426db0, 0x6182b, +0x2c420001, 0x431024, 0x5440ffe5, 0x52842, +0x8f820054, 0x3c030001, 0x8c636db0, 0x3c010001, +0xac226f30, 0x1060003b, 0x24020005, 0x3c030001, +0x8c636f40, 0x3c010001, 0xac256d98, 0x14620012, +0x24020001, 0x3c020002, 0x8c428ff8, 0x3c032000, +0x34635000, 0x431024, 0x14400006, 0x24020001, +0x3c010001, 0xac206f1c, 0x3c010001, 0xac226d98, +0x24020001, 0x3c010001, 0xac226e24, 0x3c010001, +0xac226da4, 0x24020001, 0x3c010001, 0xac226d9c, +0x3c020001, 0x8c426db0, 0x1040001e, 0x0, +0x3c020001, 0x8c426d9c, 0x10400008, 0x24020001, +0x3c010001, 0xac206d9c, 0xaee204b8, 0x3c010001, +0xac206e1c, 0x3c010001, 0xac226dd4, 0x8ee304b8, +0x24020008, 0x10620005, 0x24020001, 0xc004239, +0x0, 0x1000000b, 0x0, 0x3c030001, +0x8c636d98, 0x10620007, 0x2402000e, 0x3c030002, +0x8c638f90, 0x10620003, 0x0, 0xc004e9c, +0x8f840220, 0x8fbf0010, 0x3e00008, 0x27bd0018, +0x27bdffe0, 0x3c03fdff, 0x3c040001, 0x8c846d98, +0x3c020001, 0x8c426dc0, 0x3463ffff, 0x283a024, +0x14820006, 0xafbf0018, 0x8ee304b8, 0x3c020001, +0x8c426dc4, 0x10620006, 0x0, 0x8ee204b8, +0x3c010001, 0xac246dc0, 0x3c010001, 0xac226dc4, +0x3c030001, 0x8c636d98, 0x24020002, 0x1062019c, +0x2c620003, 0x10400005, 0x24020001, 0x1062000a, +0x0, 0x10000226, 0x0, 0x24020004, +0x106200b6, 0x24020008, 0x1062010a, 0x24020001, +0x1000021f, 0x0, 0x8ee204b8, 0x2443ffff, +0x2c620008, 0x1040021c, 0x31080, 0x3c010001, +0x220821, 0x8c226af8, 0x400008, 0x0, +0x3c030001, 0x8c636f40, 0x24020005, 0x14620010, +0x0, 0x3c020001, 0x8c426da4, 0x10400008, +0x24020003, 0xc004482, 0x0, 0x24020002, +0xaee204b8, 0x3c010001, 0x10000002, 0xac206da4, +0xaee204b8, 0x3c010001, 0x10000203, 0xac206d30, +0xc004482, 0x0, 0x3c020001, 0x8c426da4, +0x3c010001, 0xac206d30, 0x1440017a, 0x24020002, +0x1000019d, 0x24020007, 0x3c030001, 0x8c636f40, +0x24020005, 0x14620003, 0x24020001, 0x3c010001, +0xac226dd0, 0xc0045ff, 0x0, 0x3c030001, +0x8c636dd0, 0x10000174, 0x24020011, 0x3c050001, +0x8ca56d98, 0x3c060002, 0x8cc68ffc, 0xc005104, +0x2021, 0x24020005, 0x3c010001, 0xac206da4, +0x100001e1, 0xaee204b8, 0x3c040001, 0x24846aec, +0x3c05000f, 0x34a50100, 0x3021, 0x3821, +0xafa00010, 0xc002b3b, 0xafa00014, 0x100001d6, +0x0, 0x8f820220, 0x3c030004, 0x431024, +0x14400175, 0x24020007, 0x8f830054, 0x3c020001, +0x8c426f28, 0x2463d8f0, 0x431023, 0x2c422710, +0x14400003, 0x24020001, 0x3c010001, 0xac226d9c, +0x3c020002, 0x8c428ffc, 0x30425000, 0x104001c2, +0x0, 0x8f820220, 0x30428000, 0x1040017d, +0x0, 0x10000175, 0x0, 0x3c050001, +0x8ca56d98, 0xc00529b, 0x2021, 0xc00551b, +0x2021, 0x3c030002, 0x8c638ff4, 0x46101b0, +0x24020001, 0x3c020008, 0x621024, 0x10400006, +0x0, 0x8f820214, 0x3c03ffff, 0x431024, +0x10000005, 0x3442251f, 0x8f820214, 0x3c03ffff, +0x431024, 0x3442241f, 0xaf820214, 0x8f820220, +0x3c030200, 0x34420002, 0xaf820220, 0x24020008, +0xaee204b8, 0x8f820220, 0x283a025, 0x3c030004, +0x431024, 0x14400016, 0x0, 0x3c020002, +0x8c428ffc, 0x30425000, 0x1040000d, 0x0, +0x8f820220, 0x30428000, 0x10400006, 0x0, +0x8f820220, 0x3c03ffff, 0x34637fff, 0x10000003, +0x431024, 0x8f820220, 0x34428000, 0xaf820220, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, -0xaf800204, 0x3c010002, 0x100000d6, 0xac209060, -0x8f830054, 0x3c020001, 0x8c426fa0, 0x2463fff6, -0x431023, 0x2c42000a, 0x144000ef, 0x24020007, -0x100000d2, 0x0, 0xc003f28, 0x0, -0x104000e7, 0x24020001, 0x8f820214, 0x3c03ffff, -0x3c040001, 0x8c846f98, 0x431024, 0x3442251f, -0xaf820214, 0x24020008, 0x10800005, 0xaee204b8, -0x3c020001, 0x8c426ec4, 0x10400064, 0x24020001, -0x8f820220, 0x3c030008, 0x431024, 0x1040006a, -0x3c020200, 0x10000078, 0x0, 0x8ee204b8, -0x2443ffff, 0x2c620007, 0x104000cf, 0x31080, -0x3c010001, 0x220821, 0x8c226bc8, 0x400008, -0x0, 0xc003d87, 0x0, 0x3c010001, -0xac206e1c, 0xaf800204, 0x3c010002, 0xc0043d3, -0xac209060, 0x24020001, 0x3c010001, 0xac226e34, -0x24020002, 0x100000bc, 0xaee204b8, 0xc004498, -0x0, 0x3c030001, 0x8c636e34, 0x10000084, -0x24020009, 0x3c020002, 0x8c429078, 0x30424000, -0x10400003, 0x3c0200c8, 0x10000002, 0x344201f6, -0x344201fe, 0xaf820238, 0x8f830054, 0x1000008b, -0x24020004, 0x8f830054, 0x3c020001, 0x8c426fa0, -0x2463d8f0, 0x431023, 0x2c422710, 0x144000a2, -0x24020005, 0x10000079, 0x0, 0x8f820220, -0x3c03f700, 0x431025, 0xaf820220, 0xaf800204, -0x3c010002, 0x10000077, 0xac209060, 0x8f830054, -0x3c020001, 0x8c426fa0, 0x2463fff6, 0x431023, -0x2c42000a, 0x14400090, 0x24020007, 0x10000073, -0x0, 0xc003f28, 0x0, 0x10400088, -0x24020001, 0x8f820214, 0x3c03ffff, 0x3c040001, -0x8c846f98, 0x431024, 0x3442251f, 0xaf820214, -0x24020008, 0x1080000f, 0xaee204b8, 0x3c020001, -0x8c426ec4, 0x1440000b, 0x0, 0x8f820220, -0x34420002, 0xaf820220, 0x24020001, 0x3c010002, -0xac229010, 0xc004ecc, 0x8f840220, 0x10000016, -0x0, 0x8f820220, 0x3c030008, 0x431024, -0x14400011, 0x3c020200, 0x282a025, 0x2402000e, -0x3c010002, 0xac229010, 0xc00553d, 0x2021, -0x8f820220, 0x34420002, 0xc003e45, 0xaf820220, -0x3c050001, 0x8ca56e18, 0xc0052c7, 0x2021, -0x1000005d, 0x0, 0x3c020001, 0x8c426ec4, -0x10400059, 0x0, 0x3c020001, 0x8c426ec0, -0x2442ffff, 0x3c010001, 0xac226ec0, 0x14400052, -0x24020002, 0x3c010001, 0xac206ec4, 0x3c010001, -0x1000004d, 0xac226ec0, 0x8ee204b8, 0x2443ffff, -0x2c620007, 0x10400048, 0x31080, 0x3c010001, -0x220821, 0x8c226be8, 0x400008, 0x0, -0x3c020001, 0x8c426e24, 0x10400024, 0x24020007, -0xc0043d3, 0x0, 0x24020002, 0xaee204b8, -0x3c010001, 0x10000038, 0xac206e24, 0xc0048b3, -0x0, 0x3c030001, 0x8c636e54, 0x24020006, -0x14620031, 0x24020003, 0x1000002f, 0xaee204b8, -0x3c050001, 0x8ca56e18, 0x3c060002, 0x8cc69078, -0xc005134, 0x2021, 0x24020005, 0x10000026, -0xaee204b8, 0x8f820220, 0x3c03f700, 0x431025, -0xaf820220, 0x8f830054, 0x24020006, 0xaee204b8, -0x3c010001, 0x1000001c, 0xac236fa0, 0x1000001a, -0xaee204b8, 0x3c050001, 0x8ca56e18, 0xc0052c7, -0x2021, 0xc00553d, 0x2021, 0x3c020002, -0x8c429070, 0x441000e, 0x24020001, 0x8f820214, +0x3c030001, 0x8c636f40, 0x24020005, 0x1462000a, +0x0, 0x3c020001, 0x94426f26, 0x24429fbc, +0x2c420004, 0x10400004, 0x24040018, 0x24050002, +0xc004ddb, 0x24060020, 0xc003e6d, 0x0, +0x3c010001, 0x10000170, 0xac206e20, 0x8ee204b8, +0x2443ffff, 0x2c620008, 0x1040016b, 0x31080, +0x3c010001, 0x220821, 0x8c226b18, 0x400008, +0x0, 0xc004547, 0x0, 0x3c030001, +0x8c636db4, 0x100000e8, 0x24020009, 0x3c020002, +0x8c428ff8, 0x30424000, 0x10400004, 0x0, +0x8f820044, 0x10000006, 0x3442f080, 0x8f820044, +0x3c03ffff, 0x34633f7f, 0x431024, 0x3442a080, +0xaf820044, 0x8f830054, 0x100000ea, 0x24020004, +0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0, +0x431023, 0x2c422710, 0x14400147, 0x24020005, +0x100000d8, 0x0, 0x8f820220, 0x3c03f700, +0x431025, 0xaf820220, 0xaf800204, 0x3c010002, +0x100000d6, 0xac208fe0, 0x8f830054, 0x3c020001, +0x8c426f28, 0x2463fff6, 0x431023, 0x2c42000a, +0x14400135, 0x24020007, 0x100000d7, 0x0, +0xc003f50, 0x0, 0x1040012d, 0x24020001, +0x8f820214, 0x3c03ffff, 0x3c040001, 0x8c846f1c, +0x431024, 0x3442251f, 0xaf820214, 0x24020008, +0x10800005, 0xaee204b8, 0x3c020001, 0x8c426e44, +0x10400064, 0x24020001, 0x8f820220, 0x3c030008, +0x431024, 0x1040006a, 0x3c020200, 0x10000078, +0x0, 0x8ee204b8, 0x2443ffff, 0x2c620007, +0x10400115, 0x31080, 0x3c010001, 0x220821, +0x8c226b38, 0x400008, 0x0, 0xc003daf, +0x0, 0x3c010001, 0xac206d9c, 0xaf800204, +0x3c010002, 0xc004482, 0xac208fe0, 0x24020001, +0x3c010001, 0xac226db4, 0x24020002, 0x10000102, +0xaee204b8, 0xc004547, 0x0, 0x3c030001, +0x8c636db4, 0x10000084, 0x24020009, 0x3c020002, +0x8c428ff8, 0x30424000, 0x10400003, 0x3c0200c8, +0x10000002, 0x344201f6, 0x344201fe, 0xaf820238, +0x8f830054, 0x1000008b, 0x24020004, 0x8f830054, +0x3c020001, 0x8c426f28, 0x2463d8f0, 0x431023, +0x2c422710, 0x144000e8, 0x24020005, 0x10000079, +0x0, 0x8f820220, 0x3c03f700, 0x431025, +0xaf820220, 0xaf800204, 0x3c010002, 0x10000077, +0xac208fe0, 0x8f830054, 0x3c020001, 0x8c426f28, +0x2463fff6, 0x431023, 0x2c42000a, 0x144000d6, +0x24020007, 0x10000078, 0x0, 0xc003f50, +0x0, 0x104000ce, 0x24020001, 0x8f820214, +0x3c03ffff, 0x3c040001, 0x8c846f1c, 0x431024, +0x3442251f, 0xaf820214, 0x24020008, 0x1080000f, +0xaee204b8, 0x3c020001, 0x8c426e44, 0x1440000b, +0x0, 0x8f820220, 0x34420002, 0xaf820220, +0x24020001, 0x3c010002, 0xac228f90, 0xc004e9c, +0x8f840220, 0x10000016, 0x0, 0x8f820220, +0x3c030008, 0x431024, 0x14400011, 0x3c020200, +0x282a025, 0x2402000e, 0x3c010002, 0xac228f90, +0xc00551b, 0x2021, 0x8f820220, 0x34420002, +0xc003e6d, 0xaf820220, 0x3c050001, 0x8ca56d98, +0xc00529b, 0x2021, 0x100000a3, 0x0, +0x3c020001, 0x8c426e44, 0x1040009f, 0x0, +0x3c020001, 0x8c426e40, 0x2442ffff, 0x3c010001, +0xac226e40, 0x14400098, 0x24020002, 0x3c010001, +0xac206e44, 0x3c010001, 0x10000093, 0xac226e40, +0x8ee204b8, 0x2443ffff, 0x2c620007, 0x1040008e, +0x31080, 0x3c010001, 0x220821, 0x8c226b58, +0x400008, 0x0, 0x3c020001, 0x8c426da4, +0x10400018, 0x24020005, 0xc004482, 0x0, +0x24020002, 0xaee204b8, 0x3c010001, 0x1000007e, +0xac206da4, 0xc004963, 0x0, 0x3c030001, +0x8c636dd4, 0x24020006, 0x14620077, 0x24020003, +0x10000075, 0xaee204b8, 0x3c050001, 0x8ca56d98, +0x3c060002, 0x8cc68ff8, 0xc005104, 0x2021, +0x24020005, 0x1000006c, 0xaee204b8, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x8f830054, +0x24020006, 0xaee204b8, 0x3c010001, 0x10000062, +0xac236f28, 0x8f820220, 0x3c030004, 0x431024, +0x10400003, 0x24020007, 0x1000005b, 0xaee204b8, +0x8f830054, 0x3c020001, 0x8c426f28, 0x2463d8f0, +0x431023, 0x2c422710, 0x14400003, 0x24020001, +0x3c010001, 0xac226d9c, 0x3c020002, 0x8c428ff8, +0x30425000, 0x1040004c, 0x0, 0x8f820220, +0x30428000, 0x10400007, 0x0, 0x8f820220, +0x3c03ffff, 0x34637fff, 0x431024, 0x10000042, +0xaf820220, 0x8f820220, 0x34428000, 0x1000003e, +0xaf820220, 0x3c050001, 0x8ca56d98, 0xc00529b, +0x2021, 0xc00551b, 0x2021, 0x3c020002, +0x8c428ff0, 0x4410032, 0x24020001, 0x8f820214, 0x3c03ffff, 0x431024, 0x3442251f, 0xaf820214, 0x24020008, 0xaee204b8, 0x8f820220, 0x34420002, -0xc003e45, 0xaf820220, 0x10000003, 0x0, -0x3c010001, 0xac226e1c, 0x8fbf001c, 0x8fb00018, -0x3e00008, 0x27bd0020, 0x8f820200, 0x8f820220, -0x8f820220, 0x34420004, 0xaf820220, 0x8f820200, -0x3c050001, 0x8ca56e18, 0x34420004, 0xaf820200, -0x24020002, 0x10a2004b, 0x2ca20003, 0x10400005, -0x24020001, 0x10a2000a, 0x0, 0x100000b1, -0x0, 0x24020004, 0x10a20072, 0x24020008, -0x10a20085, 0x3c02f0ff, 0x100000aa, 0x0, +0xaf820220, 0x8f820220, 0x3c030004, 0x431024, +0x14400016, 0x0, 0x3c020002, 0x8c428ff8, +0x30425000, 0x1040000d, 0x0, 0x8f820220, +0x30428000, 0x10400006, 0x0, 0x8f820220, +0x3c03ffff, 0x34637fff, 0x10000003, 0x431024, +0x8f820220, 0x34428000, 0xaf820220, 0x8f820220, +0x3c03f700, 0x431025, 0xaf820220, 0x3c020001, +0x94426f26, 0x24429fbc, 0x2c420004, 0x10400004, +0x24040018, 0x24050002, 0xc004ddb, 0x24060020, +0xc003e6d, 0x0, 0x10000003, 0x0, +0x3c010001, 0xac226d9c, 0x8fbf0018, 0x3e00008, +0x27bd0020, 0x8f820200, 0x8f820220, 0x8f820220, +0x34420004, 0xaf820220, 0x8f820200, 0x3c050001, +0x8ca56d98, 0x34420004, 0xaf820200, 0x24020002, +0x10a2004b, 0x2ca20003, 0x10400005, 0x24020001, +0x10a2000a, 0x0, 0x100000b1, 0x0, +0x24020004, 0x10a20072, 0x24020008, 0x10a20085, +0x3c02f0ff, 0x100000aa, 0x0, 0x8f830050, +0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f40, +0x621824, 0x3c020700, 0x621825, 0x24020e00, +0x2484fffb, 0x2c840002, 0xaf830050, 0xaf850200, +0xaf850220, 0x14800006, 0xaf820238, 0x8f820044, +0x3c03ffff, 0x34633f7f, 0x431024, 0xaf820044, +0x3c030001, 0x8c636f40, 0x24020005, 0x14620004, +0x0, 0x8f820044, 0x34425000, 0xaf820044, +0x3c020001, 0x8c426d88, 0x3c030001, 0x8c636f40, +0x34420022, 0x2463fffc, 0x2c630002, 0x1460000c, +0xaf820200, 0x3c020001, 0x8c426dac, 0x3c030001, +0x8c636d90, 0x3c040001, 0x8c846d8c, 0x34428000, +0x621825, 0x641825, 0x1000000a, 0x34620002, +0x3c020001, 0x8c426d90, 0x3c030001, 0x8c636dac, +0x3c040001, 0x8c846d8c, 0x431025, 0x441025, +0x34420002, 0xaf820220, 0x1000002f, 0x24020001, +0x24020e01, 0xaf820238, 0x8f830050, 0x3c02f0ff, +0x3442ffff, 0x3c040001, 0x8c846f1c, 0x621824, +0x3c020d00, 0x621825, 0x24020001, 0xaf830050, +0xaf820200, 0xaf820220, 0x10800005, 0x3c033f00, +0x3c020001, 0x8c426d80, 0x10000004, 0x34630070, +0x3c020001, 0x8c426d80, 0x34630072, 0x431025, +0xaf820200, 0x3c030001, 0x8c636d84, 0x3c02f700, +0x621825, 0x3c020001, 0x8c426d90, 0x3c040001, +0x8c846dac, 0x3c050001, 0x8ca56f40, 0x431025, +0x441025, 0xaf820220, 0x24020005, 0x14a20006, +0x24020001, 0x8f820044, 0x2403afff, 0x431024, +0xaf820044, 0x24020001, 0x1000003d, 0xaf820238, 0x8f830050, 0x3c02f0ff, 0x3442ffff, 0x3c040001, -0x8c846fb8, 0x621824, 0x3c020700, 0x621825, -0x24020e00, 0x2484fffb, 0x2c840002, 0xaf830050, -0xaf850200, 0xaf850220, 0x14800006, 0xaf820238, -0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, -0xaf820044, 0x3c030001, 0x8c636fb8, 0x24020005, -0x14620004, 0x0, 0x8f820044, 0x34425000, -0xaf820044, 0x3c020001, 0x8c426e08, 0x3c030001, -0x8c636fb8, 0x34420022, 0x2463fffc, 0x2c630002, -0x1460000c, 0xaf820200, 0x3c020001, 0x8c426e2c, -0x3c030001, 0x8c636e10, 0x3c040001, 0x8c846e0c, -0x34428000, 0x621825, 0x641825, 0x1000000a, -0x34620002, 0x3c020001, 0x8c426e10, 0x3c030001, -0x8c636e2c, 0x3c040001, 0x8c846e0c, 0x431025, -0x441025, 0x34420002, 0xaf820220, 0x1000002f, -0x24020001, 0x24020e01, 0xaf820238, 0x8f830050, -0x3c02f0ff, 0x3442ffff, 0x3c040001, 0x8c846f98, -0x621824, 0x3c020d00, 0x621825, 0x24020001, -0xaf830050, 0xaf820200, 0xaf820220, 0x10800005, -0x3c033f00, 0x3c020001, 0x8c426e00, 0x10000004, -0x34630070, 0x3c020001, 0x8c426e00, 0x34630072, -0x431025, 0xaf820200, 0x3c030001, 0x8c636e04, -0x3c02f700, 0x621825, 0x3c020001, 0x8c426e10, -0x3c040001, 0x8c846e2c, 0x3c050001, 0x8ca56fb8, -0x431025, 0x441025, 0xaf820220, 0x24020005, -0x14a20006, 0x24020001, 0x8f820044, 0x2403afff, -0x431024, 0xaf820044, 0x24020001, 0x1000003d, -0xaf820238, 0x8f830050, 0x3c02f0ff, 0x3442ffff, -0x3c040001, 0x8c846f98, 0x621824, 0x3c020a00, -0x621825, 0x24020001, 0xaf830050, 0xaf820200, -0x1080001e, 0xaf820220, 0x3c020001, 0x8c426ec4, -0x1440001a, 0x3c033f00, 0x3c020001, 0x8c426e00, -0x1000001a, 0x346300e0, 0x8f830050, 0x3c040001, -0x8c846f98, 0x3442ffff, 0x621824, 0x1080000f, -0xaf830050, 0x3c020001, 0x8c426ec4, 0x1440000b, -0x3c043f00, 0x3c030001, 0x8c636e00, 0x348400e0, -0x24020001, 0xaf820200, 0xaf820220, 0x641825, -0xaf830200, 0x10000008, 0x3c05f700, 0x3c020001, -0x8c426e00, 0x3c033f00, 0x346300e2, 0x431025, -0xaf820200, 0x3c05f700, 0x34a58000, 0x3c030001, -0x8c636e04, 0x3c020001, 0x8c426e10, 0x3c040001, -0x8c846e2c, 0x651825, 0x431025, 0x441025, -0xaf820220, 0x3e00008, 0x0, 0x3c030001, -0x8c636e34, 0x3c020001, 0x8c426e38, 0x10620003, -0x24020002, 0x3c010001, 0xac236e38, 0x1062001d, -0x2c620003, 0x10400025, 0x24020001, 0x14620023, -0x24020004, 0x3c030001, 0x8c636e18, 0x10620006, -0x24020008, 0x1462000c, 0x3c0200c8, 0x344201fb, -0x10000009, 0xaf820238, 0x24020e01, 0xaf820238, -0x8f820044, 0x3c03ffff, 0x34633f7f, 0x431024, -0x34420080, 0xaf820044, 0x8f830054, 0x24020002, -0x3c010001, 0xac226e34, 0x3c010001, 0x1000000b, -0xac236fa4, 0x8f830054, 0x3c020001, 0x8c426fa4, -0x2463d8f0, 0x431023, 0x2c422710, 0x14400003, -0x24020009, 0x3c010001, 0xac226e34, 0x3e00008, +0x8c846f1c, 0x621824, 0x3c020a00, 0x621825, +0x24020001, 0xaf830050, 0xaf820200, 0x1080001e, +0xaf820220, 0x3c020001, 0x8c426e44, 0x1440001a, +0x3c033f00, 0x3c020001, 0x8c426d80, 0x1000001a, +0x346300e0, 0x8f830050, 0x3c040001, 0x8c846f1c, +0x3442ffff, 0x621824, 0x1080000f, 0xaf830050, +0x3c020001, 0x8c426e44, 0x1440000b, 0x3c043f00, +0x3c030001, 0x8c636d80, 0x348400e0, 0x24020001, +0xaf820200, 0xaf820220, 0x641825, 0xaf830200, +0x10000008, 0x3c05f700, 0x3c020001, 0x8c426d80, +0x3c033f00, 0x346300e2, 0x431025, 0xaf820200, +0x3c05f700, 0x34a58000, 0x3c030001, 0x8c636d84, +0x3c020001, 0x8c426d90, 0x3c040001, 0x8c846dac, +0x651825, 0x431025, 0x441025, 0xaf820220, +0x3e00008, 0x0, 0x3c030001, 0x8c636db4, +0x3c020001, 0x8c426db8, 0x10620003, 0x24020002, +0x3c010001, 0xac236db8, 0x1062001d, 0x2c620003, +0x10400025, 0x24020001, 0x14620023, 0x24020004, +0x3c030001, 0x8c636d98, 0x10620006, 0x24020008, +0x1462000c, 0x3c0200c8, 0x344201fb, 0x10000009, +0xaf820238, 0x24020e01, 0xaf820238, 0x8f820044, +0x3c03ffff, 0x34633f7f, 0x431024, 0x34420080, +0xaf820044, 0x8f830054, 0x24020002, 0x3c010001, +0xac226db4, 0x3c010001, 0x1000000b, 0xac236f2c, +0x8f830054, 0x3c020001, 0x8c426f2c, 0x2463d8f0, +0x431023, 0x2c422710, 0x14400003, 0x24020009, +0x3c010001, 0xac226db4, 0x3e00008, 0x0, 0x0, 0x0, 0x0, 0x27bdffd8, 0xafb20018, 0x809021, 0xafb3001c, 0xa09821, 0xafb10014, 0xc08821, 0xafb00010, 0x8021, -0xafbf0020, 0xa6200000, 0xc004dab, 0x24040001, +0xafbf0020, 0xa6200000, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x2501024, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x2501024, 0x24100010, 0x2701024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x2701024, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x2701024, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x0, 0x8fbf0020, 0x8fb3001c, +0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, 0x3e00008, 0x27bd0028, 0x27bdffd8, 0xafb10014, 0x808821, 0xafb20018, 0xa09021, 0xafb3001c, 0xc09821, -0xafb00010, 0x8021, 0xafbf0020, 0xc004dab, +0xafb00010, 0x8021, 0xafbf0020, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, 0x24040001, 0x24100010, 0x2301024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, +0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x2301024, 0x24100010, 0x2501024, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x2501024, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x2501024, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96620000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fff8, -0x0, 0xc004dec, 0x0, 0x8fbf0020, +0x24040001, 0xc004d78, 0x108042, 0x1600fff8, +0x0, 0xc004db9, 0x0, 0x8fbf0020, 0x8fb3001c, 0x8fb20018, 0x8fb10014, 0x8fb00010, -0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846e50, -0x3c020001, 0x8c426e98, 0x27bdffd8, 0xafbf0020, +0x3e00008, 0x27bd0028, 0x3c040001, 0x8c846dd0, +0x3c020001, 0x8c426e18, 0x27bdffd8, 0xafbf0020, 0xafb1001c, 0x10820003, 0xafb00018, 0x3c010001, -0xac246e98, 0x3c030001, 0x8c636fb8, 0x24020005, -0x14620005, 0x2483ffff, 0xc0048b3, 0x0, +0xac246e18, 0x3c030001, 0x8c636f40, 0x24020005, +0x14620005, 0x2483ffff, 0xc004963, 0x0, 0x1000034c, 0x0, 0x2c620013, 0x10400349, -0x31080, 0x3c010001, 0x220821, 0x8c226c10, -0x400008, 0x0, 0xc004dec, 0x8021, -0x34028000, 0xa7a20010, 0x27b10010, 0xc004dab, +0x31080, 0x3c010001, 0x220821, 0x8c226b80, +0x400008, 0x0, 0xc004db9, 0x8021, +0x34028000, 0xa7a20010, 0x27b10010, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0xc004dab, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0xc004d78, 0x2021, 0x108042, 0x1600fffc, 0x0, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x1000030e, 0x24020002, 0x27b10010, 0xa7a00010, -0x8021, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, +0x8021, 0xc004d78, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d78, +0x2021, 0xc004d78, 0x24040001, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0xc004dab, 0x2021, 0x108042, -0x1600fffc, 0x0, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, +0xc004d78, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0xc004d78, 0x2021, 0x108042, +0x1600fffc, 0x0, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x0, 0x97a20010, 0x30428000, +0xc004db9, 0x0, 0x97a20010, 0x30428000, 0x144002dc, 0x24020003, 0x100002d8, 0x0, 0x24021200, 0xa7a20010, 0x27b10010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, -0xc004dab, 0x2021, 0x108042, 0x1600fffc, -0x0, 0xc004dab, 0x24040001, 0xc004dab, +0xc004d78, 0x2021, 0x108042, 0x1600fffc, +0x0, 0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fff8, 0x0, 0xc004dec, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000296, 0x24020004, -0x8f830054, 0x3c020001, 0x8c426fb4, 0x2463ff9c, +0x8f830054, 0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440029e, 0x24020002, -0x3c030001, 0x8c636fb8, 0x10620297, 0x2c620003, +0x3c030001, 0x8c636f40, 0x10620297, 0x2c620003, 0x14400296, 0x24020011, 0x24020003, 0x10620005, 0x24020004, 0x10620291, 0x2402000f, 0x1000028f, 0x24020011, 0x1000028d, 0x24020005, 0x24020014, -0xa7a20010, 0x27b10010, 0x8021, 0xc004dab, +0xa7a20010, 0x27b10010, 0x8021, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, +0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020012, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020012, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x32020012, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fff8, -0x0, 0xc004dec, 0x0, 0x8f830054, +0x24040001, 0xc004d78, 0x108042, 0x1600fff8, +0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000248, 0x24020006, 0x8f830054, 0x3c020001, -0x8c426fb4, 0x2463ff9c, 0x431023, 0x2c420064, +0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400250, 0x24020007, 0x1000024c, 0x0, 0x24020006, 0xa7a20010, 0x27b10010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020013, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020013, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000207, 0x24020008, 0x8f830054, -0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023, +0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440020f, 0x24020009, 0x1000020b, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020018, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, +0x1600fff7, 0x0, 0xc004db9, 0x8021, 0x97a20010, 0x27b10010, 0x34420001, 0xa7a20010, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020018, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000193, 0x2402000a, 0x8f830054, -0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023, +0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x1440019b, 0x2402000b, 0x10000197, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020017, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004d78, 0x108042, 0x1600fffa, 0x32020017, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, +0x1600fff7, 0x0, 0xc004db9, 0x8021, 0x97a20010, 0x27b10010, 0x34420700, 0xa7a20010, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020017, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020017, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020017, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x1000011f, 0x2402000c, 0x8f830054, -0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023, +0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400127, 0x24020012, 0x10000123, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020014, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004d78, 0x108042, 0x1600fffa, 0x32020014, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, +0x1600fff7, 0x0, 0xc004db9, 0x8021, 0x97a20010, 0x27b10010, 0x34420010, 0xa7a20010, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020014, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020014, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020014, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x100000ab, 0x24020013, 0x8f830054, -0x3c020001, 0x8c426fb4, 0x2463ff9c, 0x431023, +0x3c020001, 0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x144000b3, 0x2402000d, 0x100000af, 0x0, 0x27b10010, 0xa7a00010, 0x8021, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020018, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, +0x1600fff7, 0x0, 0xc004db9, 0x8021, 0x97a20010, 0x27b10010, 0x3042fffe, 0xa7a20010, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020018, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fff8, 0x0, 0xc004dec, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, 0x8f830054, 0x10000037, 0x2402000e, 0x24020840, -0xa7a20010, 0x27b10010, 0x8021, 0xc004dab, +0xa7a20010, 0x27b10010, 0x8021, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, 0x24040001, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, +0x2021, 0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020013, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020013, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x34108000, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x32020013, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, 0x96220000, 0x501024, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fff8, -0x0, 0xc004dec, 0x0, 0x8f830054, -0x24020010, 0x3c010001, 0xac226e50, 0x3c010001, -0x1000000c, 0xac236fb4, 0x8f830054, 0x3c020001, -0x8c426fb4, 0x2463ff9c, 0x431023, 0x2c420064, +0x24040001, 0xc004d78, 0x108042, 0x1600fff8, +0x0, 0xc004db9, 0x0, 0x8f830054, +0x24020010, 0x3c010001, 0xac226dd0, 0x3c010001, +0x1000000c, 0xac236f3c, 0x8f830054, 0x3c020001, +0x8c426f3c, 0x2463ff9c, 0x431023, 0x2c420064, 0x14400004, 0x0, 0x24020011, 0x3c010001, -0xac226e50, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, -0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636e18, +0xac226dd0, 0x8fbf0020, 0x8fb1001c, 0x8fb00018, +0x3e00008, 0x27bd0028, 0x3c030001, 0x8c636d98, 0x27bdffc8, 0x24020002, 0xafbf0034, 0xafb20030, 0xafb1002c, 0x14620004, 0xafb00028, 0x3c120002, -0x10000003, 0x8e529078, 0x3c120002, 0x8e52907c, -0x3c030001, 0x8c636e54, 0x3c020001, 0x8c426e9c, -0x50620004, 0x2463ffff, 0x3c010001, 0xac236e9c, -0x2463ffff, 0x2c620006, 0x104004b9, 0x31080, -0x3c010001, 0x220821, 0x8c226c68, 0x400008, -0x0, 0x2021, 0x2821, 0xc004e0e, +0x10000003, 0x8e528ff8, 0x3c120002, 0x8e528ffc, +0x3c030001, 0x8c636dd4, 0x3c020001, 0x8c426e1c, +0x50620004, 0x2463ffff, 0x3c010001, 0xac236e1c, +0x2463ffff, 0x2c620006, 0x10400377, 0x31080, +0x3c010001, 0x220821, 0x8c226bd8, 0x400008, +0x0, 0x2021, 0x2821, 0xc004ddb, 0x34068000, 0x24040010, 0x24050002, 0x24060002, -0x24020002, 0xc004e0e, 0xa7a20018, 0x24020002, -0x3c010001, 0x100004a6, 0xac226e54, 0x27b10018, -0xa7a00018, 0x8021, 0xc004dab, 0x24040001, +0x24020002, 0xc004ddb, 0xa7a20018, 0x24020002, +0x3c010001, 0x10000364, 0xac226dd4, 0x27b10018, +0xa7a00018, 0x8021, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0xc004dab, 0x2021, -0x108042, 0x1600fffc, 0x0, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x32020001, 0x24100010, 0xc004d78, 0x2021, +0x108042, 0x1600fffc, 0x0, 0xc004db9, +0x34108000, 0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x96220000, 0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x0, 0x97a20018, +0x0, 0xc004db9, 0x0, 0x97a20018, 0x30428000, 0x14400004, 0x24020003, 0x3c010001, -0xac226e54, 0x24020003, 0x3c010001, 0x1000046c, -0xac226e54, 0x24040010, 0x24050002, 0x24060002, -0x24020002, 0xc004e0e, 0xa7a20018, 0x3c030001, -0x8c636ea0, 0x24020001, 0x146201e2, 0x0, -0x27b10018, 0xa7a00018, 0x8021, 0xc004dab, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020018, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020018, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x96220000, -0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0x27b10018, -0xa7a00018, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, +0xac226dd4, 0x24020003, 0x3c010001, 0x1000032a, +0xac226dd4, 0x24040010, 0x24050002, 0x24060002, +0x24020002, 0xc004ddb, 0xa7a20018, 0x3c030001, +0x8c636e20, 0x24020001, 0x146201e1, 0x8021, +0x27b10018, 0xa7a00018, 0xc004d78, 0x24040001, +0x26100001, 0x2e020020, 0x1440fffb, 0x0, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0x24100010, 0x32020001, 0x10400002, 0x2021, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x32020001, 0x24100010, 0x32020018, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020018, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, +0x50400005, 0x108042, 0x96220000, 0x501025, +0xa6220000, 0x108042, 0x1600fff7, 0x0, +0xc004db9, 0x8021, 0x27b10018, 0xa7a00018, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0x32020001, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x32020001, 0x24100010, +0x32020018, 0x10400002, 0x2021, 0x24040001, +0xc004d78, 0x108042, 0x1600fffa, 0x32020018, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, +0x96220000, 0x501025, 0xa6220000, 0x108042, +0x1600fff7, 0x0, 0xc004db9, 0x8021, +0x24040018, 0x2821, 0xc004ddb, 0x24060404, +0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d78, +0x2021, 0xc004d78, 0x24040001, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, +0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020018, 0xc004dec, 0x34108000, 0xc004dec, -0x0, 0xc004d8b, 0x0, 0x50400005, -0x108042, 0x96220000, 0x501025, 0xa6220000, -0x108042, 0x1600fff7, 0x0, 0xc004dec, -0x8021, 0x24040018, 0x2821, 0xc004e0e, -0x24060404, 0xa7a0001a, 0xc004dab, 0x24040001, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x32020018, 0xc004db9, 0x34108000, 0xc004db9, +0x0, 0xc004d58, 0x0, 0x50400005, +0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, +0x108042, 0x1600fff7, 0x0, 0xc004db9, +0x8021, 0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, 0x32020001, 0x24100010, 0x32020018, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020018, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020018, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x8021, 0xa7a0001a, 0xc004dab, +0xc004db9, 0x8021, 0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020018, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020018, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x97a2001a, -0x501025, 0xa7a2001a, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0xa7a0001c, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x24040001, 0xc004d78, +0x2021, 0x24100010, 0xc004d78, 0x2021, +0x108042, 0x1600fffc, 0x0, 0x24100010, +0x3202001e, 0x10400002, 0x2021, 0x24040001, +0xc004d78, 0x108042, 0x1600fffa, 0x3202001e, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, +0x97a2001c, 0x501025, 0xa7a2001c, 0x108042, +0x1600fff7, 0x0, 0xc004db9, 0x8021, +0xa7a0001c, 0xc004d78, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d78, +0x2021, 0xc004d78, 0x24040001, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x24100010, +0xc004d78, 0x2021, 0x108042, 0x1600fffc, +0x0, 0x24100010, 0x3202001e, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x3202001e, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, +0x50400005, 0x108042, 0x97a2001c, 0x501025, +0xa7a2001c, 0x108042, 0x1600fff7, 0x0, +0xc004db9, 0x8021, 0x24020002, 0xa7a2001e, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0x24100010, 0xc004d78, 0x2021, 0x108042, 0x1600fffc, 0x0, 0x24100010, 0x3202001e, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x3202001e, 0xc004dec, 0x34108000, 0xc004dec, -0x0, 0xc004d8b, 0x0, 0x50400005, -0x108042, 0x97a2001c, 0x501025, 0xa7a2001c, -0x108042, 0x1600fff7, 0x0, 0xc004dec, -0x8021, 0xa7a0001c, 0xc004dab, 0x24040001, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x3202001e, 0xc004d78, 0x24040001, 0xc004d78, +0x2021, 0x34108000, 0x97a2001e, 0x501024, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fff8, 0x0, 0xc004db9, +0x8021, 0xa7a00020, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0x24100010, 0xc004dab, 0x2021, 0x108042, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0x24100010, 0xc004d78, 0x2021, 0x108042, 0x1600fffc, 0x0, 0x24100010, 0x3202001e, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x3202001e, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x97a2001c, -0x501025, 0xa7a2001c, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0x24020002, -0xa7a2001e, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0x24100010, -0xc004dab, 0x2021, 0x108042, 0x1600fffc, -0x0, 0x24100010, 0x3202001e, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x3202001e, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x34108000, 0x97a2001e, -0x501024, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fff8, 0x0, -0xc004dec, 0x8021, 0xa7a00020, 0xc004dab, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x24100010, 0xc004dab, 0x2021, -0x108042, 0x1600fffc, 0x0, 0x24100010, -0x3202001e, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x3202001e, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, -0x97a20020, 0x501025, 0xa7a20020, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, -0xa7a00020, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, -0xc004dab, 0x2021, 0x108042, 0x1600fffc, -0x0, 0x24100010, 0x3202001e, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x3202001e, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, -0x50400005, 0x108042, 0x97a20020, 0x501025, -0xa7a20020, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x8021, 0xa7a00022, 0xc004dab, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0x24100010, 0xc004dab, 0x2021, -0x108042, 0x1600fffc, 0x0, 0x24100010, -0xc004dab, 0x2021, 0x108042, 0x1600fffc, -0x0, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x34108000, 0x97a20022, 0x501024, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fff8, 0x0, 0xc004dec, -0x0, 0x24040018, 0x24050002, 0xc004e0e, -0x24060004, 0x3c030001, 0x8c636ea4, 0x24020001, -0x146200fc, 0x3c024000, 0x3c010001, 0xac206ea4, -0x2421024, 0x10400276, 0x3c022000, 0x2421024, -0x10400004, 0x0, 0x3c010001, 0x10000003, -0xac236f98, 0x3c010001, 0xac206f98, 0x3c030001, -0x8c636fac, 0x24020005, 0x146200ea, 0x0, -0x3c020001, 0x8c426f98, 0x1040005f, 0x3c020004, -0x2421024, 0x10400011, 0xa7a00018, 0x3c020008, -0x2421024, 0x10400002, 0x24020200, 0xa7a20018, -0x3c020010, 0x2421024, 0x10400004, 0x0, -0x97a20018, 0x34420100, 0xa7a20018, 0x97a60018, -0x24040009, 0x10000004, 0x2821, 0x24040009, -0x2821, 0x3021, 0xc004e0e, 0x0, -0x24020001, 0xa7a2001a, 0x3c020008, 0x2421024, -0x1040000c, 0x3c020002, 0x2421024, 0x10400002, -0x24020101, 0xa7a2001a, 0x3c020001, 0x2421024, -0x10400005, 0x3c020010, 0x97a2001a, 0x34420040, -0xa7a2001a, 0x3c020010, 0x2421024, 0x1040000e, -0x3c020002, 0x2421024, 0x10400005, 0x3c020001, -0x97a2001a, 0x34420080, 0xa7a2001a, 0x3c020001, -0x2421024, 0x10400005, 0x3c0300a0, 0x97a2001a, -0x34420020, 0xa7a2001a, 0x3c0300a0, 0x2431024, -0x54430004, 0x3c020020, 0x97a2001a, 0x1000000c, -0x34420400, 0x2421024, 0x50400004, 0x3c020080, -0x97a2001a, 0x10000006, 0x34420800, 0x2421024, -0x10400004, 0x0, 0x97a2001a, 0x34420c00, -0xa7a2001a, 0x97a6001a, 0x24040004, 0xc004e0e, -0x2821, 0x32424000, 0x10400003, 0xa7a0001c, -0x24024000, 0xa7a2001c, 0x97a6001c, 0x2021, -0x2821, 0x34c61200, 0xc004e0e, 0xa7a6001c, -0x10000088, 0x0, 0x32424000, 0x10400003, -0xa7a00018, 0x24024000, 0xa7a20018, 0x3c020010, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x3202001e, 0xc004db9, +0x34108000, 0xc004db9, 0x0, 0xc004d58, +0x0, 0x50400005, 0x108042, 0x97a20020, +0x501025, 0xa7a20020, 0x108042, 0x1600fff7, +0x0, 0xc004db9, 0x8021, 0xa7a00020, +0xc004d78, 0x24040001, 0x26100001, 0x2e020020, +0x1440fffb, 0x0, 0xc004d78, 0x2021, +0xc004d78, 0x24040001, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0x24100010, 0xc004d78, +0x2021, 0x108042, 0x1600fffc, 0x0, +0x24100010, 0x3202001e, 0x10400002, 0x2021, +0x24040001, 0xc004d78, 0x108042, 0x1600fffa, +0x3202001e, 0xc004db9, 0x34108000, 0xc004db9, +0x0, 0xc004d58, 0x0, 0x50400005, +0x108042, 0x97a20020, 0x501025, 0xa7a20020, +0x108042, 0x1600fff7, 0x0, 0xc004db9, +0x8021, 0xa7a00022, 0xc004d78, 0x24040001, +0x26100001, 0x2e020020, 0x1440fffb, 0x0, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0xc004d78, 0x2021, 0xc004d78, 0x24040001, +0x24100010, 0xc004d78, 0x2021, 0x108042, +0x1600fffc, 0x0, 0x24100010, 0xc004d78, +0x2021, 0x108042, 0x1600fffc, 0x0, +0xc004d78, 0x24040001, 0xc004d78, 0x2021, +0x34108000, 0x97a20022, 0x501024, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fff8, 0x0, 0xc004db9, 0x0, +0x24040018, 0x24050002, 0xc004ddb, 0x24060004, +0x3c100001, 0x8e106e24, 0x24020001, 0x1602011d, +0x0, 0x3c020001, 0x94426f26, 0x3c010001, +0xac206e24, 0x24429fbc, 0x2c420004, 0x1040000c, +0x24040009, 0x24050001, 0xc004ddb, 0x24060400, +0x24040018, 0x24050001, 0xc004ddb, 0x24060020, +0x24040018, 0x24050001, 0xc004ddb, 0x24062000, +0x3c024000, 0x2421024, 0x10400123, 0x3c022000, +0x2421024, 0x10400004, 0x0, 0x3c010001, +0x10000003, 0xac306f1c, 0x3c010001, 0xac206f1c, +0x3c030001, 0x8c636f34, 0x24020005, 0x146200f9, +0x0, 0x3c020001, 0x8c426f1c, 0x10400067, +0x3c020004, 0x2421024, 0x10400011, 0xa7a00018, +0x3c020008, 0x2421024, 0x10400002, 0x24020200, +0xa7a20018, 0x3c020010, 0x2421024, 0x10400004, +0x0, 0x97a20018, 0x34420100, 0xa7a20018, +0x97a60018, 0x24040009, 0x10000004, 0x2821, +0x24040009, 0x2821, 0x3021, 0xc004ddb, +0x0, 0x24020001, 0xa7a2001a, 0x3c020008, +0x2421024, 0x1040000c, 0x3c020002, 0x2421024, +0x10400002, 0x24020101, 0xa7a2001a, 0x3c020001, +0x2421024, 0x10400005, 0x3c020010, 0x97a2001a, +0x34420040, 0xa7a2001a, 0x3c020010, 0x2421024, +0x1040000e, 0x3c020002, 0x2421024, 0x10400005, +0x3c020001, 0x97a2001a, 0x34420080, 0xa7a2001a, +0x3c020001, 0x2421024, 0x10400005, 0x3c0300a0, +0x97a2001a, 0x34420020, 0xa7a2001a, 0x3c0300a0, +0x2431024, 0x54430004, 0x3c020020, 0x97a2001a, +0x1000000c, 0x34420400, 0x2421024, 0x50400004, +0x3c020080, 0x97a2001a, 0x10000006, 0x34420800, +0x2421024, 0x10400004, 0x0, 0x97a2001a, +0x34420c00, 0xa7a2001a, 0x97a6001a, 0x24040004, +0xc004ddb, 0x2821, 0x3c020004, 0x2421024, +0x10400004, 0xa7a0001c, 0x32425000, 0x14400004, +0x0, 0x32424000, 0x10400005, 0x2021, +0xc004cf9, 0x2402021, 0x10000096, 0x0, +0x97a6001c, 0x2821, 0x34c61200, 0xc004ddb, +0xa7a6001c, 0x1000008f, 0x0, 0x2421024, +0x10400004, 0xa7a00018, 0x32425000, 0x14400004, +0x0, 0x32424000, 0x10400005, 0x3c020010, +0xc004cf9, 0x2402021, 0x10000019, 0xa7a0001a, 0x2421024, 0x10400004, 0x0, 0x97a20018, 0x10000004, 0xa7a20018, 0x97a20018, 0x34420100, 0xa7a20018, 0x3c020001, 0x2421024, 0x10400004, 0x0, 0x97a20018, 0x10000004, 0xa7a20018, -0x97a20018, 0x34422000, 0xa7a20018, 0x2021, -0x97a60018, 0x2821, 0xc004e0e, 0x8021, -0xa7a0001a, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, +0x97a20018, 0x34422000, 0xa7a20018, 0x97a60018, +0x2021, 0xc004ddb, 0x2821, 0xa7a0001a, +0x8021, 0xc004d78, 0x24040001, 0x26100001, +0x2e020020, 0x1440fffb, 0x0, 0xc004d78, +0x2021, 0xc004d78, 0x24040001, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0xc004dab, 0x2021, 0x108042, -0x1600fffc, 0x0, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, +0xc004d78, 0x108042, 0x1600fffa, 0x32020001, +0x24100010, 0xc004d78, 0x2021, 0x108042, +0x1600fffc, 0x0, 0xc004db9, 0x34108000, +0xc004db9, 0x0, 0xc004d58, 0x0, 0x50400005, 0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x8021, 0xa7a0001a, 0xc004dab, +0xc004db9, 0x8021, 0xa7a0001a, 0xc004d78, 0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x24040001, 0xc004d78, 0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0xc004dab, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0xc004d78, 0x2021, 0x108042, 0x1600fffc, 0x0, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, +0xc004db9, 0x34108000, 0xc004db9, 0x0, +0xc004d58, 0x0, 0x50400005, 0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x0, -0x3c040001, 0x24846c5c, 0x97a60018, 0x97a7001a, -0x3c020001, 0x8c426e18, 0x3c030001, 0x8c636f98, -0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b17, +0x1600fff7, 0x0, 0xc004db9, 0x0, +0x3c040001, 0x24846bcc, 0x97a60018, 0x97a7001a, +0x3c020001, 0x8c426d98, 0x3c030001, 0x8c636f1c, +0x3c05000d, 0x34a50205, 0xafa20010, 0xc002b3b, 0xafa30014, 0x8f830054, 0x24020004, 0x3c010001, -0xac226e54, 0x3c010001, 0x10000179, 0xac236fb0, -0x8f830054, 0x3c020001, 0x8c426fb0, 0x2463ff9c, -0x431023, 0x2c420064, 0x14400009, 0x27b10018, -0x8f820220, 0x24030005, 0x3c010001, 0xac236e54, -0x3c03f700, 0x431025, 0xaf820220, 0x27b10018, -0xa7a00018, 0x8021, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0xc004dab, 0x2021, -0x108042, 0x1600fffc, 0x0, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x96220000, -0x501025, 0xa6220000, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0xa7a0001a, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020001, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, -0x97a2001a, 0x501025, 0xa7a2001a, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, -0xa7a0001a, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0xc004dec, 0x34108000, 0xc004dec, -0x0, 0xc004d8b, 0x0, 0x50400005, -0x108042, 0x97a2001a, 0x501025, 0xa7a2001a, -0x108042, 0x1600fff7, 0x0, 0xc004dec, -0x8021, 0xa7a0001c, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x32020004, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020004, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, -0x50400005, 0x108042, 0x97a2001c, 0x501025, -0xa7a2001c, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x8021, 0xa7a0001c, 0xc004dab, -0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, -0x0, 0xc004dab, 0x2021, 0xc004dab, -0x24040001, 0xc004dab, 0x24040001, 0xc004dab, -0x2021, 0x24100010, 0x32020001, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x32020001, 0x24100010, 0x32020004, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020004, 0xc004dec, -0x34108000, 0xc004dec, 0x0, 0xc004d8b, -0x0, 0x50400005, 0x108042, 0x97a2001c, -0x501025, 0xa7a2001c, 0x108042, 0x1600fff7, -0x0, 0xc004dec, 0x8021, 0xa7a00020, -0xc004dab, 0x24040001, 0x26100001, 0x2e020020, -0x1440fffb, 0x0, 0xc004dab, 0x2021, -0xc004dab, 0x24040001, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x24100010, 0x32020001, -0x10400002, 0x2021, 0x24040001, 0xc004dab, -0x108042, 0x1600fffa, 0x32020001, 0x24100010, -0x32020019, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020019, -0xc004dec, 0x34108000, 0xc004dec, 0x0, -0xc004d8b, 0x0, 0x50400005, 0x108042, -0x97a20020, 0x501025, 0xa7a20020, 0x108042, -0x1600fff7, 0x0, 0xc004dec, 0x8021, -0xa7a00020, 0xc004dab, 0x24040001, 0x26100001, -0x2e020020, 0x1440fffb, 0x0, 0xc004dab, -0x2021, 0xc004dab, 0x24040001, 0xc004dab, -0x24040001, 0xc004dab, 0x2021, 0x24100010, -0x32020001, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fffa, 0x32020001, -0x24100010, 0x32020019, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020019, 0xc004dec, 0x34108000, 0xc004dec, -0x0, 0xc004d8b, 0x0, 0x50400005, -0x108042, 0x97a20020, 0x501025, 0xa7a20020, -0x108042, 0x1600fff7, 0x0, 0xc004dec, -0x0, 0x97a60018, 0x97a7001a, 0x97a2001c, -0x3c040001, 0x24846c5c, 0xafa20010, 0x97a20020, -0x3c05000d, 0x34a50204, 0xc002b17, 0xafa20014, -0x10000007, 0x0, 0x24020006, 0x3c010001, -0xac226e54, 0x24020011, 0x3c010001, 0xac226e50, -0x8fbf0034, 0x8fb20030, 0x8fb1002c, 0x8fb00028, -0x3e00008, 0x27bd0038, 0x8f850044, 0x8f820044, -0x3c030001, 0x431025, 0x3c030008, 0xaf820044, -0x8f840054, 0x8f820054, 0xa32824, 0x10000002, -0x24840001, 0x8f820054, 0x821023, 0x2c420002, -0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, -0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, -0x8f820054, 0x10000002, 0x24630001, 0x8f820054, -0x621023, 0x2c420002, 0x1440fffc, 0x0, -0x3e00008, 0xa01021, 0x8f830044, 0x3c02fff0, -0x3442ffff, 0x42480, 0x621824, 0x3c020002, -0x822025, 0x641825, 0xaf830044, 0x8f820044, +0xac226dd4, 0x3c010001, 0x10000017, 0xac236f38, +0x8f830054, 0x3c020001, 0x8c426f38, 0x2463ff9c, +0x431023, 0x2c420064, 0x1440000f, 0x0, +0x8f820220, 0x24030005, 0x3c010001, 0xac236dd4, +0x3c03f700, 0x431025, 0x10000007, 0xaf820220, +0x24020006, 0x3c010001, 0xac226dd4, 0x24020011, +0x3c010001, 0xac226dd0, 0x8fbf0034, 0x8fb20030, +0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0038, +0x27bdffd8, 0xafb00018, 0x808021, 0xafb1001c, +0x8821, 0x32024000, 0x10400013, 0xafbf0020, +0x3c020010, 0x2021024, 0x2c420001, 0x21023, +0x30434100, 0x3c020001, 0x2021024, 0x14400006, +0x34714000, 0x3c020002, 0x2021024, 0x14400002, +0x34716000, 0x34714040, 0x2021, 0x2821, +0x10000036, 0x2203021, 0x32021000, 0x10400035, +0x2021, 0x2821, 0xc004ddb, 0x24060040, +0x24040018, 0x2821, 0xc004ddb, 0x24060c00, +0x24040017, 0x2821, 0xc004ddb, 0x24060400, +0x24040016, 0x2821, 0xc004ddb, 0x24060006, +0x24040017, 0x2821, 0xc004ddb, 0x24062500, +0x24040016, 0x2821, 0xc004ddb, 0x24060006, +0x24040017, 0x2821, 0xc004ddb, 0x24064600, +0x24040016, 0x2821, 0xc004ddb, 0x24060006, +0x24040017, 0x2821, 0xc004ddb, 0x24066700, +0x24040016, 0x2821, 0xc004ddb, 0x24060006, +0x2404001f, 0x2821, 0xc004ddb, 0x24060010, +0x24040009, 0x2821, 0xc004ddb, 0x24061500, +0x24040009, 0x2821, 0x24061d00, 0xc004ddb, +0x0, 0x3c040001, 0x24846bf0, 0x3c05000e, +0x34a50100, 0x2003021, 0x2203821, 0xafa00010, +0xc002b3b, 0xafa00014, 0x8fbf0020, 0x8fb1001c, +0x8fb00018, 0x3e00008, 0x27bd0028, 0x8f850044, +0x8f820044, 0x3c030001, 0x431025, 0x3c030008, +0xaf820044, 0x8f840054, 0x8f820054, 0xa32824, +0x10000002, 0x24840001, 0x8f820054, 0x821023, +0x2c420002, 0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x3c030001, 0x431025, +0x0, 0x3e00008, 0xa01021, 0x8f830044, +0x3c02fff0, 0x3442ffff, 0x42480, 0x621824, +0x3c020002, 0x822025, 0x641825, 0xaf830044, +0x8f820044, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, -0x1440fffc, 0x0, 0x3e00008, 0x0, -0x8f820044, 0x2403ff7f, 0x431024, 0xaf820044, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x34420080, 0xaf820044, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x3e00008, 0x0, 0x8f820044, -0x3c03fff0, 0x3463ffff, 0x431024, 0xaf820044, -0x8f820044, 0x3c030001, 0x431025, 0xaf820044, -0x8f830054, 0x8f820054, 0x10000002, 0x24630001, -0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, -0x0, 0x8f820044, 0x3c03fffe, 0x3463ffff, -0x431024, 0xaf820044, 0x8f830054, 0x8f820054, +0x1440fffc, 0x0, 0x8f820044, 0x3c030001, +0x431025, 0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, 0x24630001, 0x8f820054, 0x621023, 0x2c420002, 0x1440fffc, 0x0, 0x3e00008, -0x0, 0x27bdffc8, 0xafb30024, 0x809821, -0xafbe002c, 0xa0f021, 0xafb20020, 0xc09021, -0x33c2ffff, 0xafbf0030, 0xafb50028, 0xafb1001c, -0xafb00018, 0x14400034, 0xa7b20010, 0x3271ffff, -0x27b20010, 0x8021, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x2301024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x2301024, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x34108000, 0x96420000, -0x501024, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x12000075, 0x0, -0x1000fff6, 0x0, 0x3275ffff, 0x27b10010, -0xa7a00010, 0x8021, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x24040001, 0xc004dab, 0x2021, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x2b01024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x2b01024, 0xc004dec, 0x34108000, -0xc004dec, 0x0, 0xc004d8b, 0x0, -0x50400005, 0x108042, 0x96220000, 0x501025, -0xa6220000, 0x108042, 0x1600fff7, 0x0, -0xc004dec, 0x0, 0x33c5ffff, 0x24020001, -0x54a20004, 0x24020002, 0x97a20010, 0x10000006, -0x521025, 0x14a20006, 0x3271ffff, 0x97a20010, -0x121827, 0x431024, 0xa7a20010, 0x3271ffff, -0x27b20010, 0x8021, 0xc004dab, 0x24040001, -0x26100001, 0x2e020020, 0x1440fffb, 0x0, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0xc004dab, 0x24040001, -0x24100010, 0x32020001, 0x10400002, 0x2021, -0x24040001, 0xc004dab, 0x108042, 0x1600fffa, -0x32020001, 0x24100010, 0x2301024, 0x10400002, -0x2021, 0x24040001, 0xc004dab, 0x108042, -0x1600fffa, 0x2301024, 0xc004dab, 0x24040001, -0xc004dab, 0x2021, 0x34108000, 0x96420000, -0x501024, 0x10400002, 0x2021, 0x24040001, -0xc004dab, 0x108042, 0x1600fff8, 0x0, -0xc004dec, 0x0, 0x8fbf0030, 0x8fbe002c, -0x8fb50028, 0x8fb30024, 0x8fb20020, 0x8fb1001c, -0x8fb00018, 0x3e00008, 0x27bd0038, 0x27bdffe8, +0x0, 0x8f820044, 0x2403ff7f, 0x431024, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, +0x24630001, 0x8f820054, 0x621023, 0x2c420002, +0x1440fffc, 0x0, 0x8f820044, 0x34420080, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, +0x24630001, 0x8f820054, 0x621023, 0x2c420002, +0x1440fffc, 0x0, 0x3e00008, 0x0, +0x8f820044, 0x3c03fff0, 0x3463ffff, 0x431024, +0xaf820044, 0x8f820044, 0x3c030001, 0x431025, +0xaf820044, 0x8f830054, 0x8f820054, 0x10000002, +0x24630001, 0x8f820054, 0x621023, 0x2c420002, +0x1440fffc, 0x0, 0x8f820044, 0x3c03fffe, +0x3463ffff, 0x431024, 0xaf820044, 0x8f830054, +0x8f820054, 0x10000002, 0x24630001, 0x8f820054, +0x621023, 0x2c420002, 0x1440fffc, 0x0, +0x3e00008, 0x0, 0x27bdffc8, 0xafb30024, +0x809821, 0xafbe002c, 0xa0f021, 0xafb20020, +0xc09021, 0x33c2ffff, 0xafbf0030, 0xafb50028, +0xafb1001c, 0xafb00018, 0x14400034, 0xa7b20010, +0x3271ffff, 0x27b20010, 0x8021, 0xc004d78, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x2301024, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x2301024, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, +0x96420000, 0x501024, 0x10400002, 0x2021, +0x24040001, 0xc004d78, 0x108042, 0x12000075, +0x0, 0x1000fff6, 0x0, 0x3275ffff, +0x27b10010, 0xa7a00010, 0x8021, 0xc004d78, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x24040001, 0xc004d78, +0x2021, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x2b01024, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x2b01024, 0xc004db9, +0x34108000, 0xc004db9, 0x0, 0xc004d58, +0x0, 0x50400005, 0x108042, 0x96220000, +0x501025, 0xa6220000, 0x108042, 0x1600fff7, +0x0, 0xc004db9, 0x0, 0x33c5ffff, +0x24020001, 0x54a20004, 0x24020002, 0x97a20010, +0x10000006, 0x521025, 0x14a20006, 0x3271ffff, +0x97a20010, 0x121827, 0x431024, 0xa7a20010, +0x3271ffff, 0x27b20010, 0x8021, 0xc004d78, +0x24040001, 0x26100001, 0x2e020020, 0x1440fffb, +0x0, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0xc004d78, +0x24040001, 0x24100010, 0x32020001, 0x10400002, +0x2021, 0x24040001, 0xc004d78, 0x108042, +0x1600fffa, 0x32020001, 0x24100010, 0x2301024, +0x10400002, 0x2021, 0x24040001, 0xc004d78, +0x108042, 0x1600fffa, 0x2301024, 0xc004d78, +0x24040001, 0xc004d78, 0x2021, 0x34108000, +0x96420000, 0x501024, 0x10400002, 0x2021, +0x24040001, 0xc004d78, 0x108042, 0x1600fff8, +0x0, 0xc004db9, 0x0, 0x8fbf0030, +0x8fbe002c, 0x8fb50028, 0x8fb30024, 0x8fb20020, +0x8fb1001c, 0x8fb00018, 0x3e00008, 0x27bd0038, +0x0, 0x0, 0x0, 0x27bdffe8, 0xafbf0010, 0x8ee304b8, 0x24020008, 0x146201e0, -0x0, 0x3c020001, 0x8c426f98, 0x14400005, -0x0, 0xc003d87, 0x8f840224, 0x100001d8, +0x0, 0x3c020001, 0x8c426f1c, 0x14400005, +0x0, 0xc003daf, 0x8f840224, 0x100001d8, 0x0, 0x8f820220, 0x3c030008, 0x431024, 0x10400026, 0x24020001, 0x8f840224, 0x8f820220, 0x3c030400, 0x431024, 0x10400006, 0x0, -0x3c010002, 0xac209020, 0x3c010002, 0x1000000b, -0xac209040, 0x3c030002, 0x24639020, 0x8c620000, +0x3c010002, 0xac208fa0, 0x3c010002, 0x1000000b, +0xac208fc0, 0x3c030002, 0x24638fa0, 0x8c620000, 0x24420001, 0xac620000, 0x2c420002, 0x14400003, -0x24020001, 0x3c010002, 0xac229040, 0x3c020002, -0x8c429040, 0x10400006, 0x30820040, 0x10400004, -0x24020001, 0x3c010002, 0x10000003, 0xac229044, -0x3c010002, 0xac209044, 0x3c010002, 0xac24901c, -0x3c010002, 0x1000000b, 0xac209050, 0x3c010002, -0xac229050, 0x3c010002, 0xac209040, 0x3c010002, -0xac209020, 0x3c010002, 0xac209044, 0x3c010002, -0xac20901c, 0x3c030002, 0x8c639010, 0x3c020002, -0x8c429014, 0x50620004, 0x2463ffff, 0x3c010002, -0xac239014, 0x2463ffff, 0x2c62000e, 0x10400194, -0x31080, 0x3c010001, 0x220821, 0x8c226c80, +0x24020001, 0x3c010002, 0xac228fc0, 0x3c020002, +0x8c428fc0, 0x10400006, 0x30820040, 0x10400004, +0x24020001, 0x3c010002, 0x10000003, 0xac228fc4, +0x3c010002, 0xac208fc4, 0x3c010002, 0xac248f9c, +0x3c010002, 0x1000000b, 0xac208fd0, 0x3c010002, +0xac228fd0, 0x3c010002, 0xac208fc0, 0x3c010002, +0xac208fa0, 0x3c010002, 0xac208fc4, 0x3c010002, +0xac208f9c, 0x3c030002, 0x8c638f90, 0x3c020002, +0x8c428f94, 0x50620004, 0x2463ffff, 0x3c010002, +0xac238f94, 0x2463ffff, 0x2c62000e, 0x10400194, +0x31080, 0x3c010001, 0x220821, 0x8c226c00, 0x400008, 0x0, 0x24020002, 0x3c010002, -0xac209040, 0x3c010002, 0xac209020, 0x3c010002, -0xac20901c, 0x3c010002, 0xac209044, 0x3c010002, -0xac209038, 0x3c010002, 0xac209030, 0xaf800224, -0x3c010002, 0xac229010, 0x3c020002, 0x8c429050, -0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003d87, +0xac208fc0, 0x3c010002, 0xac208fa0, 0x3c010002, +0xac208f9c, 0x3c010002, 0xac208fc4, 0x3c010002, +0xac208fb8, 0x3c010002, 0xac208fb0, 0xaf800224, +0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fd0, +0x1440004f, 0x3c02fdff, 0x3442ffff, 0xc003daf, 0x282a024, 0xaf800204, 0x8f820200, 0x2403fffd, -0x431024, 0xaf820200, 0x3c010002, 0xac209060, -0x8f830054, 0x3c020002, 0x8c429038, 0x24040001, -0x3c010002, 0xac24904c, 0x24420001, 0x3c010002, -0xac229038, 0x2c420004, 0x3c010002, 0xac239034, -0x14400006, 0x24020003, 0x3c010001, 0xac246e1c, -0x3c010002, 0x1000015e, 0xac209038, 0x3c010002, -0x1000015b, 0xac229010, 0x8f830054, 0x3c020002, -0x8c429034, 0x2463d8f0, 0x431023, 0x2c422710, -0x14400003, 0x24020004, 0x3c010002, 0xac229010, -0x3c020002, 0x8c429050, 0x14400021, 0x3c02fdff, +0x431024, 0xaf820200, 0x3c010002, 0xac208fe0, +0x8f830054, 0x3c020002, 0x8c428fb8, 0x24040001, +0x3c010002, 0xac248fcc, 0x24420001, 0x3c010002, +0xac228fb8, 0x2c420004, 0x3c010002, 0xac238fb4, +0x14400006, 0x24020003, 0x3c010001, 0xac246d9c, +0x3c010002, 0x1000015e, 0xac208fb8, 0x3c010002, +0x1000015b, 0xac228f90, 0x8f830054, 0x3c020002, +0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, +0x14400003, 0x24020004, 0x3c010002, 0xac228f90, +0x3c020002, 0x8c428fd0, 0x14400021, 0x3c02fdff, 0x3442ffff, 0x1000014a, 0x282a024, 0x3c040001, -0x8c846f9c, 0x3c010002, 0xc0050b4, 0xac209028, -0x3c020002, 0x8c42905c, 0xaf820204, 0x3c020002, -0x8c429050, 0x14400012, 0x3c03fdff, 0x8f820204, +0x8c846f20, 0x3c010002, 0xc005084, 0xac208fa8, +0x3c020002, 0x8c428fdc, 0xaf820204, 0x3c020002, +0x8c428fd0, 0x14400012, 0x3c03fdff, 0x8f820204, 0x3463ffff, 0x30420030, 0x1440012f, 0x283a024, -0x3c030002, 0x8c63905c, 0x24020005, 0x3c010002, -0xac229010, 0x3c010002, 0x10000131, 0xac239060, -0x3c020002, 0x8c429050, 0x10400010, 0x3c02fdff, -0x3c020001, 0x8c426ebc, 0x24420001, 0x3c010001, -0xac226ebc, 0x2c420002, 0x14400125, 0x24020001, -0x3c010001, 0xac226ec4, 0x3c010001, 0xac206ebc, -0x3c010001, 0x1000011e, 0xac226e1c, 0x3c030002, -0x8c639040, 0x3442ffff, 0x10600119, 0x282a024, -0x3c020002, 0x8c42901c, 0x10400115, 0x0, -0x3c010002, 0xac229048, 0x24020003, 0x3c010002, -0xac229020, 0x100000b8, 0x24020006, 0x3c010002, -0xac209028, 0x8f820204, 0x34420040, 0xaf820204, -0x3c020002, 0x8c429060, 0x24030007, 0x3c010002, -0xac239010, 0x34420040, 0x3c010002, 0xac229060, -0x3c020002, 0x8c429040, 0x10400005, 0x0, -0x3c020002, 0x8c42901c, 0x104000f0, 0x24020002, -0x3c050002, 0x24a59020, 0x8ca20000, 0x2c424e21, -0x104000ea, 0x24020002, 0x3c020002, 0x8c429044, -0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c42901c, -0x3c030002, 0x8c639048, 0x441024, 0x641824, +0x3c030002, 0x8c638fdc, 0x24020005, 0x3c010002, +0xac228f90, 0x3c010002, 0x10000131, 0xac238fe0, +0x3c020002, 0x8c428fd0, 0x10400010, 0x3c02fdff, +0x3c020001, 0x8c426e3c, 0x24420001, 0x3c010001, +0xac226e3c, 0x2c420002, 0x14400125, 0x24020001, +0x3c010001, 0xac226e44, 0x3c010001, 0xac206e3c, +0x3c010001, 0x1000011e, 0xac226d9c, 0x3c030002, +0x8c638fc0, 0x3442ffff, 0x10600119, 0x282a024, +0x3c020002, 0x8c428f9c, 0x10400115, 0x0, +0x3c010002, 0xac228fc8, 0x24020003, 0x3c010002, +0xac228fa0, 0x100000b8, 0x24020006, 0x3c010002, +0xac208fa8, 0x8f820204, 0x34420040, 0xaf820204, +0x3c020002, 0x8c428fe0, 0x24030007, 0x3c010002, +0xac238f90, 0x34420040, 0x3c010002, 0xac228fe0, +0x3c020002, 0x8c428fc0, 0x10400005, 0x0, +0x3c020002, 0x8c428f9c, 0x104000f0, 0x24020002, +0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21, +0x104000ea, 0x24020002, 0x3c020002, 0x8c428fc4, +0x104000ef, 0x2404ffbf, 0x3c020002, 0x8c428f9c, +0x3c030002, 0x8c638fc8, 0x441024, 0x641824, 0x10430004, 0x24020001, 0x3c010002, 0x100000e4, -0xac229010, 0x24020003, 0xaca20000, 0x24020008, -0x3c010002, 0xac229010, 0x3c020002, 0x8c42904c, -0x1040000c, 0x24020001, 0x3c040002, 0xc0050c1, -0x8c84901c, 0x3c020002, 0x8c429068, 0x14400005, -0x24020001, 0x3c020002, 0x8c429064, 0x10400006, -0x24020001, 0x3c010001, 0xac226e1c, 0x3c010002, -0x100000cb, 0xac209038, 0x3c020002, 0x8c429030, -0x3c030002, 0x8c63901c, 0x2c420001, 0x210c0, -0x30630008, 0x3c010002, 0xac229030, 0x3c010002, -0xac23902c, 0x8f830054, 0x24020009, 0x3c010002, -0xac229010, 0x3c010002, 0x100000b9, 0xac239034, -0x8f830054, 0x3c020002, 0x8c429034, 0x2463d8f0, +0xac228f90, 0x24020003, 0xaca20000, 0x24020008, +0x3c010002, 0xac228f90, 0x3c020002, 0x8c428fcc, +0x1040000c, 0x24020001, 0x3c040002, 0xc005091, +0x8c848f9c, 0x3c020002, 0x8c428fe8, 0x14400005, +0x24020001, 0x3c020002, 0x8c428fe4, 0x10400006, +0x24020001, 0x3c010001, 0xac226d9c, 0x3c010002, +0x100000cb, 0xac208fb8, 0x3c020002, 0x8c428fb0, +0x3c030002, 0x8c638f9c, 0x2c420001, 0x210c0, +0x30630008, 0x3c010002, 0xac228fb0, 0x3c010002, +0xac238fac, 0x8f830054, 0x24020009, 0x3c010002, +0xac228f90, 0x3c010002, 0x100000b9, 0xac238fb4, +0x8f830054, 0x3c020002, 0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, 0x1440009f, 0x0, -0x3c020002, 0x8c429040, 0x10400005, 0x0, -0x3c020002, 0x8c42901c, 0x104000a0, 0x24020002, -0x3c030002, 0x24639020, 0x8c620000, 0x2c424e21, -0x1040009a, 0x24020002, 0x3c020002, 0x8c42904c, -0x1040000e, 0x0, 0x3c020002, 0x8c42901c, -0x3c010002, 0xac20904c, 0x30420080, 0x1040002f, +0x3c020002, 0x8c428fc0, 0x10400005, 0x0, +0x3c020002, 0x8c428f9c, 0x104000a0, 0x24020002, +0x3c030002, 0x24638fa0, 0x8c620000, 0x2c424e21, +0x1040009a, 0x24020002, 0x3c020002, 0x8c428fcc, +0x1040000e, 0x0, 0x3c020002, 0x8c428f9c, +0x3c010002, 0xac208fcc, 0x30420080, 0x1040002f, 0x2402000c, 0x8f820204, 0x30420080, 0x1440000c, 0x24020003, 0x10000029, 0x2402000c, 0x3c020002, -0x8c42901c, 0x30420080, 0x14400005, 0x24020003, +0x8c428f9c, 0x30420080, 0x14400005, 0x24020003, 0x8f820204, 0x30420080, 0x1040001f, 0x24020003, -0xac620000, 0x2402000a, 0x3c010002, 0xac229010, -0x3c040002, 0x24849058, 0x8c820000, 0x3c030002, -0x8c639030, 0x431025, 0xaf820204, 0x8c830000, -0x3c040002, 0x8c849030, 0x2402000b, 0x3c010002, -0xac229010, 0x641825, 0x3c010002, 0xac239060, -0x3c050002, 0x24a59020, 0x8ca20000, 0x2c424e21, -0x10400066, 0x24020002, 0x3c020002, 0x8c429050, +0xac620000, 0x2402000a, 0x3c010002, 0xac228f90, +0x3c040002, 0x24848fd8, 0x8c820000, 0x3c030002, +0x8c638fb0, 0x431025, 0xaf820204, 0x8c830000, +0x3c040002, 0x8c848fb0, 0x2402000b, 0x3c010002, +0xac228f90, 0x641825, 0x3c010002, 0xac238fe0, +0x3c050002, 0x24a58fa0, 0x8ca20000, 0x2c424e21, +0x10400066, 0x24020002, 0x3c020002, 0x8c428fd0, 0x10400005, 0x0, 0x2402000c, 0x3c010002, -0x10000067, 0xac229010, 0x3c020002, 0x8c429040, -0x10400063, 0x0, 0x3c040002, 0x8c84901c, -0x10800055, 0x30820008, 0x3c030002, 0x8c63902c, -0x1062005b, 0x24020003, 0x3c010002, 0xac249048, +0x10000067, 0xac228f90, 0x3c020002, 0x8c428fc0, +0x10400063, 0x0, 0x3c040002, 0x8c848f9c, +0x10800055, 0x30820008, 0x3c030002, 0x8c638fac, +0x1062005b, 0x24020003, 0x3c010002, 0xac248fc8, 0xaca20000, 0x24020006, 0x3c010002, 0x10000054, -0xac229010, 0x8f820200, 0x34420002, 0xaf820200, -0x8f830054, 0x2402000d, 0x3c010002, 0xac229010, -0x3c010002, 0xac239034, 0x8f830054, 0x3c020002, -0x8c429034, 0x2463d8f0, 0x431023, 0x2c422710, -0x14400031, 0x0, 0x3c020002, 0x8c429050, -0x10400020, 0x2402000e, 0x3c030002, 0x8c639064, -0x3c010002, 0x14600015, 0xac229010, 0xc003e45, -0x0, 0x3c050001, 0x8ca56e18, 0xc0052c7, -0x2021, 0x3c030001, 0x8c636e18, 0x24020004, -0x14620005, 0x2403fffb, 0x3c020001, 0x8c426e14, -0x10000003, 0x2403fff7, 0x3c020001, 0x8c426e14, -0x431024, 0x3c010001, 0xac226e14, 0x8f830224, -0x3c020200, 0x3c010002, 0xac23906c, 0x10000020, -0x282a025, 0x3c020002, 0x8c429040, 0x10400005, -0x0, 0x3c020002, 0x8c42901c, 0x1040000f, -0x24020002, 0x3c020002, 0x8c429020, 0x2c424e21, -0x1040000a, 0x24020002, 0x3c020002, 0x8c429040, -0x1040000f, 0x0, 0x3c020002, 0x8c42901c, +0xac228f90, 0x8f820200, 0x34420002, 0xaf820200, +0x8f830054, 0x2402000d, 0x3c010002, 0xac228f90, +0x3c010002, 0xac238fb4, 0x8f830054, 0x3c020002, +0x8c428fb4, 0x2463d8f0, 0x431023, 0x2c422710, +0x14400031, 0x0, 0x3c020002, 0x8c428fd0, +0x10400020, 0x2402000e, 0x3c030002, 0x8c638fe4, +0x3c010002, 0x14600015, 0xac228f90, 0xc003e6d, +0x0, 0x3c050001, 0x8ca56d98, 0xc00529b, +0x2021, 0x3c030001, 0x8c636d98, 0x24020004, +0x14620005, 0x2403fffb, 0x3c020001, 0x8c426d94, +0x10000003, 0x2403fff7, 0x3c020001, 0x8c426d94, +0x431024, 0x3c010001, 0xac226d94, 0x8f830224, +0x3c020200, 0x3c010002, 0xac238fec, 0x10000020, +0x282a025, 0x3c020002, 0x8c428fc0, 0x10400005, +0x0, 0x3c020002, 0x8c428f9c, 0x1040000f, +0x24020002, 0x3c020002, 0x8c428fa0, 0x2c424e21, +0x1040000a, 0x24020002, 0x3c020002, 0x8c428fc0, +0x1040000f, 0x0, 0x3c020002, 0x8c428f9c, 0x1440000b, 0x0, 0x24020002, 0x3c010002, -0x10000007, 0xac229010, 0x3c020002, 0x8c429040, -0x10400003, 0x0, 0xc003d87, 0x0, +0x10000007, 0xac228f90, 0x3c020002, 0x8c428fc0, +0x10400003, 0x0, 0xc003daf, 0x0, 0x8f820220, 0x3c03f700, 0x431025, 0xaf820220, 0x8fbf0010, 0x3e00008, 0x27bd0018, 0x3c030002, -0x24639068, 0x8c620000, 0x10400005, 0x34422000, -0x3c010002, 0xac22905c, 0x10000003, 0xac600000, -0x3c010002, 0xac24905c, 0x3e00008, 0x0, +0x24638fe8, 0x8c620000, 0x10400005, 0x34422000, +0x3c010002, 0xac228fdc, 0x10000003, 0xac600000, +0x3c010002, 0xac248fdc, 0x3e00008, 0x0, 0x27bdffe0, 0x30820030, 0xafbf0018, 0x3c010002, -0xac229064, 0x14400067, 0x3c02ffff, 0x34421f0e, +0xac228fe4, 0x14400067, 0x3c02ffff, 0x34421f0e, 0x821024, 0x14400061, 0x24020030, 0x30822000, 0x1040005d, 0x30838000, 0x31a02, 0x30820001, -0x21200, 0x3c040001, 0x8c846f9c, 0x621825, -0x331c2, 0x3c030001, 0x24636ec8, 0x30828000, +0x21200, 0x3c040001, 0x8c846f20, 0x621825, +0x331c2, 0x3c030001, 0x24636e48, 0x30828000, 0x21202, 0x30840001, 0x42200, 0x441025, 0x239c2, 0x61080, 0x431021, 0x471021, 0x90430000, 0x24020001, 0x10620025, 0x0, @@ -8775,354 +8758,357 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x1062002c, 0x3c05000f, 0x10000037, 0x0, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, -0xaf820220, 0x3c010002, 0xac209084, 0x3c010002, -0x10000034, 0xac20908c, 0x8f820200, 0x34420100, +0xaf820220, 0x3c010002, 0xac209004, 0x3c010002, +0x10000034, 0xac20900c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, 0x24020100, 0x3c010002, -0xac229084, 0x3c010002, 0x10000026, 0xac20908c, +0xac229004, 0x3c010002, 0x10000026, 0xac20900c, 0x8f820200, 0x2403feff, 0x431024, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, -0x3c010002, 0xac209084, 0x3c010002, 0x10000019, -0xac23908c, 0x8f820200, 0x34420100, 0xaf820200, +0x3c010002, 0xac209004, 0x3c010002, 0x10000019, +0xac23900c, 0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, 0x3c030001, 0x431025, 0xaf820220, -0x24020100, 0x3c010002, 0xac229084, 0x3c010002, -0x1000000c, 0xac23908c, 0x34a5ffff, 0x3c040001, -0x24846cb8, 0xafa30010, 0xc002b17, 0xafa00014, +0x24020100, 0x3c010002, 0xac229004, 0x3c010002, +0x1000000c, 0xac23900c, 0x34a5ffff, 0x3c040001, +0x24846c38, 0xafa30010, 0xc002b3b, 0xafa00014, 0x10000004, 0x0, 0x24020030, 0x3c010002, -0xac229068, 0x8fbf0018, 0x3e00008, 0x27bd0020, +0xac228fe8, 0x8fbf0018, 0x3e00008, 0x27bd0020, 0x0, 0x0, 0x0, 0x27bdffc8, 0xafb20028, 0x809021, 0xafb3002c, 0xa09821, -0xafb00020, 0xc08021, 0x3c040001, 0x24846cd0, -0x3c050009, 0x3c020001, 0x8c426e18, 0x34a59001, +0xafb00020, 0xc08021, 0x3c040001, 0x24846c50, +0x3c050009, 0x3c020001, 0x8c426d98, 0x34a59001, 0x2403021, 0x2603821, 0xafbf0030, 0xafb10024, -0xa7a0001a, 0xafb00014, 0xc002b17, 0xafa20010, -0x24020002, 0x1262007f, 0x2e620003, 0x10400005, -0x24020001, 0x1262000a, 0x0, 0x1000016f, -0x0, 0x24020004, 0x126200f4, 0x24020008, -0x126200f3, 0x3c02ffec, 0x10000168, 0x0, -0x3c020001, 0x8c426e14, 0x30420002, 0x14400004, +0xa7a0001a, 0xafb00014, 0xc002b3b, 0xafa20010, +0x24020002, 0x12620083, 0x2e620003, 0x10400005, +0x24020001, 0x1262000a, 0x0, 0x10000173, +0x0, 0x24020004, 0x126200f8, 0x24020008, +0x126200f7, 0x3c02ffec, 0x1000016c, 0x0, +0x3c020001, 0x8c426d94, 0x30420002, 0x14400004, 0x128940, 0x3c02fffb, 0x3442ffff, 0x2028024, -0x3c010002, 0x310821, 0xac30907c, 0x3c024000, -0x2021024, 0x1040004a, 0x1023c2, 0x30840030, -0x101382, 0x3042001c, 0x3c030001, 0x24636e58, +0x3c010002, 0x310821, 0xac308ffc, 0x3c024000, +0x2021024, 0x1040004e, 0x1023c2, 0x30840030, +0x101382, 0x3042001c, 0x3c030001, 0x24636dd8, 0x431021, 0x823821, 0x3c020020, 0x2021024, 0x10400006, 0x24020100, 0x3c010002, 0x310821, -0xac229080, 0x10000005, 0x3c020080, 0x3c010002, -0x310821, 0xac209080, 0x3c020080, 0x2021024, +0xac229000, 0x10000005, 0x3c020080, 0x3c010002, +0x310821, 0xac209000, 0x3c020080, 0x2021024, 0x10400006, 0x121940, 0x3c020001, 0x3c010002, -0x230821, 0x10000005, 0xac229088, 0x121140, -0x3c010002, 0x220821, 0xac209088, 0x94e30000, -0x32024000, 0x10400003, 0xa7a30018, 0x34624000, +0x230821, 0x10000005, 0xac229008, 0x121140, +0x3c010002, 0x220821, 0xac209008, 0x94e40000, +0x3c030001, 0x8c636f40, 0x24020005, 0x10620010, +0xa7a40018, 0x32024000, 0x10400002, 0x34824000, 0xa7a20018, 0x24040001, 0x94e20002, 0x24050004, -0x24e60002, 0x34420001, 0xc00450e, 0xa4e20002, -0x24040001, 0x2821, 0xc00450e, 0x27a60018, -0x3c020001, 0x8c426e18, 0x24110001, 0x3c010001, -0xac316e24, 0x14530004, 0x32028000, 0xc003d87, +0x24e60002, 0x34420001, 0xc0045be, 0xa4e20002, +0x24040001, 0x2821, 0xc0045be, 0x27a60018, +0x3c020001, 0x8c426d98, 0x24110001, 0x3c010001, +0xac316da4, 0x14530004, 0x32028000, 0xc003daf, 0x0, 0x32028000, 0x1040011c, 0x0, -0xc003d87, 0x0, 0x3c030001, 0x8c636fb8, +0xc003daf, 0x0, 0x3c030001, 0x8c636f40, 0x24020005, 0x10620115, 0x24020002, 0x3c010001, -0xac316e1c, 0x3c010001, 0x10000110, 0xac226e18, -0x24040001, 0x24050004, 0x27b0001a, 0xc00450e, -0x2003021, 0x24040001, 0x2821, 0xc00450e, -0x2003021, 0x3c020002, 0x511021, 0x8c429074, -0x3c040001, 0x8c846e18, 0x3c03bfff, 0x3463ffff, -0x3c010001, 0xac336e24, 0x431024, 0x3c010002, -0x310821, 0x109300f7, 0xac229074, 0x100000f7, +0xac316d9c, 0x3c010001, 0x10000110, 0xac226d98, +0x24040001, 0x24050004, 0x27b0001a, 0xc0045be, +0x2003021, 0x24040001, 0x2821, 0xc0045be, +0x2003021, 0x3c020002, 0x511021, 0x8c428ff4, +0x3c040001, 0x8c846d98, 0x3c03bfff, 0x3463ffff, +0x3c010001, 0xac336da4, 0x431024, 0x3c010002, +0x310821, 0x109300f7, 0xac228ff4, 0x100000f7, 0x0, 0x3c022000, 0x2021024, 0x10400005, -0x24020001, 0x3c010001, 0xac226f98, 0x10000004, -0x128940, 0x3c010001, 0xac206f98, 0x128940, -0x3c010002, 0x310821, 0xac309078, 0x3c024000, +0x24020001, 0x3c010001, 0xac226f1c, 0x10000004, +0x128940, 0x3c010001, 0xac206f1c, 0x128940, +0x3c010002, 0x310821, 0xac308ff8, 0x3c024000, 0x2021024, 0x14400014, 0x0, 0x3c020001, -0x8c426f98, 0x10400006, 0x24040004, 0x24050001, -0xc004e0e, 0x24062000, 0x24020001, 0xaee204b8, -0x3c020002, 0x511021, 0x8c429070, 0x3c03bfff, +0x8c426f1c, 0x10400006, 0x24040004, 0x24050001, +0xc004ddb, 0x24062000, 0x24020001, 0xaee204b8, +0x3c020002, 0x511021, 0x8c428ff0, 0x3c03bfff, 0x3463ffff, 0x431024, 0x3c010002, 0x310821, -0x100000d0, 0xac229070, 0x3c020001, 0x8c426f98, +0x100000d0, 0xac228ff0, 0x3c020001, 0x8c426f1c, 0x10400028, 0x3c0300a0, 0x2031024, 0x5443000d, -0x3c020020, 0x3c020001, 0x8c426f9c, 0x24030100, -0x3c010002, 0x310821, 0xac239084, 0x3c030001, -0x3c010002, 0x310821, 0xac23908c, 0x10000015, +0x3c020020, 0x3c020001, 0x8c426f20, 0x24030100, +0x3c010002, 0x310821, 0xac239004, 0x3c030001, +0x3c010002, 0x310821, 0xac23900c, 0x10000015, 0x34420400, 0x2021024, 0x10400008, 0x24030100, -0x3c020001, 0x8c426f9c, 0x3c010002, 0x310821, -0xac239084, 0x1000000b, 0x34420800, 0x3c020080, +0x3c020001, 0x8c426f20, 0x3c010002, 0x310821, +0xac239004, 0x1000000b, 0x34420800, 0x3c020080, 0x2021024, 0x1040002e, 0x3c030001, 0x3c020001, -0x8c426f9c, 0x3c010002, 0x310821, 0xac23908c, -0x34420c00, 0x3c010001, 0xac226f9c, 0x10000025, +0x8c426f20, 0x3c010002, 0x310821, 0xac23900c, +0x34420c00, 0x3c010001, 0xac226f20, 0x10000025, 0x24040001, 0x3c020020, 0x2021024, 0x10400006, -0x24020100, 0x3c010002, 0x310821, 0xac229084, +0x24020100, 0x3c010002, 0x310821, 0xac229004, 0x10000005, 0x3c020080, 0x3c010002, 0x310821, -0xac209084, 0x3c020080, 0x2021024, 0x10400007, +0xac209004, 0x3c020080, 0x2021024, 0x10400007, 0x121940, 0x3c020001, 0x3c010002, 0x230821, -0xac22908c, 0x10000006, 0x24040001, 0x121140, -0x3c010002, 0x220821, 0xac20908c, 0x24040001, -0x2821, 0x27b0001e, 0xc0044cc, 0x2003021, -0x24040001, 0x2821, 0xc0044cc, 0x2003021, -0x24040001, 0x24050001, 0x27b0001c, 0xc0044cc, -0x2003021, 0x24040001, 0x24050001, 0xc0044cc, +0xac22900c, 0x10000006, 0x24040001, 0x121140, +0x3c010002, 0x220821, 0xac20900c, 0x24040001, +0x2821, 0x27b0001e, 0xc00457c, 0x2003021, +0x24040001, 0x2821, 0xc00457c, 0x2003021, +0x24040001, 0x24050001, 0x27b0001c, 0xc00457c, +0x2003021, 0x24040001, 0x24050001, 0xc00457c, 0x2003021, 0x10000077, 0x0, 0x3c02ffec, 0x3442ffff, 0x2028024, 0x3c020008, 0x2028025, -0x121140, 0x3c010002, 0x220821, 0xac309078, +0x121140, 0x3c010002, 0x220821, 0xac308ff8, 0x3c022000, 0x2021024, 0x10400009, 0x0, -0x3c020001, 0x8c426ec4, 0x14400005, 0x24020001, -0x3c010001, 0xac226f98, 0x10000004, 0x3c024000, -0x3c010001, 0xac206f98, 0x3c024000, 0x2021024, -0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f98, -0xaf820238, 0x3c010001, 0xac206e30, 0x10600005, -0x24022020, 0x3c010001, 0xac226f9c, 0x24020001, +0x3c020001, 0x8c426e44, 0x14400005, 0x24020001, +0x3c010001, 0xac226f1c, 0x10000004, 0x3c024000, +0x3c010001, 0xac206f1c, 0x3c024000, 0x2021024, +0x1440001d, 0x24020e01, 0x3c030001, 0x8c636f1c, +0xaf820238, 0x3c010001, 0xac206db0, 0x10600005, +0x24022020, 0x3c010001, 0xac226f20, 0x24020001, 0xaee204b8, 0x3c04bfff, 0x121940, 0x3c020002, -0x431021, 0x8c429070, 0x3c050001, 0x8ca56e18, +0x431021, 0x8c428ff0, 0x3c050001, 0x8ca56d98, 0x3484ffff, 0x441024, 0x3c010002, 0x230821, -0xac229070, 0x24020001, 0x10a20044, 0x0, -0x10000040, 0x0, 0x3c020001, 0x8c426f98, -0x1040001c, 0x24022000, 0x3c010001, 0xac226f9c, +0xac228ff0, 0x24020001, 0x10a20044, 0x0, +0x10000040, 0x0, 0x3c020001, 0x8c426f1c, +0x1040001c, 0x24022000, 0x3c010001, 0xac226f20, 0x3c0300a0, 0x2031024, 0x14430005, 0x121140, -0x3402a000, 0x3c010001, 0x1000002d, 0xac226f9c, -0x3c030002, 0x621821, 0x8c639078, 0x3c020020, +0x3402a000, 0x3c010001, 0x1000002d, 0xac226f20, +0x3c030002, 0x621821, 0x8c638ff8, 0x3c020020, 0x621024, 0x10400004, 0x24022001, 0x3c010001, -0x10000023, 0xac226f9c, 0x3c020080, 0x621024, +0x10000023, 0xac226f20, 0x3c020080, 0x621024, 0x1040001f, 0x3402a001, 0x3c010001, 0x1000001c, -0xac226f9c, 0x3c020020, 0x2021024, 0x10400007, +0xac226f20, 0x3c020020, 0x2021024, 0x10400007, 0x121940, 0x24020100, 0x3c010002, 0x230821, -0xac229084, 0x10000006, 0x3c020080, 0x121140, -0x3c010002, 0x220821, 0xac209084, 0x3c020080, +0xac229004, 0x10000006, 0x3c020080, 0x121140, +0x3c010002, 0x220821, 0xac209004, 0x3c020080, 0x2021024, 0x10400006, 0x121940, 0x3c020001, -0x3c010002, 0x230821, 0x10000005, 0xac22908c, -0x121140, 0x3c010002, 0x220821, 0xac20908c, -0x3c030001, 0x8c636e18, 0x24020001, 0x10620003, -0x0, 0xc003d87, 0x0, 0x8fbf0030, +0x3c010002, 0x230821, 0x10000005, 0xac22900c, +0x121140, 0x3c010002, 0x220821, 0xac20900c, +0x3c030001, 0x8c636d98, 0x24020001, 0x10620003, +0x0, 0xc003daf, 0x0, 0x8fbf0030, 0x8fb3002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, -0x3e00008, 0x27bd0038, 0x27bdffb8, 0xafbe003c, -0x80f021, 0xafb30034, 0x9821, 0xafb20030, -0x9021, 0xafb1002c, 0x8821, 0x24020002, -0xafbf0040, 0xafb50038, 0xafb00028, 0xa7a00020, -0xa7a00018, 0xa7a0001a, 0xa7a0001c, 0xa7a0001e, -0x10a20142, 0xa7a00022, 0x2ca20003, 0x10400005, -0x24020001, 0x10a2000a, 0x1ea940, 0x10000253, -0x2201021, 0x24020004, 0x10a20203, 0x24020008, -0x10a20202, 0x1e2940, 0x1000024c, 0x2201021, -0x3c030002, 0x751821, 0x8c63907c, 0x3c024000, -0x621024, 0x14400009, 0x24040001, 0x3c027fff, -0x3442ffff, 0x628824, 0x3c010002, 0x350821, -0xac319074, 0x1000023d, 0x2201021, 0x2821, -0xc0044cc, 0x27a60018, 0x24040001, 0x2821, -0xc0044cc, 0x27a60018, 0x24040001, 0x24050001, -0x27b0001a, 0xc0044cc, 0x2003021, 0x24040001, -0x24050001, 0xc0044cc, 0x2003021, 0x24040001, -0x24050004, 0x27b0001c, 0xc0044cc, 0x2003021, -0x24040001, 0x24050004, 0xc0044cc, 0x2003021, -0x24040001, 0x24050005, 0x27b0001e, 0xc0044cc, -0x2003021, 0x24040001, 0x24050005, 0xc0044cc, -0x2003021, 0x24040001, 0x24050009, 0xc0044cc, -0x2003021, 0x24040001, 0x24050009, 0xc0044cc, -0x2003021, 0x24040001, 0x24050001, 0xc0044cc, -0x27a60018, 0x24040001, 0x24050001, 0xc0044cc, -0x27a60018, 0x97a20018, 0x30420004, 0x104000ba, -0x3c114000, 0x3c020001, 0x8c426fb8, 0x2443ffff, -0x2c620006, 0x104000ba, 0x31080, 0x3c010001, -0x220821, 0x8c226ce8, 0x400008, 0x0, -0x24040001, 0x24050011, 0x27b00020, 0xc0044cc, -0x2003021, 0x24040001, 0x24050011, 0xc0044cc, -0x2003021, 0x97a30020, 0x30624000, 0x10400002, -0x3c120010, 0x3c120008, 0x3c130001, 0x30628000, -0x54400098, 0x3c130002, 0x10000097, 0x3c028000, -0x24040001, 0x24050014, 0x27b00020, 0xc0044cc, -0x2003021, 0x24040001, 0x24050014, 0xc0044cc, -0x2003021, 0x97a30020, 0x30621000, 0x10400002, -0x3c120010, 0x3c120008, 0x3c130001, 0x1000ffec, -0x30620800, 0x24040001, 0x24050019, 0x27b00022, -0xc0044cc, 0x2003021, 0x24040001, 0x24050019, -0xc0044cc, 0x2003021, 0x97a20022, 0x30430700, -0x24020400, 0x10620027, 0x28620401, 0x1040000e, -0x24020200, 0x1062001f, 0x28620201, 0x10400005, -0x24020100, 0x5062001e, 0x3c130001, 0x1000001e, -0x24040001, 0x24020300, 0x50620019, 0x3c130002, -0x10000019, 0x24040001, 0x24020600, 0x1062000d, -0x28620601, 0x10400005, 0x24020500, 0x5062000b, -0x3c130002, 0x10000010, 0x24040001, 0x24020700, -0x1462000d, 0x24040001, 0x3c130004, 0x1000000a, -0x3c120008, 0x10000006, 0x3c130004, 0x10000005, -0x3c120008, 0x3c130001, 0x10000002, 0x3c120008, -0x3c120010, 0x24040001, 0x24050010, 0x27b0001c, -0xc0044cc, 0x2003021, 0x24040001, 0x24050010, -0xc0044cc, 0x2003021, 0x3c020004, 0x16620010, -0x3c020001, 0x8f840054, 0x24030001, 0x24020002, -0x3c010001, 0xac236e1c, 0x3c010001, 0xac226e18, -0x3c010001, 0xac236e24, 0x3c010001, 0xac236ea4, -0x3c010001, 0xac246fa8, 0x10000041, 0x2538825, -0x16620035, 0x3c028000, 0x3c020001, 0x8c426ea0, -0x1440001e, 0x24040018, 0x2021, 0x2821, -0xc004e0e, 0x34068000, 0x8f830054, 0x8f820054, -0x2538825, 0x10000002, 0x24630032, 0x8f820054, -0x621023, 0x2c420033, 0x1440fffc, 0x0, -0x8f830054, 0x24020001, 0x3c010001, 0xac226ea0, -0x3c010001, 0xac226e1c, 0x3c010001, 0xac226e18, -0x3c010001, 0xac226e24, 0x3c010001, 0xac226ea4, -0x3c010001, 0x1000001e, 0xac236fa8, 0x2821, -0xc004e0e, 0x24060404, 0x2021, 0x2405001e, -0x27a60018, 0x24020002, 0xc00450e, 0xa7a20018, -0x2021, 0x2821, 0x27a60018, 0xc00450e, -0xa7a00018, 0x24040018, 0x24050002, 0xc004e0e, -0x24060004, 0x3c028000, 0x2221025, 0x2721825, -0x10000007, 0x438825, 0x3c110002, 0x2358821, -0x8e31907c, 0x3c027fff, 0x3442ffff, 0x2228824, -0x3c020001, 0x8c426e28, 0x1040001c, 0x0, -0x3c020001, 0x8c426f98, 0x10400002, 0x3c022000, -0x2228825, 0x1e1140, 0x3c010002, 0x220821, -0x8c229080, 0x10400003, 0x3c020020, 0x10000004, +0x3e00008, 0x27bd0038, 0x27bdffb0, 0xafb3003c, +0x9821, 0xafb50040, 0xa821, 0xafb10034, +0x8821, 0x24020002, 0xafbf0048, 0xafbe0044, +0xafb20038, 0xafb00030, 0xafa4002c, 0xa7a0001a, +0xa7a00018, 0xa7a00020, 0xa7a0001e, 0xa7a00022, +0x10a20130, 0xa7a0001c, 0x2ca20003, 0x10400005, +0x24020001, 0x10a2000a, 0x3c024000, 0x1000025d, +0x2201021, 0x24020004, 0x10a2020a, 0x24020008, +0x10a20208, 0x2201021, 0x10000256, 0x0, +0x8fa8002c, 0x88140, 0x3c030002, 0x701821, +0x8c638ffc, 0x621024, 0x14400009, 0x24040001, +0x3c027fff, 0x3442ffff, 0x628824, 0x3c010002, +0x300821, 0xac318ff4, 0x10000246, 0x2201021, +0x24050001, 0xc00457c, 0x27a60018, 0x24040001, +0x24050001, 0xc00457c, 0x27a60018, 0x97a20018, +0x30420004, 0x104000d9, 0x3c114000, 0x3c020001, +0x8c426f40, 0x2443ffff, 0x2c620006, 0x104000d9, +0x31080, 0x3c010001, 0x220821, 0x8c226c68, +0x400008, 0x0, 0x24040001, 0x24050011, +0x27b0001a, 0xc00457c, 0x2003021, 0x24040001, +0x24050011, 0xc00457c, 0x2003021, 0x97a3001a, +0x30624000, 0x10400002, 0x3c150010, 0x3c150008, +0x30628000, 0x104000aa, 0x3c130001, 0x100000a8, +0x3c130002, 0x24040001, 0x24050014, 0x27b0001a, +0xc00457c, 0x2003021, 0x24040001, 0x24050014, +0xc00457c, 0x2003021, 0x97a3001a, 0x30621000, +0x10400002, 0x3c150010, 0x3c150008, 0x30620800, +0x10400097, 0x3c130001, 0x10000095, 0x3c130002, +0x24040001, 0x24050019, 0x27b0001c, 0xc00457c, +0x2003021, 0x24040001, 0x24050019, 0xc00457c, +0x2003021, 0x97a2001c, 0x30430700, 0x24020400, +0x10620027, 0x28620401, 0x1040000e, 0x24020200, +0x1062001f, 0x28620201, 0x10400005, 0x24020100, +0x5062001e, 0x3c130001, 0x1000001e, 0x24040001, +0x24020300, 0x50620019, 0x3c130002, 0x10000019, +0x24040001, 0x24020600, 0x1062000d, 0x28620601, +0x10400005, 0x24020500, 0x5062000b, 0x3c130002, +0x10000010, 0x24040001, 0x24020700, 0x1462000d, +0x24040001, 0x3c130004, 0x1000000a, 0x3c150008, +0x10000006, 0x3c130004, 0x10000005, 0x3c150008, +0x3c130001, 0x10000002, 0x3c150008, 0x3c150010, +0x24040001, 0x24050018, 0x27b0001e, 0xc00457c, +0x2003021, 0x24040001, 0x24050018, 0xc00457c, +0x2003021, 0x8fa8002c, 0x97a7001e, 0x81140, +0x3c060002, 0xc23021, 0x8cc68ff4, 0x97a20022, +0x3c100001, 0x26106c5c, 0x2002021, 0xafa20010, +0x97a2001c, 0x3c05000c, 0x34a50303, 0xc002b3b, +0xafa20014, 0x3c020004, 0x16620010, 0x3c020001, +0x8f840054, 0x24030001, 0x24020002, 0x3c010001, +0xac236d9c, 0x3c010001, 0xac226d98, 0x3c010001, +0xac236da4, 0x3c010001, 0xac236e24, 0x3c010001, +0xac246f30, 0x1000004f, 0x2b38825, 0x16620039, +0x3c028000, 0x3c020001, 0x8c426e20, 0x1440001e, +0x24040018, 0x2021, 0x2821, 0xc004ddb, +0x34068000, 0x8f830054, 0x8f820054, 0x2b38825, +0x10000002, 0x24630032, 0x8f820054, 0x621023, +0x2c420033, 0x1440fffc, 0x0, 0x8f830054, +0x24020001, 0x3c010001, 0xac226e20, 0x3c010001, +0xac226d9c, 0x3c010001, 0xac226d98, 0x3c010001, +0xac226da4, 0x3c010001, 0xac226e24, 0x3c010001, +0x1000002c, 0xac236f30, 0x2821, 0xc004ddb, +0x24060404, 0x2021, 0x2405001e, 0x27a60018, +0x24020002, 0xc0045be, 0xa7a20018, 0x2021, +0x2821, 0x27a60018, 0xc0045be, 0xa7a00018, +0x24040018, 0x24050002, 0xc004ddb, 0x24060004, +0x3c028000, 0x2221025, 0x2b31825, 0x10000015, +0x438825, 0x2221025, 0x2751825, 0x438825, +0x2002021, 0x97a6001c, 0x3c070001, 0x8ce76d98, +0x3c05000c, 0x34a50326, 0xafb30010, 0xc002b3b, +0xafb10014, 0x10000007, 0x0, 0x3c110002, +0x2308821, 0x8e318ffc, 0x3c027fff, 0x3442ffff, +0x2228824, 0x3c020001, 0x8c426da8, 0x1040001e, +0x0, 0x3c020001, 0x8c426f1c, 0x10400002, +0x3c022000, 0x2228825, 0x8fa8002c, 0x81140, +0x3c010002, 0x220821, 0x8c229000, 0x10400003, +0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf, +0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140, +0x3c010002, 0x220821, 0x8c229008, 0x10400003, +0x3c020080, 0x10000004, 0x2228825, 0x3c02ff7f, +0x3442ffff, 0x2228824, 0x8fa8002c, 0x81140, +0x3c010002, 0x220821, 0xac318ff4, 0x10000135, +0x2201021, 0x8fa8002c, 0x8f140, 0x3c030002, +0x7e1821, 0x8c638ff8, 0x3c024000, 0x621024, +0x14400009, 0x24040001, 0x3c027fff, 0x3442ffff, +0x628824, 0x3c010002, 0x3e0821, 0xac318ff0, +0x10000124, 0x2201021, 0x2821, 0xc00457c, +0x27a60018, 0x24040001, 0x2821, 0xc00457c, +0x27a60018, 0x24040001, 0x24050001, 0x27b20020, +0xc00457c, 0x2403021, 0x24040001, 0x24050001, +0xc00457c, 0x2403021, 0x24040001, 0x24050004, +0x27b1001e, 0xc00457c, 0x2203021, 0x24040001, +0x24050004, 0xc00457c, 0x2203021, 0x24040001, +0x24050005, 0x27b00022, 0xc00457c, 0x2003021, +0x24040001, 0x24050005, 0xc00457c, 0x2003021, +0x24040001, 0x24050010, 0xc00457c, 0x27a60018, +0x24040001, 0x24050010, 0xc00457c, 0x27a60018, +0x24040001, 0x2405000a, 0xc00457c, 0x2403021, +0x24040001, 0x2405000a, 0xc00457c, 0x2403021, +0x24040001, 0x24050018, 0xc00457c, 0x2203021, +0x24040001, 0x24050018, 0xc00457c, 0x2203021, +0x24040001, 0x24050001, 0xc00457c, 0x27a60018, +0x24040001, 0x24050001, 0xc00457c, 0x27a60018, +0x97a20018, 0x30420004, 0x10400066, 0x3c114000, +0x3c030001, 0x8c636f34, 0x24020005, 0x14620067, +0x24040001, 0x24050019, 0x27b0001c, 0xc00457c, +0x2003021, 0x24040001, 0x24050019, 0xc00457c, +0x2003021, 0x97a2001c, 0x30430700, 0x24020400, +0x10620027, 0x28620401, 0x1040000e, 0x24020200, +0x1062001f, 0x28620201, 0x10400005, 0x24020100, +0x5062001e, 0x3c130001, 0x1000001e, 0x3c020004, +0x24020300, 0x50620019, 0x3c130002, 0x10000019, +0x3c020004, 0x24020600, 0x1062000d, 0x28620601, +0x10400005, 0x24020500, 0x5062000b, 0x3c130002, +0x10000010, 0x3c020004, 0x24020700, 0x1462000d, +0x3c020004, 0x3c130004, 0x1000000a, 0x3c150008, +0x10000006, 0x3c130004, 0x10000005, 0x3c150008, +0x3c130001, 0x10000002, 0x3c150008, 0x3c150010, +0x3c020004, 0x12620017, 0x3c028000, 0x8f820054, +0x24100001, 0x3c010001, 0xac306d9c, 0x3c010001, +0xac306d98, 0x3c010001, 0xac306da4, 0x3c010001, +0xac306e24, 0x3c010001, 0xac226f30, 0x3c020001, +0x16620022, 0x2758825, 0x2021, 0x2821, +0xc004ddb, 0x34068000, 0x3c010001, 0x1000001b, +0xac306e20, 0x2221025, 0x2b31825, 0x438825, +0x97a6001c, 0x3c020001, 0x8c426f1c, 0x3c070001, +0x8ce76d98, 0x3c040001, 0x24846c5c, 0xafa20010, +0x97a2001e, 0x3c05000c, 0x34a50323, 0x3c010001, +0xac206e20, 0xc002b3b, 0xafa20014, 0x10000007, +0x0, 0x3c110002, 0x23e8821, 0x8e318ff0, +0x3c027fff, 0x3442ffff, 0x2228824, 0x3c020001, +0x8c426da8, 0x10400069, 0x0, 0x3c020001, +0x8c426f1c, 0x10400002, 0x3c022000, 0x2228825, +0x8fa8002c, 0x81140, 0x3c010002, 0x220821, +0x8c229004, 0x10400003, 0x3c020020, 0x10000005, 0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, -0x1e1140, 0x3c010002, 0x220821, 0x8c229088, -0x10400003, 0x3c020080, 0x10000004, 0x2228825, -0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c040001, -0x24846cdc, 0x3c05000c, 0x97a60022, 0x3c070001, -0x8ce76e18, 0x34a50326, 0x1e1140, 0x3c010002, -0x220821, 0xac319074, 0xafb30010, 0xc002b17, -0xafb10014, 0x10000119, 0x2201021, 0x1ea940, -0x3c030002, 0x751821, 0x8c639078, 0x3c024000, -0x621024, 0x14400009, 0x24040001, 0x3c027fff, -0x3442ffff, 0x628824, 0x3c010002, 0x350821, -0xac319070, 0x10000109, 0x2201021, 0x2821, -0xc0044cc, 0x27a60018, 0x24040001, 0x2821, -0xc0044cc, 0x27a60018, 0x24040001, 0x24050001, -0x27b1001a, 0xc0044cc, 0x2203021, 0x24040001, -0x24050001, 0xc0044cc, 0x2203021, 0x24040001, -0x24050004, 0x27b0001c, 0xc0044cc, 0x2003021, -0x24040001, 0x24050004, 0xc0044cc, 0x2003021, -0x24040001, 0x24050005, 0x27b0001e, 0xc0044cc, -0x2003021, 0x24040001, 0x24050005, 0xc0044cc, -0x2003021, 0x24040001, 0x24050010, 0xc0044cc, -0x27a60018, 0x24040001, 0x24050010, 0xc0044cc, -0x27a60018, 0x24040001, 0x2405000a, 0xc0044cc, -0x2203021, 0x24040001, 0x2405000a, 0xc0044cc, -0x2203021, 0x24040001, 0x24050001, 0xc0044cc, -0x27a60018, 0x24040001, 0x24050001, 0xc0044cc, -0x27a60018, 0x97a20018, 0x30420004, 0x10400058, -0x3c114000, 0x3c030001, 0x8c636fac, 0x24020005, -0x14620059, 0x24040001, 0x24050019, 0x27b00022, -0xc0044cc, 0x2003021, 0x24040001, 0x24050019, -0xc0044cc, 0x2003021, 0x97a20022, 0x30430700, -0x24020400, 0x10620027, 0x28620401, 0x1040000e, -0x24020200, 0x1062001f, 0x28620201, 0x10400005, -0x24020100, 0x5062001e, 0x3c130001, 0x1000001e, -0x3c020004, 0x24020300, 0x50620019, 0x3c130002, -0x10000019, 0x3c020004, 0x24020600, 0x1062000d, -0x28620601, 0x10400005, 0x24020500, 0x5062000b, -0x3c130002, 0x10000010, 0x3c020004, 0x24020700, -0x1462000d, 0x3c020004, 0x3c130004, 0x1000000a, -0x3c120008, 0x10000006, 0x3c130004, 0x10000005, -0x3c120008, 0x3c130001, 0x10000002, 0x3c120008, -0x3c120010, 0x3c020004, 0x12620017, 0x3c028000, -0x8f820054, 0x24100001, 0x3c010001, 0xac306e1c, -0x3c010001, 0xac306e18, 0x3c010001, 0xac306e24, -0x3c010001, 0xac306ea4, 0x3c010001, 0xac226fa8, -0x3c020001, 0x16620014, 0x2728825, 0x2021, -0x2821, 0xc004e0e, 0x34068000, 0x3c010001, -0x1000000d, 0xac306ea0, 0x2221025, 0x2531825, -0x3c010001, 0xac206ea0, 0x10000007, 0x438825, -0x3c110002, 0x2358821, 0x8e319070, 0x3c027fff, -0x3442ffff, 0x2228824, 0x3c020001, 0x8c426e28, -0x10400066, 0x1e1140, 0x3c020001, 0x8c426f98, -0x10400002, 0x3c022000, 0x2228825, 0x1e1140, -0x3c010002, 0x220821, 0x8c229084, 0x10400003, -0x3c020020, 0x10000004, 0x2228825, 0x3c02ffdf, -0x3442ffff, 0x2228824, 0x1e1140, 0x3c010002, -0x220821, 0x8c22908c, 0x10400003, 0x3c020080, -0x1000004d, 0x2228825, 0x3c02ff7f, 0x3442ffff, -0x10000049, 0x2228824, 0x1e2940, 0x3c030002, -0x651821, 0x8c639078, 0x3c024000, 0x621024, +0x8fa8002c, 0x81140, 0x3c010002, 0x220821, +0x8c22900c, 0x10400003, 0x3c020080, 0x1000004f, +0x2228825, 0x3c02ff7f, 0x3442ffff, 0x1000004b, +0x2228824, 0x8fa8002c, 0x82940, 0x3c030002, +0x651821, 0x8c638ff8, 0x3c024000, 0x621024, 0x14400008, 0x3c027fff, 0x3442ffff, 0x628824, -0x3c010002, 0x250821, 0xac319070, 0x1000003f, -0x2201021, 0x3c020001, 0x8c426e28, 0x10400033, -0x3c11c00c, 0x3c020001, 0x8c426ec4, 0x3c04c00c, -0x34842000, 0x3c030001, 0x8c636f98, 0x2102b, +0x3c010002, 0x250821, 0xac318ff0, 0x10000041, +0x2201021, 0x3c020001, 0x8c426da8, 0x10400034, +0x3c11c00c, 0x3c020001, 0x8c426e44, 0x3c04c00c, +0x34842000, 0x3c030001, 0x8c636f1c, 0x2102b, 0x21023, 0x441024, 0x10600003, 0x518825, 0x3c022000, 0x2228825, 0x3c020002, 0x451021, -0x8c429084, 0x10400003, 0x3c020020, 0x10000004, +0x8c429004, 0x10400003, 0x3c020020, 0x10000004, 0x2228825, 0x3c02ffdf, 0x3442ffff, 0x2228824, -0x1e1140, 0x3c010002, 0x220821, 0x8c22908c, -0x10400003, 0x3c020080, 0x10000004, 0x2228825, -0x3c02ff7f, 0x3442ffff, 0x2228824, 0x3c020001, -0x8c426eb0, 0x10400002, 0x3c020800, 0x2228825, -0x3c020001, 0x8c426eb4, 0x10400002, 0x3c020400, -0x2228825, 0x3c020001, 0x8c426eb8, 0x10400006, -0x3c020100, 0x10000004, 0x2228825, 0x3c027fff, -0x3442ffff, 0x628824, 0x1e1140, 0x3c010002, -0x220821, 0xac319070, 0x2201021, 0x8fbf0040, -0x8fbe003c, 0x8fb50038, 0x8fb30034, 0x8fb20030, -0x8fb1002c, 0x8fb00028, 0x3e00008, 0x27bd0048, -0x27bdffd0, 0xafb20028, 0x809021, 0xafbf002c, -0xafb10024, 0xafb00020, 0x8f840200, 0x3c100001, -0x8e106e18, 0x8f860220, 0x24020002, 0x1202005c, -0x2e020003, 0x10400005, 0x24020001, 0x1202000a, -0x121940, 0x1000010c, 0x0, 0x24020004, -0x120200bf, 0x24020008, 0x120200be, 0x128940, -0x10000105, 0x0, 0x3c050002, 0xa32821, -0x8ca5907c, 0x3c100002, 0x2038021, 0x8e109074, -0x3c024000, 0xa21024, 0x10400038, 0x3c020008, -0x2021024, 0x10400020, 0x34840002, 0x3c020002, -0x431021, 0x8c429080, 0x10400005, 0x34840020, -0x34840100, 0x3c020020, 0x10000006, 0x2028025, -0x2402feff, 0x822024, 0x3c02ffdf, 0x3442ffff, -0x2028024, 0x121140, 0x3c010002, 0x220821, -0x8c229088, 0x10400005, 0x3c020001, 0xc23025, -0x3c020080, 0x10000016, 0x2028025, 0x3c02fffe, -0x3442ffff, 0xc23024, 0x3c02ff7f, 0x3442ffff, -0x1000000f, 0x2028024, 0x2402fedf, 0x822024, -0x3c02fffe, 0x3442ffff, 0xc23024, 0x3c02ff5f, -0x3442ffff, 0x2028024, 0x3c010002, 0x230821, -0xac209080, 0x3c010002, 0x230821, 0xac209088, -0xaf840200, 0xaf860220, 0x8f820220, 0x34420002, -0xaf820220, 0x1000000a, 0x121140, 0x3c02bfff, -0x3442ffff, 0x8f830200, 0x2028024, 0x2402fffd, -0x621824, 0xc003d87, 0xaf830200, 0x121140, -0x3c010002, 0x220821, 0x100000b7, 0xac309074, -0x3c020001, 0x8c426f98, 0x10400069, 0x24050004, -0x24040001, 0xc0044cc, 0x27a60018, 0x24040001, -0x24050005, 0xc0044cc, 0x27a6001a, 0x97a30018, -0x97a2001a, 0x3c040001, 0x24846ec8, 0x30630c00, -0x31a82, 0x30420c00, 0x21282, 0xa7a2001a, -0x21080, 0x441021, 0x431021, 0xa7a30018, -0x90480000, 0x24020001, 0x3103ffff, 0x10620029, -0x28620002, 0x10400005, 0x0, 0x10600009, -0x0, 0x1000003d, 0x0, 0x10700013, -0x24020003, 0x1062002c, 0x0, 0x10000037, -0x0, 0x8f820200, 0x2403feff, 0x431024, -0xaf820200, 0x8f820220, 0x3c03fffe, 0x3463ffff, -0x431024, 0xaf820220, 0x3c010002, 0xac209084, -0x3c010002, 0x10000032, 0xac20908c, 0x8f820200, -0x34420100, 0xaf820200, 0x8f820220, 0x3c03fffe, -0x3463ffff, 0x431024, 0xaf820220, 0x24020100, -0x3c010002, 0xac229084, 0x3c010002, 0x10000024, -0xac20908c, 0x8f820200, 0x2403feff, 0x431024, -0xaf820200, 0x8f820220, 0x3c030001, 0x431025, -0xaf820220, 0x3c010002, 0xac209084, 0x3c010002, -0x10000017, 0xac23908c, 0x8f820200, 0x34420100, -0xaf820200, 0x8f820220, 0x3c030001, 0x431025, -0xaf820220, 0x24020100, 0x3c010002, 0xac229084, -0x3c010002, 0x1000000a, 0xac23908c, 0x3c040001, -0x24846d00, 0x97a6001a, 0x97a70018, 0x3c050001, -0x34a5ffff, 0xafa80010, 0xc002b17, 0xafa00014, -0x8f820200, 0x34420002, 0x1000004b, 0xaf820200, -0x128940, 0x3c050002, 0xb12821, 0x8ca59078, -0x3c100002, 0x2118021, 0x8e109070, 0x3c024000, -0xa21024, 0x14400010, 0x0, 0x3c020001, -0x8c426f98, 0x14400005, 0x3c02bfff, 0x8f820200, -0x34420002, 0xaf820200, 0x3c02bfff, 0x3442ffff, -0xc003d87, 0x2028024, 0x3c010002, 0x310821, -0x10000031, 0xac309070, 0x3c020001, 0x8c426f98, -0x10400005, 0x3c020020, 0x3c020001, 0x8c426ec4, -0x10400025, 0x3c020020, 0xa21024, 0x10400007, -0x34840020, 0x24020100, 0x3c010002, 0x310821, -0xac229084, 0x10000006, 0x34840100, 0x3c010002, -0x310821, 0xac209084, 0x2402feff, 0x822024, -0x3c020080, 0xa21024, 0x10400007, 0x121940, -0x3c020001, 0x3c010002, 0x230821, 0xac22908c, -0x10000008, 0xc23025, 0x121140, 0x3c010002, -0x220821, 0xac20908c, 0x3c02fffe, 0x3442ffff, -0xc23024, 0xaf840200, 0xaf860220, 0x8f820220, -0x34420002, 0xaf820220, 0x121140, 0x3c010002, -0x220821, 0xac309070, 0x8fbf002c, 0x8fb20028, -0x8fb10024, 0x8fb00020, 0x3e00008, 0x27bd0030, -0x0, 0x0, 0x0, 0x1821, +0x8fa8002c, 0x81140, 0x3c010002, 0x220821, +0x8c22900c, 0x10400003, 0x3c020080, 0x10000004, +0x2228825, 0x3c02ff7f, 0x3442ffff, 0x2228824, +0x3c020001, 0x8c426e30, 0x10400002, 0x3c020800, +0x2228825, 0x3c020001, 0x8c426e34, 0x10400002, +0x3c020400, 0x2228825, 0x3c020001, 0x8c426e38, +0x10400006, 0x3c020100, 0x10000004, 0x2228825, +0x3c027fff, 0x3442ffff, 0x628824, 0x8fa8002c, +0x81140, 0x3c010002, 0x220821, 0xac318ff0, +0x2201021, 0x8fbf0048, 0x8fbe0044, 0x8fb50040, +0x8fb3003c, 0x8fb20038, 0x8fb10034, 0x8fb00030, +0x3e00008, 0x27bd0050, 0x27bdffd0, 0xafb20028, +0x809021, 0xafbf002c, 0xafb10024, 0xafb00020, +0x8f840200, 0x3c100001, 0x8e106d98, 0x8f860220, +0x24020002, 0x1202005c, 0x2e020003, 0x10400005, +0x24020001, 0x1202000a, 0x121940, 0x1000010c, +0x0, 0x24020004, 0x120200bf, 0x24020008, +0x120200be, 0x128940, 0x10000105, 0x0, +0x3c050002, 0xa32821, 0x8ca58ffc, 0x3c100002, +0x2038021, 0x8e108ff4, 0x3c024000, 0xa21024, +0x10400038, 0x3c020008, 0x2021024, 0x10400020, +0x34840002, 0x3c020002, 0x431021, 0x8c429000, +0x10400005, 0x34840020, 0x34840100, 0x3c020020, +0x10000006, 0x2028025, 0x2402feff, 0x822024, +0x3c02ffdf, 0x3442ffff, 0x2028024, 0x121140, +0x3c010002, 0x220821, 0x8c229008, 0x10400005, +0x3c020001, 0xc23025, 0x3c020080, 0x10000016, +0x2028025, 0x3c02fffe, 0x3442ffff, 0xc23024, +0x3c02ff7f, 0x3442ffff, 0x1000000f, 0x2028024, +0x2402fedf, 0x822024, 0x3c02fffe, 0x3442ffff, +0xc23024, 0x3c02ff5f, 0x3442ffff, 0x2028024, +0x3c010002, 0x230821, 0xac209000, 0x3c010002, +0x230821, 0xac209008, 0xaf840200, 0xaf860220, +0x8f820220, 0x34420002, 0xaf820220, 0x1000000a, +0x121140, 0x3c02bfff, 0x3442ffff, 0x8f830200, +0x2028024, 0x2402fffd, 0x621824, 0xc003daf, +0xaf830200, 0x121140, 0x3c010002, 0x220821, +0x100000b7, 0xac308ff4, 0x3c020001, 0x8c426f1c, +0x10400069, 0x24050004, 0x24040001, 0xc00457c, +0x27a60018, 0x24040001, 0x24050005, 0xc00457c, +0x27a6001a, 0x97a30018, 0x97a2001a, 0x3c040001, +0x24846e48, 0x30630c00, 0x31a82, 0x30420c00, +0x21282, 0xa7a2001a, 0x21080, 0x441021, +0x431021, 0xa7a30018, 0x90480000, 0x24020001, +0x3103ffff, 0x10620029, 0x28620002, 0x10400005, +0x0, 0x10600009, 0x0, 0x1000003d, +0x0, 0x10700013, 0x24020003, 0x1062002c, +0x0, 0x10000037, 0x0, 0x8f820200, +0x2403feff, 0x431024, 0xaf820200, 0x8f820220, +0x3c03fffe, 0x3463ffff, 0x431024, 0xaf820220, +0x3c010002, 0xac209004, 0x3c010002, 0x10000032, +0xac20900c, 0x8f820200, 0x34420100, 0xaf820200, +0x8f820220, 0x3c03fffe, 0x3463ffff, 0x431024, +0xaf820220, 0x24020100, 0x3c010002, 0xac229004, +0x3c010002, 0x10000024, 0xac20900c, 0x8f820200, +0x2403feff, 0x431024, 0xaf820200, 0x8f820220, +0x3c030001, 0x431025, 0xaf820220, 0x3c010002, +0xac209004, 0x3c010002, 0x10000017, 0xac23900c, +0x8f820200, 0x34420100, 0xaf820200, 0x8f820220, +0x3c030001, 0x431025, 0xaf820220, 0x24020100, +0x3c010002, 0xac229004, 0x3c010002, 0x1000000a, +0xac23900c, 0x3c040001, 0x24846c80, 0x97a6001a, +0x97a70018, 0x3c050001, 0x34a5ffff, 0xafa80010, +0xc002b3b, 0xafa00014, 0x8f820200, 0x34420002, +0x1000004b, 0xaf820200, 0x128940, 0x3c050002, +0xb12821, 0x8ca58ff8, 0x3c100002, 0x2118021, +0x8e108ff0, 0x3c024000, 0xa21024, 0x14400010, +0x0, 0x3c020001, 0x8c426f1c, 0x14400005, +0x3c02bfff, 0x8f820200, 0x34420002, 0xaf820200, +0x3c02bfff, 0x3442ffff, 0xc003daf, 0x2028024, +0x3c010002, 0x310821, 0x10000031, 0xac308ff0, +0x3c020001, 0x8c426f1c, 0x10400005, 0x3c020020, +0x3c020001, 0x8c426e44, 0x10400025, 0x3c020020, +0xa21024, 0x10400007, 0x34840020, 0x24020100, +0x3c010002, 0x310821, 0xac229004, 0x10000006, +0x34840100, 0x3c010002, 0x310821, 0xac209004, +0x2402feff, 0x822024, 0x3c020080, 0xa21024, +0x10400007, 0x121940, 0x3c020001, 0x3c010002, +0x230821, 0xac22900c, 0x10000008, 0xc23025, +0x121140, 0x3c010002, 0x220821, 0xac20900c, +0x3c02fffe, 0x3442ffff, 0xc23024, 0xaf840200, +0xaf860220, 0x8f820220, 0x34420002, 0xaf820220, +0x121140, 0x3c010002, 0x220821, 0xac308ff0, +0x8fbf002c, 0x8fb20028, 0x8fb10024, 0x8fb00020, +0x3e00008, 0x27bd0030, 0x0, 0x1821, 0x308400ff, 0x2405ffdf, 0x2406ffbf, 0x641007, 0x30420001, 0x10400004, 0x0, 0x8f820044, 0x10000003, 0x34420040, 0x8f820044, 0x461024, @@ -9131,7 +9117,7 @@ u32 tigon2FwText[(MAX_TEXT_LEN/4) + 1] __initdata = { 0x28620008, 0x5440ffee, 0x641007, 0x3e00008, 0x0, 0x2c820008, 0x1040001b, 0x0, 0x2405ffdf, 0x2406ffbf, 0x41880, 0x3c020001, -0x24426ee0, 0x621821, 0x24640004, 0x90620000, +0x24426e60, 0x621821, 0x24640004, 0x90620000, 0x10400004, 0x0, 0x8f820044, 0x10000003, 0x34420040, 0x8f820044, 0x461024, 0xaf820044, 0x8f820044, 0x34420020, 0xaf820044, 0x8f820044, @@ -9180,7 +9166,7 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x74460000, 0x4d516576, 0x505f4600, 0x5173436f, 0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 0x51725072, 0x6f644600, 0x6261644d, 0x656d537a, -0x0, 0x68774677, 0x56657200, 0x62616448, +0x0, 0x68775665, 0x72000000, 0x62616448, 0x77566572, 0x0, 0x2a2a4441, 0x574e5f41, 0x0, 0x74785278, 0x4266537a, 0x0, 0x62664174, 0x6e4d726b, 0x0, 0x7265645a, @@ -9276,12 +9262,12 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x0, 0x3f636d64, 0x48737453, 0x0, 0x3f636d64, 0x4d634d64, 0x0, 0x3f636d64, 0x50726f6d, 0x0, 0x3f636d64, 0x4c696e6b, -0x0, 0x3f636d64, 0x45727200, 0x864c, -0x8de0, 0x8de0, 0x8d68, 0x8b0c, -0x8db4, 0x8de0, 0x8724, 0x8794, -0x8924, 0x89fc, 0x89c8, 0x8de0, -0x8804, 0x8ab8, 0x8de0, 0x8ac8, -0x8748, 0x87b8, 0x0, 0x0, +0x0, 0x3f636d64, 0x45727200, 0x86ac, +0x8e5c, 0x8e5c, 0x8de4, 0x8b78, +0x8e30, 0x8e5c, 0x8790, 0x8800, +0x8990, 0x8a68, 0x8a34, 0x8e5c, +0x8870, 0x8b24, 0x8e5c, 0x8b34, +0x87b4, 0x8824, 0x0, 0x0, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, @@ -9332,10 +9318,10 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x2e313220, 0x31393939, 0x2f30312f, 0x32302031, 0x393a3439, 0x3a353120, 0x73687561, 0x6e672045, 0x78702024, 0x0, 0x46575f56, 0x45525349, -0x4f4e3a20, 0x23312053, 0x61742044, 0x65632031, -0x31203136, 0x3a30353a, 0x30332050, 0x53542031, -0x39393900, 0x46575f43, 0x4f4d5049, 0x4c455f54, -0x494d453a, 0x2031363a, 0x30353a30, 0x33000000, +0x4f4e3a20, 0x23312046, 0x72692041, 0x70722037, +0x2031373a, 0x35373a35, 0x32205044, 0x54203230, +0x30300000, 0x46575f43, 0x4f4d5049, 0x4c455f54, +0x494d453a, 0x2031373a, 0x35373a35, 0x32000000, 0x46575f43, 0x4f4d5049, 0x4c455f42, 0x593a2064, 0x65767263, 0x73000000, 0x46575f43, 0x4f4d5049, 0x4c455f48, 0x4f53543a, 0x20636f6d, 0x70757465, @@ -9343,7 +9329,7 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x4f4d4149, 0x4e3a2065, 0x6e672e61, 0x6374656f, 0x6e2e636f, 0x6d000000, 0x46575f43, 0x4f4d5049, 0x4c45523a, 0x20676363, 0x20766572, 0x73696f6e, -0x20322e37, 0x2e320000, 0x0, 0x12040100, +0x20322e37, 0x2e320000, 0x0, 0x12041100, 0x0, 0x24486561, 0x6465723a, 0x202f7072, 0x6f6a6563, 0x74732f72, 0x63732f73, 0x772f6765, 0x2f2e2f6e, 0x69632f66, 0x77322f63, 0x6f6d6d6f, @@ -9411,31 +9397,32 @@ u32 tigon2FwRodata[(MAX_RODATA_LEN/4) + 1] __initdata = { 0x6e495f46, 0x0, 0x5173436f, 0x6e734600, 0x51725072, 0x6f644600, 0x0, 0x0, 0x0, 0x50726f62, 0x65506879, 0x0, -0x6c6e6b41, 0x53535254, 0x0, 0x108d0, -0x10948, 0x10968, 0x109a4, 0x10ea8, -0x109d0, 0x10a0c, 0x10f3c, 0x10c18, -0x10ac0, 0x10ad8, 0x10b1c, 0x10b44, -0x10b64, 0x10b8c, 0x10f3c, 0x10c18, -0x10c50, 0x10c68, 0x10c98, 0x10cc0, -0x10ce0, 0x10d08, 0x0, 0x10e34, -0x10e60, 0x10e84, 0x10f3c, 0x10ea8, -0x109d0, 0x10ed8, 0x0, 0x0, -0x0, 0x115ac, 0x1167c, 0x11754, -0x11824, 0x11880, 0x1195c, 0x11984, -0x11a60, 0x11a88, 0x11c30, 0x11c58, -0x11e00, 0x11ff8, 0x1228c, 0x121a0, -0x1228c, 0x122b8, 0x11e28, 0x11fd0, -0x7273745f, 0x676d6969, 0x0, 0x12348, -0x12380, 0x12468, 0x13034, 0x135fc, -0x13614, 0x13c7c, 0x13cbc, 0x13d4c, -0x13d90, 0x13df4, 0x13e80, 0x13eb4, -0x13f3c, 0x13fd4, 0x140a4, 0x140e4, -0x14168, 0x1418c, 0x1429c, 0x646f4261, +0x6c6e6b41, 0x53535254, 0x0, 0x109a4, +0x10a1c, 0x10a50, 0x10a7c, 0x11050, +0x10aa8, 0x10b10, 0x111fc, 0x10dc0, +0x10c68, 0x10c80, 0x10cc4, 0x10cec, +0x10d0c, 0x10d34, 0x111fc, 0x10dc0, +0x10df8, 0x10e10, 0x10e40, 0x10e68, +0x10e88, 0x10eb0, 0x0, 0x10fdc, +0x11008, 0x1102c, 0x111fc, 0x11050, +0x11078, 0x11108, 0x0, 0x0, +0x0, 0x1186c, 0x1193c, 0x11a14, +0x11ae4, 0x11b40, 0x11c1c, 0x11c44, +0x11d20, 0x11d48, 0x11ef0, 0x11f18, +0x120c0, 0x122b8, 0x1254c, 0x12460, +0x1254c, 0x12578, 0x120e8, 0x12290, +0x7273745f, 0x676d6969, 0x0, 0x12608, +0x12640, 0x12728, 0x13374, 0x133b4, +0x133cc, 0x7365746c, 0x6f6f7000, 0x0, +0x0, 0x13bbc, 0x13bfc, 0x13c8c, +0x13cd0, 0x13d34, 0x13dc0, 0x13df4, +0x13e7c, 0x13f14, 0x13fe4, 0x14024, +0x140a8, 0x140cc, 0x141dc, 0x646f4261, 0x73655067, 0x0, 0x0, 0x0, 0x0, 0x73746d61, 0x634c4e4b, 0x0, -0x6765746d, 0x636c6e6b, 0x0, 0x14fb4, -0x14fb4, 0x14ce4, 0x14d34, 0x14d78, -0x14fb4, 0x7365746d, 0x61636163, 0x74000000, +0x6765746d, 0x636c6e6b, 0x0, 0x14ed8, +0x14ed8, 0x14b8c, 0x14bd8, 0x14c24, +0x14ed8, 0x7365746d, 0x61636163, 0x74000000, 0x0, 0x0 }; u32 tigon2FwData[(MAX_DATA_LEN/4) + 1] __initdata = { 0x1, diff --git a/drivers/net/bsd_comp.c b/drivers/net/bsd_comp.c index 493c2f6c5..ff44715fd 100644 --- a/drivers/net/bsd_comp.c +++ b/drivers/net/bsd_comp.c @@ -1,3 +1,11 @@ +/* + * Update: The Berkeley copyright was changed, and the change + * is retroactive to all "true" BSD software (ie everything + * from UCB as opposed to other peoples code that just carried + * the same license). The new copyright doesn't clash with the + * GPL, so the module-only restriction has been removed.. + */ + /* Because this code is derived from the 4.3BSD compress source: * * Copyright (c) 1985, 1986 The Regents of the University of California. @@ -53,10 +61,6 @@ * From: bsd_comp.c,v 1.3 1994/12/08 01:59:58 paulus Exp */ -#ifndef MODULE -#error This file must be compiled as a module. -#endif - #include <linux/module.h> #include <linux/init.h> #include <linux/malloc.h> diff --git a/drivers/net/pcmcia/Config.in b/drivers/net/pcmcia/Config.in index b6035305c..2052c6eaf 100644 --- a/drivers/net/pcmcia/Config.in +++ b/drivers/net/pcmcia/Config.in @@ -15,7 +15,7 @@ if [ "$CONFIG_NET_PCMCIA" = "y" ]; then dep_tristate ' SMC 91Cxx PCMCIA support' CONFIG_PCMCIA_SMC91C92 $CONFIG_PCMCIA dep_tristate ' Xircom 16-bit PCMCIA support' CONFIG_PCMCIA_XIRC2PS $CONFIG_PCMCIA dep_tristate ' COM20020 ARCnet PCMCIA support' CONFIG_ARCNET_COM20020_CS $CONFIG_ARCNET_COM20020 $CONFIG_ARCNET $CONFIG_PCMCIA - dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA + dep_tristate ' IBM PCMCIA tokenring adapter support' CONFIG_PCMCIA_IBMTR $CONFIG_TR $CONFIG_PCMCIA if [ "$CONFIG_CARDBUS" = "y" ]; then tristate ' Xircom Tulip-like CardBus support' CONFIG_PCMCIA_XIRTULIP diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index 9db7132ec..9e772466c 100644 --- a/drivers/net/pppoe.c +++ b/drivers/net/pppoe.c @@ -39,7 +39,6 @@ #include <linux/ppp_defs.h> #include <linux/if_ppp.h> #include <linux/if_pppvar.h> -#include <linux/init.h> #include <linux/notifier.h> #include <linux/file.h> #include <linux/proc_fs.h> diff --git a/drivers/net/pppox.c b/drivers/net/pppox.c index 6bef505b4..941bf369e 100644 --- a/drivers/net/pppox.c +++ b/drivers/net/pppox.c @@ -17,6 +17,7 @@ * */ +#include <linux/config.h> #include <linux/string.h> #include <linux/module.h> diff --git a/drivers/net/skfp/fplustm.c b/drivers/net/skfp/fplustm.c index 83a935791..f5bda2464 100644 --- a/drivers/net/skfp/fplustm.c +++ b/drivers/net/skfp/fplustm.c @@ -390,9 +390,9 @@ struct s_smc *smc ; outpw(FM_A(FM_TREQ0),(unsigned)t_requ) ; } -void set_long(p,l) +void set_int(p,l) char *p; -long l; +int l; { p[0] = (char)(l >> 24) ; p[1] = (char)(l >> 16) ; @@ -416,12 +416,12 @@ unsigned off; /* start address within buffer memory */ int len ; /* lenght of the frame including the FC */ { int i ; - u_long *p ; + u_int *p ; CHECK_NPP() ; MARW(off) ; /* set memory address reg for writes */ - p = (u_long *) mac ; + p = (u_int *) mac ; for (i = (len + 3)/4 ; i ; i--) { if (i == 1) { /* last word, set the tag bit */ @@ -460,7 +460,7 @@ int len ; /* lenght of the frame including the FC */ static void directed_beacon(smc) struct s_smc *smc ; { - SK_LOC_DECL(u_long,a[2]) ; + SK_LOC_DECL(u_int,a[2]) ; /* * set UNA in frame @@ -491,7 +491,7 @@ static void build_claim_beacon(smc,t_request) struct s_smc *smc ; u_long t_request; { - u_long td ; + u_int td ; int len ; struct fddi_mac_sf *mac ; @@ -499,13 +499,13 @@ u_long t_request; * build claim packet */ len = 17 ; - td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ; + td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; mac = &smc->hw.fp.mac_sfb ; mac->mac_fc = FC_CLAIM ; /* DA == SA in claim frame */ mac->mac_source = mac->mac_dest = MA ; /* 2's complement */ - set_long((char *)mac->mac_info,(long)t_request) ; + set_int((char *)mac->mac_info,(int)t_request) ; copy_tx_mac(smc,td,(struct fddi_mac *)mac, smc->hw.fp.fifo.rbc_ram_start + CLAIM_FRAME_OFF,len) ; @@ -516,11 +516,11 @@ u_long t_request; * build beacon packet */ len = 17 ; - td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ; + td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; mac->mac_fc = FC_BEACON ; mac->mac_source = MA ; mac->mac_dest = null_addr ; /* DA == 0 in beacon frame */ - set_long((char *) mac->mac_info,((long)BEACON_INFO<<24L) + 0 ) ; + set_int((char *) mac->mac_info,((int)BEACON_INFO<<24) + 0 ) ; copy_tx_mac(smc,td,(struct fddi_mac *)mac, smc->hw.fp.fifo.rbc_ram_start + BEACON_FRAME_OFF,len) ; @@ -532,13 +532,13 @@ u_long t_request; * contains optional UNA */ len = 23 ; - td = TX_DESCRIPTOR | ((((u_long)len-1)&3)<<27) ; + td = TX_DESCRIPTOR | ((((u_int)len-1)&3)<<27) ; mac->mac_fc = FC_BEACON ; mac->mac_source = MA ; mac->mac_dest = dbeacon_multi ; /* multicast */ - set_long((char *) mac->mac_info,((long)DBEACON_INFO<<24L) + 0 ) ; - set_long((char *) mac->mac_info+4,0L) ; - set_long((char *) mac->mac_info+8,0L) ; + set_int((char *) mac->mac_info,((int)DBEACON_INFO<<24) + 0 ) ; + set_int((char *) mac->mac_info+4,0) ; + set_int((char *) mac->mac_info+8,0) ; copy_tx_mac(smc,td,(struct fddi_mac *)mac, smc->hw.fp.fifo.rbc_ram_start + DBEACON_FRAME_OFF,len) ; diff --git a/drivers/net/skfp/h/fplustm.h b/drivers/net/skfp/h/fplustm.h index 9e1ce036e..bb9f3b2ac 100644 --- a/drivers/net/skfp/h/fplustm.h +++ b/drivers/net/skfp/h/fplustm.h @@ -54,12 +54,12 @@ struct err_st { * Transmit Descriptor struct */ struct s_smt_fp_txd { - u_long txd_tbctrl ; /* transmit buffer control */ - u_long txd_txdscr ; /* transmit frame status word */ - u_long txd_tbadr ; /* physical tx buffer address */ - u_long txd_ntdadr ; /* physical pointer to the next TxD */ + u_int txd_tbctrl ; /* transmit buffer control */ + u_int txd_txdscr ; /* transmit frame status word */ + u_int txd_tbadr ; /* physical tx buffer address */ + u_int txd_ntdadr ; /* physical pointer to the next TxD */ #ifdef ENA_64BIT_SUP - u_long txd_tbadr_hi ; /* physical tx buffer addr (high dword)*/ + u_int txd_tbadr_hi ; /* physical tx buffer addr (high dword)*/ #endif char far *txd_virt ; /* virtual pointer to the data frag */ /* virt pointer to the next TxD */ @@ -71,12 +71,12 @@ struct s_smt_fp_txd { * Receive Descriptor struct */ struct s_smt_fp_rxd { - u_long rxd_rbctrl ; /* receive buffer control */ - u_long rxd_rfsw ; /* receive frame status word */ - u_long rxd_rbadr ; /* physical rx buffer address */ - u_long rxd_nrdadr ; /* physical pointer to the next RxD */ + u_int rxd_rbctrl ; /* receive buffer control */ + u_int rxd_rfsw ; /* receive frame status word */ + u_int rxd_rbadr ; /* physical rx buffer address */ + u_int rxd_nrdadr ; /* physical pointer to the next RxD */ #ifdef ENA_64BIT_SUP - u_long rxd_rbadr_hi ; /* physical tx buffer addr (high dword)*/ + u_int rxd_rbadr_hi ; /* physical tx buffer addr (high dword)*/ #endif char far *rxd_virt ; /* virtual pointer to the data frag */ /* virt pointer to the next RxD */ @@ -259,8 +259,10 @@ struct s_smt_fp { (((x)>> 8L)&0x0000ff00L) + \ (((x)>>24L)&0x000000ffL)) #else +#ifndef AIX_REVERSE #define AIX_REVERSE(x) (x) #endif +#endif #ifdef MDR_REV #define MDR_REVERSE(x) ((((x)<<24L)&0xff000000L) + \ @@ -268,7 +270,9 @@ struct s_smt_fp { (((x)>> 8L)&0x0000ff00L) + \ (((x)>>24L)&0x000000ffL)) #else +#ifndef MDR_REVERSE #define MDR_REVERSE(x) (x) #endif +#endif #endif diff --git a/drivers/net/skfp/h/osdef1st.h b/drivers/net/skfp/h/osdef1st.h index 69f27707d..a6866248a 100644 --- a/drivers/net/skfp/h/osdef1st.h +++ b/drivers/net/skfp/h/osdef1st.h @@ -97,22 +97,27 @@ * * Note: The size of these structures must follow this rule: * - * size = 8 + n * 16, n >= 0 + * sizeof(struct) + 2*sizeof(void*) == n * 16, n >= 1 * - * NOTE: The size of this structures may not be changed, because - * libskfddi.a depends on it. But the dummy fields can be - * used freely. + * We use the dma_addr fields under Linux to keep track of the + * DMA address of the packet data, for later pci_unmap_single. -DaveM */ struct s_txd_os { // os-specific part of transmit descriptor struct sk_buff *skb; - long dummy; + dma_addr_t dma_addr; } ; struct s_rxd_os { // os-specific part of receive descriptor struct sk_buff *skb; - long dummy; + dma_addr_t dma_addr; } ; +/* + * So we do not need to make too many modifications to the generic driver + * parts, we take advantage of the AIX byte swapping macro interface. + */ +#define AIX_REVERSE(x) ((u32)le32_to_cpu((u32)(x))) +#define MDR_REVERSE(x) ((u32)le32_to_cpu((u32)(x))) diff --git a/drivers/net/skfp/h/smt.h b/drivers/net/skfp/h/smt.h index 08eb1ccbf..5a2606d16 100644 --- a/drivers/net/skfp/h/smt.h +++ b/drivers/net/skfp/h/smt.h @@ -53,7 +53,7 @@ _packed struct smt_header { u_char smt_class ; /* NIF, SIF ... */ u_char smt_type ; /* req., response .. */ u_short smt_version ; /* version id */ - u_long smt_tid ; /* transaction ID */ + u_int smt_tid ; /* transaction ID */ struct smt_sid smt_sid ; /* station ID */ u_short smt_pad ; /* pad with 0 */ u_short smt_len ; /* length of info field */ @@ -278,15 +278,15 @@ struct smt_p_mac_status { struct smt_para para ; /* generic parameter header */ u_short st_mib_index ; /* MIB index */ u_short st_mac_index ; /* n+1 .. n+m */ - u_long st_t_req ; /* T_Req */ - u_long st_t_neg ; /* T_Neg */ - u_long st_t_max ; /* T_Max */ - u_long st_tvx_value ; /* TVX_Value */ - u_long st_t_min ; /* T_Min */ - u_long st_sba ; /* synchr. bandwidth alloc */ - u_long st_frame_ct ; /* frame counter */ - u_long st_error_ct ; /* error counter */ - u_long st_lost_ct ; /* lost frames counter */ + u_int st_t_req ; /* T_Req */ + u_int st_t_neg ; /* T_Neg */ + u_int st_t_max ; /* T_Max */ + u_int st_tvx_value ; /* TVX_Value */ + u_int st_t_min ; /* T_Min */ + u_int st_sba ; /* synchr. bandwidth alloc */ + u_int st_frame_ct ; /* frame counter */ + u_int st_error_ct ; /* error counter */ + u_int st_lost_ct ; /* lost frames counter */ } ; /* @@ -305,8 +305,8 @@ struct smt_p_lem { u_char lem_cutoff ; /* 0x4 .. 0xf, default 0x7 */ u_char lem_alarm ; /* 0x4 .. 0xf, default 0x8 */ u_char lem_estimate ; /* 0x0 .. 0xff */ - u_long lem_reject_ct ; /* 0x00000000 .. 0xffffffff */ - u_long lem_ct ; /* 0x00000000 .. 0xffffffff */ + u_int lem_reject_ct ; /* 0x00000000 .. 0xffffffff */ + u_int lem_ct ; /* 0x00000000 .. 0xffffffff */ } ; /* @@ -319,8 +319,8 @@ struct smt_p_mac_counter { struct smt_para para ; /* generic parameter header */ u_short mc_mib_index ; /* MIB index */ u_short mc_index ; /* mac index */ - u_long mc_receive_ct ; /* receive counter */ - u_long mc_transmit_ct ; /* transmit counter */ + u_int mc_receive_ct ; /* receive counter */ + u_int mc_transmit_ct ; /* transmit counter */ } ; /* @@ -333,7 +333,7 @@ struct smt_p_mac_fnc { struct smt_para para ; /* generic parameter header */ u_short nc_mib_index ; /* MIB index */ u_short nc_index ; /* mac index */ - u_long nc_counter ; /* not copied counter */ + u_int nc_counter ; /* not copied counter */ } ; @@ -347,7 +347,7 @@ struct smt_p_priority { struct smt_para para ; /* generic parameter header */ u_short pr_mib_index ; /* MIB index */ u_short pr_index ; /* mac index */ - u_long pr_priority[7] ; /* priority values */ + u_int pr_priority[7] ; /* priority values */ } ; /* @@ -360,7 +360,7 @@ struct smt_p_eb { struct smt_para para ; /* generic parameter header */ u_short eb_mib_index ; /* MIB index */ u_short eb_index ; /* phy index */ - u_long eb_error_ct ; /* # of eb overflows */ + u_int eb_error_ct ; /* # of eb overflows */ } ; /* @@ -406,7 +406,7 @@ struct smt_p_echo { struct smt_p_reason { struct smt_para para ; /* generic parameter header */ - u_long rdf_reason ; /* CLASS/VERSION */ + u_int rdf_reason ; /* CLASS/VERSION */ } ; #define SMT_RDF_CLASS 0x00000001 /* class not supported */ #define SMT_RDF_VERSION 0x00000002 /* version not supported */ @@ -428,7 +428,7 @@ struct smt_p_reason { struct smt_p_refused { struct smt_para para ; /* generic parameter header */ - u_long ref_fc ; /* 3 bytes 0 + FC */ + u_int ref_fc ; /* 3 bytes 0 + FC */ struct smt_header ref_header ; /* refused header */ } ; @@ -454,7 +454,7 @@ struct smt_p_version { struct smt_p_0015 { struct smt_para para ; /* generic parameter header */ - u_long res_type ; /* recsource type */ + u_int res_type ; /* recsource type */ } ; #define SYNC_BW 0x00000001L /* Synchronous Bandwidth */ @@ -466,7 +466,7 @@ struct smt_p_0015 { struct smt_p_0016 { struct smt_para para ; /* generic parameter header */ - u_long sba_cmd ; /* command for the SBA */ + u_int sba_cmd ; /* command for the SBA */ } ; #define REQUEST_ALLOCATION 0x1 /* req allocation of sync bandwidth */ @@ -482,7 +482,7 @@ struct smt_p_0016 { struct smt_p_0017 { struct smt_para para ; /* generic parameter header */ - long sba_pl_req ; /* total sync bandwidth measured in */ + int sba_pl_req ; /* total sync bandwidth measured in */ } ; /* bytes per 125 us */ /* @@ -492,7 +492,7 @@ struct smt_p_0017 { struct smt_p_0018 { struct smt_para para ; /* generic parameter header */ - long sba_ov_req ; /* total sync bandwidth req for overhead*/ + int sba_ov_req ; /* total sync bandwidth req for overhead*/ } ; /* measuered in bytes per T_Neg */ /* @@ -513,7 +513,7 @@ struct smt_p_0019 { struct smt_p_001a { struct smt_para para ; /* generic parameter header */ - u_long category ; /* Allocator defined classification */ + u_int category ; /* Allocator defined classification */ } ; /* @@ -523,7 +523,7 @@ struct smt_p_001a { struct smt_p_001b { struct smt_para para ; /* generic parameter header */ - u_long max_t_neg ; /* longest T_NEG for the sync service*/ + u_int max_t_neg ; /* longest T_NEG for the sync service*/ } ; /* @@ -533,7 +533,7 @@ struct smt_p_001b { struct smt_p_001c { struct smt_para para ; /* generic parameter header */ - u_long min_seg_siz ; /* smallest number of bytes per frame*/ + u_int min_seg_siz ; /* smallest number of bytes per frame*/ } ; /* @@ -543,7 +543,7 @@ struct smt_p_001c { struct smt_p_001d { struct smt_para para ; /* generic parameter header */ - u_long allocatable ; /* total sync bw availabel for alloc */ + u_int allocatable ; /* total sync bw availabel for alloc */ } ; /* @@ -575,8 +575,8 @@ struct smt_p_fsc { */ #define SWAP_SMT_P1048 "ll" struct smt_p_1048 { - u_long p1048_flag ; - u_long p1048_cf_state ; + u_int p1048_flag ; + u_int p1048_cf_state ; } ; /* @@ -586,7 +586,7 @@ struct smt_p_1048 { */ #define SWAP_SMT_P208C "4lss66" struct smt_p_208c { - u_long p208c_flag ; + u_int p208c_flag ; u_short p208c_pad ; u_short p208c_dupcondition ; struct fddi_addr p208c_fddilong ; @@ -595,26 +595,26 @@ struct smt_p_208c { #define SWAP_SMT_P208D "4lllll" struct smt_p_208d { - u_long p208d_flag ; - u_long p208d_frame_ct ; - u_long p208d_error_ct ; - u_long p208d_lost_ct ; - u_long p208d_ratio ; + u_int p208d_flag ; + u_int p208d_frame_ct ; + u_int p208d_error_ct ; + u_int p208d_lost_ct ; + u_int p208d_ratio ; } ; #define SWAP_SMT_P208E "4llll" struct smt_p_208e { - u_long p208e_flag ; - u_long p208e_not_copied ; - u_long p208e_copied ; - u_long p208e_not_copied_ratio ; + u_int p208e_flag ; + u_int p208e_not_copied ; + u_int p208e_copied ; + u_int p208e_not_copied_ratio ; } ; #define SWAP_SMT_P208F "4ll6666s6" struct smt_p_208f { - u_long p208f_multiple ; - u_long p208f_nacondition ; + u_int p208f_multiple ; + u_int p208f_nacondition ; struct fddi_addr p208f_old_una ; struct fddi_addr p208f_new_una ; struct fddi_addr p208f_old_dna ; @@ -626,10 +626,10 @@ struct smt_p_208f { #define SWAP_SMT_P2090 "4lssl" struct smt_p_2090 { - u_long p2090_multiple ; + u_int p2090_multiple ; u_short p2090_availablepaths ; u_short p2090_currentpath ; - u_long p2090_requestedpaths ; + u_int p2090_requestedpaths ; } ; /* @@ -649,7 +649,7 @@ struct smt_p_2090 { struct smt_p_320b { struct smt_para para ; /* generic parameter header */ - u_long mib_index ; + u_int mib_index ; u_short path_pad ; u_short path_index ; } ; @@ -658,33 +658,33 @@ struct smt_p_320b { struct smt_p_320f { struct smt_para para ; /* generic parameter header */ - u_long mib_index ; - u_long mib_payload ; + u_int mib_index ; + u_int mib_payload ; } ; #define SWAP_SMT_P3210 "4l" struct smt_p_3210 { struct smt_para para ; /* generic parameter header */ - u_long mib_index ; - u_long mib_overhead ; + u_int mib_index ; + u_int mib_overhead ; } ; #define SWAP_SMT_P4050 "4l1111ll" struct smt_p_4050 { - u_long p4050_flag ; + u_int p4050_flag ; u_char p4050_pad ; u_char p4050_cutoff ; u_char p4050_alarm ; u_char p4050_estimate ; - u_long p4050_reject_ct ; - u_long p4050_ct ; + u_int p4050_reject_ct ; + u_int p4050_ct ; } ; #define SWAP_SMT_P4051 "4lssss" struct smt_p_4051 { - u_long p4051_multiple ; + u_int p4051_multiple ; u_short p4051_porttype ; u_short p4051_connectstate ; u_short p4051_pc_neighbor ; @@ -693,17 +693,17 @@ struct smt_p_4051 { #define SWAP_SMT_P4052 "4ll" struct smt_p_4052 { - u_long p4052_flag ; - u_long p4052_eberrorcount ; + u_int p4052_flag ; + u_int p4052_eberrorcount ; } ; #define SWAP_SMT_P4053 "4lsslss" struct smt_p_4053 { - u_long p4053_multiple ; + u_int p4053_multiple ; u_short p4053_availablepaths ; u_short p4053_currentpath ; - u_long p4053_requestedpaths ; + u_int p4053_requestedpaths ; u_short p4053_mytype ; u_short p4053_neighbortype ; } ; @@ -714,7 +714,7 @@ struct smt_p_4053 { struct smt_p_setcount { struct smt_para para ; /* generic parameter header */ - u_long count ; + u_int count ; u_char timestamp[8] ; } ; diff --git a/drivers/net/skfp/h/targetos.h b/drivers/net/skfp/h/targetos.h index dd88fb35e..7c6c1bd85 100644 --- a/drivers/net/skfp/h/targetos.h +++ b/drivers/net/skfp/h/targetos.h @@ -93,7 +93,7 @@ #define u8 unsigned char #define u16 unsigned short -#define u32 unsigned long +#define u32 unsigned int #define MAX_TX_QUEUE_LEN 20 // number of packets queued by driver #define MAX_FRAME_SIZE 4550 @@ -127,11 +127,12 @@ struct s_smt_os { u32 bus_type; /* bus type (0 == PCI, 1 == EISA) */ struct pci_dev pdev; /* PCI device structure */ - u32 base_addr; + unsigned long base_addr; unsigned char factory_mac_addr[8]; ulong SharedMemSize; ulong SharedMemHeap; void* SharedMemAddr; + dma_addr_t SharedMemDMA; ulong QueueSkb; struct sk_buff_head SendSkbQueue; @@ -144,8 +145,10 @@ struct s_smt_os { // receive into this local buffer if no skb available // data will be not valid, because multiple RxDs can - // point here at the same time - unsigned char LocalRxBuffer[MAX_FRAME_SIZE]; + // point here at the same time, it must be at least + // MAX_FRAME_SIZE bytes in size + unsigned char *LocalRxBuffer; + dma_addr_t LocalRxBufferDMA; // Version (required by SMT module). u_long smc_version ; diff --git a/drivers/net/skfp/hwmtm.c b/drivers/net/skfp/hwmtm.c index 366b3b890..ece539646 100644 --- a/drivers/net/skfp/hwmtm.c +++ b/drivers/net/skfp/hwmtm.c @@ -456,7 +456,7 @@ u_char *mac_addr ; /* canonical address */ /* * make sure that the start pointer is 16 byte aligned */ - i = 16 - ((int)smc->os.hwm.descr_p & 0xf) ; + i = 16 - ((long)smc->os.hwm.descr_p & 0xf) ; if (i != 16) { DB_GEN("i = %d",i,0,3) ; smc->os.hwm.descr_p = (union s_fp_descr volatile *) @@ -1087,9 +1087,8 @@ struct s_smc *smc ; DB_RX("Check RxD %x for OWN and EOF",(void *)r,0,5) ; DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORCPU) ; rbctrl = CR_READ(r->rxd_rbctrl) ; -#ifdef AIX rbctrl = AIX_REVERSE(rbctrl) ; -#endif + if (rbctrl & BMU_OWN) { NDD_TRACE("RHxE",r,rfsw,rbctrl) ; DB_RX("End of RxDs",0,0,4) ; @@ -1425,26 +1424,19 @@ int len ; int frame_status ; { struct s_smt_fp_rxd volatile *r ; -#ifdef AIX - u_long rbctrl ; -#endif + u_int rbctrl ; NDD_TRACE("RHfB",virt,len,frame_status) ; DB_RX("hwm_rx_frag: len = %d, frame_status = %x\n",len,frame_status,2) ; r = smc->hw.fp.rx_q[QUEUE_R1].rx_curr_put ; r->rxd_virt = virt ; r->rxd_rbadr = AIX_REVERSE(phys) ; -#ifndef AIX - r->rxd_rbctrl = (((u_long)frame_status & (FIRST_FRAG|LAST_FRAG))<<26) | - (((u_long) frame_status & FIRST_FRAG) << 21) | - BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len ; -#else rbctrl = AIX_REVERSE( (((u_long)frame_status & (FIRST_FRAG|LAST_FRAG))<<26) | (((u_long) frame_status & FIRST_FRAG) << 21) | BMU_OWN | BMU_CHECK | BMU_EN_IRQ_EOF | len) ; r->rxd_rbctrl = rbctrl ; -#endif + DRV_BUF_FLUSH(r,DDI_DMA_SYNC_FORDEV) ; outpd(ADDR(B0_R1_CSR),CSR_START) ; smc->hw.fp.rx_q[QUEUE_R1].rx_free-- ; @@ -1687,9 +1679,7 @@ int frame_status ; { struct s_smt_fp_txd volatile *t ; struct s_smt_tx_queue *queue ; -#ifdef AIX - u_long tbctrl ; -#endif + u_int tbctrl ; queue = smc->os.hwm.tx_p ; @@ -1708,19 +1698,15 @@ int frame_status ; t->txd_virt = virt ; t->txd_txdscr = AIX_REVERSE(smc->os.hwm.tx_descr) ; t->txd_tbadr = AIX_REVERSE(phys) ; -#ifndef AIX - t->txd_tbctrl = (((u_long)frame_status & - (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) | - BMU_OWN|BMU_CHECK |len ; - DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; - outpd(queue->tx_bmu_ctl,CSR_START) ; - -#else /* ifndef AIX */ tbctrl = AIX_REVERSE((((u_long)frame_status & (FIRST_FRAG|LAST_FRAG|EN_IRQ_EOF))<< 26) | BMU_OWN|BMU_CHECK |len) ; t->txd_tbctrl = tbctrl ; +#ifndef AIX + DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; + outpd(queue->tx_bmu_ctl,CSR_START) ; +#else /* ifndef AIX */ DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; if (frame_status & QUEUE_A0) { outpd(ADDR(B0_XA_CSR),CSR_START) ; @@ -1888,9 +1874,7 @@ int fc; struct s_smt_tx_queue *queue ; struct s_smt_fp_txd volatile *t ; u_long phys ; -#ifdef AIX - u_long tbctrl ; -#endif + u_int tbctrl ; NDD_TRACE("THSB",mb,fc,0) ; DB_TX("smt_send_mbuf: mb = 0x%x, fc = 0x%x",mb,fc,4) ; @@ -1908,7 +1892,7 @@ int fc; frag_count = 0 ; len = mb->sm_len ; while (len) { - n = SMT_PAGESIZE - ((int)data & (SMT_PAGESIZE-1)) ; + n = SMT_PAGESIZE - ((long)data & (SMT_PAGESIZE-1)) ; if (n >= len) { n = len ; } @@ -1964,17 +1948,14 @@ int fc; phys = dma_master(smc, (void far *)virt[i], frag_len[i], DMA_RD|SMT_BUF) ; t->txd_tbadr = AIX_REVERSE(phys) ; -#ifndef AIX - t->txd_tbctrl = (((u_long) frame_status & - (FIRST_FRAG|LAST_FRAG)) << 26) | - BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i] ; - DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; - outpd(queue->tx_bmu_ctl,CSR_START) ; -#else tbctrl = AIX_REVERSE((((u_long) frame_status & (FIRST_FRAG|LAST_FRAG)) << 26) | BMU_OWN | BMU_CHECK | BMU_SMT_TX |frag_len[i]) ; t->txd_tbctrl = tbctrl ; +#ifndef AIX + DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; + outpd(queue->tx_bmu_ctl,CSR_START) ; +#else DRV_BUF_FLUSH(t,DDI_DMA_SYNC_FORDEV) ; outpd(ADDR(B0_XA_CSR),CSR_START) ; #endif @@ -2039,9 +2020,8 @@ struct s_smc *smc ; DRV_BUF_FLUSH(t1,DDI_DMA_SYNC_FORCPU) ; DB_TX("check OWN/EOF bit of TxD 0x%x",t1,0,5) ; tbctrl = CR_READ(t1->txd_tbctrl) ; -#ifdef AIX tbctrl = AIX_REVERSE(tbctrl) ; -#endif + if (tbctrl & BMU_OWN || !queue->tx_used){ DB_TX("End of TxDs queue %d",i,0,4) ; goto free_next_queue ; /* next queue */ diff --git a/drivers/net/skfp/skfddi.c b/drivers/net/skfp/skfddi.c index 1bbd5f068..5b5ffc9f9 100644 --- a/drivers/net/skfp/skfddi.c +++ b/drivers/net/skfp/skfddi.c @@ -19,6 +19,9 @@ * Maintainers: * CG Christoph Goos (cgoos@syskonnect.de) * + * Contributors: + * DM David S. Miller + * * Address all question to: * linux@syskonnect.de * @@ -52,20 +55,20 @@ * 26-Oct-99 CG Fixed compilation error on 2.2.13 * 12-Nov-99 CG Source code release * 22-Nov-99 CG Included in kernel source. + * 07-May-00 DM 64 bit fixes, new dma interface * * Compilation options (-Dxxx): * DRIVERDEBUG print lots of messages to log file * DUMPPACKETS print received/transmitted packets to logfile * - * Limitations: - * I changed the driver to support memory mapped I/O, so it - * might run on non-x86 architectures (not tested). - * But the hardware module does not yet support 64 bit OS'es. + * Tested cpu architectures: + * - i386 + * - sparc64 */ /* Version information string - should be updated prior to */ /* each new release!!! */ -#define VERSION "2.05" +#define VERSION "2.06" static const char *boot_msg = "SysKonnect FDDI PCI Adapter driver v" VERSION " for\n" @@ -666,18 +669,28 @@ static int skfp_driver_init(struct net_device *dev) spin_lock_init(&bp->DriverLock); + // Allocate invalid frame + bp->LocalRxBuffer = pci_alloc_consistent(&bp->pdev, MAX_FRAME_SIZE, &bp->LocalRxBufferDMA); + if (!bp->LocalRxBuffer) { + printk("could not allocate mem for "); + printk("LocalRxBuffer: %d byte\n", MAX_FRAME_SIZE); + goto fail; + } + // Determine the required size of the 'shared' memory area. bp->SharedMemSize = mac_drv_check_space(); PRINTK(KERN_INFO "Memory for HWM: %ld\n", bp->SharedMemSize); if (bp->SharedMemSize > 0) { bp->SharedMemSize += 16; // for descriptor alignment - bp->SharedMemAddr = kmalloc(bp->SharedMemSize, GFP_KERNEL); + bp->SharedMemAddr = pci_alloc_consistent(&bp->pdev, + bp->SharedMemSize, + &bp->SharedMemDMA); if (!bp->SharedMemSize) { printk("could not allocate mem for "); printk("hardware module: %ld byte\n", bp->SharedMemSize); - return (-1); + goto fail; } bp->SharedMemHeap = 0; // Nothing used yet. @@ -693,7 +706,7 @@ static int skfp_driver_init(struct net_device *dev) PRINTK(KERN_INFO "mac_drv_init()..\n"); if (mac_drv_init(smc) != 0) { PRINTK(KERN_INFO "mac_drv_init() failed.\n"); - return (-1); + goto fail; } read_address(smc, NULL); PRINTK(KERN_INFO "HW-Addr: %02x %02x %02x %02x %02x %02x\n", @@ -708,6 +721,21 @@ static int skfp_driver_init(struct net_device *dev) smt_reset_defaults(smc, 0); return (0); + +fail: + if (bp->SharedMemAddr) { + pci_free_consistent(&bp->pdev, + bp->SharedMemSize, + bp->SharedMemAddr, + bp->SharedMemDMA); + bp->SharedMemAddr = NULL; + } + if (bp->LocalRxBuffer) { + pci_free_consistent(&bp->pdev, MAX_FRAME_SIZE, + bp->LocalRxBuffer, bp->LocalRxBufferDMA); + bp->LocalRxBuffer = NULL; + } + return (-1); } // skfp_driver_init @@ -1282,7 +1310,7 @@ static int skfp_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) * is contained in a single physically contiguous buffer * in which the virtual address of the start of packet * (skb->data) can be converted to a physical address - * by using virt_to_bus(). + * by using pci_map_single(). * * We have an internal queue for packets we can not send * immediately. Packets in this queue can be given to the @@ -1378,6 +1406,7 @@ static void send_queued_packets(struct s_smc *smc) unsigned char fc; int queue; struct s_smt_fp_txd *txd; // Current TxD. + dma_addr_t dma_address; unsigned long Flags; int frame_status; // HWM tx frame status. @@ -1442,13 +1471,18 @@ static void send_queued_packets(struct s_smc *smc) txd = (struct s_smt_fp_txd *) HWM_GET_CURR_TXD(smc, queue); + dma_address = pci_map_single(&bp->pdev, skb->data, + skb->len, PCI_DMA_TODEVICE); if (frame_status & LAN_TX) { - txd->txd_os.skb = skb; // save skb + txd->txd_os.skb = skb; // save skb + txd->txd_os.dma_addr = dma_address; // save dma mapping } - hwm_tx_frag(smc, skb->data, virt_to_bus(skb->data), skb->len, + hwm_tx_frag(smc, skb->data, dma_address, skb->len, frame_status | FIRST_FRAG | LAST_FRAG | EN_IRQ_EOF); if (!(frame_status & LAN_TX)) { // local only frame + pci_unmap_single(&bp->pdev, dma_address, + skb->len, PCI_DMA_TODEVICE); dev_kfree_skb_irq(skb); } spin_unlock_irqrestore(&bp->DriverLock, Flags); @@ -1571,7 +1605,7 @@ void *mac_drv_get_space(struct s_smc *smc, unsigned int size) { void *virt; - PRINTK(KERN_INFO "mac_drv_get_space\n"); + PRINTK(KERN_INFO "mac_drv_get_space (%d bytes), ", size); virt = (void *) (smc->os.SharedMemAddr + smc->os.SharedMemHeap); if ((smc->os.SharedMemHeap + size) > smc->os.SharedMemSize) { @@ -1581,8 +1615,10 @@ void *mac_drv_get_space(struct s_smc *smc, unsigned int size) smc->os.SharedMemHeap += size; // Move heap pointer. PRINTK(KERN_INFO "mac_drv_get_space end\n"); - PRINTK(KERN_INFO "virt addr: %08lx\n", (ulong) virt); - PRINTK(KERN_INFO "bus addr: %08lx\n", (ulong) virt_to_bus(virt)); + PRINTK(KERN_INFO "virt addr: %lx\n", (ulong) virt); + PRINTK(KERN_INFO "bus addr: %lx\n", (ulong) + (smc->os.SharedMemDMA + + ((char *) virt - (char *)smc->os.SharedMemAddr))); return (virt); } // mac_drv_get_space @@ -1616,7 +1652,7 @@ void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size) virt = mac_drv_get_space(smc, size); - size = (u_int) ((0 - (unsigned int) virt) & 15); + size = (u_int) ((0 - (unsigned long) virt) & 15UL); PRINTK("Allocate %u bytes alignment gap ", size); PRINTK("for descriptor memory.\n"); @@ -1644,7 +1680,8 @@ void *mac_drv_get_desc_mem(struct s_smc *smc, unsigned int size) ************************/ unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt) { - return virt_to_bus(virt); + return (smc->os.SharedMemDMA + + ((char *) virt - (char *)smc->os.SharedMemAddr)); } // mac_drv_virt2phys @@ -1657,7 +1694,8 @@ unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt) * for the DMA transfer, it should do it in this function. * * The hardware module calls this dma_master if it wants to send an SMT - * frame. + * frame. This means that the virt address passed in here is part of + * the 'shared' memory area. * Args * smc - A pointer to the SMT context struct. * @@ -1677,7 +1715,8 @@ unsigned long mac_drv_virt2phys(struct s_smc *smc, void *virt) ************************/ u_long dma_master(struct s_smc * smc, void *virt, int len, int flag) { - return (virt_to_bus(virt)); + return (smc->os.SharedMemDMA + + ((char *) virt - (char *)smc->os.SharedMemAddr)); } // dma_master @@ -1704,7 +1743,31 @@ u_long dma_master(struct s_smc * smc, void *virt, int len, int flag) ************************/ void dma_complete(struct s_smc *smc, volatile union s_fp_descr *descr, int flag) { - return; + /* For TX buffers, there are two cases. If it is an SMT transmit + * buffer, there is nothing to do since we use consistent memory + * for the 'shared' memory area. The other case is for normal + * transmit packets given to us by the networking stack, and in + * that case we cleanup the PCI DMA mapping in mac_drv_tx_complete + * below. + * + * For RX buffers, we have to unmap dynamic PCI DMA mappings here + * because the hardware module is about to potentially look at + * the contents of the buffer. If we did not call the PCI DMA + * unmap first, the hardware module could read inconsistent data. + */ + if (flag & DMA_WR) { + skfddi_priv *bp = (skfddi_priv *) & smc->os; + volatile struct s_smt_fp_rxd *r = &descr->r; + + /* If SKB is NULL, we used the local buffer. */ + if (r->rxd_os.skb && r->rxd_os.dma_addr) { + int MaxFrameSize = bp->MaxFrameSize; + + pci_unmap_single(&bp->pdev, r->rxd_os.dma_addr, + MaxFrameSize, PCI_DMA_FROMDEVICE); + r->rxd_os.dma_addr = 0; + } + } } // dma_complete @@ -1735,6 +1798,11 @@ void mac_drv_tx_complete(struct s_smc *smc, volatile struct s_smt_fp_txd *txd) } txd->txd_os.skb = NULL; + // release the DMA mapping + pci_unmap_single(&smc->os.pdev, txd->txd_os.dma_addr, + skb->len, PCI_DMA_TODEVICE); + txd->txd_os.dma_addr = 0; + smc->os.MacStat.tx_packets++; // Count transmitted packets. smc->os.MacStat.tx_bytes+=skb->len; // Count bytes @@ -1823,6 +1891,8 @@ void mac_drv_rx_complete(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, } virt = skb->data; + // The DMA mapping was released in dma_complete above. + dump_data(skb->data, len); /* @@ -1923,7 +1993,7 @@ void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, struct sk_buff *skb; int MaxFrameSize; unsigned char *v_addr; - unsigned long b_addr; + dma_addr_t b_addr; if (frag_count != 1) // This is not allowed to happen. @@ -1939,25 +2009,34 @@ void mac_drv_requeue_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, if (skb == NULL) { // this should not happen PRINTK("Requeue with no skb in rxd!\n"); - skb = alloc_skb(MaxFrameSize, GFP_ATOMIC); + skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); if (skb) { // we got a skb rxd->rxd_os.skb = skb; + skb_reserve(skb, 3); skb_put(skb, MaxFrameSize); v_addr = skb->data; - b_addr = virt_to_bus(v_addr); + b_addr = pci_map_single(&smc->os.pdev, + v_addr, + MaxFrameSize, + PCI_DMA_FROMDEVICE); + rxd->rxd_os.dma_addr = b_addr; } else { // no skb available, use local buffer PRINTK("Queueing invalid buffer!\n"); rxd->rxd_os.skb = NULL; v_addr = smc->os.LocalRxBuffer; - b_addr = virt_to_bus(v_addr); + b_addr = smc->os.LocalRxBufferDMA; } } else { // we use skb from old rxd rxd->rxd_os.skb = skb; v_addr = skb->data; - b_addr = virt_to_bus(v_addr); + b_addr = pci_map_single(&smc->os.pdev, + v_addr, + MaxFrameSize, + PCI_DMA_FROMDEVICE); + rxd->rxd_os.dma_addr = b_addr; } hwm_rx_frag(smc, v_addr, b_addr, MaxFrameSize, FIRST_FRAG | LAST_FRAG); @@ -2002,12 +2081,17 @@ void mac_drv_fill_rxd(struct s_smc *smc) PRINTK(KERN_INFO ".\n"); rxd = HWM_GET_CURR_RXD(smc); - skb = alloc_skb(MaxFrameSize, GFP_ATOMIC); + skb = alloc_skb(MaxFrameSize + 3, GFP_ATOMIC); if (skb) { // we got a skb + skb_reserve(skb, 3); skb_put(skb, MaxFrameSize); v_addr = skb->data; - b_addr = virt_to_bus(v_addr); + b_addr = pci_map_single(&smc->os.pdev, + v_addr, + MaxFrameSize, + PCI_DMA_FROMDEVICE); + rxd->rxd_os.dma_addr = b_addr; } else { // no skb available, use local buffer // System has run out of buffer memory, but we want to @@ -2016,7 +2100,7 @@ void mac_drv_fill_rxd(struct s_smc *smc) // so data in it must be considered invalid. PRINTK("Queueing invalid buffer!\n"); v_addr = smc->os.LocalRxBuffer; - b_addr = virt_to_bus(v_addr); + b_addr = smc->os.LocalRxBufferDMA; } rxd->rxd_os.skb = skb; @@ -2060,6 +2144,12 @@ void mac_drv_clear_rxd(struct s_smc *smc, volatile struct s_smt_fp_rxd *rxd, for (; frag_count > 0; frag_count--) { skb = rxd->rxd_os.skb; if (skb != NULL) { + skfddi_priv *bp = (skfddi_priv *) & smc->os; + int MaxFrameSize = bp->MaxFrameSize; + + pci_unmap_single(&bp->pdev, rxd->rxd_os.dma_addr, + MaxFrameSize, PCI_DMA_FROMDEVICE); + dev_kfree_skb(skb); rxd->rxd_os.skb = NULL; } @@ -2111,11 +2201,12 @@ int mac_drv_rx_init(struct s_smc *smc, int len, int fc, len, la_len, (unsigned long) look_ahead); return (0); } - skb = alloc_skb(len, GFP_ATOMIC); + skb = alloc_skb(len + 3, GFP_ATOMIC); if (!skb) { PRINTK("fddi: Local SMT: skb memory exhausted.\n"); return (0); } + skb_reserve(skb, 3); skb_put(skb, len); memcpy(skb->data, look_ahead, len); @@ -2162,7 +2253,40 @@ void smt_timer_poll(struct s_smc *smc) ************************/ void ring_status_indication(struct s_smc *smc, u_long status) { - PRINTK("ring_status_indication(%08lXh)\n", (unsigned long) status); + PRINTK("ring_status_indication( "); + if (status & RS_RES15) + PRINTK("RS_RES15 "); + if (status & RS_HARDERROR) + PRINTK("RS_HARDERROR "); + if (status & RS_SOFTERROR) + PRINTK("RS_SOFTERROR "); + if (status & RS_BEACON) + PRINTK("RS_BEACON "); + if (status & RS_PATHTEST) + PRINTK("RS_PATHTEST "); + if (status & RS_SELFTEST) + PRINTK("RS_SELFTEST "); + if (status & RS_RES9) + PRINTK("RS_RES9 "); + if (status & RS_DISCONNECT) + PRINTK("RS_DISCONNECT "); + if (status & RS_RES7) + PRINTK("RS_RES7 "); + if (status & RS_DUPADDR) + PRINTK("RS_DUPADDR "); + if (status & RS_NORINGOP) + PRINTK("RS_NORINGOP "); + if (status & RS_VERSION) + PRINTK("RS_VERSION "); + if (status & RS_STUCKBYPASSS) + PRINTK("RS_STUCKBYPASSS "); + if (status & RS_EVENT) + PRINTK("RS_EVENT "); + if (status & RS_RINGOPCHANGE) + PRINTK("RS_RINGOPCHANGE "); + if (status & RS_RES0) + PRINTK("RS_RES0 "); + PRINTK("]\n"); } // ring_status_indication @@ -2261,9 +2385,18 @@ void cfm_state_change(struct s_smc *smc, int c_state) case SC7_WRAP_S: s = "SC7_WRAP_S"; break; - default: - s = "unknown"; + case SC9_C_WRAP_A: + s = "SC9_C_WRAP_A"; + break; + case SC10_C_WRAP_B: + s = "SC10_C_WRAP_B"; + break; + case SC11_C_WRAP_S: + s = "SC11_C_WRAP_S"; break; + default: + PRINTK(KERN_INFO "cfm_state_change: unknown %d\n", c_state); + return; } PRINTK(KERN_INFO "cfm_state_change: %s\n", s); #endif // DRIVERDEBUG @@ -2478,7 +2611,18 @@ static struct net_device *unlink_modules(struct net_device *p) next = lp->os.next_module; if (lp->os.SharedMemAddr) { - kfree(lp->os.SharedMemAddr); + pci_free_consistent(&lp->os.pdev, + lp->os.SharedMemSize, + lp->os.SharedMemAddr, + lp->os.SharedMemDMA); + lp->os.SharedMemAddr = NULL; + } + if (lp->os.LocalRxBuffer) { + pci_free_consistent(&lp->os.pdev, + MAX_FRAME_SIZE, + lp->os.LocalRxBuffer, + lp->os.LocalRxBufferDMA); + lp->os.LocalRxBuffer = NULL; } release_region(p->base_addr, (lp->os.bus_type == SK_BUS_TYPE_PCI ? FP_IO_LEN : 0)); diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c index f206a44f9..58f71b963 100644 --- a/drivers/net/tokenring/ibmtr.c +++ b/drivers/net/tokenring/ibmtr.c @@ -1750,9 +1750,9 @@ static void tr_rx(struct net_device *dev) /* Copy the payload... */ for (;;) { if (IPv4_p) - chksum = csum_partial_copy(bus_to_virt(rbufdata), data, + chksum = csum_partial_copy_generic(bus_to_virt(rbufdata), data, length < rbuffer_len ? length : rbuffer_len, - chksum); + chksum, NULL, NULL); else isa_memcpy_fromio(data, rbufdata, rbuffer_len); rbuffer = ntohs(isa_readw(rbuffer)); diff --git a/drivers/s390/Config.in b/drivers/s390/Config.in new file mode 100644 index 000000000..257c65d9a --- /dev/null +++ b/drivers/s390/Config.in @@ -0,0 +1,70 @@ +mainmenu_option next_comment +comment 'S/390 block device drivers' + +tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP +if [ "$CONFIG_NET" = "y" ]; then + tristate 'Network block device support' CONFIG_BLK_DEV_NBD +fi +bool 'Multiple devices driver support' CONFIG_BLK_DEV_MD +if [ "$CONFIG_BLK_DEV_MD" = "y" ]; then + tristate ' Linear (append) mode' CONFIG_MD_LINEAR + tristate ' RAID-0 (striping) mode' CONFIG_MD_STRIPED + tristate ' RAID-1 (mirroring) mode' CONFIG_MD_MIRRORING + tristate ' RAID-4/RAID-5 mode' CONFIG_MD_RAID5 +fi +if [ "$CONFIG_MD_LINEAR" = "y" -o "$CONFIG_MD_STRIPED" = "y" ]; then + bool ' Boot support (linear, striped)' CONFIG_MD_BOOT +fi +tristate 'RAM disk support' CONFIG_BLK_DEV_RAM +if [ "$CONFIG_BLK_DEV_RAM" = "y" ]; then + bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD +fi + +bool 'Support for VM minidisk (VM only)' CONFIG_MDISK +if [ "$CONFIG_MDISK" = "y" ]; then + bool ' Support for synchronous read-write' CONFIG_MDISK_SYNC +fi + +tristate 'Support for DASD devices' CONFIG_DASD +if [ "$CONFIG_DASD" != "n" ]; then + comment 'DASD disciplines' + bool ' Support for ECKD Disks' CONFIG_DASD_ECKD +# bool ' Support for CKD Disks' CONFIG_DASD_CKD + bool ' Support for DIAG access to CMS reserved Disks' CONFIG_DASD_MDSK +fi + +#menu_option next_comment +#endmenu + +if [ "$CONFIG_NET" = "y" ]; then + mainmenu_option next_comment + comment 'S/390 Network device support' + bool 'Channel Device Configuration (Temporary Option)' CONFIG_CHANDEV + bool 'Network device support' CONFIG_NETDEVICES + if [ "$CONFIG_NETDEVICES" = "y" ]; then + menu_option next_comment + comment 'S390 Network devices' + bool 'CTC device support' CONFIG_CTC + bool 'IUCV device support (VM only)' CONFIG_IUCV + tristate 'Dummy net driver support' CONFIG_DUMMY + bool 'Ethernet (10 or 100Mbit)' CONFIG_NET_ETHERNET + bool 'Token Ring driver support' CONFIG_TR + bool 'FDDI driver support' CONFIG_FDDI + fi + endmenu +fi + +mainmenu_option next_comment +comment 'S/390 Terminal and Console options' + +bool 'Support for 3215 line mode terminal' CONFIG_3215 +if [ "$CONFIG_3215" = "y" ]; then + bool 'Support for console on 3215 line mode terminal' CONFIG_3215_CONSOLE +fi + +bool 'Support for HWC line mode terminal' CONFIG_HWC +if [ "$CONFIG_HWC" = "y" ]; then + bool 'console on HWC line mode terminal' CONFIG_HWC_CONSOLE +fi +endmenu + diff --git a/drivers/s390/Makefile b/drivers/s390/Makefile new file mode 100644 index 000000000..009916137 --- /dev/null +++ b/drivers/s390/Makefile @@ -0,0 +1,40 @@ +# +# Makefile for the linux i386-specific parts of the memory manager. +# +# 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... + +all: io.o + +CFLAGS += +O_TARGET := io.o +O_OBJS := +M_OBJS := + +SUBDIRS := $(SUBDIRS) arch/s390/drivers/block arch/s390/drivers/char \ + arch/s390/drivers/misc arch/s390/drivers/net +MOD_SUB_DIRS += ./net + +O_OBJS := block/s390-block.o \ + char/s390-char.o \ + misc/s390-misc.o \ + net/s390-net.o + +io.o: $(O_OBJS) + +block/s390-block.o: dummy + $(MAKE) -C block + +char/s390-char.o: dummy + $(MAKE) -C char + +misc/s390-misc.o: dummy + $(MAKE) -C misc + +net/s390-net.o: dummy + $(MAKE) -C net + +include $(TOPDIR)/Rules.make diff --git a/drivers/s390/block/Makefile b/drivers/s390/block/Makefile new file mode 100644 index 000000000..16a56acb1 --- /dev/null +++ b/drivers/s390/block/Makefile @@ -0,0 +1,31 @@ +all: s390-block.o + +CFLAGS += +O_TARGET := s390-block.o +O_OBJS := +M_OBJS := + +ifeq ($(CONFIG_DASD),y) + O_OBJS += dasd.o dasd_ccwstuff.o dasd_erp.o + ifeq ($(CONFIG_PROC_FS),y) + O_OBJS += dasd_proc.o dasd_profile.o + endif + ifeq ($(CONFIG_DASD_ECKD),y) + O_OBJS += dasd_eckd.o + endif + ifeq ($(CONFIG_DASD_MDSK),y) + O_OBJS += dasd_mdsk.o + endif +# ifeq ($(CONFIG_DASD_CKD),y) +# O_OBJS += dasd_ckd.o +# endif +endif + +ifeq ($(CONFIG_MDISK),y) + O_OBJS += mdisk.o +endif + +dasd_mod.o: $(D_OBJS) + $(LD) $(LD_RFLAG) -r -o $@ $+ + +include $(TOPDIR)/Rules.make diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c new file mode 100644 index 000000000..79e8f27dc --- /dev/null +++ b/drivers/s390/block/dasd.c @@ -0,0 +1,1560 @@ +/* + * File...........: linux/drivers/s390/block/dasd.c + * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> + * : Utz Bacher <utz.bacher@de.ibm.com> + * Bugreports.to..: <Linux390@de.ibm.com> + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + */ + +#include <linux/config.h> +#include <linux/init.h> +#include <linux/stddef.h> +#include <linux/kernel.h> + +#ifdef MODULE +#include <linux/module.h> +#endif /* MODULE */ + +#include <linux/tqueue.h> +#include <linux/timer.h> +#include <linux/malloc.h> +#include <linux/genhd.h> +#include <linux/devfs_fs_kernel.h> +#include <linux/hdreg.h> +#include <linux/interrupt.h> +#include <linux/ctype.h> +#include <asm/io.h> +#include <asm/semaphore.h> +#include <asm/ebcdic.h> +#include <asm/uaccess.h> + +#include <asm/irq.h> + +#include <linux/dasd.h> +#include <linux/blk.h> + +#include "dasd_erp.h" +#include "dasd_types.h" +#include "dasd_ccwstuff.h" + +#define PRINTK_HEADER DASD_NAME":" + +#define CCW_READ_DEVICE_CHARACTERISTICS 0x64 + +#define DASD_SSCH_RETRIES 2 + +/* This macro is a little tricky, but makes the code more easy to read... */ +#define MATCH(info,ct,cm,dt,dm) ( \ +(( info -> sid_data.cu_type ct ) && ( info -> sid_data.cu_model cm )) && \ +(( info -> sid_data.dev_type dt ) && ( info -> sid_data.dev_model dm )) ) + +/* Prototypes for the functions called from external */ +static int dasd_ioctl (struct inode *, struct file *, unsigned int, unsigned long); +static int dasd_open (struct inode *, struct file *); +static int dasd_release (struct inode *, struct file *); + +void dasd_debug (unsigned long tag); +void dasd_profile_add (cqr_t *cqr); +void dasd_proc_init (void); + +static int dasd_format( int, format_data_t * ); + +static struct block_device_operations dasd_device_operations; + +spinlock_t dasd_lock; /* general purpose lock for the dasd driver */ + +/* All asynchronous I/O should waint on this wait_queue */ +wait_queue_head_t dasd_waitq; + +static int dasd_autodetect = 1; +static int dasd_devno[DASD_MAX_DEVICES] = +{0,}; +static int dasd_count = 0; + +extern dasd_chanq_t *cq_head; + +static int +dasd_get_hexdigit (char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + if ((c >= 'a') && (c <= 'f')) + return c + 10 - 'a'; + if ((c >= 'A') && (c <= 'F')) + return c + 10 - 'A'; + return -1; +} + +/* sets the string pointer after the next comma */ +static void +dasd_scan_for_next_comma (char **strptr) +{ + while (((**strptr) != ',') && ((**strptr)++)) + (*strptr)++; + + /* set the position AFTER the comma */ + if (**strptr == ',') + (*strptr)++; +} + +/*sets the string pointer after the next comma, if a parse error occured */ +static int +dasd_get_next_int (char **strptr) +{ + int j, i = -1; /* for cosmetic reasons first -1, then 0 */ + if (isxdigit (**strptr)) { + for (i = 0; isxdigit (**strptr);) { + i <<= 4; + j = dasd_get_hexdigit (**strptr); + if (j == -1) { + PRINT_ERR ("no integer: skipping range.\n"); + dasd_scan_for_next_comma (strptr); + i = -1; + break; + } + i += j; + (*strptr)++; + if (i > 0xffff) { + PRINT_ERR (" value too big, skipping range.\n"); + dasd_scan_for_next_comma (strptr); + i = -1; + break; + } + } + } + return i; +} + +static inline int +devindex_from_devno (int devno) +{ + int i; + for (i = 0; i < dasd_count; i++) { + if (dasd_devno[i] == devno) + return i; + } + if (dasd_autodetect) { + if (dasd_count < DASD_MAX_DEVICES) { + dasd_devno[dasd_count] = devno; + return dasd_count++; + } + return -EOVERFLOW; + } + return -ENODEV; +} + +/* returns 1, if dasd_no is in the specified ranges, otherwise 0 */ +static inline int +dasd_is_accessible (int devno) +{ + return (devindex_from_devno (devno) >= 0); +} + +/* dasd_insert_range skips ranges, if the start or the end is -1 */ +static void +dasd_insert_range (int start, int end) +{ + int curr; + FUNCTION_ENTRY ("dasd_insert_range"); + if (dasd_count >= DASD_MAX_DEVICES) { + PRINT_ERR (" too many devices specified, ignoring some.\n"); + FUNCTION_EXIT ("dasd_insert_range"); + return; + } + if ((start == -1) || (end == -1)) { + PRINT_ERR + ("invalid format of parameter, skipping range\n"); + FUNCTION_EXIT ("dasd_insert_range"); + return; + } + if (end < start) { + PRINT_ERR (" ignoring range from %x to %x - start value " \ + "must be less than end value.\n", start, end); + FUNCTION_EXIT ("dasd_insert_range"); + return; + } +/* concurrent execution would be critical, but will not occur here */ + for (curr = start; curr <= end; curr++) { + if (dasd_is_accessible (curr)) { + PRINT_WARN (" %x is already in list as device %d\n", + curr, devindex_from_devno (curr)); + } + dasd_devno[dasd_count] = curr; + dasd_count++; + if (dasd_count >= DASD_MAX_DEVICES) { + PRINT_ERR (" too many devices specified, ignoring some.\n"); + break; + } + } + PRINT_INFO (" added dasd range from %x to %x.\n", + start, dasd_devno[dasd_count - 1]); + + FUNCTION_EXIT ("dasd_insert_range"); +} + +static int __init +dasd_setup (char *str) +{ + int devno, devno2; + + FUNCTION_ENTRY ("dasd_setup"); + dasd_autodetect = 0; + while (*str && *str != 1) { + if (!isxdigit (*str)) { + str++; /* to avoid looping on two commas */ + PRINT_ERR (" kernel parameter in invalid format.\n"); + continue; + } + devno = dasd_get_next_int (&str); + + /* range was skipped? -> scan for comma has been done */ + if (devno == -1) + continue; + + if (*str == ',') { + str++; + dasd_insert_range (devno, devno); + continue; + } + if (*str == '-') { + str++; + devno2 = dasd_get_next_int (&str); + if (devno2 == -1) { + PRINT_ERR (" invalid character in " \ + "kernel parameters."); + } else { + dasd_insert_range (devno, devno2); + } + dasd_scan_for_next_comma (&str); + continue; + } + if (*str == 0) { + dasd_insert_range (devno, devno); + break; + } + PRINT_ERR (" unexpected character in kernel parameter, " \ + "skipping range.\n"); + } + FUNCTION_EXIT ("dasd_setup"); + return 1; +} + +__setup("dasd=", dasd_setup); + +dasd_information_t *dasd_info[DASD_MAX_DEVICES] = {NULL,}; +static struct hd_struct dd_hdstruct[DASD_MAX_DEVICES << PARTN_BITS]; +static int dasd_blks[256] = {0,}; +static int dasd_secsize[256] = {0,}; +static int dasd_blksize[256] = {0,}; +static int dasd_maxsecs[256] = {0,}; + +struct gendisk dd_gendisk = +{ + MAJOR_NR, /* Major number */ + "dasd", /* Major name */ + PARTN_BITS, /* Bits to shift to get real from partn */ + 1 << PARTN_BITS, /* Number of partitions per real */ + dd_hdstruct, /* hd struct */ + dasd_blks, /* sizes in blocks */ + DASD_MAX_DEVICES, /* number */ + NULL, /* internal */ + NULL /* next */ + +}; + +static atomic_t bh_scheduled = ATOMIC_INIT (0); + +static inline void +schedule_bh (void (*func) (void)) +{ + static struct tq_struct dasd_tq = + {0,}; + /* Protect against rescheduling, when already running */ + if (atomic_compare_and_swap (0, 1, &bh_scheduled)) + return; + dasd_tq.routine = (void *) (void *) func; + queue_task (&dasd_tq, &tq_immediate); + mark_bh (IMMEDIATE_BH); + return; +} + +void +sleep_done (struct semaphore *sem) +{ + if (sem != NULL) { + up (sem); + } +} + +void +sleep (int timeout) +{ + struct semaphore sem; + struct timer_list timer; + + init_MUTEX_LOCKED (&sem); + init_timer (&timer); + timer.data = (unsigned long) &sem; + timer.expires = jiffies + timeout; + timer.function = (void (*)(unsigned long)) sleep_done; + printk (KERN_DEBUG PRINTK_HEADER + "Sleeping for timer tics %d\n", timeout); + add_timer (&timer); + down (&sem); + del_timer (&timer); +} + +#ifdef CONFIG_DASD_ECKD +extern dasd_operations_t dasd_eckd_operations; +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK +extern dasd_operations_t dasd_mdsk_operations; +#endif /* CONFIG_DASD_MDSK */ + +dasd_operations_t *dasd_disciplines[] = +{ +#ifdef CONFIG_DASD_ECKD + &dasd_eckd_operations, +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + &dasd_mdsk_operations, +#endif /* CONFIG_DASD_MDSK */ +#ifdef CONFIG_DASD_CKD + &dasd_ckd_operations, +#endif /* CONFIG_DASD_CKD */ + NULL +}; + +char *dasd_name[] = +{ +#ifdef CONFIG_DASD_ECKD + "ECKD", +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + "MDSK", +#endif /* CONFIG_DASD_MDSK */ +#ifdef CONFIG_DASD_CKD + "CKD", +#endif /* CONFIG_DASD_CKD */ + "END" +}; + + +static inline int +do_dasd_ioctl (struct inode *inp, unsigned int no, unsigned long data) +{ + int rc; + int di; + dasd_information_t *dev; + + di = DEVICE_NR (inp->i_rdev); + if (!dasd_info[di]) { + PRINT_WARN ("No device registered as %d\n", inp->i_rdev); + return -EINVAL; + } + if ((_IOC_DIR (no) != _IOC_NONE) && (data == 0)) { + PRINT_DEBUG ("empty data ptr"); + return -EINVAL; + } + dev = dasd_info[di]; + if (!dev) { + PRINT_WARN ("No device registered as %d\n", inp->i_rdev); + return -EINVAL; + } + PRINT_INFO ("ioctl 0x%08x %s'0x%x'%d(%d) on dev %d/%d (%d) with data %8lx\n", no, + _IOC_DIR (no) == _IOC_NONE ? "0" : + _IOC_DIR (no) == _IOC_READ ? "r" : + _IOC_DIR (no) == _IOC_WRITE ? "w" : + _IOC_DIR (no) == (_IOC_READ | _IOC_WRITE) ? "rw" : "u", + _IOC_TYPE (no), _IOC_NR (no), _IOC_SIZE (no), + MAJOR (inp->i_rdev), MINOR (inp->i_rdev), di, data); + + switch (no) { + case BLKGETSIZE:{ /* Return device size */ + unsigned long blocks; + if (inp->i_rdev & 0x01) { + blocks = (dev->sizes.blocks - 3) << + dev->sizes.s2b_shift; + } else { + blocks = dev->sizes.kbytes << dev->sizes.s2b_shift; + } + rc = copy_to_user ((long *) data, &blocks, sizeof (long)); + break; + } + case BLKFLSBUF:{ + rc = fsync_dev (inp->i_rdev); + break; + } + case BLKRAGET:{ + rc = copy_to_user ((long *) data, + read_ahead + MAJOR_NR, sizeof (long)); + break; + } + case BLKRASET:{ + rc = copy_from_user (read_ahead + MAJOR_NR, + (long *) data, sizeof (long)); + break; + } + case BLKRRPART:{ + INTERNAL_CHECK ("BLKRPART not implemented%s", ""); + rc = -EINVAL; + break; + } + case HDIO_GETGEO:{ + INTERNAL_CHECK ("HDIO_GETGEO not implemented%s", ""); + rc = -EINVAL; + break; + } + + case BIODASDRSID:{ + rc = copy_to_user ((void *) data, + &(dev->info.sid_data), + sizeof (senseid_t)); + break; + } + case BIODASDRWTB:{ + int offset = 0; + int xlt; + rc = copy_from_user (&xlt, (void *) data, + sizeof (int)); + PRINT_INFO("Xlating %d to",xlt); + if (rc) + break; + if (MINOR (inp->i_rdev) & 1) + offset = 3; + xlt += offset; + printk(" %d \n",xlt); + rc = copy_to_user ((void *) data, &xlt, + sizeof (int)); + break; + } + case BIODASDFORMAT:{ + /* fdata == NULL is a valid arg to dasd_format ! */ + format_data_t *fdata = NULL; + if (data) { + fdata = kmalloc (sizeof (format_data_t), + GFP_ATOMIC); + if (!fdata) { + rc = -ENOMEM; + break; + } + rc = copy_from_user (fdata, (void *) data, + sizeof (format_data_t)); + if (rc) + break; + } + rc = dasd_format (inp->i_rdev, fdata); + if (fdata) { + kfree (fdata); + } + break; + } + default: + rc = -EINVAL; + break; + } + return rc; +} + +static void +dasd_end_request (struct request *req, int uptodate) +{ + struct buffer_head *bh; + FUNCTION_ENTRY ("dasd_end_request"); +#if DASD_PARANOIA > 2 + if (!req) { + INTERNAL_CHECK ("end_request called with zero arg%s\n", ""); + } +#endif /* DASD_PARANOIA */ + while ((bh = req->bh) != NULL) { + req->bh = bh->b_reqnext; + bh->b_reqnext = NULL; + bh->b_end_io (bh, uptodate); + } + if (!end_that_request_first (req, uptodate, DEVICE_NAME)) { +#ifndef DEVICE_NO_RANDOM + add_blkdev_randomness (MAJOR (req->rq_dev)); +#endif + DEVICE_OFF (req->rq_dev); + end_that_request_last (req); + } + FUNCTION_EXIT ("dasd_end_request"); + return; +} + +void +dasd_wakeup (void) +{ + wake_up (&dasd_waitq); +} + +int +dasd_unregister_dasd (int irq, dasd_type_t dt, dev_info_t * info) +{ + int rc = 0; + FUNCTION_ENTRY ("dasd_unregister_dasd"); + INTERNAL_CHECK ("dasd_unregister_dasd not implemented%s\n", ""); + FUNCTION_EXIT ("dasd_unregister_dasd"); + return rc; +} + +/* Below you find the functions already cleaned up */ +static dasd_type_t +check_type (dev_info_t * info) +{ + dasd_type_t type = dasd_none; + + FUNCTION_ENTRY ("check_type"); +#ifdef CONFIG_DASD_ECKD + if (MATCH (info, == 0x3990, ||1, == 0x3390, ||1) || + MATCH (info, == 0x9343, ||1, == 0x9345, ||1) || + MATCH (info, == 0x3990, ||1, == 0x3380, ||1)) { + type = dasd_eckd; + } else +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + if ( MACHINE_IS_VM ) { + type = dasd_mdsk; + } else +#endif /* CONFIG_DASD_MDSK */ + { + type = dasd_none; + } + + FUNCTION_EXIT ("check_type"); + return type; +} + +static int +dasd_read_characteristics (dasd_information_t * info) +{ + int rc; + int ct = 0; + dev_info_t *di; + dasd_type_t dt; + + FUNCTION_ENTRY ("read_characteristics"); + if (info == NULL) { + return -ENODEV; + } + di = &(info->info); + if (di == NULL) { + return -ENODEV; + } + dt = check_type (di); + /* Some cross-checks, if the cu supports RDC */ + if (MATCH (di, == 0x2835, ||1, ||1, ||1) || + MATCH (di, == 0x3830, ||1, ||1, ||1) || + MATCH (di, == 0x3830, ||1, ||1, ||1) || + MATCH (di, == 0x3990, <=0x03, == 0x3380, <=0x0d)) { + PRINT_WARN ("Device %d (%x/%x at %x/%x) supports no RDC\n", + info->info.irq, + di->sid_data.dev_type, + di->sid_data.dev_model, + di->sid_data.cu_type, + di->sid_data.cu_model); + return -EINVAL; + } + switch (dt) { +#ifdef CONFIG_DASD_ECKD + case dasd_eckd: + ct = 64; + rc = read_dev_chars (info->info.irq, + (void *) &(info->rdc_data), ct); + break; +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + case dasd_mdsk: + ct = 0; + break; +#endif /* CONFIG_DASD_MDSK */ + default: + INTERNAL_ERROR ("don't know dasd type %d\n", dt); + } + if (rc) { + PRINT_WARN ("RDC resulted in rc=%d\n", rc); + } + FUNCTION_EXIT ("read_characteristics"); + return rc; +} + +/* How many sectors must be in a request to dequeue it ? */ +#define QUEUE_BLOCKS 25 +#define QUEUE_SECTORS (QUEUE_BLOCKS << dasd_info[di]->sizes.s2b_shift) + +/* How often to retry an I/O before raising an error */ +#define DASD_MAX_RETRIES 5 + + +static inline + cqr_t * +dasd_cqr_from_req (struct request *req) +{ + cqr_t *cqr = NULL; + int di; + dasd_information_t *info; + + if (!req) { + PRINT_ERR ("No request passed!"); + return NULL; + } + di = DEVICE_NR (req->rq_dev); + info = dasd_info[di]; + if (!info) + return NULL; + /* if applicable relocate block */ + if (MINOR (req->rq_dev) & ((1 << PARTN_BITS) - 1) ) { + req->sector += + dd_gendisk.part[MINOR(req->rq_dev)].start_sect; + } + /* Now check for consistency */ + if (!req->nr_sectors) { + PRINT_WARN ("req: %p dev: %08x sector: %ld nr_sectors: %ld bh: %p\n", + req, req->rq_dev, req->sector, req->nr_sectors, req->bh); + return NULL; + } + if (((req->sector + req->nr_sectors) >> 1) > info->sizes.kbytes) { + printk (KERN_ERR PRINTK_HEADER + "Requesting I/O past end of device %d\n", + di); + return NULL; + } + cqr = dasd_disciplines[info->type]->get_req_ccw (di, req); + if (!cqr) { + PRINT_WARN ("empty CQR generated\n"); + } else { + cqr->req = req; + cqr->int4cqr = cqr; + cqr->devindex = di; +#ifdef DASD_PROFILE + asm volatile ("STCK %0":"=m" (cqr->buildclk)); +#endif /* DASD_PROFILE */ + if (atomic_compare_and_swap (CQR_STATUS_EMPTY, + CQR_STATUS_FILLED, + &cqr->status)) { + PRINT_WARN ("cqr from req stat changed %d\n", + atomic_read (&cqr->status)); + } + } + return cqr; +} + +int +dasd_start_IO (cqr_t * cqr) +{ + int rc = 0; + int retries = DASD_SSCH_RETRIES; + int di, irq; + + dasd_debug ((unsigned long) cqr); /* cqr */ + + if (!cqr) { + PRINT_WARN ("(start_IO) no cqr passed\n"); + return -EINVAL; + } + if (cqr->magic != DASD_MAGIC) { + PRINT_WARN ("(start_IO) magic number mismatch\n"); + return -EINVAL; + } + if (atomic_compare_and_swap (CQR_STATUS_QUEUED, + CQR_STATUS_IN_IO, + &cqr->status)) { + PRINT_WARN ("start_IO: status changed %d\n", + atomic_read (&cqr->status)); + atomic_set (&cqr->status, CQR_STATUS_ERROR); + return -EINVAL; + } + di = cqr->devindex; + irq = dasd_info[di]->info.irq; + do { + asm volatile ("STCK %0":"=m" (cqr->startclk)); + rc = do_IO (irq, cqr->cpaddr, (long) cqr, 0x00, cqr->options); + switch (rc) { + case 0: + if (!(cqr->options & DOIO_WAIT_FOR_INTERRUPT)) + atomic_set_mask (DASD_CHANQ_BUSY, + &dasd_info[di]->queue.flags); + break; + case -ENODEV: + PRINT_WARN ("cqr %p: 0x%04x error, %d retries left\n", + cqr, dasd_info[di]->info.devno, retries); + break; + case -EIO: + PRINT_WARN ("cqr %p: 0x%04x I/O, %d retries left\n", + cqr, dasd_info[di]->info.devno, retries); + break; + case -EBUSY: /* set up timer, try later */ + + PRINT_WARN ("cqr %p: 0x%04x busy, %d retries left\n", + cqr, dasd_info[di]->info.devno, retries); + break; + default: + + PRINT_WARN ("cqr %p: 0x%04x %d, %d retries left\n", + cqr, rc, dasd_info[di]->info.devno, + retries); + break; + } + } while (rc && --retries); + if (rc) { + if (atomic_compare_and_swap (CQR_STATUS_IN_IO, + CQR_STATUS_ERROR, + &cqr->status)) { + PRINT_WARN ("start_IO:(done) status changed %d\n", + atomic_read (&cqr->status)); + atomic_set (&cqr->status, CQR_STATUS_ERROR); + } + } + return rc; +} + +static inline +void +dasd_end_cqr (cqr_t * cqr, int uptodate) +{ + struct request *req = cqr->req; + asm volatile ("STCK %0":"=m" (cqr->endclk)); +#ifdef DASD_PROFILE + dasd_profile_add (cqr); +#endif /* DASD_PROFILE */ + dasd_chanq_deq (&dasd_info[cqr->devindex]->queue, cqr); + if (req) { + dasd_end_request (req, uptodate); + } +} + +void +dasd_dump_sense (devstat_t * stat) +{ + int sl, sct; + if ( ! stat->flag | DEVSTAT_FLAG_SENSE_AVAIL) { + PRINT_INFO("I/O status w/o sense data"); + } else { + printk (KERN_INFO PRINTK_HEADER + "-------------------I/O result:-----------\n"); + for (sl = 0; sl < 4; sl++) { + printk (KERN_INFO PRINTK_HEADER "Sense:"); + for (sct = 0; sct < 8; sct++) { + printk (" %2d:0x%02X", 8 * sl + sct, + stat->ii.sense.data[8 * sl + sct]); + } + printk ("\n"); + } + } +} + +static int +register_dasd_last (int di) +{ + int rc = 0; + int minor; + struct buffer_head *bh; + rc = dasd_disciplines[dasd_info[di]->type]->fill_sizes_last (di); + switch (rc) { + case -EMEDIUMTYPE: + dasd_info[di]->flags |= DASD_INFO_FLAGS_NOT_FORMATTED; + break; + } + PRINT_INFO ("%ld kB <- 'soft'-block: %d, hardsect %d Bytes\n", + dasd_info[di]->sizes.kbytes, + dasd_info[di]->sizes.bp_block, + dasd_info[di]->sizes.bp_sector); + switch (dasd_info[di]->type) { +#ifdef CONFIG_DASD_ECKD + case dasd_eckd: + dasd_info[di]->sizes.label_block = 2; + break; +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + case dasd_mdsk: + dasd_info[di]->sizes.label_block = -1; + break; +#endif /* CONFIG_DASD_ECKD */ + + default: + INTERNAL_CHECK ("Unknown dasd type %d\n", dasd_info[di]->type); + } + minor = di << PARTN_BITS; + dasd_blks[minor] = dasd_info[di]->sizes.kbytes; + dasd_secsize[minor] = dasd_info[di]->sizes.bp_sector; + dasd_blksize[minor] = dasd_info[di]->sizes.bp_block; + dasd_maxsecs[minor] = 252<<dasd_info[di]->sizes.s2b_shift; + dasd_secsize[minor+1] = dasd_info[di]->sizes.bp_sector; + dasd_blksize[minor+1] = dasd_info[di]->sizes.bp_block; + dasd_maxsecs[minor+1] = 252<<dasd_info[di]->sizes.s2b_shift; + + { +#define DASD_NAME_PREFIX "dasd_" + char * name = (char *) kmalloc ( 1+strlen (DASD_NAME_PREFIX) + + 2 /* 0x */ + 4 /* devno */, + GFP_KERNEL); + sprintf ( name , DASD_NAME_PREFIX "%04x%c", + dasd_info[di]->info.devno,'\0' ); + dasd_info[di] -> devfs_entry = + devfs_register ( NULL /* dir */, + name, strlen(name), + 0 /* flags */, + DASD_MAJOR, minor, + 0755 /* mode */, + 0 /* uid */ , 0 /* gid */, + &dasd_device_operations, + (void *)dasd_info[di]); + } + /* end of that stuff */ + return rc; +} + +void +dasd_partn_detect ( int di ) +{ + int minor = di << PARTN_BITS; + LOOP_CONTROL ("Setting partitions of DASD %d\n", di); + register_disk (&dd_gendisk, + MKDEV(DASD_MAJOR,minor), + 1 << PARTN_BITS, + &dasd_device_operations, + dasd_info[di]->sizes.kbytes << 1); +} + +void +dasd_do_chanq (void) +{ + dasd_chanq_t *qp = NULL; + cqr_t *cqr; + long flags; + int irq; + int tasks; + atomic_set (&bh_scheduled, 0); + dasd_debug (0xc4c40000); /* DD */ + while ((tasks = atomic_read(&chanq_tasks)) != 0) { +/* initialization and wraparound */ + if (qp == NULL) { + dasd_debug (0xc4c46df0); /* DD_0 */ + qp = cq_head; + if (!qp) { + dasd_debug (0xc4c46ff1); /* DD?1 */ + dasd_debug (tasks); + PRINT_ERR("Mismatch of NULL queue pointer and " + "still %d chanq_tasks to do!!\n" + "Please send output of /proc/dasd/debug " + "to Linux390@de.ibm.com\n", tasks); + atomic_set(&chanq_tasks,0); + break; + } + } +/* Get first request */ + dasd_debug ((unsigned long) qp); + cqr = (cqr_t *) (qp->head); +/* empty queue -> dequeue and proceed */ + if (!cqr) { + dasd_chanq_t *nqp = qp->next_q; + cql_deq (qp); + qp = nqp; + continue; + } +/* process all requests on that queue */ + do { + cqr_t *next; + dasd_debug ((unsigned long) cqr); /* cqr */ + if (cqr->magic != DASD_MAGIC) { + dasd_debug (0xc4c46ff2); /* DD?2 */ + panic ( PRINTK_HEADER "do_cq:" + "magic mismatch %p -> %x\n", + cqr, cqr -> magic); + break; + } + irq = dasd_info[cqr->devindex]->info.irq; + s390irq_spin_lock_irqsave (irq, flags); + switch (atomic_read (&cqr->status)) { + case CQR_STATUS_IN_IO: + dasd_debug (0xc4c4c9d6); /* DDIO */ + cqr = NULL; + break; + case CQR_STATUS_QUEUED: + dasd_debug (0xc4c4e2e3); /* DDST */ + if (dasd_start_IO (cqr) == 0) { + atomic_dec (&chanq_tasks); + cqr = NULL; + } + break; + case CQR_STATUS_ERROR: + dasd_debug (0xc4c4c5d9); /* DDER */ + dasd_dump_sense (cqr->dstat); + if ( ++ cqr->retries < 2 ) { + atomic_set (&cqr->status, + CQR_STATUS_QUEUED); + dasd_debug (0xc4c4e2e3); /* DDST */ + if (dasd_start_IO (cqr) == 0) { + atomic_dec ( &qp -> + dirty_requests); + atomic_dec (&chanq_tasks); + cqr = NULL; + } + } else { + atomic_set (&cqr->status, + CQR_STATUS_FAILED); + } + break; + case CQR_STATUS_DONE: + next = cqr->next; + dasd_debug (0xc4c49692); /* DDok */ + dasd_end_cqr (cqr, 1); + atomic_dec (&chanq_tasks); + cqr = next; + break; + case CQR_STATUS_FAILED: + next = cqr->next; + dasd_debug (0xc4c47a7a); /* DD:: */ + if ( ! ( dasd_info[cqr->devindex]-> flags & + DASD_INFO_FLAGS_INITIALIZED ) ) { + dasd_info[cqr->devindex]-> flags |= + DASD_INFO_FLAGS_INITIALIZED | + DASD_INFO_FLAGS_NOT_FORMATTED; + } + dasd_end_cqr (cqr, 0); + atomic_dec ( &qp -> dirty_requests ); + atomic_dec (&chanq_tasks); + cqr = next; + break; + default: + PRINT_WARN ("unknown cqrstatus\n"); + cqr = NULL; + } + s390irq_spin_unlock_irqrestore (irq, flags); + } while (cqr); + qp = qp->next_q; + } + spin_lock (&io_request_lock); + do_dasd_request (&blk_dev[DASD_MAJOR].request_queue); + spin_unlock (&io_request_lock); + dasd_debug (0xc4c46d6d); /* DD__ */ +} + +/* + The request_fn is called from ll_rw_blk for any new request. + We use it to feed the chanqs. + This implementation assumes we are serialized by the io_request_lock. + */ + +#define QUEUE_THRESHOLD 5 + +void +do_dasd_request (request_queue_t *queue) +{ + struct request *req; + cqr_t *cqr; + dasd_chanq_t *q; + long flags; + int di, irq, go; + int broken, busy; + + dasd_debug (0xc4d90000); /* DR */ + dasd_debug ((unsigned long) __builtin_return_address(0)); + go = 1; + while (go && !list_empty(&queue->queue_head)) { + req = blkdev_entry_next_request(&queue->queue_head); + req = blkdev_entry_next_request(&queue->queue_head); + di = DEVICE_NR (req->rq_dev); + dasd_debug ((unsigned long) req); /* req */ + dasd_debug (0xc4d90000 + /* DR## */ + ((((di/16)<9?(di/16)+0xf0:(di/16)+0xc1))<<8) + + (((di%16)<9?(di%16)+0xf0:(di%16)+0xc1))); + irq = dasd_info[di]->info.irq; + s390irq_spin_lock_irqsave (irq, flags); + q = &dasd_info[di]->queue; + busy = atomic_read(&q->flags) & DASD_CHANQ_BUSY; + broken = atomic_read(&q->flags)&DASD_REQUEST_Q_BROKEN; + if ( ! busy || + ( ! broken && + (req->nr_sectors >= QUEUE_SECTORS))) { + blkdev_dequeue_request(req); + /* + printk ( KERN_INFO "0x%04x %c %d %d\n", + req->rq_dev,req->cmd ?'w':'r', + req->sector,req->nr_sectors); + */ + cqr = dasd_cqr_from_req (req); + if (!cqr) { + dasd_debug (0xc4d96ff1); /* DR?1 */ + dasd_end_request (req, 0); + goto cont; + } + dasd_debug ((unsigned long) cqr); /* cqr */ + dasd_chanq_enq (q, cqr); + if (!(atomic_read (&q->flags) & + DASD_CHANQ_ACTIVE)) { + cql_enq_head (q); + } + if ( ! busy ) { + atomic_clear_mask (DASD_REQUEST_Q_BROKEN, + &q->flags ); + if (atomic_read( &q->dirty_requests) == 0 ) { + if ( dasd_start_IO (cqr) == 0 ) { + } else { + atomic_inc (&chanq_tasks); + schedule_bh (dasd_do_chanq); + } + } + } + } else { + dasd_debug (0xc4d9c2d9); /* DRBR */ + atomic_set_mask (DASD_REQUEST_Q_BROKEN, &q->flags ); + go = 0; + } + cont: + s390irq_spin_unlock_irqrestore (irq, flags); + } + dasd_debug (0xc4d96d6d); /* DR__ */ +} + +void +dasd_handler (int irq, void *ds, struct pt_regs *regs) +{ + devstat_t *stat = (devstat_t *) ds; + int ip; + cqr_t *cqr; + int done_fast_io = 0; + + dasd_debug (0xc4c80000); /* DH */ + if (!stat) + PRINT_ERR ("handler called without devstat"); + ip = stat->intparm; + dasd_debug (ip); /* intparm */ + switch (ip) { /* filter special intparms... */ + case 0x00000000: /* no intparm: unsolicited interrupt */ + dasd_debug (0xc4c8a489); /* DHui */ + PRINT_INFO ("Unsolicited interrupt on device %04X\n", + stat->devno); + dasd_dump_sense (stat); + return; + default: + if (ip & 0x80000001) { + dasd_debug (0xc4c8a489); /* DHui */ + PRINT_INFO ("Spurious interrupt %08x on device %04X\n", + ip, stat->devno); + return; + } + cqr = (cqr_t *) ip; + if (cqr->magic != DASD_MAGIC) { + dasd_debug (0xc4c86ff1); /* DH?1 */ + PRINT_ERR ("handler:magic mismatch on %p %08x\n", + cqr, cqr->magic); + return; + } + asm volatile ("STCK %0":"=m" (cqr->stopclk)); + if ( ( stat->cstat == 0x00 && + stat->dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END) ) || + dasd_erp_examine ( cqr ) == dasd_era_none ) { + dasd_debug (0xc4c89692); /* DHok */ + if (atomic_compare_and_swap (CQR_STATUS_IN_IO, + CQR_STATUS_DONE, + &cqr->status)) { + PRINT_WARN ("handler: cqrstat changed%d\n", + atomic_read (&cqr->status)); + atomic_set(&cqr->status, CQR_STATUS_DONE); + } + if ( ! ( dasd_info[cqr->devindex]-> flags & + DASD_INFO_FLAGS_INITIALIZED ) ) { + int rc = register_dasd_last ( cqr->devindex ); + dasd_info[cqr->devindex]-> flags |= + DASD_INFO_FLAGS_INITIALIZED; + if ( rc ) { + dasd_info[cqr->devindex]->flags &= + ~DASD_INFO_FLAGS_NOT_FORMATTED; + } else { + dasd_info[cqr->devindex]->flags |= + DASD_INFO_FLAGS_NOT_FORMATTED; + } + } + if (cqr->next) { + dasd_debug (0xc4c8e2e3); /* DHST */ + if (dasd_start_IO (cqr->next) == 0) { + done_fast_io = 1; + } else { + atomic_inc (&chanq_tasks); + } + } + break; + } + /* only visited in case of error ! */ + dasd_debug (0xc4c8c5d9); /* DHER */ + if (!cqr->dstat) + cqr->dstat = kmalloc (sizeof (devstat_t), + GFP_ATOMIC); + if (cqr->dstat) { + memcpy (cqr->dstat, stat, sizeof (devstat_t)); + } else { + PRINT_ERR ("no memory for dstat\n"); + } + /* errorprocessing */ + atomic_set (&cqr->status, CQR_STATUS_ERROR); + atomic_inc (&dasd_info[cqr->devindex]->queue.dirty_requests); + } + if (done_fast_io == 0) + atomic_clear_mask (DASD_CHANQ_BUSY, + &dasd_info[cqr->devindex]->queue.flags); + + if (cqr->flags & DASD_DO_IO_SLEEP) { + dasd_debug (0xc4c8a6a4); /* DHwu */ + dasd_wakeup (); + } else if (! (cqr->options & DOIO_WAIT_FOR_INTERRUPT) ){ + dasd_debug (0xc4c8a293); /* DHsl */ + atomic_inc (&chanq_tasks); + schedule_bh (dasd_do_chanq); + } else { + dasd_debug (0x64686f6f); /* DH_g */ + dasd_debug (cqr->flags); /* DH_g */ + } + dasd_debug (0xc4c86d6d); /* DHwu */ +} + +static int +dasd_format (int dev, format_data_t * fdata) +{ + int rc; + int devindex = DEVICE_NR (dev); + dasd_chanq_t *q; + cqr_t *cqr; + int irq; + long flags; + PRINT_INFO ("Format called with devno %x\n", dev); + if (MINOR (dev) & (0xff >> (8 - PARTN_BITS))) { + PRINT_WARN ("Can't format partition! minor %x %x\n", + MINOR (dev), 0xff >> (8 - PARTN_BITS)); + return -EINVAL; + } + down (&dasd_info[devindex]->sem); + if (dasd_info[devindex]->open_count == 1) { + rc = dasd_disciplines[dasd_info[devindex]->type]-> + dasd_format (devindex, fdata); + if (rc) { + PRINT_WARN ("Formatting failed rc=%d\n", rc); + } + } else { + PRINT_WARN ("device is open! %d\n", dasd_info[devindex]->open_count); + rc = -EINVAL; + } + if (!rc) { +#if DASD_PARANOIA > 1 + if (!dasd_disciplines[dasd_info[devindex]->type]->fill_sizes_first) { + INTERNAL_CHECK ("No fill_sizes for dt=%d\n", dasd_info[devindex]->type); + } else +#endif /* DASD_PARANOIA */ + { + dasd_info[devindex]->flags &= ~DASD_INFO_FLAGS_INITIALIZED; + irq = dasd_info[devindex]->info.irq; + PRINT_INFO ("Trying to access DASD %x, irq %x, index %d\n", + get_devno_by_irq(irq), irq, devindex); + s390irq_spin_lock_irqsave (irq, flags); + q = &dasd_info[devindex]->queue; + cqr = dasd_disciplines[dasd_info[devindex]->type]-> + fill_sizes_first (devindex); + dasd_chanq_enq (q, cqr); + schedule_bh(dasd_do_chanq); + s390irq_spin_unlock_irqrestore (irq, flags); + } + } + up (&dasd_info[devindex]->sem); + return rc; +} + + +static int +register_dasd (int irq, dasd_type_t dt, dev_info_t * info) +{ + int rc = 0; + int di; + unsigned long flags; + dasd_chanq_t *q; + cqr_t * cqr; + static spinlock_t register_lock = SPIN_LOCK_UNLOCKED; + spin_lock (®ister_lock); + FUNCTION_ENTRY ("register_dasd"); + di = devindex_from_devno (info->devno); + if (di < 0) { + INTERNAL_CHECK ("Can't get index for devno %d\n", info->devno); + return -ENODEV; + } + if (dasd_info[di]) { /* devindex is not free */ + INTERNAL_CHECK ("reusing allocated deviceindex %d\n", di); + return -ENODEV; + } + dasd_info[di] = (dasd_information_t *) + kmalloc (sizeof (dasd_information_t), GFP_ATOMIC); + if (dasd_info[di] == NULL) { + PRINT_WARN ("No memory for dasd_info_t on irq %d\n", irq); + return -ENOMEM; + } + memset (dasd_info[di], 0, sizeof (dasd_information_t)); + memcpy (&(dasd_info[di]->info), info, sizeof (dev_info_t)); + spin_lock_init (&dasd_info[di]->queue.f_lock); + spin_lock_init (&dasd_info[di]->queue.q_lock); + dasd_info[di]->type = dt; + dasd_info[di]->irq = irq; + init_MUTEX (&dasd_info[di]->sem); + rc = dasd_read_characteristics (dasd_info[di]); + if (rc) { + PRINT_WARN ("RDC returned error %d\n", rc); + rc = -ENODEV; + goto unalloc; + } +#if DASD_PARANOIA > 1 + if (dasd_disciplines[dt]->ck_characteristics) +#endif /* DASD_PARANOIA */ + rc = dasd_disciplines[dt]-> + ck_characteristics (dasd_info[di]->rdc_data); + + if (rc) { + INTERNAL_CHECK ("Discipline returned non-zero when" + "checking device characteristics%s\n", ""); + rc = -ENODEV; + goto unalloc; + } + rc = request_irq (irq, dasd_handler, 0, "dasd", + &(dasd_info[di]->dev_status)); + if (rc) { +#if DASD_PARANOIA > 0 + printk (KERN_WARNING PRINTK_HEADER + "Cannot register irq %d, rc=%d\n", + irq, rc); +#endif /* DASD_PARANOIA */ + rc = -ENODEV; + goto unalloc; + } +#if DASD_PARANOIA > 1 + if (!dasd_disciplines[dt]->fill_sizes_first) { + INTERNAL_CHECK ("No fill_sizes for dt=%d\n", dt); + goto unregister; + } +#endif /* DASD_PARANOIA */ + irq = dasd_info[di]->info.irq; + PRINT_INFO ("Trying to access DASD %x, irq %x, index %d\n", + get_devno_by_irq(irq), irq, di); + s390irq_spin_lock_irqsave (irq, flags); + q = &dasd_info[di]->queue; + cqr = dasd_disciplines[dt]->fill_sizes_first (di); + dasd_chanq_enq (q, cqr); + cql_enq_head(q); + if (dasd_start_IO(cqr) != 0) { + atomic_inc(&chanq_tasks); + } + s390irq_spin_unlock_irqrestore (irq, flags); + + goto exit; + + unregister: + free_irq (irq, &(dasd_info[di]->dev_status)); + unalloc: + kfree (dasd_info[di]); + exit: + spin_unlock (®ister_lock); + FUNCTION_EXIT ("register_dasd"); + return rc; +} + +static int +probe_for_dasd (int irq) +{ + int rc; + dev_info_t info; + dasd_type_t dt; + + FUNCTION_ENTRY ("probe_for_dasd"); + + rc = get_dev_info_by_irq (irq, &info); + if (rc == -ENODEV) { /* end of device list */ + return rc; + } +#if DASD_PARANOIA > 2 + if (rc) { + INTERNAL_CHECK ("unknown rc %d of get_dev_info", rc); + return rc; + } +#endif /* DASD_PARANOIA */ + if ((info.status & DEVSTAT_NOT_OPER)) { + return -ENODEV; + } + dt = check_type (&info); + switch (dt) { +#ifdef CONFIG_DASD_ECKD + case dasd_eckd: +#endif /* CONFIG_DASD_ECKD */ + FUNCTION_CONTROL ("Probing devno %d...\n", info.devno); + if (!dasd_is_accessible (info.devno)) { + FUNCTION_CONTROL ("out of range...skip%s\n", ""); + return -ENODEV; + } + if (dasd_disciplines[dt]->ck_devinfo) { + rc = dasd_disciplines[dt]->ck_devinfo (&info); + } +#if DASD_PARANOIA > 1 + else { + INTERNAL_ERROR ("no ck_devinfo function%s\n", ""); + return -ENODEV; + } +#endif /* DASD_PARANOIA */ + if (rc == -ENODEV) { + return rc; + } +#if DASD_PARANOIA > 2 + if (rc) { + INTERNAL_CHECK ("unknown error rc=%d\n", rc); + return -ENODEV; + } +#endif /* DASD_PARANOIA */ + rc = register_dasd (irq, dt, &info); + if (rc) { + PRINT_INFO ("devno %x not enabled as minor %d due to errors\n", + info.devno, + devindex_from_devno (info.devno) << + PARTN_BITS); + } else { + PRINT_INFO ("devno %x added as minor %d (%s)\n", + info.devno, + devindex_from_devno (info.devno) << PARTN_BITS, + dasd_name[dt]); + } + case dasd_none: + break; + default: + PRINT_DEBUG ("unknown device type\n"); + break; + } + FUNCTION_EXIT ("probe_for_dasd"); + return rc; +} + +static int +register_major (int major) +{ + request_queue_t *q; + int rc = 0; + + FUNCTION_ENTRY ("register_major"); + rc = devfs_register_blkdev (major, DASD_NAME, &dasd_device_operations); +#if DASD_PARANOIA > 1 + if (rc) { + PRINT_WARN ("registering major -> rc=%d aborting... \n", rc); + return rc; + } +#endif /* DASD_PARANOIA */ + q = BLK_DEFAULT_QUEUE(major); + blk_init_queue(q, do_dasd_request); + blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); + FUNCTION_CONTROL ("successfully registered major: %d\n", major); + FUNCTION_EXIT ("register_major"); + return rc; +} + +/* + Below you find functions which are called from outside. Some of them may be + static, because they are called by their function pointers only. Thus static + modifier is to make sure, that they are only called via the kernel's methods + */ + +static int +dasd_ioctl (struct inode *inp, struct file *filp, + unsigned int no, unsigned long data) +{ + int rc = 0; + FUNCTION_ENTRY ("dasd_ioctl"); + if ((!inp) || !(inp->i_rdev)) { + return -EINVAL; + } + rc = do_dasd_ioctl (inp, no, data); + FUNCTION_EXIT ("dasd_ioctl"); + return rc; +} + +static int +dasd_open (struct inode *inp, struct file *filp) +{ + int rc = 0; + dasd_information_t *dev; + FUNCTION_ENTRY ("dasd_open"); + if ((!inp) || !(inp->i_rdev)) { + return -EINVAL; + } + dev = dasd_info[DEVICE_NR (inp->i_rdev)]; + if (!dev) { + PRINT_DEBUG ("No device registered as %d (%d)\n", + inp->i_rdev, DEVICE_NR (inp->i_rdev)); + return -EINVAL; + } + down (&dev->sem); + up (&dev->sem); +#ifdef MODULE + MOD_INC_USE_COUNT; +#endif /* MODULE */ +#if DASD_PARANOIA > 2 + if (dev->open_count < 0) { + INTERNAL_ERROR ("open count cannot be less than 0: %d", + dev->open_count); + return -EINVAL; + } +#endif /* DASD_PARANOIA */ + dev->open_count++; + FUNCTION_EXIT ("dasd_open"); + return rc; +} + +static int +dasd_release (struct inode *inp, struct file *filp) +{ + int rc = 0; + dasd_information_t *dev; + FUNCTION_ENTRY ("dasd_release"); + if ((!inp) || !(inp->i_rdev)) { + return -EINVAL; + } + dev = dasd_info[DEVICE_NR (inp->i_rdev)]; + if (!dev) { + PRINT_WARN ("No device registered as %d\n", inp->i_rdev); + return -EINVAL; + } +#ifdef MODULE + MOD_DEC_USE_COUNT; +#endif /* MODULE */ +#if DASD_PARANOIA > 2 + if (!dev->open_count) { + PRINT_WARN ("device %d has not been opened before:\n", + inp->i_rdev); + } +#endif /* DASD_PARANOIA */ + dev->open_count--; +#if DASD_PARANOIA > 2 + if (dev->open_count < 0) { + INTERNAL_ERROR ("open count cannot be less than 0: %d", + dev->open_count); + return -EINVAL; + } +#endif /* DASD_PARANOIA */ + FUNCTION_EXIT ("dasd_release"); + return rc; +} + +static struct +block_device_operations dasd_device_operations = +{ + ioctl: dasd_ioctl, + open: dasd_open, + release: dasd_release, +}; + +int +dasd_init (void) +{ + int rc = 0; + int i; + + FUNCTION_ENTRY ("dasd_init"); + PRINT_INFO ("initializing...\n"); + atomic_set (&chanq_tasks, 0); + atomic_set (&bh_scheduled, 0); + spin_lock_init (&dasd_lock); + init_waitqueue_head(&dasd_waitq); + /* First register to the major number */ + rc = register_major (MAJOR_NR); +#if DASD_PARANOIA > 1 + if (rc) { + PRINT_WARN ("registering major_nr returned rc=%d\n", rc); + return rc; + } +#endif /* DASD_PARANOIA */ + read_ahead[MAJOR_NR] = 8; + blk_size[MAJOR_NR] = dasd_blks; + hardsect_size[MAJOR_NR] = dasd_secsize; + blksize_size[MAJOR_NR] = dasd_blksize; + max_sectors[MAJOR_NR] = dasd_maxsecs; +#ifdef CONFIG_PROC_FS + dasd_proc_init (); +#endif /* CONFIG_PROC_FS */ + /* Now scan the device list for DASDs */ + FUNCTION_CONTROL ("entering detection loop%s\n", ""); + for (i = 0; i < NR_IRQS; i++) { + int irc; /* Internal return code */ + LOOP_CONTROL ("Probing irq %d...\n", i); + irc = probe_for_dasd (i); + switch (irc) { + case 0: + LOOP_CONTROL ("Added DASD%s\n", ""); + break; + case -ENODEV: + LOOP_CONTROL ("No DASD%s\n", ""); + break; + case -EMEDIUMTYPE: + PRINT_WARN ("DASD not formatted%s\n", ""); + break; + default: + INTERNAL_CHECK ("probe_for_dasd: unknown rc=%d", irc); + break; + } + } + FUNCTION_CONTROL ("detection loop completed %s partn check...\n", ""); +/* Finally do the genhd stuff */ + dd_gendisk.next = gendisk_head; + gendisk_head = &dd_gendisk; + for ( i = 0; i < DASD_MAX_DEVICES; i ++ ) + if ( dasd_info[i] ) + dasd_partn_detect ( i ); + + FUNCTION_EXIT ("dasd_init"); + return rc; +} + +#ifdef MODULE +int +init_module (void) +{ + int rc = 0; + + FUNCTION_ENTRY ("init_module"); + PRINT_INFO ("trying to load module\n"); + rc = dasd_init (); + if (rc == 0) { + PRINT_INFO ("module loaded successfully\n"); + } else { + PRINT_WARN ("warning: Module load returned rc=%d\n", rc); + } + FUNCTION_EXIT ("init_module"); + return rc; +} + +void +cleanup_module (void) +{ + int rc = 0; + + FUNCTION_ENTRY ("cleanup_module"); + PRINT_INFO ("trying to unload module \n"); + + /* FIXME: replace by proper unload functionality */ + INTERNAL_ERROR ("Modules not yet implemented %s", ""); + + if (rc == 0) { + PRINT_INFO ("module unloaded successfully\n"); + } else { + PRINT_WARN ("module unloaded with errors\n"); + } + FUNCTION_EXIT ("cleanup_module"); +} +#endif /* MODULE */ + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff --git a/drivers/s390/block/dasd_ccwstuff.c b/drivers/s390/block/dasd_ccwstuff.c new file mode 100644 index 000000000..4f666da28 --- /dev/null +++ b/drivers/s390/block/dasd_ccwstuff.c @@ -0,0 +1,419 @@ +/* + * File...........: linux/drivers/s390/block/dasd_ccwstuff.c + * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> + * Bugreports.to..: <Linux390@de.ibm.com> + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> +#include <linux/malloc.h> +#include <linux/dasd.h> +#include <asm/atomic.h> + +#include "dasd_types.h" + +#define PRINTK_HEADER "dasd_ccw:" +#define MAX_CP_POWER 9 /* Maximum allowed index */ +#define CP_PER_PAGE_POWER 9 /* Maximum index, fitting on page */ + +#define get_free_pages __get_free_pages + +/* Stuff for the handling task_list */ +dasd_chanq_t *cq_head = NULL; /* head of task_list */ +atomic_t chanq_tasks; + +/* Array of freelists for the channel programs' -space */ +static ccw1_t *ccwarea[CP_PER_PAGE_POWER + 1] = +{NULL,}; + +/* array of pages retrieved for internal use */ +#define MAX_DASD_PAGES 64 +static int dasd_page_count = 0; +static long dasd_page[MAX_DASD_PAGES]; + +static spinlock_t ccw_lock=SPIN_LOCK_UNLOCKED; /* spinlock for ccwareas */ +static spinlock_t cq_lock=SPIN_LOCK_UNLOCKED; /* spinlock for cq_head */ + +void +ccwarea_enq (int index, ccw1_t * area) +{ + FUNCTION_ENTRY ("ccwarea_enq"); +#if DASD_PARANOIA > 2 + if (!area) { + INTERNAL_CHECK ("zero area %s\n", ""); + } + if (index > CP_PER_PAGE_POWER) { + INTERNAL_CHECK ("index too large %d\n", index); + } +#endif + *(ccw1_t **) area = ccwarea[index]; + ccwarea[index] = area; + FUNCTION_EXIT ("ccwarea_enq"); + return; +} + +ccw1_t * +ccwarea_deq (int index) +{ + ccw1_t *cp; + FUNCTION_ENTRY ("ccwarea_deq"); +#if DASD_PARANOIA > 2 + if (index > CP_PER_PAGE_POWER) { + INTERNAL_CHECK ("index too large %d\n", index); + } +#endif + cp = ccwarea[index]; + ccwarea[index] = *(ccw1_t **) ccwarea[index]; +#if DASD_PARANOIA > 2 + if (!cp) { + INTERNAL_CHECK ("returning NULL %s\n", ""); + } +#endif + FUNCTION_EXIT ("ccwarea_deq"); + return cp; +} + +ccw1_t * +request_cpa (int index) +{ + ccw1_t *freeblk; + FUNCTION_ENTRY ("request_cpa"); + if (index > MAX_CP_POWER) { + INTERNAL_ERROR ("index too large %d\n", index); + freeblk = NULL; + goto exit; + } + if (index > CP_PER_PAGE_POWER) { + int pc = 1 << (index - CP_PER_PAGE_POWER); + do { + freeblk = (ccw1_t *) get_free_pages (GFP_ATOMIC, index - CP_PER_PAGE_POWER); + if (dasd_page_count + pc >= MAX_DASD_PAGES) { + PRINT_WARN ("Requesting too many pages..."); + } else { + int i; + for (i = 0; i < pc; i++) + dasd_page[dasd_page_count++] = + (long) freeblk + i * PAGE_SIZE; + } + FUNCTION_CONTROL ("requesting index %d", index); + if ( ! freeblk ) { + panic ("No memory received\n"); + } + } while (!freeblk); + memset(freeblk,0,PAGE_SIZE<<(index-CP_PER_PAGE_POWER)); + goto exit; + } + while (ccwarea[index] == NULL) { + ccw1_t *blk; + if (index == CP_PER_PAGE_POWER) { + do { + blk = (ccw1_t *) get_free_page (GFP_ATOMIC); + if (dasd_page_count + 1 >= MAX_DASD_PAGES) { + PRINT_WARN ("Requesting too many pages..."); + } else { + dasd_page[dasd_page_count++] = + (long) blk; + } + if (blk == NULL) { + PRINT_WARN ("Can't allocate page!\n"); + } + } while ( ! blk ); + memset(blk,0,PAGE_SIZE); + ccwarea_enq (CP_PER_PAGE_POWER, blk); + continue; + } + blk = request_cpa (index + 1); +#if DASD_PARANOIA > 1 + if (!blk) { + PRINT_WARN ("retrieved NULL"); + } +#endif /* DASD_PARANOIA */ + ccwarea_enq (index, blk); + ccwarea_enq (index, blk + (1 << index)); + } +#if DASD_PARANOIA > 2 + if (!ccwarea[index]) { + INTERNAL_ERROR ("ccwarea is NULL\n%s", ""); + } +#endif /* DASD_PARANOIA */ + + freeblk = ccwarea_deq (index); +#if DASD_PARANOIA > 1 + if (!freeblk) { + INTERNAL_ERROR ("freeblk is NULL\n%s", ""); + } +#endif /* DASD_PARANOIA */ + exit: + FUNCTION_EXIT ("request_cpa"); + return freeblk; +} + +ccw1_t * +request_cp (int size) +{ + ccw1_t *freeblk; + int index; + int blksize; + /* Determine the index of ccwarea to look at */ + for (index = 0, blksize = 1; + size > blksize; + index++, blksize = blksize << 1) { + } + if (index > MAX_CP_POWER) { + INTERNAL_ERROR ("index too large %d\n", index); + } + spin_lock (&ccw_lock); + freeblk = request_cpa (index); + spin_unlock (&ccw_lock); + if (freeblk == NULL) { + printk (KERN_WARNING PRINTK_HEADER + "No way to deliver free ccw space\n"); + } + return freeblk; +} + +void +release_cp (int size, ccw1_t * area) +{ + int index; + int blksize; + /* Determine the index of ccwarea to look at */ + for (index = 0, blksize = 1; + size > blksize; + index++, blksize = blksize << 1) { + } + if (index > MAX_CP_POWER) { + INTERNAL_ERROR ("index too large %d\n", index); + } else if (index > CP_PER_PAGE_POWER) { + free_pages ((unsigned long) area, + index - CP_PER_PAGE_POWER); + INTERNAL_CHECK ("large index used: %d\n", index); + } else { + spin_lock (&ccw_lock); + ccwarea_enq (index, area); + spin_unlock (&ccw_lock); + } + return; +} + +/* ---------------------------------------------------------- */ + +static cqr_t *cqrp = NULL; +static spinlock_t cqr_lock=SPIN_LOCK_UNLOCKED; + +void +cqf_enq (cqr_t * cqf) +{ + *(cqr_t **) cqf = cqrp; + cqrp = cqf; +} + +cqr_t * +cqf_deq (void) +{ + cqr_t *cqr = cqrp; + cqrp = *(cqr_t **) cqrp; + return cqr; +} + +cqr_t * +request_cq (void) +{ + cqr_t *cqr = NULL; + int i; + cqr_t *area; + + spin_lock (&cqr_lock); + while (cqrp == NULL) { + do { + area = (cqr_t *) get_free_page (GFP_ATOMIC); + if (area == NULL) { + printk (KERN_WARNING PRINTK_HEADER + "No memory for chanq area\n"); + } + } while ( ! area ); + memset(area,0,PAGE_SIZE); + if (dasd_page_count + 1 >= MAX_DASD_PAGES) { + PRINT_WARN ("Requesting too many pages..."); + } else { + dasd_page[dasd_page_count++] = + (long) area; + } + for (i = 0; i < 4096 / sizeof (cqr_t); i++) { + cqf_enq (area + i); + } + } + cqr = cqf_deq (); + spin_unlock (&cqr_lock); + return cqr; +} + +void +release_cq (cqr_t * cqr) +{ + spin_lock (&cqr_lock); + cqf_enq (cqr); + spin_unlock (&cqr_lock); + return; +} + +/* ----------------------------------------------------------- */ +cqr_t * +request_cqr (int cpsize, int datasize) +{ + cqr_t *cqr = NULL; + cqr = request_cq (); + if (cqr == NULL) { + printk (KERN_WARNING PRINTK_HEADER __FILE__ + "No memory for chanq request\n"); + goto exit; + } + memset (cqr, 0, sizeof (cqr_t)); + cqr -> magic = DASD_MAGIC; + if (cpsize) { + cqr->cpaddr = request_cp (cpsize); + if (cqr->cpaddr == NULL) { + printk (KERN_WARNING PRINTK_HEADER __FILE__ + "No memory for channel program\n"); + goto nocp; + } + cqr->cplength = cpsize; + } + if (datasize) { + do { + cqr->data = (char *) kmalloc (datasize, GFP_ATOMIC); + if (cqr->data == NULL) { + printk (KERN_WARNING PRINTK_HEADER __FILE__ + "No memory for cqr data area\n"); + } + } while (!cqr->data); + memset (cqr->data,0,datasize); + } + goto exit; + nocp: + release_cq (cqr); + cqr = NULL; + exit: + return cqr; +} + +int +release_cqr (cqr_t * cqr) +{ + int rc = 0; + if (cqr == NULL) { + rc = -ENOENT; + return rc; + } + if (cqr->data) { + kfree (cqr->data); + } + if (cqr->dstat) { + kfree (cqr->dstat); + } + if (cqr->cpaddr) { + release_cp (cqr->cplength, cqr->cpaddr); + } + cqr -> magic = dasd_MAGIC; + release_cq (cqr); + return rc; +} + +/* -------------------------------------------------------------- */ +void +dasd_chanq_enq (dasd_chanq_t * q, cqr_t * cqr) +{ + if (q->head != NULL) { + q->tail->next = cqr; + } else + q->head = cqr; + cqr->next = NULL; + q->tail = cqr; + q->queued_requests ++; + if (atomic_compare_and_swap(CQR_STATUS_FILLED, + CQR_STATUS_QUEUED, + &cqr->status)) { + PRINT_WARN ("q_cqr: %p status changed %d\n", + cqr,atomic_read(&cqr->status)); + atomic_set(&cqr->status,CQR_STATUS_QUEUED); + } +} + +int +dasd_chanq_deq (dasd_chanq_t * q, cqr_t * cqr) +{ + cqr_t *prev; + + if (cqr == NULL) + return -ENOENT; + if (cqr == (cqr_t *) q->head) { + q->head = cqr->next; + if (q->head == NULL) + q->tail = NULL; + } else { + prev = (cqr_t *) q->head; + while (prev && prev->next != cqr) + prev = prev->next; + if (prev == NULL) + return -ENOENT; + prev->next = cqr->next; + if (prev->next == NULL) + q->tail = prev; + } + cqr->next = NULL; + q->queued_requests --; + return release_cqr(cqr); +} + +/* -------------------------------------------------------------------------- */ +void +cql_enq_head (dasd_chanq_t * q) +{ + if (q == NULL) { + INTERNAL_ERROR ("NULL queue passed%s\n", ""); + return; + } + if (atomic_read(&q->flags) & DASD_CHANQ_ACTIVE) { + PRINT_WARN("Queue already active"); + return; + } + spin_lock(&cq_lock); + atomic_set_mask(DASD_CHANQ_ACTIVE,&q->flags); + q->next_q = cq_head; + cq_head = q; + spin_unlock(&cq_lock); +} + +void +cql_deq (dasd_chanq_t * q) +{ + dasd_chanq_t *c; + + if (cq_head == NULL) { + INTERNAL_ERROR ("Channel queue is empty%s\n", ""); + return; + } + if (q == NULL) { + INTERNAL_ERROR ("NULL queue passed%s\n", ""); + return; + } + spin_lock(&cq_lock); + if (! (atomic_read(&q->flags) & DASD_CHANQ_ACTIVE)) { + PRINT_WARN("Queue not active\n"); + } + else if (cq_head == q) { + cq_head = q->next_q; + } else { + c = cq_head; + while (c->next_q && c->next_q != q) + c = c->next_q; + if (c->next_q != q) + INTERNAL_ERROR ("Entry not in queue%s\n", ""); + else + c->next_q = q->next_q; + } + q->next_q = NULL; + atomic_clear_mask(DASD_CHANQ_ACTIVE,&q->flags); + spin_unlock(&cq_lock); +} diff --git a/drivers/s390/block/dasd_ccwstuff.h b/drivers/s390/block/dasd_ccwstuff.h new file mode 100644 index 000000000..611777e17 --- /dev/null +++ b/drivers/s390/block/dasd_ccwstuff.h @@ -0,0 +1,9 @@ +extern atomic_t chanq_tasks; +extern dasd_chanq_t *cq_head; + +cqr_t *request_cqr (int, int); +int release_cqr (cqr_t *); +int dasd_chanq_enq (dasd_chanq_t *, cqr_t *); +int dasd_chanq_deq (dasd_chanq_t *, cqr_t *); +void cql_enq_head (dasd_chanq_t * q); +void cql_deq (dasd_chanq_t * q); diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c new file mode 100644 index 000000000..30e41f815 --- /dev/null +++ b/drivers/s390/block/dasd_eckd.c @@ -0,0 +1,973 @@ +/* + * File...........: linux/drivers/s390/block/dasd_eckd.c + * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> + * Bugreports.to..: <Linux390@de.ibm.com> + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + */ + +#include <linux/stddef.h> +#include <linux/kernel.h> + +#ifdef MODULE +#include <linux/module.h> +#endif /* MODULE */ + +#include <linux/malloc.h> +#include <linux/dasd.h> +#include <asm/io.h> + +#include <asm/irq.h> + +#include "dasd_types.h" +#include "dasd_ccwstuff.h" + + +#ifdef PRINTK_HEADER +#undef PRINTK_HEADER +#endif /* PRINTK_HEADER */ +#define PRINTK_HEADER "dasd(eckd):" + +#define ECKD_C0(i) (i->home_bytes) +#define ECKD_F(i) (i -> formula) +#define ECKD_F1(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f1):(i->factors.f_0x02.f1)) +#define ECKD_F2(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f2):(i->factors.f_0x02.f2)) +#define ECKD_F3(i) (ECKD_F(i)==0x01?(i->factors.f_0x01.f3):(i->factors.f_0x02.f3)) +#define ECKD_F4(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f4):0) +#define ECKD_F5(i) (ECKD_F(i)==0x02?(i->factors.f_0x02.f5):0) +#define ECKD_F6(i) (i -> factor6) +#define ECKD_F7(i) (i -> factor7) +#define ECKD_F8(i) (i -> factor8) + +#define DASD_ECKD_CCW_LOCATE_RECORD 0x47 + +#define DASD_ECKD_CCW_READ_HOME_ADDRESS 0x0a +#define DASD_ECKD_CCW_WRITE_HOME_ADDRESS 0x09 + +#define DASD_ECKD_CCW_READ_RECORD_ZERO 0x16 +#define DASD_ECKD_CCW_WRITE_RECORD_ZERO 0x15 + +#define DASD_ECKD_CCW_READ_COUNT 0x12 +#define DASD_ECKD_CCW_READ 0x06 +#define DASD_ECKD_CCW_READ_MT 0x86 +#define DASD_ECKD_CCW_WRITE 0x05 +#define DASD_ECKD_CCW_WRITE_MT 0x85 +#define DASD_ECKD_CCW_READ_CKD 0x1e +#define DASD_ECKD_CCW_READ_CKD_MT 0x9e +#define DASD_ECKD_CCW_WRITE_CKD 0x1d +#define DASD_ECKD_CCW_WRITE_CKD_MT 0x9d + +typedef +struct { + __u16 cyl; + __u16 head; +} __attribute__ ((packed)) + +ch_t; + +typedef +struct { + __u16 cyl; + __u16 head; + __u32 sector; +} __attribute__ ((packed)) + +chs_t; + +typedef +struct { + __u16 cyl; + __u16 head; + __u8 record; +} __attribute__ ((packed)) + +chr_t; + +typedef +struct { + __u16 cyl; + __u16 head; + __u32 sector; +} geom_t; + +typedef struct { + struct { + struct { + unsigned char identifier:2; + unsigned char token_id:1; + unsigned char sno_valid:1; + unsigned char subst_sno:1; + unsigned char recNED:1; + unsigned char emuNED:1; + unsigned char reserved:1; + } __attribute__ ((packed)) flags; + __u8 descriptor; + __u8 dev_class; + __u8 reserved; + unsigned char dev_type[6]; + unsigned char dev_model[3]; + unsigned char HDA_manufacturer[3]; + unsigned char HDA_location[2]; + unsigned char HDA_seqno[12]; + __u16 ID; + } __attribute__ ((packed)) ned1; + struct { + struct { + unsigned char identifier:2; + unsigned char token_id:1; + unsigned char sno_valid:1; + unsigned char subst_sno:1; + unsigned char recNED:1; + unsigned char emuNED:1; + unsigned char reserved:1; + } __attribute__ ((packed)) flags; + __u8 descriptor; + __u8 reserved[2]; + unsigned char dev_type[6]; + unsigned char dev_model[3]; + unsigned char DASD_manufacturer[3]; + unsigned char DASD_location[2]; + unsigned char DASD_seqno[12]; + __u16 ID; + } __attribute__ ((packed)) ned2; + struct { + struct { + unsigned char identifier:2; + unsigned char token_id:1; + unsigned char sno_valid:1; + unsigned char subst_sno:1; + unsigned char recNED:1; + unsigned char emuNED:1; + unsigned char reserved:1; + } __attribute__ ((packed)) flags; + __u8 descriptor; + __u8 reserved[2]; + unsigned char cont_type[6]; + unsigned char cont_model[3]; + unsigned char cont_manufacturer[3]; + unsigned char cont_location[2]; + unsigned char cont_seqno[12]; + __u16 ID; + } __attribute__ ((packed)) ned3; + struct { + struct { + unsigned char identifier:2; + unsigned char token_id:1; + unsigned char sno_valid:1; + unsigned char subst_sno:1; + unsigned char recNED:1; + unsigned char emuNED:1; + unsigned char reserved:1; + } __attribute__ ((packed)) flags; + __u8 descriptor; + __u8 reserved[2]; + unsigned char cont_type[6]; + unsigned char empty[3]; + unsigned char cont_manufacturer[3]; + unsigned char cont_location[2]; + unsigned char cont_seqno[12]; + __u16 ID; + } __attribute__ ((packed)) ned4; + unsigned char ned5[32]; + unsigned char ned6[32]; + unsigned char ned7[32]; + struct { + struct { + unsigned char identifier:2; + unsigned char reserved:6; + } __attribute__ ((packed)) flags; + __u8 selector; + __u16 interfaceID; + __u32 reserved; + __u16 subsystemID; + struct { + unsigned char sp0:1; + unsigned char sp1:1; + unsigned char reserved:5; + unsigned char scluster:1; + } __attribute__ ((packed)) spathID; + __u8 unit_address; + __u8 dev_ID; + __u8 dev_address; + __u8 adapterID; + __u16 link_address; + struct { + unsigned char parallel:1; + unsigned char escon:1; + unsigned char reserved:1; + unsigned char ficon:1; + unsigned char reserved2:4; + } __attribute__ ((packed)) protocol_type; + struct { + unsigned char PID_in_236:1; + unsigned char reserved:7; + } __attribute__ ((packed)) format_flags; + __u8 log_dev_address; + unsigned char reserved2[12]; + } __attribute__ ((packed)) neq; + +} __attribute__ ((packed)) + +eckd_confdata_t; + +typedef +struct { + struct { + unsigned char perm:2; /* Permissions on this extent */ + unsigned char reserved:1; + unsigned char seek:2; /* Seek control */ + unsigned char auth:2; /* Access authorization */ + unsigned char pci:1; /* PCI Fetch mode */ + } __attribute__ ((packed)) mask; + struct { + unsigned char mode:2; /* Architecture mode */ + unsigned char ckd:1; /* CKD Conversion */ + unsigned char operation:3; /* Operation mode */ + unsigned char cfw:1; /* Cache fast write */ + unsigned char dfw:1; /* DASD fast write */ + } __attribute__ ((packed)) attributes; + __u16 short blk_size; /* Blocksize */ + __u16 fast_write_id; + __u8 unused; + __u8 reserved; + ch_t beg_ext; + ch_t end_ext; +} __attribute__ ((packed, aligned (32))) + +DE_eckd_data_t; + +typedef +struct { + struct { + unsigned char orientation:2; + unsigned char operation:6; + } __attribute__ ((packed)) operation; + struct { + unsigned char last_bytes_used:1; + unsigned char reserved:6; + unsigned char read_count_suffix:1; + } __attribute__ ((packed)) auxiliary; + __u8 unused; + __u8 count; + ch_t seek_addr; + chr_t search_arg; + __u8 sector; + __u16 length; +} __attribute__ ((packed, aligned (32))) + +LO_eckd_data_t; + +/* Stuff for handling home addresses */ +typedef struct { + __u8 skip_control[14]; + __u16 cell_number; + __u8 physical_addr[3]; + __u8 flag; + ch_t track_addr; + __u8 reserved; + __u8 key_length; + __u8 reserved2[2]; +} __attribute__ ((packed, aligned (32))) + +eckd_home_t; + + +static unsigned int +round_up_multiple (unsigned int no, unsigned int mult) +{ + int rem = no % mult; + return (rem ? no - rem + mult : no); +/* return (no % mult ? no - (no % mult) + mult : no); */ +} + +static unsigned int +ceil_quot (unsigned int d1, unsigned int d2) +{ + return (d1 + (d2 - 1)) / d2; +} + +static int +bytes_per_record (dasd_eckd_characteristics_t * rdc, + int kl, /* key length */ + int dl /* data length */ ) +{ + int bpr = 0; + switch (rdc->formula) { + case 0x01:{ + unsigned int fl1, fl2; + fl1 = round_up_multiple (ECKD_F2 (rdc) + dl, + ECKD_F1 (rdc)); + fl2 = round_up_multiple (kl ? ECKD_F2 (rdc) + kl : 0, + ECKD_F1 (rdc)); + bpr = fl1 + fl2; + break; + } + case 0x02:{ + unsigned int fl1, fl2, int1, int2; + int1 = ceil_quot (dl + ECKD_F6 (rdc), + ECKD_F5 (rdc) << 1); + int2 = ceil_quot (kl + ECKD_F6 (rdc), + ECKD_F5 (rdc) << 1); + fl1 = round_up_multiple (ECKD_F1 (rdc) * + ECKD_F2 (rdc) + + (dl + ECKD_F6 (rdc) + + ECKD_F4 (rdc) * int1), + ECKD_F1 (rdc)); + fl2 = round_up_multiple (ECKD_F1 (rdc) * + ECKD_F3 (rdc) + + (kl + ECKD_F6 (rdc) + + ECKD_F4 (rdc) * int2), + ECKD_F1 (rdc)); + bpr = fl1 + fl2; + break; + } + default: + INTERNAL_ERROR ("unknown formula%d\n", rdc->formula); + } + return bpr; +} + +static inline unsigned int +bytes_per_track (dasd_eckd_characteristics_t * rdc) +{ + return *(unsigned int *) (rdc->byte_per_track) >> 8; +} + +static unsigned int +recs_per_track (dasd_eckd_characteristics_t * rdc, + unsigned int kl, unsigned int dl) +{ + int rpt = 0; + int dn; + switch ( rdc -> dev_type ) { + case 0x3380: + if (kl) + return 1499 / (15 + + 7 + ceil_quot (kl + 12, 32) + + ceil_quot (dl + 12, 32)); + else + return 1499 / (15 + ceil_quot (dl + 12, 32)); + case 0x3390: + dn = ceil_quot (dl + 6, 232) + 1; + if (kl) { + int kn = ceil_quot (kl + 6, 232) + 1; + return 1729 / (10 + + 9 + ceil_quot (kl + 6 * kn, 34) + + 9 + ceil_quot (dl + 6 * dn, 34)); + } else + return 1729 / (10 + + 9 + ceil_quot (dl + 6 * dn, 34)); + case 0x9345: + dn = ceil_quot (dl + 6, 232) + 1; + if (kl) { + int kn = ceil_quot (kl + 6, 232) + 1; + return 1420 / (18 + + 7 + ceil_quot (kl + 6 * kn, 34) + + ceil_quot (dl + 6 * dn, 34)); + } else + return 1420 / (18 + + 7 + ceil_quot (dl + 6 * dn, 34)); + } + return rpt; +} + +static +void +define_extent (ccw1_t * de_ccw, + DE_eckd_data_t * data, + int trk, + int totrk, + int cmd, + dasd_information_t * info) +{ + ch_t geo, beg, end; + + geo.cyl = info->rdc_data->eckd.no_cyl; + geo.head = info->rdc_data->eckd.trk_per_cyl; + beg.cyl = trk / geo.head; + beg.head = trk % geo.head; + end.cyl = totrk / geo.head; + end.head = totrk % geo.head; + + memset (de_ccw, 0, sizeof (ccw1_t)); + de_ccw->cmd_code = CCW_DEFINE_EXTENT; + de_ccw->count = 16; + de_ccw->cda = (void *) virt_to_phys (data); + + memset (data, 0, sizeof (DE_eckd_data_t)); + switch (cmd) { + case DASD_ECKD_CCW_READ_HOME_ADDRESS: + case DASD_ECKD_CCW_READ_RECORD_ZERO: + case DASD_ECKD_CCW_READ: + case DASD_ECKD_CCW_READ_MT: + case DASD_ECKD_CCW_READ_CKD: /* Fallthrough */ + case DASD_ECKD_CCW_READ_CKD_MT: + case DASD_ECKD_CCW_READ_COUNT: + data->mask.perm = 0x1; + data->attributes.operation = 0x3; /* enable seq. caching */ + break; + case DASD_ECKD_CCW_WRITE: + case DASD_ECKD_CCW_WRITE_MT: + data->attributes.operation = 0x3; /* enable seq. caching */ + break; + case DASD_ECKD_CCW_WRITE_CKD: + case DASD_ECKD_CCW_WRITE_CKD_MT: + data->attributes.operation = 0x1; /* format through cache */ + break; + case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: + case DASD_ECKD_CCW_WRITE_RECORD_ZERO: + data->mask.perm = 0x3; + data->mask.auth = 0x1; + data->attributes.operation = 0x1; /* format through cache */ + break; + default: + INTERNAL_ERROR ("unknown opcode 0x%x\n", cmd); + break; + } + data->attributes.mode = 0x3; + data->beg_ext.cyl = beg.cyl; + data->beg_ext.head = beg.head; + data->end_ext.cyl = end.cyl; + data->end_ext.head = end.head; +} + +static inline void +locate_record (ccw1_t * lo_ccw, + LO_eckd_data_t * data, + int trk, + int rec_on_trk, + int no_rec, + int cmd, + dasd_information_t * info) +{ + ch_t geo = + {info->rdc_data->eckd.no_cyl, + info->rdc_data->eckd.trk_per_cyl}; + ch_t seek = + {trk / (geo.head), trk % (geo.head)}; + int reclen = info->sizes.bp_block; + memset (lo_ccw, 0, sizeof (ccw1_t)); + lo_ccw->cmd_code = DASD_ECKD_CCW_LOCATE_RECORD; + lo_ccw->count = 16; + lo_ccw->cda = (void *) virt_to_phys (data); + + memset (data, 0, sizeof (LO_eckd_data_t)); + switch (cmd) { + case DASD_ECKD_CCW_WRITE_HOME_ADDRESS: + data->operation.orientation = 0x3; + data->operation.operation = 0x03; + break; + case DASD_ECKD_CCW_READ_HOME_ADDRESS: + data->operation.orientation = 0x3; + data->operation.operation = 0x16; + break; + case DASD_ECKD_CCW_WRITE_RECORD_ZERO: + data->operation.orientation = 0x3; + data->operation.operation = 0x03; + data->count++; + break; + case DASD_ECKD_CCW_READ_RECORD_ZERO: + data->operation.orientation = 0x3; + data->operation.operation = 0x16; + data->count++; + break; + case DASD_ECKD_CCW_WRITE: + case DASD_ECKD_CCW_WRITE_MT: + data->auxiliary.last_bytes_used = 0x1; + data->length = reclen; + data->operation.operation = 0x01; + break; + case DASD_ECKD_CCW_WRITE_CKD: + case DASD_ECKD_CCW_WRITE_CKD_MT: + data->auxiliary.last_bytes_used = 0x1; + data->length = reclen; + data->operation.operation = 0x03; + break; + case DASD_ECKD_CCW_READ: + case DASD_ECKD_CCW_READ_MT: + data->auxiliary.last_bytes_used = 0x1; + data->length = reclen; + data->operation.operation = 0x06; + break; + case DASD_ECKD_CCW_READ_CKD: + case DASD_ECKD_CCW_READ_CKD_MT: + data->auxiliary.last_bytes_used = 0x1; + data->length = reclen; + data->operation.operation = 0x16; + break; + case DASD_ECKD_CCW_READ_COUNT: + data->operation.operation = 0x06; + break; + default: + INTERNAL_ERROR ("unknown opcode 0x%x\n", cmd); + } + memcpy (&(data->seek_addr), &seek, sizeof (ch_t)); + memcpy (&(data->search_arg), &seek, sizeof (ch_t)); + data->search_arg.record = rec_on_trk; + data->count += no_rec; +} + +void +dasd_eckd_print_error (devstat_t * stat) +{ + int sct, sl; + char *sense = stat->ii.sense.data; + PRINT_WARN ("IRQ on devno %x: with intparm:%x DS:0x%02x CS:0x%02x\n", + stat->devno, stat->intparm, stat->dstat, stat->cstat); + PRINT_WARN ("Failing CCW: %p\n", (ccw1_t *) stat->cpa); + for (sl = 0; sl < 4; sl++) { + PRINT_DEBUG ("Sense:"); + for (sct = 0; sct < 8; sct++) { + printk (" %2d:0x%02x", + 8 * sl + sct, sense[8 * sl + sct]); + } + printk ("\n"); + } + if (sense[27] & 0x80) { /* 32 Byte Sense Data */ + PRINT_INFO ("Sense Data is 32 Byte information\n"); + PRINT_INFO ("Format: %x Exception class %x\n", + sense[6] & 0x0f, sense[22] >> 4); + } else { /* 24 Byte Sense Data */ + PRINT_INFO ("Sense Data is 24 Byte information\n"); + PRINT_INFO ("FMT: %x MSG %x, %s MSGb to SYSOP\n", + sense[7] >> 4, sense[7] & 0x0f, + sense[1] & 0x10 ? "" : "no"); + } +} + +int +dasd_eckd_format_track (int di, int trk, int bs) +{ + int rc = 0; + int i; + int flags = 0x00; /* FORMAT_R0 = 0x01, FORMAT_HA = 0x03 */ + dasd_information_t * info=dasd_info[di]; + cqr_t *fcp; + DE_eckd_data_t *DE_data; + LO_eckd_data_t *LO_data; + eckd_count_t *ct_data; + eckd_count_t *r0_data; + ccw1_t *last_ccw; + int retries = 5; + + int rpt = recs_per_track (&(info->rdc_data->eckd), 0, bs); + int cyl = trk / info->rdc_data->eckd.trk_per_cyl; + int head = trk % info->rdc_data->eckd.trk_per_cyl; + + fcp = request_cqr (2 + 1 + rpt, + sizeof (DE_eckd_data_t) + + sizeof (LO_eckd_data_t) + + (rpt + 1) * sizeof (eckd_count_t)); + fcp -> devindex=di; + DE_data = (DE_eckd_data_t *) fcp->data; + LO_data = (LO_eckd_data_t *) (((long) DE_data) + + sizeof (DE_eckd_data_t)); + r0_data = (eckd_count_t *) (((long) LO_data) + + sizeof (LO_eckd_data_t)); + ct_data = (eckd_count_t *) (((long) r0_data) + + sizeof (eckd_count_t)); + last_ccw = fcp->cpaddr; + switch (flags) { + case 0x03: + define_extent (last_ccw, DE_data, trk, trk, + DASD_ECKD_CCW_WRITE_HOME_ADDRESS, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + locate_record (last_ccw, LO_data, trk, 0, rpt, + DASD_ECKD_CCW_WRITE_HOME_ADDRESS, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + break; + case 0x01: + define_extent (last_ccw, DE_data, trk, trk, + DASD_ECKD_CCW_WRITE_RECORD_ZERO, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + locate_record (last_ccw, LO_data, trk, 0, rpt, + DASD_ECKD_CCW_WRITE_RECORD_ZERO, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + break; + case 0x00: + define_extent (last_ccw, DE_data, trk, trk, + DASD_ECKD_CCW_WRITE_CKD, info); + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + locate_record (last_ccw, LO_data, trk, 0, rpt, + DASD_ECKD_CCW_WRITE_CKD, info); + LO_data->length = bs; + last_ccw->flags = CCW_FLAG_CC; + last_ccw++; + break; + default: + PRINT_WARN ("Unknown format flags...%d\n", flags); + return -EINVAL; + } + if (flags & 0x02) { + PRINT_WARN ("Unsupported format flag...%d\n", flags); + return -EINVAL; + } + if (flags & 0x01) { /* write record zero */ + memset (r0_data, 0, sizeof (eckd_count_t)); + r0_data->cyl = cyl; + r0_data->head = head; + r0_data->record = 0; + r0_data->kl = 0; + r0_data->dl = 8; + last_ccw->cmd_code = 0x03; + last_ccw->count = 8; + last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI; + last_ccw->cda = (void *) virt_to_phys (r0_data); + last_ccw++; + } + /* write remaining records */ + for (i = 0; i < rpt; i++, last_ccw++) { + memset (ct_data + i, 0, sizeof (eckd_count_t)); + (ct_data + i)->cyl = cyl; + (ct_data + i)->head = head; + (ct_data + i)->record = i + 1; + (ct_data + i)->kl = 0; + (ct_data + i)->dl = bs; + last_ccw->cmd_code = DASD_ECKD_CCW_WRITE_CKD; + last_ccw->flags = CCW_FLAG_CC | CCW_FLAG_SLI; + last_ccw->count = 8; + last_ccw->cda = (void *) + virt_to_phys (ct_data + i); + } + (last_ccw - 1)->flags &= ~(CCW_FLAG_CC | CCW_FLAG_DC); + fcp -> devindex = di; + fcp -> flags = DASD_DO_IO_SLEEP; + do { + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + int irq; + int cs; + + irq = dasd_info[fcp->devindex]->info.irq; + s390irq_spin_lock_irqsave (irq, flags); + atomic_set(&fcp->status,CQR_STATUS_QUEUED); + rc = dasd_start_IO ( fcp ); + add_wait_queue (&dasd_waitq, &wait); + do { + current->state = TASK_UNINTERRUPTIBLE; + s390irq_spin_unlock_irqrestore (irq, flags); + schedule (); + s390irq_spin_lock_irqsave (irq, flags); + } while (((cs = atomic_read (&fcp->status)) != + CQR_STATUS_DONE) && + (cs != CQR_STATUS_ERROR)); + remove_wait_queue (&dasd_waitq, &wait); + s390irq_spin_unlock_irqrestore (irq, flags); + + retries --; + } while ( (rc || (atomic_read(&fcp->status) != CQR_STATUS_DONE)) && + retries); + if ((rc || (atomic_read(&fcp->status) != CQR_STATUS_DONE))) + rc = -EIO; + release_cqr (fcp); + return rc; +} + +int +dasd_eckd_ck_devinfo (dev_info_t * info) +{ + return 0; +} + +cqr_t * +dasd_eckd_build_req (int devindex, + struct request * req) +{ + cqr_t *rw_cp = NULL; + ccw1_t *ccw; + + DE_eckd_data_t *DE_data; + LO_eckd_data_t *LO_data; + struct buffer_head *bh; + int rw_cmd; + dasd_information_t *info = dasd_info[devindex]; + int blk_per_trk = recs_per_track (&(info->rdc_data->eckd), + 0, info->sizes.bp_block); + int byt_per_blk = info->sizes.bp_block; + int noblk = req-> nr_sectors >> info->sizes.s2b_shift; + int btrk = (req->sector >> info->sizes.s2b_shift) / blk_per_trk; + int etrk = ((req->sector + req->nr_sectors - 1) >> + info->sizes.s2b_shift) / blk_per_trk; + + if ( ! noblk ) { + PRINT_ERR("No blocks to write...returning\n"); + return NULL; + } + + if (req->cmd == READ) { + rw_cmd = DASD_ECKD_CCW_READ_MT; + } else +#if DASD_PARANOIA > 2 + if (req->cmd == WRITE) +#endif /* DASD_PARANOIA */ + { + rw_cmd = DASD_ECKD_CCW_WRITE_MT; + } +#if DASD_PARANOIA > 2 + else { + PRINT_ERR ("Unknown command %d\n", req->cmd); + return NULL; + } +#endif /* DASD_PARANOIA */ + /* Build the request */ + rw_cp = request_cqr (2 + noblk, + sizeof (DE_eckd_data_t) + + sizeof (LO_eckd_data_t)); + if ( ! rw_cp ) { + return NULL; + } + DE_data = rw_cp->data; + LO_data = rw_cp->data + sizeof (DE_eckd_data_t); + ccw = rw_cp->cpaddr; + + define_extent (ccw, DE_data, btrk, etrk, rw_cmd, info); + ccw->flags = CCW_FLAG_CC; + ccw++; + locate_record (ccw, LO_data, btrk, + (req->sector >> info->sizes.s2b_shift) % + blk_per_trk + 1, + req->nr_sectors >> info->sizes.s2b_shift, + rw_cmd, info); + ccw->flags = CCW_FLAG_CC; + for (bh = req->bh; bh; bh = bh->b_reqnext) { + long size; + for (size = 0; size < bh->b_size; size += byt_per_blk) { + ccw++; + ccw->flags = CCW_FLAG_CC; + ccw->cmd_code = rw_cmd; + ccw->count = byt_per_blk; + ccw->cda = (void *) virt_to_phys (bh->b_data + size); + } + } + ccw->flags &= ~(CCW_FLAG_DC | CCW_FLAG_CC); + return rw_cp; +} + +cqr_t * +dasd_eckd_rw_label (int devindex, int rw, char *buffer) +{ + int cmd_code = 0x03; + dasd_information_t *info = dasd_info[devindex]; + cqr_t *cqr; + ccw1_t *ccw; + + switch (rw) { + case READ: + cmd_code = DASD_ECKD_CCW_READ; + break; + case WRITE: + cmd_code = DASD_ECKD_CCW_WRITE; + break; +#if DASD_PARANOIA > 2 + default: + INTERNAL_ERROR ("unknown cmd %d", rw); + return NULL; +#endif /* DASD_PARANOIA */ + } + cqr = request_cqr (3, sizeof (DE_eckd_data_t) + + sizeof (LO_eckd_data_t)); + ccw = cqr->cpaddr; + define_extent (ccw, cqr->data, 0, 0, cmd_code, info); + ccw->flags |= CCW_FLAG_CC; + ccw++; + locate_record (ccw, cqr->data + 1, 0, 2, 1, cmd_code, info); + ccw->flags |= CCW_FLAG_CC; + ccw++; + ccw->cmd_code = cmd_code; + ccw->flags |= CCW_FLAG_SLI; + ccw->count = sizeof (dasd_volume_label_t); + ccw->cda = (void *) virt_to_phys ((void *) buffer); + return cqr; + +} + +void +dasd_eckd_print_char (dasd_characteristics_t * i) +{ + dasd_eckd_characteristics_t * c = + (dasd_eckd_characteristics_t *)i; + PRINT_INFO ("%x/%x (%x/%x) Cyl: %d Head: %d Sec: %d \n", + c->dev_type, c->dev_model, + c->cu_type, c->cu_model.model, + c->no_cyl, c->trk_per_cyl, + c->sec_per_trk); + PRINT_INFO ("Estimate: %d Byte/trk %d byte/kByte %d kByte/trk \n", + bytes_per_track (c), + bytes_per_record (c, 0, 1024), + recs_per_track (c, 0, 1024)); +}; + +int +dasd_eckd_ck_char (dasd_characteristics_t * i) +{ + int rc = 0; + dasd_eckd_print_char (i); + return rc; +} + +int +dasd_eckd_format (int devindex, format_data_t * fdata) +{ + int rc = 0; + int i; + dasd_information_t *info = dasd_info[devindex]; + format_data_t fd; + + if (!fdata) { + fd.start_unit = 0; + fd.stop_unit = info->rdc_data->eckd.no_cyl * + info->rdc_data->eckd.trk_per_cyl - 1; + fd.blksize = 4096; + } else { + memcpy (&fd, fdata, sizeof (format_data_t)); + if ( fd.stop_unit == -1 ) { + fd.stop_unit = info->rdc_data->eckd.no_cyl * + info->rdc_data->eckd.trk_per_cyl - 1; + } + if ( fd.blksize == 0 ) { + fd.blksize = 4096; + } + } + PRINT_INFO("Formatting device %d from %d to %d with bs %d\n", + devindex,fd.start_unit,fd.stop_unit,fd.blksize); + if ( fd.start_unit > fd.stop_unit ) { + PRINT_WARN ("start unit .gt. stop unit\n"); + return -EINVAL; + } + if ( (fd.start_unit > info->rdc_data->eckd.no_cyl * + info->rdc_data->eckd.trk_per_cyl - 1) ) { + PRINT_WARN ("start unit beyond end of disk\n"); + return -EINVAL; + } + if ( (fd.stop_unit > info->rdc_data->eckd.no_cyl * + info->rdc_data->eckd.trk_per_cyl - 1) ) { + PRINT_WARN ("stop unit beyond end of disk\n"); + return -EINVAL; + } + switch (fd.blksize) { + case 512: + case 1024: + case 2048: + case 4096: + break; + default: + PRINT_WARN ("invalid blocksize\n"); + return -EINVAL; + } + for (i = fd.start_unit; i <= fd.stop_unit; i++) { + /* print 20 messages per disk at all */ + if ( ! ( i % (info->rdc_data->eckd.trk_per_cyl * + (info->rdc_data->eckd.no_cyl / 20 ) ))) { + PRINT_INFO ("Format %d Cylinder: %d\n",devindex, + i/info->rdc_data->eckd.trk_per_cyl); + } + rc = dasd_eckd_format_track (devindex, i, fd.blksize); + if (rc) { + PRINT_WARN ("Formatting of Track %d failed...exiting\n", i); + break; + } + } + PRINT_INFO("Formated device %d from %d to %d with bs %d\n", + devindex,fd.start_unit,fd.stop_unit,fd.blksize); + return rc; +} + +cqr_t * +dasd_eckd_fill_sizes_first (int di) +{ + cqr_t *rw_cp = NULL; + ccw1_t *ccw; + DE_eckd_data_t *DE_data; + LO_eckd_data_t *LO_data; + dasd_information_t *info = dasd_info[di]; + eckd_count_t *count_data= &(info->private.eckd.count_data); + rw_cp = request_cqr (3, + sizeof (DE_eckd_data_t) + + sizeof (LO_eckd_data_t)); + DE_data = rw_cp->data; + LO_data = rw_cp->data + sizeof (DE_eckd_data_t); + ccw = rw_cp->cpaddr; + define_extent (ccw, DE_data, 0, 0, DASD_ECKD_CCW_READ_COUNT, info); + ccw->flags = CCW_FLAG_CC; + ccw++; + locate_record (ccw, LO_data, 0, 1, 1, DASD_ECKD_CCW_READ_COUNT, info); + ccw->flags = CCW_FLAG_CC; + ccw++; + ccw->cmd_code = DASD_ECKD_CCW_READ_COUNT; + ccw->count = 8; + ccw->cda = (void *) __pa (count_data); + rw_cp->devindex = di; + atomic_set(&rw_cp->status,CQR_STATUS_FILLED); + return rw_cp; +} + +int dasd_eckd_fill_sizes_last (int devindex) +{ + int sb; + dasd_information_t *in = dasd_info[devindex]; + int bs = in->private.eckd.count_data.dl; + if (bs <= 0) { + PRINT_INFO("Cannot figure out blocksize. did you format the disk?\n"); + memset (&(in -> sizes), 0, sizeof(dasd_sizes_t )); + return -EMEDIUMTYPE; + } else { + in->sizes.bp_block = bs; + } + in->sizes.bp_sector = in->sizes.bp_block; + + in->sizes.b2k_shift = 0; /* bits to shift a block to get 1k */ + for (sb = 1024; sb < bs; sb = sb << 1) + in->sizes.b2k_shift++; + + in->sizes.s2b_shift = 0; /* bits to shift 512 to get a block */ + for (sb = 512; sb < bs; sb = sb << 1) + in->sizes.s2b_shift++; + + in->sizes.blocks = in->rdc_data->eckd.no_cyl * + in->rdc_data->eckd.trk_per_cyl * + recs_per_track (&(in->rdc_data->eckd), 0, bs); + in->sizes.kbytes = in->sizes.blocks << in->sizes.b2k_shift; + + PRINT_INFO ("Verified: %d B/trk %d B/Blk(%d B) %d Blks/trk %d kB/trk \n", + bytes_per_track (&(in->rdc_data->eckd)), + bytes_per_record (&(in->rdc_data->eckd), 0, in->sizes.bp_block), + in->sizes.bp_block, + recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block), + (recs_per_track (&(in->rdc_data->eckd), 0, in->sizes.bp_block) << + in->sizes.b2k_shift )); + return 0; +} + +dasd_operations_t dasd_eckd_operations = +{ + ck_devinfo: dasd_eckd_ck_devinfo, + get_req_ccw: dasd_eckd_build_req, + rw_label: dasd_eckd_rw_label, + ck_characteristics: dasd_eckd_ck_char, + fill_sizes_first: dasd_eckd_fill_sizes_first, + fill_sizes_last: dasd_eckd_fill_sizes_last, + dasd_format: dasd_eckd_format, +}; + +/* + * Overrides for Emacs so that we follow Linus's tabbing style. + * Emacs will notice this stuff at the end of the file and automatically + * adjust the settings for this buffer only. This must remain at the end + * of the file. + * --------------------------------------------------------------------------- + * Local variables: + * c-indent-level: 4 + * c-brace-imaginary-offset: 0 + * c-brace-offset: -4 + * c-argdecl-indent: 4 + * c-label-offset: -4 + * c-continued-statement-offset: 4 + * c-continued-brace-offset: 0 + * indent-tabs-mode: nil + * tab-width: 8 + * End: + */ diff --git a/drivers/s390/block/dasd_erp.c b/drivers/s390/block/dasd_erp.c new file mode 100644 index 000000000..9028b797f --- /dev/null +++ b/drivers/s390/block/dasd_erp.c @@ -0,0 +1,21 @@ +/* + * File...........: linux/drivers/s390/block/dasd_erp.c + * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> + * Bugreports.to..: <Linux390@de.ibm.com> + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 + */ + +#include <asm/irq.h> +#include <linux/dasd.h> +#include "dasd_erp.h" +#include "dasd_types.h" + +dasd_era_t +dasd_erp_examine ( cqr_t * cqr) +{ + devstat_t *stat = cqr->dstat ; + if ( stat->cstat == 0x00 && + stat->dstat == (DEV_STAT_CHN_END|DEV_STAT_DEV_END ) ) + return dasd_era_none; + return dasd_era_fatal; +} diff --git a/drivers/s390/block/dasd_erp.h b/drivers/s390/block/dasd_erp.h new file mode 100644 index 000000000..ab92bd122 --- /dev/null +++ b/drivers/s390/block/dasd_erp.h @@ -0,0 +1,15 @@ +/* + * File...........: linux/drivers/s390/block/dasd_erp.h + * Author(s)......: Holger Smolinski <Holger.Smolinski@de.ibm.com> + * Bugreports.to..: <Linux390@de.ibm.com> + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 2000 + */ + +#include "dasd_types.h" + +typedef enum { + dasd_era_fatal = -1, + dasd_era_none = 0 +} dasd_era_t; + +dasd_era_t dasd_erp_examine ( cqr_t * ); diff --git a/drivers/s390/block/dasd_mdsk.c b/drivers/s390/block/dasd_mdsk.c new file mode 100644 index 000000000..63de4a6b4 --- /dev/null +++ b/drivers/s390/block/dasd_mdsk.c @@ -0,0 +1,14 @@ +#include <linux/dasd.h> +#include "dasd_types.h" +#include "dasd_erp.h" + +dasd_operations_t dasd_mdsk_operations = +{ + NULL, + /* dasd_mdsk_ck_devinfo, + dasd_mdsk_build_req, + dasd_mdsk_rw_label, + dasd_mdsk_ck_char, + dasd_mdsk_fill_sizes, + dasd_mdsk_format, */ +}; diff --git a/drivers/s390/block/dasd_proc.c b/drivers/s390/block/dasd_proc.c new file mode 100644 index 000000000..e757c435f --- /dev/null +++ b/drivers/s390/block/dasd_proc.c @@ -0,0 +1,116 @@ +/* + Structure of the proc filesystem: + /proc/dasd/ + /proc/dasd/devices # List of devices + /proc/dasd/ddabcd # Device node for devno abcd + /proc/dasd/ddabcd1 # Device node for partition abcd + /proc/dasd/abcd # Device information for devno abcd +*/ + +#include <linux/proc_fs.h> + +#include <linux/dasd.h> + +#include "dasd_types.h" + +int dasd_proc_read_devices ( char *, char **, off_t, int); +#ifdef DASD_PROFILE +extern int dasd_proc_read_statistics ( char *, char **, off_t, int); +extern int dasd_proc_read_debug ( char *, char **, off_t, int); +#endif /* DASD_PROFILE */ + +struct proc_dir_entry dasd_proc_root_entry = { + 0, + 4,"dasd", + S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, +}; + +struct proc_dir_entry dasd_proc_devices_entry = { + 0, + 7,"devices", + S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, + &dasd_proc_read_devices, +}; + +#ifdef DASD_PROFILE +struct proc_dir_entry dasd_proc_stats_entry = { + 0, + 10,"statistics", + S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, + &dasd_proc_read_statistics, +}; + +struct proc_dir_entry dasd_proc_debug_entry = { + 0, + 5,"debug", + S_IFREG | S_IRUGO | S_IXUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, + &dasd_proc_read_debug, +}; +#endif /* DASD_PROFILE */ + +struct proc_dir_entry dasd_proc_device_template = { + 0, + 6,"dd????", + S_IFBLK | S_IRUGO | S_IWUSR | S_IWGRP, + 1,0,0, + 0, + NULL, +}; + +void +dasd_proc_init ( void ) +{ + proc_register( & proc_root, & dasd_proc_root_entry); + proc_register( & dasd_proc_root_entry, & dasd_proc_devices_entry); +#ifdef DASD_PROFILE + proc_register( & dasd_proc_root_entry, & dasd_proc_stats_entry); + proc_register( & dasd_proc_root_entry, & dasd_proc_debug_entry); +#endif /* DASD_PROFILE */ +} + + +int +dasd_proc_read_devices ( char * buf, char **start, off_t off, int len) +{ + int i; + len = sprintf ( buf, "dev# MAJ minor node Format\n"); + for ( i = 0; i < DASD_MAX_DEVICES; i++ ) { + dasd_information_t *info = dasd_info[i]; + if ( ! info ) + continue; + if ( len >= PAGE_SIZE - 80 ) + len += sprintf ( buf + len, "terminated...\n"); + len += sprintf ( buf + len, + "%04X %3d %5d /dev/dasd%c", + dasd_info[i]->info.devno, + DASD_MAJOR, + i << PARTN_BITS, + 'a' + i ); + if (info->flags == DASD_INFO_FLAGS_NOT_FORMATTED) { + len += sprintf ( buf + len, " n/a"); + } else { + len += sprintf ( buf + len, " %6d", + info->sizes.bp_block); + } + len += sprintf ( buf + len, "\n"); + } + return len; +} + + +void +dasd_proc_add_node (int di) +{ +} diff --git a/drivers/s390/block/dasd_profile.c b/drivers/s390/block/dasd_profile.c new file mode 100644 index 000000000..7484f2be2 --- /dev/null +++ b/drivers/s390/block/dasd_profile.c @@ -0,0 +1,208 @@ +#include <linux/mm.h> + +#include <linux/dasd.h> + +#include "dasd_types.h" + +#define PRINTK_HEADER "dasd_profile:" + +static long dasd_io_reqs=0; /* number of requests processed at all */ +static long dasd_io_secs[16]; /* histogram of request's sizes */ +static long dasd_io_times[16]; /* histogram of requests's times */ +static long dasd_io_timps[16]; /* histogram of requests's times per sector */ +static long dasd_io_time1[16]; /* histogram of time from build to start */ +static long dasd_io_time2[16]; /* histogram of time from start to irq */ +static long dasd_io_time2ps[16]; /* histogram of time from start to irq */ +static long dasd_io_time3[16]; /* histogram of time from irq to end */ + +void +dasd_profile_add ( cqr_t *cqr ) +{ + int ind; + long strtime,irqtime,endtime,tottime; + long tottimeps,sectors; + long help; + if ( ! cqr -> req ) + return; + sectors = cqr -> req -> nr_sectors; + strtime = ((cqr->startclk - cqr->buildclk) >> 12); + irqtime = ((cqr->stopclk - cqr->startclk) >> 12); + endtime = ((cqr->endclk - cqr->stopclk) >> 12); + tottime = ((cqr->endclk - cqr->buildclk) >> 12); + tottimeps = tottime / sectors; + + if (! dasd_io_reqs ++){ + for ( ind = 0; ind < 16; ind ++) { + dasd_io_secs[ind] = 0; + dasd_io_times[ind]=0; + dasd_io_timps[ind]=0; + dasd_io_time1[ind]=0; + dasd_io_time2[ind]=0; + dasd_io_time2ps[ind]=0; + dasd_io_time3[ind]=0; + } + }; + + for ( ind = 0, help = sectors >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_secs[ind] ++; + + for ( ind = 0, help = tottime >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_times[ind] ++; + + for ( ind = 0, help = tottimeps >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_timps[ind] ++; + + for ( ind = 0, help = strtime >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_time1[ind] ++; + + for ( ind = 0, help = irqtime >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_time2[ind] ++; + + for ( ind = 0, help = (irqtime/sectors) >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_time2ps[ind] ++; + + for ( ind = 0, help = endtime >> 3; + ind < 15 && help; + help = help >> 1,ind ++); + dasd_io_time3[ind] ++; +} + +int +dasd_proc_read_statistics ( char * buf, char **start, + off_t off, int len, int d) +{ + int i; + int shift, help; + + for ( shift = 0, help = dasd_io_reqs; + help > 8192; + help = help >> 1,shift ++); + len = sprintf ( buf, "%ld dasd I/O requests\n", dasd_io_reqs); + len += sprintf ( buf+len, "__<4 ___8 __16 __32 __64 _128 _256 _512 __1k __2k __4k __8k _16k _32k _64k >64k\n"); + len += sprintf ( buf+len, "Histogram of sizes (512B secs)\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_secs[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O times\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_times[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O times per sector\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_timps[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O time till ssch\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_time1[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O time between ssch and irq\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_time2[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O time between ssch and irq per sector\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_time2ps[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + len += sprintf ( buf+len, "Histogram of I/O time between irq and end\n"); + for ( i = 0; i < 16; i ++) { + len += sprintf ( buf+len, "%4ld ",dasd_io_time3[i] >> shift ); + } + len += sprintf ( buf+len, "\n"); + return len; +} +typedef +struct { + union { + unsigned long long clock; + struct { + unsigned int ts1; + unsigned int ts2 : 20; + unsigned int unused : 8; + unsigned int cpu : 4; + } __attribute__ ((packed)) s; + } __attribute__ ((packed)) u; + unsigned long caller_address; + unsigned long tag; +} __attribute__ ((packed)) dasd_debug_entry; + +static dasd_debug_entry *dasd_debug_area = NULL; +static dasd_debug_entry *dasd_debug_actual; +static spinlock_t debug_lock = SPIN_LOCK_UNLOCKED; + +void +dasd_debug ( unsigned long tag ) +{ + long flags; + dasd_debug_entry *d; + /* initialize in first call ... */ + if ( ! dasd_debug_area ) { + dasd_debug_actual = dasd_debug_area = + (dasd_debug_entry *) get_free_page (GFP_ATOMIC); + if ( ! dasd_debug_area ) { + PRINT_WARN("No debug area allocated\n"); + return; + } + memset (dasd_debug_area,0,PAGE_SIZE); + } + /* renormalize to page */ + spin_lock_irqsave(&debug_lock,flags); + dasd_debug_actual = (dasd_debug_entry *) + ( (unsigned long) dasd_debug_area + + ( ( (unsigned long)dasd_debug_actual - + (unsigned long)dasd_debug_area ) % PAGE_SIZE ) ); + d = dasd_debug_actual ++; + spin_unlock_irqrestore(&debug_lock,flags); + /* write CPUID to lowest 12 bits of clock... */ + __asm__ __volatile__ ( "STCK %0" + :"=m" (d->u.clock)); + d->tag = tag; + d -> caller_address = (unsigned long) __builtin_return_address(0); + d->u.s.cpu = smp_processor_id(); +} + +int +dasd_proc_read_debug ( char * buf, char **start, + off_t off, int len, int dd) +{ + dasd_debug_entry *d; + char tag[9] = { 0, }; + long flags; + spin_lock_irqsave(&debug_lock,flags); + len = 0; + for( d = dasd_debug_area; + len < 4068 ; + d ++ ) { + if ( *(char*)(&d->tag) == 'D' ) { + memcpy(tag,&(d->tag),4); + tag[4]=0; + } + else { + sprintf(tag,"%08lx", d->tag); + tag[8]=0; + } + len += sprintf ( buf+len, + "%x %08x%05x %08lx (%8s)\n", + d->u.s.cpu, d->u.s.ts1, d->u.s.ts2, + d->caller_address,tag); + } + spin_unlock_irqrestore(&debug_lock,flags); + return len; +} diff --git a/drivers/s390/block/dasd_types.h b/drivers/s390/block/dasd_types.h new file mode 100644 index 000000000..b453bc2f8 --- /dev/null +++ b/drivers/s390/block/dasd_types.h @@ -0,0 +1,284 @@ +/* + * File...........: linux/drivers/s390/block/dasd_types.h + * Author.........: Holger Smolinski <Holger.Smolinski@de.ibm.com> + * Created........: 08/31/1999 + * Last Modified..: 09/29/1999 + * (C) IBM Corporation, IBM Deutschland Entwicklung GmbH, 1999,2000 + + * List of Changes: + - Initial Release as of 09/29/1999 + + * Description + + * Restrictions + + * Known Bugs + + * Todo-List + + */ + +#ifndef DASD_TYPES_H +#define DASD_TYPES_H + +#include <linux/config.h> +#include <linux/dasd.h> +#include <linux/blkdev.h> + +#include <asm/irq.h> + +#define CCW_DEFINE_EXTENT 0x63 +#define CCW_LOCATE_RECORD 0x43 +#define CCW_READ_DEVICE_CHARACTERISTICS 0x64 + +typedef +enum { + dasd_none = -1, +#ifdef CONFIG_DASD_ECKD + dasd_eckd, +#endif /* CONFIG_DASD_ECKD */ +#ifdef CONFIG_DASD_MDSK + dasd_mdsk, +#endif /* CONFIG_DASD_MDSK */ +#ifdef CONFIG_DASD_CKD + dasd_ckd, +#endif /* CONFIG_DASD_CKD */ + dasd_end +} dasd_type_t; + +typedef +struct { + __u16 cu_type; + struct { + unsigned char support:2; + unsigned char async:1; + unsigned char reserved:1; + unsigned char cache_info:1; + unsigned char model:3; + } __attribute__ ((packed)) cu_model; + __u16 dev_type; + __u8 dev_model; + struct { + unsigned char mult_burst:1; + unsigned char RT_in_LR:1; + unsigned char reserved1:1; + unsigned char RD_IN_LR:1; + unsigned char reserved2:4; + unsigned char reserved3:8; + unsigned char defect_wr:1; + unsigned char reserved4:2; + unsigned char striping:1; + unsigned char reserved5:4; + unsigned char cfw:1; + unsigned char reserved6:2; + unsigned char cache:1; + unsigned char dual_copy:1; + unsigned char dfw:1; + unsigned char reset_alleg:1; + unsigned char sense_down:1; + } __attribute__ ((packed)) facilities; + __u8 dev_class; + __u8 unit_type; + __u16 no_cyl; + __u16 trk_per_cyl; + __u8 sec_per_trk; + __u8 byte_per_track[3]; + __u16 home_bytes; + __u8 formula; + union { + struct { + __u8 f1; + __u16 f2; + __u16 f3; + } __attribute__ ((packed)) f_0x01; + struct { + __u8 f1; + __u8 f2; + __u8 f3; + __u8 f4; + __u8 f5; + } __attribute__ ((packed)) f_0x02; + } __attribute__ ((packed)) factors; + __u16 first_alt_trk; + __u16 no_alt_trk; + __u16 first_dia_trk; + __u16 no_dia_trk; + __u16 first_sup_trk; + __u16 no_sup_trk; + __u8 MDR_ID; + __u8 OBR_ID; + __u8 director; + __u8 rd_trk_set; + __u16 max_rec_zero; + __u8 reserved1; + __u8 RWANY_in_LR; + __u8 factor6; + __u8 factor7; + __u8 factor8; + __u8 reserved2[3]; + __u8 reserved3[10]; +} __attribute__ ((packed, aligned (32))) + +dasd_eckd_characteristics_t; + +/* eckd count area */ +typedef struct { + __u16 cyl; + __u16 head; + __u8 record; + __u8 kl; + __u16 dl; +} __attribute__ ((packed)) + +eckd_count_t; + +#ifdef CONFIG_DASD_CKD +struct dasd_ckd_characteristics { + char info[64]; +}; + +#endif /* CONFIG_DASD_CKD */ + +#ifdef CONFIG_DASD_ECKD +struct dasd_eckd_characteristics { + char info[64]; +}; + +#endif /* CONFIG_DASD_ECKD */ + +typedef +union { + char __attribute__ ((aligned (32))) bytes[64]; +#ifdef CONFIG_DASD_CKD + struct dasd_ckd_characteristics ckd; +#endif /* CONFIG_DASD_CKD */ +#ifdef CONFIG_DASD_ECKD + dasd_eckd_characteristics_t eckd; +#endif /* CONFIG_DASD_ECKD */ +} __attribute__ ((aligned (32))) + +dasd_characteristics_t; + +#define CQR_STATUS_EMPTY 0x00 +#define CQR_STATUS_FILLED 0x01 +#define CQR_STATUS_QUEUED 0x02 +#define CQR_STATUS_IN_IO 0x04 +#define CQR_STATUS_DONE 0x08 +#define CQR_STATUS_RETRY 0x10 +#define CQR_STATUS_ERROR 0x20 +#define CQR_STATUS_FAILED 0x40 +#define CQR_STATUS_SLEEP 0x80 + +#define CQR_FLAGS_SLEEP 0x01 +#define CQR_FLAGS_WAIT 0x02 +#define CQR_FLAGS_NOLOCK 0x04 +#define CQR_FLAGS_NORETRY 0x08 + +typedef +struct cqr_t { + unsigned int magic; /* magic number should be "DASD" */ + atomic_t status; /* current status of request */ + unsigned short retries; /* counter for retry in error case */ + unsigned short cplength;/* Length of channel program (CP) */ + unsigned short devindex;/* device number */ + unsigned short flags; /* Flags for execution */ + + void * data; /* additional data area for CP */ + ccw1_t *cpaddr; /* Address of CP */ + struct request *req; /* backpointer to struct request */ + struct cqr_t *next; /* forward chain in chanq */ + struct cqr_t *int4cqr; /* which cqr ist the nect PCI for? */ + unsigned long long buildclk; + unsigned long long startclk; + unsigned long long stopclk; + unsigned long long endclk; + devstat_t *dstat; /* savearea for devstat */ + spinlock_t lock; + int options; +} __attribute__ ((packed)) +cqr_t; + +typedef +struct { + unsigned long int kbytes; + unsigned int bp_sector; + unsigned int bp_block; + unsigned int blocks; + unsigned int s2b_shift; + unsigned int b2k_shift; + unsigned int label_block; +} dasd_sizes_t; + +#define DASD_CHANQ_ACTIVE 0x01 +#define DASD_CHANQ_BUSY 0x02 +#define DASD_REQUEST_Q_BROKEN 0x04 + +typedef +struct dasd_chanq_t { + volatile cqr_t *head; + volatile cqr_t *tail; + spinlock_t q_lock; /* lock for queue operations */ + spinlock_t f_lock; /* lock for flag operations */ + int queued_requests; + atomic_t flags; + atomic_t dirty_requests; + struct dasd_chanq_t *next_q; /* pointer to next queue */ +} __attribute__ ((packed, aligned (16))) +dasd_chanq_t; + +#define DASD_INFO_FLAGS_INITIALIZED 0x01 +#define DASD_INFO_FLAGS_NOT_FORMATTED 0x02 +#define DASD_INFO_FLAGS_PARTNS_DETECTED 0x04 + +typedef +struct dasd_information_t { + devstat_t dev_status; + dasd_characteristics_t *rdc_data; + dasd_volume_label_t *label; + dasd_type_t type; + dev_info_t info; + dasd_sizes_t sizes; + dasd_chanq_t queue; + int open_count; + spinlock_t lock; + struct semaphore sem; + unsigned long flags; + int irq; + struct proc_dir_entry *proc_device; + devfs_handle_t devfs_entry; + union { + struct { + eckd_count_t count_data; + } eckd; + struct { + char dummy; + } fba; + struct { + char dummy; + } mdsk; + struct { + char dummy; + } ckd; + } private; +} dasd_information_t; + +typedef struct { + int start_unit; + int stop_unit; + int blksize; +} format_data_t; + +typedef +struct { + int (*ck_devinfo) (dev_info_t *); + cqr_t *(*get_req_ccw) (int, struct request *); + cqr_t *(*rw_label) (int, int, char *); + int (*ck_characteristics) (dasd_characteristics_t *); + cqr_t *(*fill_sizes_first) (int); + int (*fill_sizes_last) (int); + int (*dasd_format) (int, format_data_t *); +} dasd_operations_t; + +extern dasd_information_t *dasd_info[]; + +#endif /* DASD_TYPES_H */ diff --git a/drivers/s390/block/mdisk.c b/drivers/s390/block/mdisk.c new file mode 100644 index 000000000..f485cb668 --- /dev/null +++ b/drivers/s390/block/mdisk.c @@ -0,0 +1,790 @@ +/* + * drivers/s390/block/mdisk.c + * VM minidisk device driver. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + */ + + +#ifndef __KERNEL__ +# define __KERNEL__ +#endif + +#define __NO_VERSION__ +#include <linux/config.h> +#include <linux/version.h> + +char kernel_version [] = UTS_RELEASE; + +#include <linux/module.h> +#include <linux/sched.h> +#include <linux/kernel.h> /* printk() */ +#include <linux/malloc.h> /* kmalloc() */ +#include <linux/vmalloc.h> /* vmalloc() */ +#include <linux/fs.h> /* everything... */ +#include <linux/errno.h> /* error codes */ +#include <linux/timer.h> +#include <linux/types.h> /* size_t */ +#include <linux/fcntl.h> /* O_ACCMODE */ +#include <linux/hdreg.h> /* HDIO_GETGEO */ +#include <linux/init.h> /* initfunc */ +#include <linux/interrupt.h> +#include <linux/ctype.h> + +#include <asm/system.h> /* cli(), *_flags */ +#include <asm/uaccess.h> /* access_ok */ +#include <asm/io.h> /* virt_to_phys */ + + /* Added statement HSM 12/03/99 */ +#include <asm/irq.h> + +#define MAJOR_NR MDISK_MAJOR /* force definitions on in blk.h */ + +#include <linux/blk.h> + + +#include "mdisk.h" /* local definitions */ + +/* + * structure for all device specific information + */ + +typedef struct mdisk_Dev { + u32 vdev; /* vdev of mindisk */ + u32 size; /* size in blocks */ + u32 status; /* status of last io operation */ + u32 nr_bhs; /* number of buffer of last io operation */ + u32 blksize; /* blksize from minidisk */ + u32 blkmult; /* multiplier between blksize and 512 HARDSECT */ + u32 blkshift; /* loe2 of multiplier above */ + /* + * each device has own iob and bio, + * it's possible to run io in parallel + * not used yet due to only one CURRENT per MAJOR + */ + + mdisk_rw_io_t* iob; /* each device has it own iob and bio */ + mdisk_bio_t* bio; + /* Added statement HSM 12/03/99 */ + devstat_t dev_status; /* Here we hold the I/O status */ + + int usage; /* usage counter */ + + struct tq_struct tqueue; /* per device task queue */ +} mdisk_Dev; + + +/* + * appended to global structures in mdisk_init; + */ + +static int mdisk_blksizes[MDISK_DEVS]; +static int mdisk_sizes[MDISK_DEVS] = { 0 }; +static int mdisk_hardsects[MDISK_DEVS]; +static int mdisk_maxsectors[MDISK_DEVS]; + +/* + * structure hold device specific information + */ + +static mdisk_Dev mdisk_devices[MDISK_DEVS]; +static mdisk_rw_io_t mdisk_iob[MDISK_DEVS] __attribute__ ((aligned(8))); +static mdisk_bio_t mdisk_bio[MDISK_DEVS][256]__attribute__ ((aligned(8))); + + +/* + * Parameter parsing + */ +struct { + long vdev[MDISK_DEVS]; + long size[MDISK_DEVS]; + long offset[MDISK_DEVS]; + long blksize[MDISK_DEVS]; +} mdisk_setup_data; + +/* + * Parameter parsing function, called from init/main.c + * vdev : virtual device number + * size : size in kbyte + * offset : offset after which minidisk is available + * blksize : blocksize minidisk is formated + * Format is: mdisk=<vdev>:<size>:<offset>:<blksize>,<vdev>:<size>:<offset>... + * <vdev>:<size>:<offset>:<blksize> can be shortened to <vdev>:<size> with offset=0,blksize=512 + */ +int __init mdisk_setup(char *str) +{ + char *cur = str; + int vdev, size, offset=0,blksize; + static int i = 0; + if (!i) + memset(&mdisk_setup_data,0,sizeof(mdisk_setup_data)); + + while (*cur != 0) { + blksize=MDISK_HARDSECT; + vdev = size = offset = 0; + if (!isxdigit(*cur)) goto syntax_error; + vdev = simple_strtoul(cur,&cur,16); + if (*cur != 0 && *cur != ',') { + if (*cur++ != ':') goto syntax_error; + if (!isxdigit(*cur)) goto syntax_error; + size = simple_strtoul(cur,&cur,16); + if (*cur == ':') { /* another colon -> offset specified */ + cur++; + if (!isxdigit(*cur)) goto syntax_error; + offset = simple_strtoul(cur,&cur,16); + if (*cur == ':') { /* another colon -> blksize */ + cur++; + if (!isxdigit(*cur)) goto syntax_error; + blksize = simple_strtoul(cur,&cur,16); + } + } + if (*cur != ',' && *cur != 0) goto syntax_error; + } + if (*cur == ',') cur++; + if (i >= MDISK_DEVS) { + printk(KERN_WARNING "mnd: too many devices\n"); + return 1; + } + mdisk_setup_data.vdev[i] = vdev; + mdisk_setup_data.size[i] = size; + mdisk_setup_data.offset[i] = offset; + mdisk_setup_data.blksize[i] = blksize; + + i++; + } + + return 1; + +syntax_error: + printk(KERN_WARNING "mnd: syntax error in parameter string: %s\n", str); + return 0; +} + +__setup("mdisk=", mdisk_setup); + +/* + * Open and close + */ + +static int mdisk_open (struct inode *inode, struct file *filp) +{ + mdisk_Dev *dev; /* device information */ + int num = MINOR(inode->i_rdev); + + /* + * size 0 means device not installed + */ + if ((num >= MDISK_DEVS) || (mdisk_sizes[num] == 0)) + return -ENODEV; + MOD_INC_USE_COUNT; + dev = &mdisk_devices[num]; + dev->usage++; + return 0; /* success */ +} + +static int mdisk_release (struct inode *inode, struct file *filp) +{ + mdisk_Dev *dev = &mdisk_devices[MINOR(inode->i_rdev)]; + + /* + * flush device + */ + + fsync_dev(inode->i_rdev); + dev->usage--; + MOD_DEC_USE_COUNT; + return 0; +} + + +/* + * The mdisk() implementation + */ + +static int mdisk_ioctl (struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) +{ + int err,rc, size=0; + struct hd_geometry *geo = (struct hd_geometry *)arg; + mdisk_Dev *dev = mdisk_devices + MINOR(inode->i_rdev); + + switch(cmd) { + + case BLKGETSIZE: + rc = copy_to_user ((long *) arg, &dev->size, sizeof (long)); + printk(KERN_WARNING "mnd: ioctl BLKGETSIZE %d\n",dev->size); + return rc; + case BLKFLSBUF: /* flush */ + if (!suser()) return -EACCES; /* only root */ + fsync_dev(inode->i_rdev); + invalidate_buffers(inode->i_rdev); + return 0; + + case BLKRAGET: /* return the readahead value */ + if (!arg) return -EINVAL; + err = access_ok(VERIFY_WRITE, (long *) arg, sizeof(long)); + if (err) return err; + put_user(read_ahead[MAJOR(inode->i_rdev)],(long *) arg); + return 0; + + case BLKRASET: /* set the readahead value */ + if (!suser()) return -EACCES; + if (arg > 0xff) return -EINVAL; /* limit it */ + read_ahead[MAJOR(inode->i_rdev)] = arg; + return 0; + + case BLKRRPART: /* re-read partition table: can't do it */ + return -EINVAL; + + case HDIO_GETGEO: + /* + * get geometry of device -> linear + */ + size = dev->size; + if (geo==NULL) return -EINVAL; + err = access_ok(VERIFY_WRITE, geo, sizeof(*geo)); + if (err) return err; + put_user(1, &geo->cylinders); + put_user(1, &geo->heads); + put_user(size, &geo->sectors); + put_user(0, &geo->start); + return 0; + } + + return -EINVAL; /* unknown command */ +} + +/* + * The file operations + */ + +static struct block_device_operations mdisk_fops = { + ioctl: mdisk_ioctl, + open: mdisk_open, + release: mdisk_release, +}; + +/* + * The 'low level' IO function + */ + + +static __inline__ int +dia250(void* iob,int cmd) +{ + int rc; + + iob = (void*) virt_to_phys(iob); + + asm volatile (" lr 2,%1\n" + " lr 3,%2\n" + " .long 0x83230250\n" + " lr %0,3" + : "=d" (rc) + : "d" (iob) , "d" (cmd) + : "2", "3" ); + return rc; +} +/* + * Init of minidisk device + */ + +static __inline__ int +mdisk_init_io(mdisk_Dev *dev,int blocksize,int offset,int size) +{ + mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob; + int rc; + + memset(iob,0,sizeof(mdisk_init_io_t)); + + iob->dev_nr = dev->vdev; + iob->block_size = blocksize; + iob->offset = offset; + iob->start_block= 0; + iob->end_block = size; + + rc = dia250(iob,INIT_BIO); + + /* + * clear for following io once + */ + + memset(iob,0,sizeof(mdisk_rw_io_t)); + + return rc; +} + +/* + * release of minidisk device + */ + +static __inline__ int +mdisk_term_io(mdisk_Dev *dev) +{ + mdisk_init_io_t *iob = (mdisk_init_io_t*) dev->iob; + + memset(iob,0,sizeof(mdisk_init_io_t)); + + iob->dev_nr = dev->vdev; + + return dia250(iob,TERM_BIO); +} + +/* + * setup and start of minidisk io request + */ + +static __inline__ int +mdisk_rw_io_clustered (mdisk_Dev *dev, + mdisk_bio_t* bio_array, + int length, + int req, + int sync) +{ + int rc; + mdisk_rw_io_t *iob = dev->iob; + + iob->dev_nr = dev->vdev; + iob->key = 0; + iob->flags = sync; + + iob->block_count = length; + iob->interrupt_params = req; + iob->bio_list = virt_to_phys(bio_array); + + rc = dia250(iob,RW_BIO); + return rc; +} + + + +/* + * The device characteristics function + */ + +static __inline__ int +dia210(void* devchar) +{ + int rc; + + devchar = (void*) virt_to_phys(devchar); + + asm volatile (" lr 2,%1\n" + " .long 0x83200210\n" + " ipm %0\n" + " srl %0,28" + : "=d" (rc) + : "d" (devchar) + : "2" ); + return rc; +} +/* + * read the label of a minidisk and extract its characteristics + */ + +static __inline__ int +mdisk_read_label (mdisk_Dev *dev, int i) +{ + static mdisk_dev_char_t devchar; + static long label[1024]; + int block, b; + int rc; + mdisk_bio_t *bio; + + devchar.dev_nr = dev -> vdev; + devchar.rdc_len = sizeof(mdisk_dev_char_t); + + if (dia210(&devchar) == 0) { + if (devchar.vdev_class == DEV_CLASS_FBA) { + block = 2; + } + else { + block = 3; + } + bio = dev->bio; + for (b=512;b<4097;b=b*2) { + rc = mdisk_init_io(dev, b, 0, 64); + if (rc > 4) { + continue; + } + memset(&bio[0], 0, sizeof(mdisk_bio_t)); + bio[0].type = MDISK_READ_REQ; + bio[0].block_number = block; + bio[0].buffer = virt_to_phys(&label); + dev->nr_bhs = 1; + if (mdisk_rw_io_clustered(dev, + &bio[0], + 1, + (unsigned long) dev, + MDISK_SYNC) + == 0 ) { + if (label[0] != 0xc3d4e2f1) { /* CMS1 */ + printk ( KERN_WARNING "mnd: %4lX " + "is not CMS format\n", + mdisk_setup_data.vdev[i]); + rc = mdisk_term_io(dev); + return 1; + } + if (label[13] == 0) { + printk ( KERN_WARNING "mnd: %4lX " + "is not reserved\n", + mdisk_setup_data.vdev[i]); + rc = mdisk_term_io(dev); + return 2; + } + mdisk_setup_data.size[i] = + (label[7] - 1 - label[13]) * + (label[3] >> 9) >> 1; + mdisk_setup_data.blksize[i] = label[3]; + mdisk_setup_data.offset[i] = label[13] + 1; + rc = mdisk_term_io(dev); + return rc; + } + rc = mdisk_term_io(dev); + } + printk ( KERN_WARNING "mnd: Cannot read label of %4lX " + "- is it formatted?\n", + mdisk_setup_data.vdev[i]); + return 3; + } + return 4; +} + + + + + +/* + * this handles a clustered request in success case + * all buffers are detach and marked uptodate to the kernel + * then CURRENT->bh is set to the last processed but not + * update buffer + */ + +static __inline__ void +mdisk_end_request(int nr_bhs) +{ + int i; + struct buffer_head *bh; + struct request *req; + + if (nr_bhs > 1) { + req = CURRENT; + bh = req->bh; + + for (i=0; i < nr_bhs-1; i++) { + req->bh = bh->b_reqnext; + bh->b_reqnext = NULL; + bh->b_end_io(bh,1); + bh = req->bh; + } + + /* + * set CURRENT to last processed, not marked buffer + */ + req->buffer = bh->b_data; + req->current_nr_sectors = bh->b_size >> 9; + CURRENT = req; + } + end_request(1); +} + + + +/* + * Block-driver specific functions + */ + +void mdisk_request(request_queue_t *queue) +{ + mdisk_Dev *dev; + mdisk_bio_t *bio; + struct buffer_head *bh; + unsigned int sector, nr, offset; + int rc,rw,i; + + i = 0; + while(CURRENT) { + INIT_REQUEST; + + /* Check if the minor number is in range */ + if (DEVICE_NR(CURRENT_DEV) > MDISK_DEVS) { + static int count = 0; + if (count++ < 5) /* print the message at most five times */ + printk(KERN_WARNING "mnd: request for minor %d out of range\n", + DEVICE_NR(CURRENT_DEV) ) ; + end_request(0); + continue; + } + + /* + * Pointer to device structure, from the static array + */ + dev = mdisk_devices + DEVICE_NR(CURRENT_DEV); + + /* + * check, if operation is past end of devices + */ + if (CURRENT->nr_sectors + CURRENT->sector > dev->size) { + static int count = 0; + if (count++ < 5) + printk(KERN_WARNING "mnd%c: request past end of device\n", + DEVICE_NR(CURRENT_DEV)); + end_request(0); + continue; + } + + /* + * do command (read or write) + */ + switch(CURRENT->cmd) { + case READ: + rw = MDISK_READ_REQ; + break; + case WRITE: + rw = MDISK_WRITE_REQ; + break; + default: + /* can't happen */ + end_request(0); + continue; + } + + /* + * put the clustered requests in mdisk_bio array + * nr_sectors is checked against max_sectors in make_request + * nr_sectors and sector are always blocks of 512 + * but bh_size depends on the filesystems size + */ + sector = CURRENT->sector>>dev->blkshift; + bh = CURRENT->bh; + bio = dev->bio; + dev->nr_bhs = 0; + + /* + * sector is translated to block in minidisk context + * + */ + offset = 0; + + + + for (nr = 0,i = 0; + nr < CURRENT->nr_sectors && bh; + nr+=dev->blkmult, sector++,i++) { + memset(&bio[i], 0, sizeof(mdisk_bio_t)); + bio[i].type = rw; + bio[i].block_number = sector; + bio[i].buffer = virt_to_phys(bh->b_data+offset); + offset += dev->blksize; + if (bh->b_size <= offset) { + offset = 0; + bh = bh->b_reqnext; + dev->nr_bhs++; + } + } + + if (( rc = mdisk_rw_io_clustered(dev, &bio[0], i, + (unsigned long) dev, +#ifdef CONFIG_MDISK_SYNC + MDISK_SYNC +#else + MDISK_ASYNC +#endif + )) > 8 ) { + printk(KERN_WARNING "mnd%c: %s request failed rc %d" + " sector %ld nr_sectors %ld \n", + DEVICE_NR(CURRENT_DEV), + rw == MDISK_READ_REQ ? "read" : "write", + rc, CURRENT->sector, CURRENT->nr_sectors); + end_request(0); + continue; + } + i = 0; + /* + * Synchron: looping to end of request (INIT_REQUEST has return) + * Asynchron: end_request done in bottom half + */ +#ifdef CONFIG_MDISK_SYNC + mdisk_end_request(dev->nr_bhs); +#else + if (rc == 0) + mdisk_end_request(dev->nr_bhs); + else + return; +#endif + } +} + + +/* + * mdisk interrupt handler called when read/write request finished + * queues and marks a bottom half. + * + */ +void do_mdisk_interrupt(void) +{ + u16 code; + mdisk_Dev *dev; + + code = S390_lowcore.cpu_addr; + + if ((code >> 8) != 0x03) { + printk("mnd: wrong sub-interruption code %d",code>>8); + return; + } + + /* + * pointer to devives structure given as external interruption + * parameter + */ + dev = (mdisk_Dev*) S390_lowcore.ext_params; + dev->status = code & 0x00ff; + + queue_task(&dev->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/* + * the bottom half checks the status of request + * on success it calls end_request and calls mdisk_request + * if more transfer to do + */ + +static void +do_mdisk_bh(void *data) +{ + mdisk_Dev *dev = (mdisk_Dev*) data; + unsigned long flags; + + spin_lock_irqsave(&io_request_lock, flags); + /* + * check for status of asynchronous rw + */ + if (dev->status != 0x00) { + printk("mnd: status of async rw %d",dev->status); + end_request(0); + } else { + /* + * end request for clustered requests + */ + if (CURRENT) + mdisk_end_request(dev->nr_bhs); + } + + /* + * if more to do, call mdisk_request + */ + if (CURRENT) + mdisk_request(NULL); + spin_unlock_irqrestore(&io_request_lock, flags); +} + +void /* Added fuction HSM 12/03/99 */ +mdisk_handler (int cpu, void *ds, struct pt_regs *regs) +{ + printk (KERN_ERR "mnd: received I/O interrupt... shouldn't happen\n"); +} + +int __init mdisk_init(void) +{ + int rc,i; + mdisk_Dev *dev; + request_queue_t *q; + + /* + * register block device + */ + if (register_blkdev(MAJOR_NR,"mnd",&mdisk_fops) < 0) { + printk("mnd: unable to get major %d for mini disk\n" + ,MAJOR_NR); + return MAJOR_NR; + } + q = BLK_DEFAULT_QUEUE(MAJOR_NR); + blk_init_queue(q, mdisk_request); + blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0); + + /* + * setup sizes for available devices + */ + read_ahead[MAJOR_NR] = MDISK_RAHEAD; /* 8 sector (4kB) read-ahead */ + blk_size[MAJOR_NR] = mdisk_sizes; /* size of reserved mdisk */ + blksize_size[MAJOR_NR] = mdisk_blksizes; /* blksize of device */ + hardsect_size[MAJOR_NR] = mdisk_hardsects; + max_sectors[MAJOR_NR] = mdisk_maxsectors; + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DEVICE_REQUEST); + + for (i=0;i<MDISK_DEVS;i++) { + if (mdisk_setup_data.vdev[i] == 0) { + continue; + } + /* Added block HSM 12/03/99 */ + if ( request_irq(get_irq_by_devno(mdisk_setup_data.vdev[i]), + mdisk_handler, 0, "mnd", + &(mdisk_devices[i].dev_status)) ){ + printk ( KERN_WARNING "mnd: Cannot acquire I/O irq of" + " %4lX for paranoia reasons, skipping\n", + mdisk_setup_data.vdev[i]); + continue; + } + /* + * open VM minidisk low level device + */ + dev = &mdisk_devices[i]; + dev->bio=mdisk_bio[i]; + dev->iob=&mdisk_iob[i]; + dev->vdev = mdisk_setup_data.vdev[i]; + + if ( mdisk_setup_data.size[i] == 0 ) + rc = mdisk_read_label(dev, i); + dev->size = mdisk_setup_data.size[i] * 2; /* buffer 512 b */ + dev->blksize = mdisk_setup_data.blksize[i]; + dev->tqueue.routine = do_mdisk_bh; + dev->tqueue.data = dev; + dev->blkmult = dev->blksize/512; + dev->blkshift = + dev->blkmult==1?0: + dev->blkmult==2?1: + dev->blkmult==4?2: + dev->blkmult==8?3:-1; + + mdisk_sizes[i] = mdisk_setup_data.size[i]; + mdisk_blksizes[i] = mdisk_setup_data.blksize[i]; + mdisk_hardsects[i] = mdisk_setup_data.blksize[i]; + + /* + * max sectors for one clustered req + */ + mdisk_maxsectors[i] = MDISK_MAXSECTORS*dev->blkmult; + + rc = mdisk_init_io(dev, + mdisk_setup_data.blksize[i], + mdisk_setup_data.offset[i],/* offset in vdev*/ + dev->size>>dev->blkshift /* size in blocks */ + ); + if (rc > 4) { + printk("mnd%c: init failed (rc: %d)\n",'a'+i,rc); + mdisk_sizes[i] = 0; + continue; + } + + /* + * set vdev in device structure for further rw access + * vdev and size given by linload + */ + printk("mnd%c: register device at major %X with %d blocks %d blksize \n", + 'a' + i, MAJOR_NR, dev->size>>dev->blkshift,dev->blkmult*512); + } + + /* + * enable service-signal external interruptions, + * Control Register 0 bit 22 := 1 + * (besides PSW bit 7 must be set to 1 somewhere for external + * interruptions) + */ + ctl_set_bit(0, 9); + + return 0; +} diff --git a/drivers/s390/block/mdisk.h b/drivers/s390/block/mdisk.h new file mode 100644 index 000000000..084293031 --- /dev/null +++ b/drivers/s390/block/mdisk.h @@ -0,0 +1,94 @@ +/* + * drivers/s390/block/mdisk.h + * VM minidisk device driver. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Hartmut Penner (hp@de.ibm.com) + */ + +#include <linux/ioctl.h> +#include <linux/types.h> + +#define MDISK_DEVS 8 /* for disks */ +#define MDISK_RAHEAD 8 /* read ahead */ +#define MDISK_BLKSIZE 1024 /* 1k blocks */ +#define MDISK_HARDSECT 512 /* FIXME -- 512 byte blocks */ +#define MDISK_MAXSECTORS 256 /* max sectors for one request */ + + + +/* + * low level io defines for diagnose 250 + */ + +#define MDISK_WRITE_REQ 0x01 +#define MDISK_READ_REQ 0x02 + +#define MDISK_SYNC 0x00 +#define MDISK_ASYNC 0x02 +#define INIT_BIO 0x00 +#define RW_BIO 0x01 +#define TERM_BIO 0x02 + +/* + * This stucture is used for clustered request + * up to 256 different request can be handled with one invocation + */ + +typedef struct { + u8 type; + u8 status; + u16 spare1; + u32 block_number; + u32 alet; + u32 buffer; +} mdisk_bio_t; + +typedef struct { + u16 dev_nr; + u16 spare1[11]; + u32 block_size; + u32 offset; + u32 start_block; + u32 end_block; + u32 spare2[6]; +} mdisk_init_io_t; + +typedef struct { + u16 dev_nr; + u16 spare1[11]; + u8 key; + u8 flags; + u16 spare2; + u32 block_count; + u32 alet; + u32 bio_list; + u32 interrupt_params; + u32 spare3[5]; +} mdisk_rw_io_t; + +/* + * low level definitions for Diagnose 210 + */ + +#define DEV_CLASS_FBA 0x01 + +/* + * Data structures for Diagnose 210 + */ + +typedef struct { + u16 dev_nr; + u16 rdc_len; + u8 vdev_class; + u8 vdev_type; + u8 vdev_status; + u8 vdev_flags; + u8 rdev_class; + u8 rdev_type; + u8 rdev_model; + u8 rdev_features; +} mdisk_dev_char_t; + + diff --git a/drivers/s390/char/Makefile b/drivers/s390/char/Makefile new file mode 100644 index 000000000..1cc89d053 --- /dev/null +++ b/drivers/s390/char/Makefile @@ -0,0 +1,16 @@ +all: s390-char.o + +CFLAFS += +O_TARGET := s390-char.o +O_OBJS := +M_OBJS := + +ifeq ($(CONFIG_3215_CONSOLE),y) + O_OBJS += con3215.o +endif + +ifeq ($(CONFIG_HWC),y) + O_OBJS += hwc_con.o hwc_rw.o hwc_tty.o +endif + +include $(TOPDIR)/Rules.make diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c new file mode 100644 index 000000000..96e35aece --- /dev/null +++ b/drivers/s390/char/con3215.c @@ -0,0 +1,1129 @@ +/* + * drivers/s390/char/con3215.c + * 3215 line mode terminal driver. + * + * S390 version + * Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Schwidefsky (schwidefsky@de.ibm.com), + */ + +#include <linux/config.h> +#include <linux/types.h> +#include <linux/kdev_t.h> +#include <linux/tty.h> +#include <linux/vt_kern.h> +#include <linux/init.h> +#include <linux/console.h> +#include <linux/interrupt.h> + +#include <linux/malloc.h> +#include <linux/bootmem.h> +#include <asm/io.h> +#include <asm/ebcdic.h> +#include <asm/uaccess.h> + +#include "../../../arch/s390/kernel/cpcmd.h" +#include <asm/irq.h> + +#define NR_3215 1 +#define NR_3215_REQ (4*NR_3215) +#define RAW3215_BUFFER_SIZE 65536 /* output buffer size */ +#define RAW3215_INBUF_SIZE 256 /* input buffer size */ +#define RAW3215_MIN_SPACE 128 /* minimum free space for wakeup */ +#define RAW3215_MIN_WRITE 1024 /* min. length for immediate output */ +#define RAW3215_MAX_CCWLEN 3968 /* max. bytes to write with one ccw */ +#define RAW3215_NR_CCWS ((RAW3215_BUFFER_SIZE/RAW3215_MAX_CCWLEN)+2) +#define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ + +#define RAW3215_FIXED 1 /* 3215 console device is not be freed */ +#define RAW3215_ACTIVE 2 /* set if the device is in use */ +#define RAW3215_WORKING 4 /* set if a request is being worked on */ +#define RAW3215_THROTTLED 8 /* set if reading is disabled */ +#define RAW3215_STOPPED 16 /* set if writing is disabled */ +#define RAW3215_CLOSING 32 /* set while in close process */ +#define RAW3215_TIMER_RUNS 64 /* set if the output delay timer is on */ +#define RAW3215_FLUSHING 128 /* set to flush buffer (no delay) */ +#define RAW3215_BH_PENDING 256 /* indication for bh scheduling */ + +struct _raw3215_info; /* forward declaration ... */ + +int raw3215_condevice = -1; /* preset console device */ + +/* + * Request types for a 3215 device + */ +typedef enum { + RAW3215_FREE, RAW3215_READ, RAW3215_WRITE +} raw3215_type; + +/* + * Request structure for a 3215 device + */ +typedef struct _raw3215_req { + raw3215_type type; /* type of the request */ + int start, end; /* start/end index into output buffer */ + int residual; /* residual count for read request */ + ccw1_t ccws[RAW3215_NR_CCWS]; /* space for the channel program */ + struct _raw3215_info *info; /* pointer to main structure */ + struct _raw3215_req *next; /* pointer to next request */ +} raw3215_req __attribute__ ((aligned(8))); + +typedef struct _raw3215_info { + int flags; /* state flags */ + int irq; /* interrupt number to do_IO */ + char *buffer; /* pointer to output buffer */ + char *inbuf; /* pointer to input buffer */ + int head; /* first free byte in output buffer */ + int count; /* number of bytes in output buffer */ + devstat_t devstat; /* device status structure for do_IO */ + struct tty_struct *tty; /* pointer to tty structure if present */ + struct tq_struct tqueue; /* task queue to bottom half */ + raw3215_req *queued_read; /* pointer to queued read requests */ + raw3215_req *queued_write; /* pointer to queued write requests */ + wait_queue_head_t empty_wait; /* wait queue for flushing */ + struct timer_list timer; /* timer for delayed output */ + char *message; /* pending message from raw3215_irq */ + int msg_dstat; /* dstat for pending message */ + int msg_cstat; /* cstat for pending message */ +} raw3215_info; + +static raw3215_info *raw3215[NR_3215]; /* array of 3215 devices structures */ +static raw3215_req *raw3215_freelist; /* list of free request structures */ +static spinlock_t raw3215_freelist_lock;/* spinlock to protect free list */ + +static struct tty_driver tty3215_driver; +static struct tty_struct *tty3215_table[NR_3215]; +static struct termios *tty3215_termios[NR_3215]; +static struct termios *tty3215_termios_locked[NR_3215]; +static int tty3215_refcount; + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static int __init con3215_setup(char *str) +{ + int vdev; + + vdev = simple_strtoul(str,&str,16); + if (vdev >= 0 && vdev < 65536) + raw3215_condevice = vdev; + return 1; +} + +__setup("condev=", con3215_setup); + +/* + * Get a request structure from the free list + */ +extern inline raw3215_req *raw3215_alloc_req(void) { + raw3215_req *req; + unsigned long flags; + + spin_lock_irqsave(&raw3215_freelist_lock, flags); + req = raw3215_freelist; + raw3215_freelist = req->next; + spin_unlock_irqrestore(&raw3215_freelist_lock, flags); + return req; +} + +/* + * Put a request structure back to the free list + */ +extern inline void raw3215_free_req(raw3215_req *req) { + unsigned long flags; + + if (req->type == RAW3215_FREE) + return; /* don't free a free request */ + req->type = RAW3215_FREE; + spin_lock_irqsave(&raw3215_freelist_lock, flags); + req->next = raw3215_freelist; + raw3215_freelist = req; + spin_unlock_irqrestore(&raw3215_freelist_lock, flags); +} + +/* + * Get a write request structure. That is either a new or the last + * queued write request. The request structure is set up in + * raw3215_mk_write_ccw. + */ +static raw3215_req *raw3215_mk_write_req(raw3215_info *raw) +{ + raw3215_req *req; + + /* check if there is a queued write request */ + req = raw->queued_write; + if (req == NULL) { + /* no queued write request, use new req structure */ + req = raw3215_alloc_req(); + req->type = RAW3215_WRITE; + req->info = raw; + req->start = raw->head; + } else + raw->queued_write = NULL; + return req; +} + +/* + * Get a read request structure. If there is a queued read request + * it is used, but that shouldn't happen because a 3215 terminal + * won't accept a new read before the old one is completed. + */ +static raw3215_req *raw3215_mk_read_req(raw3215_info *raw) +{ + raw3215_req *req; + + /* there can only be ONE read request at a time */ + req = raw->queued_read; + if (req == NULL) { + /* no queued read request, use new req structure */ + req = raw3215_alloc_req(); + req->type = RAW3215_READ; + req->info = raw; + } else + raw->queued_read = NULL; + return req; +} + +/* + * Set up a write request with the information from the main structure. + * A ccw chain is created that writes everything in the output buffer + * to the 3215 device. + */ +static int raw3215_mk_write_ccw(raw3215_info *raw, raw3215_req *req) +{ + ccw1_t *ccw; + int len, count, ix; + + ccw = req->ccws; + req->end = (raw->head - 1) & (RAW3215_BUFFER_SIZE - 1); + len = ((req->end - req->start) & (RAW3215_BUFFER_SIZE - 1)) + 1; + ix = req->start; + while (len > 0) { + if (ccw > req->ccws) + ccw[-1].flags |= 0x40; /* use command chaining */ + ccw->cmd_code = 0x01; /* write, auto carrier return */ + ccw->flags = 0x20; /* ignore incorrect length ind. */ + ccw->cda = + (void *) virt_to_phys(raw->buffer + ix); + count = (len > RAW3215_MAX_CCWLEN) ? + RAW3215_MAX_CCWLEN : len; + if (ix + count > RAW3215_BUFFER_SIZE) + count = RAW3215_BUFFER_SIZE-ix; + ccw->count = count; + len -= count; + ix = (ix + count) & (RAW3215_BUFFER_SIZE - 1); + ccw++; + } + return len; +} + +/* + * Set up a read request that reads up to 160 byte from the 3215 device. + */ +static void raw3215_mk_read_ccw(raw3215_info *raw, raw3215_req *req) +{ + ccw1_t *ccw; + + ccw = req->ccws; + ccw->cmd_code = 0x0A; /* read inquiry */ + ccw->flags = 0x20; /* ignore incorrect length */ + ccw->count = 160; + ccw->cda = (void *) virt_to_phys(raw->inbuf); +} + +/* + * Start a read or a write request + */ +static void raw3215_start_io(raw3215_info *raw) +{ + raw3215_req *req; + int res; + + req = raw->queued_read; + if (req != NULL && + !(raw->flags & (RAW3215_WORKING | RAW3215_THROTTLED))) { + /* dequeue request */ + raw->queued_read = NULL; + res = do_IO(raw->irq, req->ccws, (__u32) req, 0, 0); + if (res != 0) { + /* do_IO failed, put request back to queue */ + raw->queued_read = req; + } else { + raw->flags |= RAW3215_WORKING; + } + } + req = raw->queued_write; + if (req != NULL && + !(raw->flags & (RAW3215_WORKING | RAW3215_STOPPED))) { + /* dequeue request */ + raw->queued_write = NULL; + res = do_IO(raw->irq, req->ccws, (__u32) req, 0, 0); + if (res != 0) { + /* do_IO failed, put request back to queue */ + raw->queued_write = req; + } else { + raw->flags |= RAW3215_WORKING; + } + } +} + +/* + * Function to start a delayed output after RAW3215_TIMEOUT seconds + */ +static void raw3215_timeout(unsigned long __data) +{ + raw3215_info *raw = (raw3215_info *) __data; + unsigned long flags; + + s390irq_spin_lock_irqsave(raw->irq, flags); + if (raw->flags & RAW3215_TIMER_RUNS) { + del_timer(&raw->timer); + raw->flags &= ~RAW3215_TIMER_RUNS; + raw3215_start_io(raw); + } + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +/* + * Function to conditionally start an IO. A read is started immediatly, + * a write is only started immediatly if the flush flag is on or the + * amount of data is bigger than RAW3215_MIN_WRITE. If a write is not + * done immediatly a timer is started with a delay of RAW3215_TIMEOUT. + */ +extern inline void raw3215_try_io(raw3215_info *raw) +{ + if (!(raw->flags & RAW3215_ACTIVE)) + return; + if (raw->queued_read != NULL) + raw3215_start_io(raw); + else if (raw->queued_write != NULL) { + if (raw->count >= RAW3215_MIN_WRITE || + (raw->flags & RAW3215_FLUSHING)) { + /* execute write requests bigger than minimum size */ + raw3215_start_io(raw); + if (raw->flags & RAW3215_TIMER_RUNS) { + del_timer(&raw->timer); + raw->flags &= ~RAW3215_TIMER_RUNS; + } + } else if (!(raw->flags & RAW3215_TIMER_RUNS)) { + /* delay small writes */ + init_timer(&raw->timer); + raw->timer.expires = RAW3215_TIMEOUT + jiffies; + raw->timer.data = (unsigned long) raw; + raw->timer.function = raw3215_timeout; + add_timer(&raw->timer); + raw->flags |= RAW3215_TIMER_RUNS; + } + } +} + +/* + * The bottom half handler routine for 3215 devices. It tries to start + * the next IO and wakes up processes waiting on the tty. + */ +static void raw3215_softint(void *data) +{ + raw3215_info *raw; + struct tty_struct *tty; + unsigned long flags; + + raw = (raw3215_info *) data; + s390irq_spin_lock_irqsave(raw->irq, flags); + raw3215_try_io((raw3215_info *) data); + raw->flags &= ~RAW3215_BH_PENDING; + s390irq_spin_unlock_irqrestore(raw->irq, flags); + /* Check for pending message from raw3215_irq */ + if (raw->message != NULL) { + printk(raw->message, raw->irq, raw->msg_dstat, raw->msg_cstat); + raw->message = NULL; + } + tty = raw->tty; + if (tty != NULL && + RAW3215_BUFFER_SIZE - raw->count >= RAW3215_MIN_SPACE) { + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); + wake_up_interruptible(&tty->write_wait); + } +} + +/* + * Function to safely add raw3215_softint to tq_immediate. + * The s390irq spinlock must be held. + */ +static inline void raw3215_sched_bh(raw3215_info *raw) +{ + if (raw->flags & RAW3215_BH_PENDING) + return; /* already pending */ + raw->flags |= RAW3215_BH_PENDING; + raw->tqueue.routine = raw3215_softint; + raw->tqueue.data = raw; + queue_task(&raw->tqueue, &tq_immediate); + mark_bh(IMMEDIATE_BH); +} + +/* + * Find the raw3215_info structure associated with irq + */ +static inline raw3215_info *raw3215_find_info(int irq) { + raw3215_info *raw; + int i; + + for (i = 0; i < NR_3215; i++) { + raw = raw3215[i]; + if (raw != NULL && raw->irq == irq && + (raw->flags & RAW3215_ACTIVE)) + break; + } + return (i >= NR_3215) ? NULL : raw; +} + +/* + * Interrupt routine, called from Ingo's I/O layer + */ +static void raw3215_irq(int irq, void *int_parm, struct pt_regs *regs) +{ + raw3215_info *raw; + raw3215_req *req; + struct tty_struct *tty; + devstat_t *stat; + int cstat, dstat; + int count, slen; + + stat = (devstat_t *) int_parm; + req = (raw3215_req *) stat->intparm; + cstat = stat->cstat; + dstat = stat->dstat; + if (cstat != 0) { + raw = raw3215_find_info(irq); + if (raw != NULL) { + raw->message = KERN_WARNING + "Got nonzero channel status in raw3215_irq " + "(dev %i, dev sts 0x%2x, sch sts 0x%2x)"; + raw->msg_dstat = dstat; + raw->msg_cstat = cstat; + raw3215_sched_bh(raw); + } + } + if (dstat & 0x01) { /* we got a unit exception */ + dstat &= ~0x01; /* we can ignore it */ + } + switch (dstat) { + case 0x80: + if (cstat != 0) + break; + /* Attention interrupt, someone hit the enter key */ + if ((raw = raw3215_find_info(irq)) == NULL) + return; /* That shouldn't happen ... */ + /* Setup a read request */ + req = raw3215_mk_read_req(raw); + raw3215_mk_read_ccw(raw, req); + raw->queued_read = req; + if (MACHINE_IS_P390) + memset(raw->inbuf, 0, RAW3215_INBUF_SIZE); + raw3215_sched_bh(raw); + break; + case 0x08: + case 0x0C: + /* Channel end interrupt. */ + raw = req->info; + if (req->type == RAW3215_READ) { + /* store residual count, then wait for device end */ + req->residual = stat->rescnt; + } + if (dstat == 0x08) + break; + case 0x04: + /* Device end interrupt. */ + raw = req->info; + if (req->type == RAW3215_READ && raw->tty != NULL) { + tty = raw->tty; + count = 160 - req->residual; + if (MACHINE_IS_P390) { + slen = strnlen(raw->inbuf, RAW3215_INBUF_SIZE); + if (count > slen) + count = slen; + } else + if (count >= TTY_FLIPBUF_SIZE - tty->flip.count) + count = TTY_FLIPBUF_SIZE - tty->flip.count - 1; + EBCASC(raw->inbuf, count); + if (count == 2 && ( + /* hat is 0xb0 in codepage 037 (US etc.) and thus */ + /* converted to 0x5e in ascii ('^') */ + strncmp(raw->inbuf, "^c", 2) == 0 || + /* hat is 0xb0 in several other codepages (German,*/ + /* UK, ...) and thus converted to ascii octal 252 */ + strncmp(raw->inbuf, "\252c", 2) == 0) ) { + /* emulate a control C = break */ + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = INTR_CHAR(tty); + tty_flip_buffer_push(raw->tty); + } else if (count == 2 && ( + strncmp(raw->inbuf, "^d", 2) == 0 || + strncmp(raw->inbuf, "\252d", 2) == 0) ) { + /* emulate a control D = end of file */ + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = EOF_CHAR(tty); + tty_flip_buffer_push(raw->tty); + } else if (count == 2 && ( + strncmp(raw->inbuf, "^z", 2) == 0 || + strncmp(raw->inbuf, "\252z", 2) == 0) ) { + /* emulate a control Z = suspend */ + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = SUSP_CHAR(tty); + tty_flip_buffer_push(raw->tty); + } else { + memcpy(tty->flip.char_buf_ptr, + raw->inbuf, count); + if (count < 2 || + (strncmp(raw->inbuf+count-2, "^n", 2) || + strncmp(raw->inbuf+count-2, "\252n", 2)) ) { /* don't add the auto \n */ + tty->flip.char_buf_ptr[count] = '\n'; + memset(tty->flip.flag_buf_ptr, + TTY_NORMAL, count + 1); + count++; + } else + count-=2; + tty->flip.char_buf_ptr += count; + tty->flip.flag_buf_ptr += count; + tty->flip.count += count; + tty_flip_buffer_push(raw->tty); + } + } else if (req->type == RAW3215_WRITE) { + raw->count -= ((req->end - req->start) & + (RAW3215_BUFFER_SIZE - 1)) + 1; + } + raw->flags &= ~RAW3215_WORKING; + raw3215_free_req(req); + /* check for empty wait */ + if (waitqueue_active(&raw->empty_wait) && + raw->queued_write == NULL && + raw->queued_read == NULL) { + wake_up_interruptible(&raw->empty_wait); + } + raw3215_sched_bh(raw); + break; + default: + /* Strange interrupt, I'll do my best to clean up */ + if ((raw = raw3215_find_info(irq)) == NULL) + return; /* That shouldn't happen ... */ + if (raw == NULL) break; + if (req != NULL && req->type != RAW3215_FREE) { + if (req->type == RAW3215_WRITE) + raw->count -= ((req->end - req->start) & + (RAW3215_BUFFER_SIZE-1))+1; + raw->flags &= ~RAW3215_WORKING; + raw3215_free_req(req); + } + raw->message = KERN_WARNING + "Spurious interrupt in in raw3215_irq " + "(dev %i, dev sts 0x%2x, sch sts 0x%2x)"; + raw->msg_dstat = dstat; + raw->msg_cstat = cstat; + raw3215_sched_bh(raw); + } + return; +} + +/* + * String write routine for 3215 devices + */ +static int +raw3215_write(raw3215_info *raw, const char *str, + int from_user, unsigned int length) +{ + raw3215_req *req; + unsigned long flags; + int ret, c; + int count; + + ret = 0; + while (length > 0) { + s390irq_spin_lock_irqsave(raw->irq, flags); + count = (length > RAW3215_BUFFER_SIZE) ? + RAW3215_BUFFER_SIZE : length; + length -= count; + + while (RAW3215_BUFFER_SIZE - raw->count < count) { + /* there might be a request pending */ + raw3215_try_io(raw); + if (wait_cons_dev(raw->irq) != 0) { + /* that shouldn't happen */ + raw->count = 0; + } + } + + req = raw3215_mk_write_req(raw); + /* copy string to output buffer and convert it to EBCDIC */ + if (from_user) { + while (1) { + c = MIN(count, + MIN(RAW3215_BUFFER_SIZE - raw->count, + RAW3215_BUFFER_SIZE - raw->head)); + if (c <= 0) + break; + c -= copy_from_user(raw->buffer + raw->head, + str, c); + if (c == 0) { + if (!ret) + ret = -EFAULT; + break; + } + ASCEBC(raw->buffer + raw->head, c); + raw->head = (raw->head + c) & + (RAW3215_BUFFER_SIZE - 1); + raw->count += c; + str += c; + count -= c; + ret += c; + } + } else { + while (1) { + c = MIN(count, + MIN(RAW3215_BUFFER_SIZE - raw->count, + RAW3215_BUFFER_SIZE - raw->head)); + if (c <= 0) + break; + memcpy(raw->buffer + raw->head, str, c); + ASCEBC(raw->buffer + raw->head, c); + raw->head = (raw->head + c) & + (RAW3215_BUFFER_SIZE - 1); + raw->count += c; + str += c; + count -= c; + ret += c; + } + } + raw3215_mk_write_ccw(raw, req); + raw->queued_write = req; + /* start or queue request */ + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); + + } + + return ret; +} + +/* + * Put character routine for 3215 devices + */ +static void raw3215_putchar(raw3215_info *raw, unsigned char ch) +{ + raw3215_req *req; + unsigned long flags; + + s390irq_spin_lock_irqsave(raw->irq, flags); + while (RAW3215_BUFFER_SIZE - raw->count < 1) { + /* there might be a request pending */ + raw3215_try_io(raw); + if (wait_cons_dev(raw->irq) != 0) { + /* that shouldn't happen */ + raw->count = 0; + } + } + + req = raw3215_mk_write_req(raw); + raw->buffer[raw->head] = (char) _ascebc[(int) ch]; + raw->head = (raw->head + 1) & (RAW3215_BUFFER_SIZE - 1); + raw->count++; + raw3215_mk_write_ccw(raw, req); + raw->queued_write = req; + /* start or queue request */ + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +/* + * Flush routine, it simply sets the flush flag and tries to start + * pending IO. + */ +static void raw3215_flush_buffer(raw3215_info *raw) +{ + unsigned long flags; + + s390irq_spin_lock_irqsave(raw->irq, flags); + if (raw->count > 0) { + raw->flags |= RAW3215_FLUSHING; + raw3215_try_io(raw); + raw->flags &= ~RAW3215_FLUSHING; + } + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +/* + * Fire up a 3215 device. + */ +static int raw3215_startup(raw3215_info *raw) +{ + unsigned long flags; + + if (raw->flags & RAW3215_ACTIVE) + return 0; + if (request_irq(raw->irq, raw3215_irq, SA_INTERRUPT, + "3215 terminal driver", &raw->devstat) != 0) + return -1; + raw->flags |= RAW3215_ACTIVE; + s390irq_spin_lock_irqsave(raw->irq, flags); + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); + + return 0; +} + +/* + * Shutdown a 3215 device. + */ +static void raw3215_shutdown(raw3215_info *raw) +{ + DECLARE_WAITQUEUE(wait, current); + unsigned long flags; + + if (!(raw->flags & RAW3215_ACTIVE) || (raw->flags & RAW3215_FIXED)) + return; + /* Wait for outstanding requests, then free irq */ + s390irq_spin_lock_irqsave(raw->irq, flags); + if ((raw->flags & RAW3215_WORKING) || + raw->queued_write != NULL || + raw->queued_read != NULL) { + raw->flags |= RAW3215_CLOSING; + add_wait_queue(&raw->empty_wait, &wait); + current->state = TASK_INTERRUPTIBLE; + s390irq_spin_unlock_irqrestore(raw->irq, flags); + schedule(); + s390irq_spin_lock_irqsave(raw->irq, flags); + current->state = TASK_RUNNING; + raw->flags &= ~(RAW3215_ACTIVE | RAW3215_CLOSING); + } + free_irq(raw->irq, NULL); + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +static int +raw3215_find_dev(int number) +{ + dev_info_t dinfo; + int irq; + int count; + + irq = get_irq_first(); + count = 0; + while (count <= number && irq != -ENODEV) { + if (get_dev_info(irq, &dinfo) == -ENODEV) + break; + if (dinfo.devno == raw3215_condevice || + dinfo.sid_data.cu_type == 0x3215) { + count++; + if (count > number) + return irq; + } + irq = get_irq_next(irq); + } + return -1; /* console not found */ +} + +#ifdef CONFIG_3215_CONSOLE + +/* + * Try to request the console IRQ. Called from init/main.c + */ +int con3215_activate(void) +{ + raw3215_info *raw; + + if (!MACHINE_IS_VM && !MACHINE_IS_P390) + return 0; + raw = raw3215[0]; /* 3215 console is the first one */ + if (raw->irq == -1) /* now console device found in con3215_init */ + return -1; + return raw3215_startup(raw); +} + +/* + * Write a string to the 3215 console + */ +static void +con3215_write(struct console *co, const char *str, unsigned int count) +{ + raw3215_info *raw; + + if (count <= 0) + return; + raw = raw3215[0]; /* console 3215 is the first one */ + raw3215_write(raw, str, 0, count); +} + +kdev_t con3215_device(struct console *c) +{ + return MKDEV(TTY_MAJOR, c->index); +} + +/* + * panic() calls console_unblank before the system enters a + * disabled, endless loop. + */ +void con3215_unblank(void) +{ + raw3215_info *raw; + unsigned long flags; + + raw = raw3215[0]; /* console 3215 is the first one */ + s390irq_spin_lock_irqsave(raw->irq, flags); + while (raw->count > 0) { + /* there might be a request pending */ + raw->flags |= RAW3215_FLUSHING; + raw3215_try_io(raw); + if (wait_cons_dev(raw->irq) != 0) { + /* that shouldn't happen */ + raw->count = 0; + } + raw->flags &= ~RAW3215_FLUSHING; + } + s390irq_spin_unlock_irqrestore(raw->irq, flags); +} + +static int __init con3215_consetup(struct console *co, char *options) +{ + return 0; +} + +/* + * The console structure for the 3215 console + */ +static struct console con3215 = { + "tty3215", + con3215_write, + NULL, + con3215_device, + NULL, + con3215_unblank, + con3215_consetup, + CON_PRINTBUFFER, + 0, + 0, + NULL +}; + +#endif + +/* + * tty3215_open + * + * This routine is called whenever a 3215 tty is opened. + */ +static int tty3215_open(struct tty_struct *tty, struct file * filp) +{ + raw3215_info *raw; + int retval, line; + + line = MINOR(tty->device) - tty->driver.minor_start; + if ((line < 0) || (line >= NR_3215)) + return -ENODEV; + + raw = raw3215[line]; + if (raw == NULL) { + raw = kmalloc(sizeof(raw3215_info) + + RAW3215_INBUF_SIZE, GFP_KERNEL); + if (raw == NULL) + return -ENOMEM; + raw->irq = raw3215_find_dev(line); + if (raw->irq == -1) { + kfree(raw); + return -ENODEV; + } + raw->inbuf = (char *) raw + sizeof(raw3215_info); + memset(raw, 0, sizeof(raw3215_info)); + raw->buffer = (char *) kmalloc(RAW3215_BUFFER_SIZE, GFP_KERNEL); + if (raw->buffer == NULL) { + kfree_s(raw, sizeof(raw3215_info)); + return -ENOMEM; + } + raw->tqueue.routine = raw3215_softint; + raw->tqueue.data = raw; + init_waitqueue_head(&raw->empty_wait); + raw3215[line] = raw; + } + + tty->driver_data = raw; + raw->tty = tty; + + tty->low_latency = 0; /* don't use bottom half for pushing chars */ + /* + * Start up 3215 device + */ + retval = raw3215_startup(raw); + if (retval) + return retval; + + return 0; +} + +/* + * tty3215_close() + * + * This routine is called when the 3215 tty is closed. We wait + * for the remaining request to be completed. Then we clean up. + */ +static void tty3215_close(struct tty_struct *tty, struct file * filp) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + if (raw == NULL || tty->count > 1) + return; + tty->closing = 1; + /* Shutdown the terminal */ + raw3215_shutdown(raw); + tty->closing = 0; + raw->tty = NULL; +} + +/* + * Returns the amount of free space in the output buffer. + */ +static int tty3215_write_room(struct tty_struct *tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + return RAW3215_BUFFER_SIZE - raw->count; +} + +/* + * String write routine for 3215 ttys + */ +static int tty3215_write(struct tty_struct * tty, int from_user, + const unsigned char *buf, int count) +{ + raw3215_info *raw; + int ret; + + if (!tty) + return 0; + raw = (raw3215_info *) tty->driver_data; + ret = raw3215_write(raw, buf, from_user, count); + return ret; +} + +/* + * Put character routine for 3215 ttys + */ +static void tty3215_put_char(struct tty_struct *tty, unsigned char ch) +{ + raw3215_info *raw; + + if (!tty) + return; + raw = (raw3215_info *) tty->driver_data; + raw3215_putchar(raw, ch); +} + +static void tty3215_flush_chars(struct tty_struct *tty) +{ +} + +/* + * Returns the number of characters in the output buffer + */ +static int tty3215_chars_in_buffer(struct tty_struct *tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + return raw->count; +} + +static void tty3215_flush_buffer(struct tty_struct *tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + raw3215_flush_buffer(raw); + wake_up_interruptible(&tty->write_wait); + if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc.write_wakeup) + (tty->ldisc.write_wakeup)(tty); +} + +/* + * Currently we don't have any io controls for 3215 ttys + */ +static int tty3215_ioctl(struct tty_struct *tty, struct file * file, + unsigned int cmd, unsigned long arg) +{ + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + switch (cmd) { + default: + return -ENOIOCTLCMD; + } + return 0; +} + +/* + * Disable reading from a 3215 tty + */ +static void tty3215_throttle(struct tty_struct * tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + raw->flags |= RAW3215_THROTTLED; +} + +/* + * Enable reading from a 3215 tty + */ +static void tty3215_unthrottle(struct tty_struct * tty) +{ + raw3215_info *raw; + unsigned long flags; + + raw = (raw3215_info *) tty->driver_data; + if (raw->flags & RAW3215_THROTTLED) { + s390irq_spin_lock_irqsave(raw->irq, flags); + raw->flags &= ~RAW3215_THROTTLED; + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); + } +} + +/* + * Disable writing to a 3215 tty + */ +static void tty3215_stop(struct tty_struct *tty) +{ + raw3215_info *raw; + + raw = (raw3215_info *) tty->driver_data; + raw->flags |= RAW3215_STOPPED; +} + +/* + * Enable writing to a 3215 tty + */ +static void tty3215_start(struct tty_struct *tty) +{ + raw3215_info *raw; + unsigned long flags; + + raw = (raw3215_info *) tty->driver_data; + if (raw->flags & RAW3215_STOPPED) { + s390irq_spin_lock_irqsave(raw->irq, flags); + raw->flags &= ~RAW3215_STOPPED; + raw3215_try_io(raw); + s390irq_spin_unlock_irqrestore(raw->irq, flags); + } +} + +/* + * 3215 console driver boottime initialization code. + * Register console. We can't request the IRQ here, because + * it's too early (kmalloc isn't working yet). We'll have to + * buffer all the console requests until we can request the + * irq. For this purpose we use some pages of fixed memory. + */ +void __init con3215_init(void) +{ + raw3215_info *raw; + raw3215_req *req; + int i; + + if (!MACHINE_IS_VM && !MACHINE_IS_P390) + return; + if (MACHINE_IS_VM) { + cpcmd("TERM CONMODE 3215", NULL, 0); + cpcmd("TERM AUTOCR OFF", NULL, 0); + } + + /* allocate 3215 request structures */ + raw3215_freelist = NULL; + spin_lock_init(&raw3215_freelist_lock); + for (i = 0; i < NR_3215_REQ; i++) { + req = (raw3215_req *) alloc_bootmem(sizeof(raw3215_req)); + req->next = raw3215_freelist; + raw3215_freelist = req; + } + +#ifdef CONFIG_3215_CONSOLE + raw3215[0] = raw = (raw3215_info *) + alloc_bootmem(sizeof(raw3215_info)); + memset(raw, 0, sizeof(raw3215_info)); + raw->buffer = (char *) alloc_bootmem(RAW3215_BUFFER_SIZE); + raw->inbuf = (char *) alloc_bootmem(RAW3215_INBUF_SIZE); + /* Find the first console */ + raw->irq = raw3215_find_dev(0); + raw->flags |= RAW3215_FIXED; + raw->tqueue.routine = raw3215_softint; + raw->tqueue.data = raw; + init_waitqueue_head(&raw->empty_wait); + + if (raw->irq != -1) { + register_console(&con3215); + s390irq_spin_lock(raw->irq); + set_cons_dev(raw->irq); + s390irq_spin_unlock(raw->irq); + } else { + free_bootmem((unsigned long) raw->inbuf, RAW3215_INBUF_SIZE); + free_bootmem((unsigned long) raw->buffer, RAW3215_BUFFER_SIZE); + free_bootmem((unsigned long) raw, sizeof(raw3215_info)); + raw3215[0] = NULL; + printk("Couldn't find a 3215 console device\n"); + } +#endif + + /* + * Initialize the tty_driver structure + * Entries in tty3215_driver that are NOT initialized: + * proc_entry, set_termios, flush_buffer, set_ldisc, write_proc + */ + + memset(&tty3215_driver, 0, sizeof(struct tty_driver)); + tty3215_driver.magic = TTY_DRIVER_MAGIC; + tty3215_driver.driver_name = "tty3215"; + tty3215_driver.name = "ttyS"; + tty3215_driver.name_base = 0; + tty3215_driver.major = TTY_MAJOR; + tty3215_driver.minor_start = 64; + tty3215_driver.num = NR_3215; + tty3215_driver.type = TTY_DRIVER_TYPE_SYSTEM; + tty3215_driver.subtype = SYSTEM_TYPE_TTY; + tty3215_driver.init_termios = tty_std_termios; + tty3215_driver.init_termios.c_iflag = IGNBRK | IGNPAR; + tty3215_driver.init_termios.c_oflag = ONLCR; + tty3215_driver.init_termios.c_lflag = ISIG; + tty3215_driver.flags = TTY_DRIVER_REAL_RAW; + tty3215_driver.refcount = &tty3215_refcount; + tty3215_driver.table = tty3215_table; + tty3215_driver.termios = tty3215_termios; + tty3215_driver.termios_locked = tty3215_termios_locked; + + tty3215_driver.open = tty3215_open; + tty3215_driver.close = tty3215_close; + tty3215_driver.write = tty3215_write; + tty3215_driver.put_char = tty3215_put_char; + tty3215_driver.flush_chars = tty3215_flush_chars; + tty3215_driver.write_room = tty3215_write_room; + tty3215_driver.chars_in_buffer = tty3215_chars_in_buffer; + tty3215_driver.flush_buffer = tty3215_flush_buffer; + tty3215_driver.ioctl = tty3215_ioctl; + tty3215_driver.throttle = tty3215_throttle; + tty3215_driver.unthrottle = tty3215_unthrottle; + tty3215_driver.send_xchar = NULL; + tty3215_driver.set_termios = NULL; + tty3215_driver.stop = tty3215_stop; + tty3215_driver.start = tty3215_start; + tty3215_driver.hangup = NULL; + tty3215_driver.break_ctl = NULL; + tty3215_driver.wait_until_sent = NULL; + tty3215_driver.read_proc = NULL; + + if (tty_register_driver(&tty3215_driver)) + panic("Couldn't register tty3215 driver\n"); + +} diff --git a/drivers/s390/char/hwc.h b/drivers/s390/char/hwc.h new file mode 100644 index 000000000..5de3d1b6f --- /dev/null +++ b/drivers/s390/char/hwc.h @@ -0,0 +1,249 @@ +/* + * drivers/s390/char/hwc.h + * + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke <peschke@fh-brandenburg.de> + * + * + * + */ + +#ifndef __HWC_H__ +#define __HWC_H__ + +#define ET_OpCmd 0x01 +#define ET_Msg 0x02 +#define ET_StateChange 0x08 +#define ET_PMsgCmd 0x09 +#define ET_CntlProgOpCmd 0x20 + +#define ET_OpCmd_Mask 0x80000000 +#define ET_Msg_Mask 0x40000000 +#define ET_StateChange_Mask 0x01000000 +#define ET_PMsgCmd_Mask 0x00800000 +#define ET_CtlProgOpCmd_Mask 0x00000001 + +#define GMF_DOM 0x8000 +#define GMF_SndAlrm 0x4000 +#define GMF_HoldMsg 0x2000 + +#define LTF_CntlText 0x8000 +#define LTF_LabelText 0x4000 +#define LTF_DataText 0x2000 +#define LTF_EndText 0x1000 +#define LTF_PromptText 0x0800 + +#define HWC_COMMAND_INITIATED 0 +#define HWC_BUSY 2 +#define HWC_NOT_OPERATIONAL 3 + +#define HWC_CMDW_READDATA 0x00770005 + +#define HWC_CMDW_WRITEDATA 0x00760005 + +#define HWC_CMDW_WRITEMASK 0x00780005 + +#define GDS_ID_MDSMU 0x1310 + +#define GDS_ID_MDSRouteInfo 0x1311 + +#define GDS_ID_AgUnWrkCorr 0x1549 + +#define GDS_ID_SNACondReport 0x1532 + +#define GDS_ID_CPMSU 0x1212 + +#define GDS_ID_RoutTargInstr 0x154D + +#define GDS_ID_OpReq 0x8070 + +#define GDS_ID_TextCmd 0x1320 + +#define GDS_KEY_SelfDefTextMsg 0x31 + +#define _HWCB_HEADER u16 length; \ + u8 function_code; \ + u8 control_mask[3]; \ + u16 response_code; + +#define _EBUF_HEADER u16 length; \ + u8 type; \ + u8 flags; \ + u16 _reserved; + +typedef struct { + _EBUF_HEADER +} __attribute__ ((packed)) + +evbuf_t; + +#define _MDB_HEADER u16 length; \ + u16 type; \ + u32 tag; \ + u32 revision_code; + +#define _GO_HEADER u16 length; \ + u16 type; \ + u32 domid; \ + u8 hhmmss_time[8]; \ + u8 th_time[3]; \ + u8 _reserved_0; \ + u8 dddyyyy_date[7]; \ + u8 _reserved_1; \ + u16 general_msg_flags; \ + u8 _reserved_2[10]; \ + u8 originating_system_name[8]; \ + u8 job_guest_name[8]; + +#define _MTO_HEADER u16 length; \ + u16 type; \ + u16 line_type_flags; \ + u8 alarm_control; \ + u8 _reserved[3]; + +typedef struct { + _GO_HEADER +} __attribute__ ((packed)) + +go_t; + +typedef struct { + go_t go; +} __attribute__ ((packed)) + +mdb_body_t; + +typedef struct { + _MDB_HEADER + mdb_body_t mdb_body; +} __attribute__ ((packed)) + +mdb_t; + +typedef struct { + _EBUF_HEADER + mdb_t mdb; +} __attribute__ ((packed)) + +msgbuf_t; + +typedef struct { + _HWCB_HEADER + msgbuf_t msgbuf; +} __attribute__ ((packed)) + +write_hwcb_t; + +typedef struct { + _MTO_HEADER +} __attribute__ ((packed)) + +mto_t; + +static write_hwcb_t write_hwcb_template = +{ + sizeof (write_hwcb_t), + 0x00, + { + 0x00, + 0x00, + 0x00 + }, + 0x0000, + { + sizeof (msgbuf_t), + ET_Msg, + 0x00, + 0x0000, + { + sizeof (mdb_t), + 0x0001, + 0xD4C4C240, + 0x00000001, + { + { + sizeof (go_t), + 0x0001 + + } + } + } + } +}; + +static mto_t mto_template = +{ + sizeof (mto_t), + 0x0004, + LTF_EndText, + 0x00 +}; + +typedef u32 _hwcb_mask_t; + +typedef struct { + _HWCB_HEADER + u16 _reserved; + u16 mask_length; + _hwcb_mask_t cp_receive_mask; + _hwcb_mask_t cp_send_mask; + _hwcb_mask_t hwc_receive_mask; + _hwcb_mask_t hwc_send_mask; +} __attribute__ ((packed)) + +init_hwcb_t; + +static init_hwcb_t init_hwcb_template = +{ + sizeof (init_hwcb_t), + 0x00, + { + 0x00, + 0x00, + 0x00 + }, + 0x0000, + 0x0000, + sizeof (_hwcb_mask_t), + ET_OpCmd_Mask | ET_PMsgCmd_Mask, + ET_Msg_Mask +}; + +#define _GDS_VECTOR_HEADER u16 length; \ + u16 gds_id; + +#define _GDS_SUBVECTOR_HEADER u8 length; \ + u8 key; + +typedef struct { + _GDS_VECTOR_HEADER +} __attribute__ ((packed)) + +gds_vector_t; + +typedef struct { + _GDS_SUBVECTOR_HEADER +} __attribute__ ((packed)) + +gds_subvector_t; + +typedef struct { + _HWCB_HEADER +} __attribute__ ((packed)) + +read_hwcb_t; + +static read_hwcb_t read_hwcb_template = +{ + PAGE_SIZE, + 0x00, + { + 0x00, + 0x00, + 0x80 + } +}; + +#endif /* __HWC_H__ */ diff --git a/drivers/s390/char/hwc_con.c b/drivers/s390/char/hwc_con.c new file mode 100644 index 000000000..16d5553e8 --- /dev/null +++ b/drivers/s390/char/hwc_con.c @@ -0,0 +1,99 @@ +/* + * drivers/s390/char/hwc_con.c + * HWC line mode console driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke <peschke@fh-brandenburg.de> + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/major.h> +#include <linux/errno.h> +#include <linux/kdev_t.h> +#include <linux/string.h> +#include <linux/console.h> +#include <linux/fs.h> +#include <linux/init.h> + +#include "hwc_rw.h" + +extern void hwc_tty_init (void); + +#ifdef CONFIG_HWC_CONSOLE + +#define hwc_console_major 4 +#define hwc_console_minor 0 +#define hwc_console_name "console" + +void hwc_console_write (struct console *, const char *, unsigned int); +kdev_t hwc_console_device (struct console *); + +#define HWC_CON_PRINT_HEADER "hwc console driver: " + +struct console hwc_console = +{ + + hwc_console_name, + hwc_console_write, + NULL, + hwc_console_device, + NULL, + NULL, + NULL, + CON_PRINTBUFFER, + 0, + 0, + NULL +}; + +void +hwc_console_write ( + struct console *console, + const char *message, + unsigned int count) +{ + + if (console->device (console) != hwc_console.device (&hwc_console)) { + + hwc_printk (KERN_WARNING HWC_CON_PRINT_HEADER + "hwc_console_write() called with wrong " + "device number"); + return; + } + hwc_write (0, message, count); +} + +kdev_t +hwc_console_device (struct console * c) +{ + return MKDEV (hwc_console_major, hwc_console_minor); +} + +#endif + +void __init +hwc_console_init (void) +{ + +#ifdef CONFIG_3215 + if (MACHINE_IS_VM) + return; +#endif + if (MACHINE_IS_P390) + return; + + if (hwc_init () == 0) { + +#ifdef CONFIG_HWC_CONSOLE + + register_console (&hwc_console); +#endif + + hwc_tty_init (); + } else + panic (HWC_CON_PRINT_HEADER "hwc initialisation failed !"); + + return; +} diff --git a/drivers/s390/char/hwc_rw.c b/drivers/s390/char/hwc_rw.c new file mode 100644 index 000000000..6ffecb799 --- /dev/null +++ b/drivers/s390/char/hwc_rw.c @@ -0,0 +1,2016 @@ +/* + * drivers/s390/char/hwc_rw.c + * driver: reading from and writing to system console on S/390 via HWC + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke <peschke@fh-brandenburg.de> + * + * + * + * + * + * + */ + +#include <linux/config.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/errno.h> +#include <linux/ctype.h> +#include <linux/mm.h> +#include <linux/timer.h> +#include <linux/bootmem.h> + +#include <asm/ebcdic.h> +#include <asm/uaccess.h> +#include <asm/types.h> +#include <asm/bitops.h> +#include <asm/setup.h> +#include <asm/page.h> + +#ifndef MIN +#define MIN(a,b) ((a<b) ? a : b) +#endif + +#define HWC_RW_PRINT_HEADER "hwc low level driver: " + +#define USE_VM_DETECTION + +#define DEFAULT_CASE_DELIMITER '%' + +#define DUMP_HWC_INIT_ERROR + +#define DUMP_HWC_WRITE_ERROR + +#define DUMP_HWC_WRITE_LIST_ERROR + +#define DUMP_HWC_READ_ERROR + +#undef DUMP_HWCB_INPUT + +#undef BUFFER_STRESS_TEST + +typedef struct { + unsigned char *next; + unsigned short int mto_char_sum; + unsigned char mto_number; + unsigned char times_lost; + unsigned short int mto_number_lost; + unsigned long int mto_char_sum_lost; +} __attribute__ ((packed)) + +hwcb_list_t; + +#define MAX_HWCB_ROOM (PAGE_SIZE - sizeof(hwcb_list_t)) + +#define MAX_MESSAGE_SIZE (MAX_HWCB_ROOM - sizeof(write_hwcb_t)) + +#define BUF_HWCB hwc_data.hwcb_list_tail +#define OUT_HWCB hwc_data.hwcb_list_head +#define ALL_HWCB_MTO hwc_data.mto_number +#define ALL_HWCB_CHAR hwc_data.mto_char_sum + +#define _LIST(hwcb) ((hwcb_list_t*)(&(hwcb)[PAGE_SIZE-sizeof(hwcb_list_t)])) + +#define _HWCB_CHAR(hwcb) (_LIST(hwcb)->mto_char_sum) + +#define _HWCB_MTO(hwcb) (_LIST(hwcb)->mto_number) + +#define _HWCB_CHAR_LOST(hwcb) (_LIST(hwcb)->mto_char_sum_lost) + +#define _HWCB_MTO_LOST(hwcb) (_LIST(hwcb)->mto_number_lost) + +#define _HWCB_TIMES_LOST(hwcb) (_LIST(hwcb)->times_lost) + +#define _HWCB_NEXT(hwcb) (_LIST(hwcb)->next) + +#define BUF_HWCB_CHAR _HWCB_CHAR(BUF_HWCB) + +#define BUF_HWCB_MTO _HWCB_MTO(BUF_HWCB) + +#define BUF_HWCB_NEXT _HWCB_NEXT(BUF_HWCB) + +#define OUT_HWCB_CHAR _HWCB_CHAR(OUT_HWCB) + +#define OUT_HWCB_MTO _HWCB_MTO(OUT_HWCB) + +#define OUT_HWCB_NEXT _HWCB_NEXT(OUT_HWCB) + +#define BUF_HWCB_CHAR_LOST _HWCB_CHAR_LOST(BUF_HWCB) + +#define BUF_HWCB_MTO_LOST _HWCB_MTO_LOST(BUF_HWCB) + +#define OUT_HWCB_CHAR_LOST _HWCB_CHAR_LOST(OUT_HWCB) + +#define OUT_HWCB_MTO_LOST _HWCB_MTO_LOST(OUT_HWCB) + +#define BUF_HWCB_TIMES_LOST _HWCB_TIMES_LOST(BUF_HWCB) + +#include "hwc.h" + +#define __HWC_RW_C__ +#include "hwc_rw.h" +#undef __HWC_RW_C__ + +static unsigned char _obuf[MAX_HWCB_ROOM]; + +static unsigned char + _page[PAGE_SIZE] __attribute__ ((aligned (PAGE_SIZE))); + +typedef u32 kmem_pages_t; + +#define MAX_KMEM_PAGES (sizeof(kmem_pages_t) << 3) + +#define HWC_TIMER_RUNS 1 +#define FLUSH_HWCBS 2 + +static struct { + + hwc_ioctls_t ioctls; + + hwc_ioctls_t init_ioctls; + + unsigned char *hwcb_list_head; + + unsigned char *hwcb_list_tail; + + unsigned short int mto_number; + + unsigned int mto_char_sum; + + unsigned char hwcb_count; + + unsigned long kmem_start; + + unsigned long kmem_end; + + kmem_pages_t kmem_pages; + + unsigned char *obuf; + + unsigned short int obuf_cursor; + + unsigned short int obuf_count; + + unsigned short int obuf_start; + + unsigned char *page; + + u32 current_servc; + + unsigned char *current_hwcb; + + unsigned char write_nonprio:1; + unsigned char write_prio:1; + unsigned char read_nonprio:1; + unsigned char read_prio:1; + + unsigned char flags; + + spinlock_t lock; + + struct timer_list write_timer; +} hwc_data = +{ + { + }, + { + 8, + 0, + 80, + CODE_ASCII, + 1, + 50, + MAX_KMEM_PAGES, + + 0, + + 0x6c + + }, + NULL, + NULL, + 0, + 0, + 0, + 0, + 0, + 0, + _obuf, + 0, + 0, + 0, + _page, + 0, + NULL, + 0, + 0, + 0, + 0, + 0 + +}; + +#define DELAYED_WRITE 0 +#define IMMEDIATE_WRITE 1 + +static signed int do_hwc_write (int from_user, unsigned char *, + unsigned int, + unsigned char, + unsigned char); + +static asmlinkage int +internal_print (char write_time, const char *fmt,...) +{ + va_list args; + int i; + unsigned char buf[512]; + + va_start (args, fmt); + i = vsprintf (buf, fmt, args); + va_end (args); + return do_hwc_write (0, buf, i, CODE_ASCII, write_time); +} + +int +hwc_printk (const char *fmt,...) +{ + va_list args; + int i; + unsigned char buf[512]; + unsigned long flags; + int retval; + + spin_lock_irqsave (&hwc_data.lock, flags); + + i = vsprintf (buf, fmt, args); + va_end (args); + retval = do_hwc_write (0, buf, i, CODE_ASCII, IMMEDIATE_WRITE); + + spin_unlock_irqrestore (&hwc_data.lock, flags); + + return retval; +} + +#ifdef DUMP_HWCB_INPUT + +static void +dump_storage_area (unsigned char *area, unsigned short int count) +{ + unsigned short int index; + ioctl_nl_t old_final_nl; + + if (!area || !count) + return; + + old_final_nl = hwc_data.ioctls.final_nl; + hwc_data.ioctls.final_nl = 1; + + internal_print (DELAYED_WRITE, "\n%8x ", area); + + for (index = 0; index < count; index++) { + + if (area[index] <= 0xF) + internal_print (DELAYED_WRITE, "0%x", area[index]); + else + internal_print (DELAYED_WRITE, "%x", area[index]); + + if ((index & 0xF) == 0xF) + internal_print (DELAYED_WRITE, "\n%8x ", + &area[index + 1]); + else if ((index & 3) == 3) + internal_print (DELAYED_WRITE, " "); + } + + internal_print (IMMEDIATE_WRITE, "\n"); + + hwc_data.ioctls.final_nl = old_final_nl; +} +#endif + +static inline u32 +service_call ( + u32 hwc_command_word, + unsigned char hwcb[]) +{ + unsigned int condition_code = 1; + + __asm__ __volatile__ ("L 1, 0(0,%0) \n\t" + "LRA 2, 0(0,%1) \n\t" + ".long 0xB2200012 \n\t" + : + :"a" (&hwc_command_word), "a" (hwcb) + :"1", "2", "memory"); + + __asm__ __volatile__ ("IPM %0 \n\t" + "SRL %0, 28 \n\t" + :"=r" (condition_code)); + + return condition_code; +} + +static inline unsigned char * +ext_int_param (void) +{ + u32 param; + + __asm__ __volatile__ ("L %0,128(0,0)\n\t" + :"=r" (param)); + + return ((unsigned char *) param); +} + +static int +prepare_write_hwcb (void) +{ + write_hwcb_t *hwcb; + + if (!BUF_HWCB) + return -ENOMEM; + + BUF_HWCB_MTO = 0; + BUF_HWCB_CHAR = 0; + + hwcb = (write_hwcb_t *) BUF_HWCB; + + memcpy (hwcb, &write_hwcb_template, sizeof (write_hwcb_t)); + + if (!hwc_data.write_nonprio && hwc_data.write_prio) + hwcb->msgbuf.type = ET_PMsgCmd; + + return 0; +} + +static int +sane_write_hwcb (void) +{ + unsigned short int lost_msg; + unsigned int lost_char; + unsigned char lost_hwcb; + unsigned char *bad_addr; + unsigned long page; + int page_nr; + + if (!OUT_HWCB) + return -ENOMEM; + + if ((unsigned long) OUT_HWCB & 0xFFF) { + + bad_addr = OUT_HWCB; + +#ifdef DUMP_HWC_WRITE_LIST_ERROR + __asm__ ("LHI 1,0xe30\n\t" + "LRA 2,0(0,%0) \n\t" + "J .+0 \n\t" + : + : "a" (bad_addr) + : "1", "2"); +#endif + + hwc_data.kmem_pages = 0; + if ((unsigned long) BUF_HWCB & 0xFFF) { + + lost_hwcb = hwc_data.hwcb_count; + lost_msg = ALL_HWCB_MTO; + lost_char = ALL_HWCB_CHAR; + + OUT_HWCB = NULL; + BUF_HWCB = NULL; + ALL_HWCB_MTO = 0; + ALL_HWCB_CHAR = 0; + hwc_data.hwcb_count = 0; + } else { + + lost_hwcb = hwc_data.hwcb_count - 1; + lost_msg = ALL_HWCB_MTO - BUF_HWCB_MTO; + lost_char = ALL_HWCB_CHAR - BUF_HWCB_CHAR; + OUT_HWCB = BUF_HWCB; + ALL_HWCB_MTO = BUF_HWCB_MTO; + ALL_HWCB_CHAR = BUF_HWCB_CHAR; + hwc_data.hwcb_count = 1; + page = (unsigned long) BUF_HWCB; + + if (page >= hwc_data.kmem_start && + page < hwc_data.kmem_end) { + + page_nr = (int) + ((page - hwc_data.kmem_start) >> 12); + set_bit (page_nr, &hwc_data.kmem_pages); + } + } + + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "found invalid HWCB at address 0x%x. List corrupted. " + "Lost %i HWCBs with %i characters within up to %i " + "messages. Saved %i HWCB with last %i characters i" + "within up to %i messages.\n", + (unsigned int) bad_addr, + lost_hwcb, lost_char, lost_msg, + hwc_data.hwcb_count, + ALL_HWCB_CHAR, ALL_HWCB_MTO); + } + return 0; +} + +static int +reuse_write_hwcb (void) +{ + int retval; + + if (hwc_data.hwcb_count < 2) +#ifdef DUMP_HWC_WRITE_LIST_ERROR + __asm__ ("LHI 1,0xe31\n\t" + "LRA 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "J .+0 \n\t" + : + : "a" (BUF_HWCB), "a" (OUT_HWCB) + : "1", "2", "3"); +#else + return -EPERM; +#endif + + if (hwc_data.current_hwcb == OUT_HWCB) { + + if (hwc_data.hwcb_count > 2) { + + BUF_HWCB_NEXT = OUT_HWCB_NEXT; + + BUF_HWCB = OUT_HWCB_NEXT; + + OUT_HWCB_NEXT = BUF_HWCB_NEXT; + + BUF_HWCB_NEXT = NULL; + } + } else { + + BUF_HWCB_NEXT = OUT_HWCB; + + BUF_HWCB = OUT_HWCB; + + OUT_HWCB = OUT_HWCB_NEXT; + + BUF_HWCB_NEXT = NULL; + } + + BUF_HWCB_TIMES_LOST += 1; + BUF_HWCB_CHAR_LOST += BUF_HWCB_CHAR; + BUF_HWCB_MTO_LOST += BUF_HWCB_MTO; + ALL_HWCB_MTO -= BUF_HWCB_MTO; + ALL_HWCB_CHAR -= BUF_HWCB_CHAR; + + retval = prepare_write_hwcb (); + + if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb) + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "reached my own limit of " + "allowed buffer space for output (%i HWCBs = %li " + "bytes), skipped content of oldest HWCB %i time(s) " + "(%i lines = %i characters)\n", + hwc_data.ioctls.max_hwcb, + hwc_data.ioctls.max_hwcb * PAGE_SIZE, + BUF_HWCB_TIMES_LOST, + BUF_HWCB_MTO_LOST, + BUF_HWCB_CHAR_LOST); + else + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "page allocation failed, " + "could not expand buffer for output (currently in " + "use: %i HWCBs = %li bytes), skipped content of " + "oldest HWCB %i time(s) (%i lines = %i characters)\n", + hwc_data.hwcb_count, + hwc_data.hwcb_count * PAGE_SIZE, + BUF_HWCB_TIMES_LOST, + BUF_HWCB_MTO_LOST, + BUF_HWCB_CHAR_LOST); + + return retval; +} + +static int +allocate_write_hwcb (void) +{ + unsigned char *page; + int page_nr; + + if (hwc_data.hwcb_count == hwc_data.ioctls.max_hwcb) + return -ENOMEM; + + page_nr = find_first_zero_bit (&hwc_data.kmem_pages, MAX_KMEM_PAGES); + if (page_nr < hwc_data.ioctls.kmem_hwcb) { + + page = (unsigned char *) + (hwc_data.kmem_start + (page_nr << 12)); + set_bit (page_nr, &hwc_data.kmem_pages); + } else + page = (unsigned char *) __get_free_page (GFP_ATOMIC); + + if (!page) + return -ENOMEM; + + if (!OUT_HWCB) + OUT_HWCB = page; + else + BUF_HWCB_NEXT = page; + + BUF_HWCB = page; + + BUF_HWCB_NEXT = NULL; + + hwc_data.hwcb_count++; + + prepare_write_hwcb (); + + BUF_HWCB_TIMES_LOST = 0; + BUF_HWCB_MTO_LOST = 0; + BUF_HWCB_CHAR_LOST = 0; + +#ifdef BUFFER_STRESS_TEST + + internal_print ( + DELAYED_WRITE, + "*** " HWC_RW_PRINT_HEADER + "page #%i at 0x%x for buffering allocated. ***\n", + hwc_data.hwcb_count, page); + +#endif + + return 0; +} + +static int +release_write_hwcb (void) +{ + unsigned long page; + int page_nr; + + if (!hwc_data.hwcb_count) + return -ENODATA; + + if (hwc_data.hwcb_count == 1) { + + prepare_write_hwcb (); + + ALL_HWCB_CHAR = 0; + ALL_HWCB_MTO = 0; + BUF_HWCB_TIMES_LOST = 0; + BUF_HWCB_MTO_LOST = 0; + BUF_HWCB_CHAR_LOST = 0; + } else { + page = (unsigned long) OUT_HWCB; + + ALL_HWCB_MTO -= OUT_HWCB_MTO; + ALL_HWCB_CHAR -= OUT_HWCB_CHAR; + hwc_data.hwcb_count--; + + OUT_HWCB = OUT_HWCB_NEXT; + + if (page >= hwc_data.kmem_start && + page < hwc_data.kmem_end) { + + memset ((void *) page, 0, PAGE_SIZE); + + page_nr = (int) ((page - hwc_data.kmem_start) >> 12); + clear_bit (page_nr, &hwc_data.kmem_pages); + } else + free_page (page); +#ifdef BUFFER_STRESS_TEST + + internal_print ( + DELAYED_WRITE, + "*** " HWC_RW_PRINT_HEADER + "page at 0x%x released, %i pages still in use ***\n", + page, hwc_data.hwcb_count); + +#endif + } + return 0; +} + +static int +add_mto ( + unsigned char *message, + unsigned short int count) +{ + unsigned short int mto_size; + write_hwcb_t *hwcb; + mto_t *mto; + void *dest; + + if (!BUF_HWCB) + return -ENOMEM; + + if (BUF_HWCB == hwc_data.current_hwcb) + return -ENOMEM; + + mto_size = sizeof (mto_t) + count; + + hwcb = (write_hwcb_t *) BUF_HWCB; + + if ((MAX_HWCB_ROOM - hwcb->length) < mto_size) + return -ENOMEM; + + mto = (mto_t *) (((unsigned long) hwcb) + hwcb->length); + + memcpy (mto, &mto_template, sizeof (mto_t)); + + dest = (void *) (((unsigned long) mto) + sizeof (mto_t)); + + memcpy (dest, message, count); + + mto->length += count; + + hwcb->length += mto_size; + hwcb->msgbuf.length += mto_size; + hwcb->msgbuf.mdb.length += mto_size; + + BUF_HWCB_MTO++; + ALL_HWCB_MTO++; + BUF_HWCB_CHAR += count; + ALL_HWCB_CHAR += count; + + return count; +} + +static int +write_event_data_1 (void) +{ + unsigned short int condition_code; + int retval; + + if ((!hwc_data.write_prio) && (!hwc_data.write_nonprio)) + return -EPERM; + + if (hwc_data.current_servc) + return -EBUSY; + + retval = sane_write_hwcb (); + if (retval < 0) + return retval; + + if (!OUT_HWCB_MTO) + return -ENODATA; + + condition_code = service_call (HWC_CMDW_WRITEDATA, OUT_HWCB); + +#ifdef DUMP_HWC_WRITE_ERROR + if (condition_code != HWC_COMMAND_INITIATED) + __asm__ ("LHI 1,0xe20\n\t" + "L 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "J .+0 \n\t" + : + : "a" (&condition_code), "a" (OUT_HWCB) + : "1", "2", "3"); +#endif + + switch (condition_code) { + case HWC_COMMAND_INITIATED: + hwc_data.current_servc = HWC_CMDW_WRITEDATA; + hwc_data.current_hwcb = OUT_HWCB; + retval = condition_code; + break; + case HWC_BUSY: + retval = -EBUSY; + break; + default: + retval = -EIO; + } + + return retval; +} + +static void +flush_hwcbs (void) +{ + while (hwc_data.hwcb_count > 1) + release_write_hwcb (); + + release_write_hwcb (); + + hwc_data.flags &= ~FLUSH_HWCBS; +} + +static int +write_event_data_2 (void) +{ + write_hwcb_t *hwcb; + int retval; + unsigned char *param; + + param = ext_int_param (); + if (param != hwc_data.current_hwcb) + return -EINVAL; + + hwcb = (write_hwcb_t *) OUT_HWCB; + +#ifdef DUMP_HWC_WRITE_ERROR +#if 0 + if (((unsigned char *) hwcb) != param) + __asm__ ("LHI 1,0xe22\n\t" + "LRA 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "LRA 4,0(0,%2)\n\t" + "LRA 5,0(0,%3)\n\t" + "J .+0 \n\t" + : + : "a" (OUT_HWCB), + "a" (hwc_data.current_hwcb), + "a" (BUF_HWCB), + "a" (param) + : "1", "2", "3", "4", "5"); +#endif + if (hwcb->response_code != 0x0020) +#if 0 + internal_print (DELAYED_WRITE, HWC_RW_PRINT_HEADER + "\n************************ error in write_event_data_2()\n" + "OUT_HWCB: 0x%x\n" + "BUF_HWCB: 0x%x\n" + "response_code: 0x%x\n" + "hwc_data.hwcb_count: %d\n" + "hwc_data.kmem_pages: 0x%x\n" + "hwc_data.ioctls.kmem_hwcb: %d\n" + "hwc_data.ioctls.max_hwcb: %d\n" + "hwc_data.kmem_start: 0x%x\n" + "hwc_data.kmem_end: 0x%x\n" + "*****************************************************\n", + OUT_HWCB, + BUF_HWCB, + hwcb->response_code, + hwc_data.hwcb_count, + hwc_data.kmem_pages, + hwc_data.ioctls.kmem_hwcb, + hwc_data.ioctls.max_hwcb, + hwc_data.kmem_start, + hwc_data.kmem_end); +#endif + __asm__ ("LHI 1,0xe21\n\t" + "LRA 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "LRA 4,0(0,%2)\n\t" + "LH 5,0(0,%3)\n\t" + "SRL 5,8(0)\n\t" + "J .+0 \n\t" + : + : "a" (OUT_HWCB), "a" (hwc_data.current_hwcb), + "a" (BUF_HWCB), + "a" (&(hwc_data.hwcb_count)) + : "1", "2", "3", "4", "5"); +#endif + + if (hwcb->response_code == 0x0020) { + + retval = OUT_HWCB_CHAR; + release_write_hwcb (); + } else + retval = -EIO; + + hwc_data.current_servc = 0; + hwc_data.current_hwcb = NULL; + + if (hwc_data.flags & FLUSH_HWCBS) + flush_hwcbs (); + + return retval; +} + +static void +do_put_line ( + unsigned char *message, + unsigned short count) +{ + + if (add_mto (message, count) != count) { + + if (allocate_write_hwcb () < 0) + reuse_write_hwcb (); + +#ifdef DUMP_HWC_WRITE_LIST_ERROR + if (add_mto (message, count) != count) + __asm__ ("LHI 1,0xe32\n\t" + "LRA 2,0(0,%0)\n\t" + "L 3,0(0,%1)\n\t" + "LRA 4,0(0,%2)\n\t" + "LRA 5,0(0,%3)\n\t" + "J .+0 \n\t" + : + : "a" (message), "a" (&hwc_data.kmem_pages), + "a" (BUF_HWCB), "a" (OUT_HWCB) + : "1", "2", "3", "4", "5"); +#else + add_mto (message, count); +#endif + } +} + +static void +put_line ( + unsigned char *message, + unsigned short count) +{ + + if ((!hwc_data.obuf_start) && (hwc_data.flags & HWC_TIMER_RUNS)) { + del_timer (&hwc_data.write_timer); + hwc_data.flags &= ~HWC_TIMER_RUNS; + } + hwc_data.obuf_start += count; + + do_put_line (message, count); + + hwc_data.obuf_start -= count; +} + +static void +set_alarm (void) +{ + write_hwcb_t *hwcb; + + if ((!BUF_HWCB) || (BUF_HWCB == hwc_data.current_hwcb)) + allocate_write_hwcb (); + + hwcb = (write_hwcb_t *) BUF_HWCB; + hwcb->msgbuf.mdb.mdb_body.go.general_msg_flags |= GMF_SndAlrm; +} + +static void +hwc_write_timeout (unsigned long data) +{ + unsigned long flags; + + spin_lock_irqsave (&hwc_data.lock, flags); + + hwc_data.obuf_start = hwc_data.obuf_count; + if (hwc_data.obuf_count) + put_line (hwc_data.obuf, hwc_data.obuf_count); + hwc_data.obuf_start = 0; + + hwc_data.obuf_cursor = 0; + hwc_data.obuf_count = 0; + + write_event_data_1 (); + + spin_unlock_irqrestore (&hwc_data.lock, flags); +} + +static int +do_hwc_write ( + int from_user, + unsigned char *msg, + unsigned int count, + unsigned char code, + unsigned char write_time) +{ + unsigned int i_msg = 0; + unsigned short int spaces = 0; + unsigned int processed_characters = 0; + unsigned char ch, orig_ch; + unsigned short int obuf_count; + unsigned short int obuf_cursor; + unsigned short int obuf_columns; + + if (hwc_data.obuf_start) { + obuf_cursor = 0; + obuf_count = 0; + obuf_columns = MIN (hwc_data.ioctls.columns, + MAX_MESSAGE_SIZE - hwc_data.obuf_start); + } else { + obuf_cursor = hwc_data.obuf_cursor; + obuf_count = hwc_data.obuf_count; + obuf_columns = hwc_data.ioctls.columns; + } + + for (i_msg = 0; i_msg < count; i_msg++) { + + if (from_user) + get_user (orig_ch, msg + i_msg); + else + orig_ch = msg[i_msg]; + if (code == CODE_EBCDIC) + ch = _ebcasc[orig_ch]; + else + ch = orig_ch; + + processed_characters++; + + if ((obuf_cursor == obuf_columns) && + + (ch != '\n') && + + (ch != '\t')) { + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_columns); + obuf_cursor = 0; + obuf_count = 0; + } + switch (ch) { + + case '\n': + + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_count); + obuf_cursor = 0; + obuf_count = 0; + break; + + case '\a': + + hwc_data.obuf_start += obuf_count; + set_alarm (); + hwc_data.obuf_start -= obuf_count; + + break; + + case '\t': + + do { + if (obuf_cursor < obuf_columns) { + hwc_data.obuf[hwc_data.obuf_start + + obuf_cursor] + = 0x20; + obuf_cursor++; + } else + break; + } while (obuf_cursor % hwc_data.ioctls.width_htab); + + break; + + case '\f': + case '\v': + + spaces = obuf_cursor; + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_count); + obuf_count = obuf_cursor; + while (spaces) { + hwc_data.obuf[hwc_data.obuf_start + + obuf_cursor - spaces] + = 0x20; + spaces--; + } + + break; + + case '\b': + + if (obuf_cursor) + obuf_cursor--; + break; + + case '\r': + + obuf_cursor = 0; + break; + + case 0x00: + + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_count); + obuf_cursor = 0; + obuf_count = 0; + goto out; + + default: + + if (isprint (ch)) + hwc_data.obuf[hwc_data.obuf_start + + obuf_cursor++] + = (code == CODE_ASCII) ? + _ascebc[orig_ch] : orig_ch; + } + if (obuf_cursor > obuf_count) + obuf_count = obuf_cursor; + } + + if (obuf_cursor) { + + if (hwc_data.obuf_start || + (hwc_data.ioctls.final_nl == 0)) { + + put_line (&hwc_data.obuf[hwc_data.obuf_start], + obuf_count); + obuf_cursor = 0; + obuf_count = 0; + } else { + + if (hwc_data.ioctls.final_nl > 0) { + + if (hwc_data.flags & HWC_TIMER_RUNS) { + + hwc_data.write_timer.expires = + jiffies + + hwc_data.ioctls.final_nl * HZ / 10; + } else { + + init_timer (&hwc_data.write_timer); + hwc_data.write_timer.function = + hwc_write_timeout; + hwc_data.write_timer.data = + (unsigned long) NULL; + hwc_data.write_timer.expires = + jiffies + + hwc_data.ioctls.final_nl * HZ / 10; + add_timer (&hwc_data.write_timer); + hwc_data.flags |= HWC_TIMER_RUNS; + } + } else; + + } + } else; + + out: + + if (!hwc_data.obuf_start) { + hwc_data.obuf_cursor = obuf_cursor; + hwc_data.obuf_count = obuf_count; + } + if (write_time == IMMEDIATE_WRITE) + write_event_data_1 (); + + return processed_characters; +} + +signed int +hwc_write (int from_user, const unsigned char *msg, unsigned int count) +{ + unsigned long flags; + int retval; + + spin_lock_irqsave (&hwc_data.lock, flags); + + retval = do_hwc_write (from_user, msg, count, hwc_data.ioctls.code, + IMMEDIATE_WRITE); + + spin_unlock_irqrestore (&hwc_data.lock, flags); + + return retval; +} + +unsigned int +hwc_chars_in_buffer (unsigned char flag) +{ + unsigned short int number = 0; + unsigned long flags; + + spin_lock_irqsave (&hwc_data.lock, flags); + + if (flag & IN_HWCB) + number += ALL_HWCB_CHAR; + + if (flag & IN_WRITE_BUF) + number += hwc_data.obuf_cursor; + + spin_unlock_irqrestore (&hwc_data.lock, flags); + + return number; +} + +static inline int +nr_setbits (kmem_pages_t arg) +{ + int i; + int nr = 0; + + for (i = 0; i < (sizeof (arg) << 3); i++) { + if (arg & 1) + nr++; + arg >>= 1; + } + + return nr; +} + +unsigned int +hwc_write_room (unsigned char flag) +{ + unsigned int number = 0; + unsigned long flags; + write_hwcb_t *hwcb; + + spin_lock_irqsave (&hwc_data.lock, flags); + + if (flag & IN_HWCB) { + + if (BUF_HWCB) { + hwcb = (write_hwcb_t *) BUF_HWCB; + number += MAX_HWCB_ROOM - hwcb->length; + } + number += (hwc_data.ioctls.kmem_hwcb - + nr_setbits (hwc_data.kmem_pages)) * + (MAX_HWCB_ROOM - + (sizeof (write_hwcb_t) + sizeof (mto_t))); + } + if (flag & IN_WRITE_BUF) + number += MAX_HWCB_ROOM - hwc_data.obuf_cursor; + + spin_unlock_irqrestore (&hwc_data.lock, flags); + + return number; +} + +void +hwc_flush_buffer (unsigned char flag) +{ + unsigned long flags; + + spin_lock_irqsave (&hwc_data.lock, flags); + + if (flag & IN_HWCB) { + if (hwc_data.current_servc != HWC_CMDW_WRITEDATA) + flush_hwcbs (); + else + hwc_data.flags |= FLUSH_HWCBS; + } + if (flag & IN_WRITE_BUF) { + hwc_data.obuf_cursor = 0; + hwc_data.obuf_count = 0; + } + spin_unlock_irqrestore (&hwc_data.lock, flags); +} + +unsigned short int +seperate_cases (unsigned char *buf, unsigned short int count) +{ + + unsigned short int i_in; + + unsigned short int i_out = 0; + + unsigned char _case = 0; + + for (i_in = 0; i_in < count; i_in++) { + + if (buf[i_in] == hwc_data.ioctls.delim) { + + if ((i_in + 1 < count) && + (buf[i_in + 1] == hwc_data.ioctls.delim)) { + + buf[i_out] = hwc_data.ioctls.delim; + + i_out++; + + i_in++; + + } else + _case = ~_case; + + } else { + + if (_case) { + + if (hwc_data.ioctls.tolower) + buf[i_out] = _ebc_toupper[buf[i_in]]; + + else + buf[i_out] = _ebc_tolower[buf[i_in]]; + + } else + buf[i_out] = buf[i_in]; + + i_out++; + } + } + + return i_out; +} + +#ifdef DUMP_HWCB_INPUT + +static int +gds_vector_name (u16 id, unsigned char name[]) +{ + int retval = 0; + + switch (id) { + case GDS_ID_MDSMU: + name = "Multiple Domain Support Message Unit"; + break; + case GDS_ID_MDSRouteInfo: + name = "MDS Routing Information"; + break; + case GDS_ID_AgUnWrkCorr: + name = "Agent Unit of Work Correlator"; + break; + case GDS_ID_SNACondReport: + name = "SNA Condition Report"; + break; + case GDS_ID_CPMSU: + name = "CP Management Services Unit"; + break; + case GDS_ID_RoutTargInstr: + name = "Routing and Targeting Instructions"; + break; + case GDS_ID_OpReq: + name = "Operate Request"; + break; + case GDS_ID_TextCmd: + name = "Text Command"; + break; + + default: + name = "unknown GDS variable"; + retval = -EINVAL; + } + + return retval; +} +#endif + +inline static gds_vector_t * +find_gds_vector ( + gds_vector_t * start, void *end, u16 id) +{ + gds_vector_t *vec; + gds_vector_t *retval = NULL; + + vec = start; + + while (((void *) vec) < end) { + if (vec->gds_id == id) { + +#ifdef DUMP_HWCB_INPUT + int retval_name; + unsigned char name[64]; + + retval_name = gds_vector_name (id, name); + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "%s at 0x%x up to 0x%x, length: %d", + name, + (unsigned long) vec, + ((unsigned long) vec) + vec->length - 1, + vec->length); + if (retval_name < 0) + internal_print ( + IMMEDIATE_WRITE, + ", id: 0x%x\n", + vec->gds_id); + else + internal_print ( + IMMEDIATE_WRITE, + "\n"); +#endif + + retval = vec; + break; + } + vec = (gds_vector_t *) (((unsigned long) vec) + vec->length); + } + + return retval; +} + +inline static gds_subvector_t * +find_gds_subvector ( + gds_subvector_t * start, void *end, u8 key) +{ + gds_subvector_t *subvec; + gds_subvector_t *retval = NULL; + + subvec = start; + + while (((void *) subvec) < end) { + if (subvec->key == key) { + retval = subvec; + break; + } + subvec = (gds_subvector_t *) + (((unsigned long) subvec) + subvec->length); + } + + return retval; +} + +inline static int +get_input (void *start, void *end) +{ + int count; + + count = ((unsigned long) end) - ((unsigned long) start); + + if (hwc_data.ioctls.tolower) + EBC_TOLOWER (start, count); + + if (hwc_data.ioctls.delim) + count = seperate_cases (start, count); + + if (hwc_data.ioctls.echo) + do_hwc_write (0, start, count, CODE_EBCDIC, IMMEDIATE_WRITE); + + if (hwc_data.ioctls.code == CODE_ASCII) + EBCASC (start, count); + + store_hwc_input (start, count); + + return count; +} + +inline static int +eval_selfdeftextmsg (gds_subvector_t * start, void *end) +{ + gds_subvector_t *subvec; + void *subvec_data; + void *subvec_end; + int retval = 0; + + subvec = start; + + while (((void *) subvec) < end) { + subvec = find_gds_subvector (subvec, end, 0x30); + if (!subvec) + break; + subvec_data = (void *) + (((unsigned long) subvec) + + sizeof (gds_subvector_t)); + subvec_end = (void *) + (((unsigned long) subvec) + subvec->length); + retval += get_input (subvec_data, subvec_end); + subvec = (gds_subvector_t *) subvec_end; + } + + return retval; +} + +inline static int +eval_textcmd (gds_subvector_t * start, void *end) +{ + gds_subvector_t *subvec; + gds_subvector_t *subvec_data; + void *subvec_end; + int retval = 0; + + subvec = start; + + while (((void *) subvec) < end) { + subvec = find_gds_subvector ( + subvec, end, GDS_KEY_SelfDefTextMsg); + if (!subvec) + break; + subvec_data = (gds_subvector_t *) + (((unsigned long) subvec) + + sizeof (gds_subvector_t)); + subvec_end = (void *) + (((unsigned long) subvec) + subvec->length); + retval += eval_selfdeftextmsg (subvec_data, subvec_end); + subvec = (gds_subvector_t *) subvec_end; + } + + return retval; +} + +inline static int +eval_cpmsu (gds_vector_t * start, void *end) +{ + gds_vector_t *vec; + gds_subvector_t *vec_data; + void *vec_end; + int retval = 0; + + vec = start; + + while (((void *) vec) < end) { + vec = find_gds_vector (vec, end, GDS_ID_TextCmd); + if (!vec) + break; + vec_data = (gds_subvector_t *) + (((unsigned long) vec) + sizeof (gds_vector_t)); + vec_end = (void *) (((unsigned long) vec) + vec->length); + retval += eval_textcmd (vec_data, vec_end); + vec = (gds_vector_t *) vec_end; + } + + return retval; +} + +inline static int +eval_mdsmu (gds_vector_t * start, void *end) +{ + gds_vector_t *vec; + gds_vector_t *vec_data; + void *vec_end; + int retval = 0; + + vec = find_gds_vector (start, end, GDS_ID_CPMSU); + if (vec) { + vec_data = (gds_vector_t *) + (((unsigned long) vec) + sizeof (gds_vector_t)); + vec_end = (void *) (((unsigned long) vec) + vec->length); + retval = eval_cpmsu (vec_data, vec_end); + } + return retval; +} + +inline static int +eval_evbuf (gds_vector_t * start, void *end) +{ + gds_vector_t *vec; + gds_vector_t *vec_data; + void *vec_end; + int retval = 0; + + vec = find_gds_vector (start, end, GDS_ID_MDSMU); + if (vec) { + vec_data = (gds_vector_t *) + (((unsigned long) vec) + sizeof (gds_vector_t)); + vec_end = (void *) (((unsigned long) vec) + vec->length); + retval = eval_mdsmu (vec_data, vec_end); + } + return retval; +} + +static int +process_evbufs (void *start, void *end) +{ + int retval = 0; + evbuf_t *evbuf; + void *evbuf_end; + gds_vector_t *evbuf_data; + + evbuf = (evbuf_t *) start; + while (((void *) evbuf) < end) { + evbuf_data = (gds_vector_t *) + (((unsigned long) evbuf) + sizeof (evbuf_t)); + evbuf_end = (void *) (((unsigned long) evbuf) + evbuf->length); + switch (evbuf->type) { + case ET_OpCmd: + case ET_CntlProgOpCmd: + case ET_PMsgCmd: +#ifdef DUMP_HWCB_INPUT + + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "event buffer " + "at 0x%x up to 0x%x, length: %d\n", + (unsigned long) evbuf, + (unsigned long) (evbuf_end - 1), + evbuf->length); + dump_storage_area ((void *) evbuf, evbuf->length); +#endif + retval += eval_evbuf (evbuf_data, evbuf_end); + break; + case ET_StateChange: + + retval = -ENOSYS; + break; + default: + printk ( + KERN_WARNING + HWC_RW_PRINT_HEADER + "unconditional read: " + "unknown event buffer found, " + "type 0x%x", + evbuf->type); + retval = -ENOSYS; + } + evbuf = (evbuf_t *) evbuf_end; + } + return retval; +} + +static int +unconditional_read_1 (void) +{ + unsigned short int condition_code; + read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page; + int retval; + + if ((!hwc_data.read_prio) && (!hwc_data.read_nonprio)) + return -EOPNOTSUPP; + + if (hwc_data.current_servc) + return -EBUSY; + + memset (hwcb, 0x00, PAGE_SIZE); + memcpy (hwcb, &read_hwcb_template, sizeof (read_hwcb_t)); + + condition_code = service_call (HWC_CMDW_READDATA, hwc_data.page); + +#ifdef DUMP_HWC_READ_ERROR + if (condition_code == HWC_NOT_OPERATIONAL) + __asm__ ("LHI 1,0xe40\n\t" + "L 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "J .+0 \n\t" + : + : "a" (&condition_code), "a" (hwc_data.page) + : "1", "2", "3"); +#endif + + switch (condition_code) { + case HWC_COMMAND_INITIATED: + hwc_data.current_servc = HWC_CMDW_READDATA; + hwc_data.current_hwcb = hwc_data.page; + retval = condition_code; + break; + case HWC_BUSY: + retval = -EBUSY; + break; + default: + retval = -EIO; + } + + return retval; +} + +static int +unconditional_read_2 (void) +{ + read_hwcb_t *hwcb = (read_hwcb_t *) hwc_data.page; + +#ifdef DUMP_HWC_READ_ERROR + if ((hwcb->response_code != 0x0020) && + (hwcb->response_code != 0x0220) && + (hwcb->response_code != 0x60F0) && + (hwcb->response_code != 0x62F0)) + __asm__ ("LHI 1,0xe41\n\t" + "LRA 2,0(0,%0)\n\t" + "L 3,0(0,%1)\n\t" + "J .+0\n\t" + : + : "a" (hwc_data.page), "a" (&(hwcb->response_code)) + : "1", "2", "3"); +#endif + + hwc_data.current_servc = 0; + hwc_data.current_hwcb = NULL; + + switch (hwcb->response_code) { + + case 0x0020: + case 0x0220: + return process_evbufs ( + (void *) (((unsigned long) hwcb) + sizeof (read_hwcb_t)), + (void *) (((unsigned long) hwcb) + hwcb->length)); + + case 0x60F0: + case 0x62F0: + return 0; + + case 0x0100: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: HWCB boundary violation - this " + "must not occur in a correct driver, please contact " + "author\n"); + return -EIO; + + case 0x0300: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: " + "insufficient HWCB length - this must not occur in a " + "correct driver, please contact author\n"); + return -EIO; + + case 0x01F0: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: " + "invalid command - this must not occur in a correct " + "driver, please contact author\n"); + return -EIO; + + case 0x40F0: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: invalid function code - this " + "must not occur in a correct driver, please contact " + "author\n"); + return -EIO; + + case 0x70F0: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: invalid selection mask - this " + "must not occur in a correct driver, please contact " + "author\n"); + return -EIO; + + case 0x0040: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: HWC equipment check - don't " + "know how to handle this case\n"); + return -EIO; + + default: + internal_print ( + IMMEDIATE_WRITE, + HWC_RW_PRINT_HEADER + "unconditional read: invalid response code %x - this " + "must not occur in a correct driver, please contact " + "author\n", + hwcb->response_code); + return -EIO; + } +} + +static int +write_event_mask_1 (void) +{ + unsigned int condition_code; + int retval; + + memcpy (hwc_data.page, &init_hwcb_template, sizeof (init_hwcb_t)); + + condition_code = service_call (HWC_CMDW_WRITEMASK, hwc_data.page); + +#ifdef DUMP_HWC_INIT_ERROR + + if (condition_code != HWC_COMMAND_INITIATED) + __asm__ ("LHI 1,0xe10\n\t" + "L 2,0(0,%0)\n\t" + "LRA 3,0(0,%1)\n\t" + "J .+0\n\t" + : + : "a" (&condition_code), "a" (hwc_data.page) + : "1", "2", "3"); +#endif + + switch (condition_code) { + case HWC_COMMAND_INITIATED: + hwc_data.current_servc = HWC_CMDW_WRITEMASK; + hwc_data.current_hwcb = hwc_data.page; + retval = condition_code; + break; + case HWC_BUSY: + retval = -EBUSY; + break; + default: + retval = -EIO; + } + + return retval; +} + +static int +write_event_mask_2 (void) +{ + init_hwcb_t *hwcb = (init_hwcb_t *) hwc_data.page; + int retval = 0; + + if (hwcb->hwc_receive_mask & ET_Msg_Mask) + hwc_data.write_nonprio = 1; + + if (hwcb->hwc_receive_mask & ET_PMsgCmd_Mask) + hwc_data.write_prio = 1; + + if (hwcb->hwc_send_mask & ET_OpCmd_Mask) + hwc_data.read_nonprio = 1; + + if (hwcb->hwc_send_mask & ET_PMsgCmd_Mask) + hwc_data.read_nonprio = 1; + + if ((hwcb->response_code != 0x0020) || + (!hwc_data.write_nonprio) || + ((!hwc_data.read_nonprio) && (!hwc_data.read_prio))) +#ifdef DUMP_HWC_INIT_ERROR + __asm__ ("LHI 1,0xe11\n\t" + "LRA 2,0(0,%0)\n\t" + "L 3,0(0,%1)\n\t" + "J .+0\n\t" + : + : "a" (hwcb), "a" (&(hwcb->response_code)) + : "1", "2", "3"); +#else + retval = -EIO +#endif + + hwc_data.current_servc = 0; + hwc_data.current_hwcb = NULL; + + return retval; +} + +static int +set_hwc_ioctls (hwc_ioctls_t * ioctls, char correct) +{ + int retval = 0; + hwc_ioctls_t tmp; + + if (ioctls->width_htab > MAX_MESSAGE_SIZE) { + if (correct) + tmp.width_htab = MAX_MESSAGE_SIZE; + else + retval = -EINVAL; + } else + tmp.width_htab = ioctls->width_htab; + + tmp.echo = ioctls->echo; + + if (ioctls->columns > MAX_MESSAGE_SIZE) { + if (correct) + tmp.columns = MAX_MESSAGE_SIZE; + else + retval = -EINVAL; + } else + tmp.columns = ioctls->columns; + + switch (ioctls->code) { + case CODE_EBCDIC: + case CODE_ASCII: + tmp.code = ioctls->code; + break; + default: + if (correct) + tmp.code = CODE_ASCII; + else + retval = -EINVAL; + } + + tmp.final_nl = ioctls->final_nl; + + if (ioctls->max_hwcb < 2) { + if (correct) + tmp.max_hwcb = 2; + else + retval = -EINVAL; + } else + tmp.max_hwcb = ioctls->max_hwcb; + + tmp.tolower = ioctls->tolower; + + if (ioctls->kmem_hwcb > ioctls->max_hwcb) { + if (correct) + tmp.kmem_hwcb = ioctls->max_hwcb; + else + retval = -EINVAL; + } else + tmp.kmem_hwcb = ioctls->kmem_hwcb; + + if (ioctls->kmem_hwcb > MAX_KMEM_PAGES) { + if (correct) + ioctls->kmem_hwcb = MAX_KMEM_PAGES; + else + retval = -EINVAL; + } + if (ioctls->kmem_hwcb < 2) { + if (correct) + ioctls->kmem_hwcb = 2; + else + retval = -EINVAL; + } + tmp.delim = ioctls->delim; + + if (!(retval < 0)) + hwc_data.ioctls = tmp; + + return retval; +} + +int +hwc_init (void) +{ + int retval; +#ifdef BUFFER_STRESS_TEST + + init_hwcb_t *hwcb; + int i; + +#endif + +#ifdef CONFIG_3215 + if (MACHINE_IS_VM) + return 0; +#endif + + spin_lock_init (&hwc_data.lock); + + retval = write_event_mask_1 (); + if (retval < 0) + return retval; + +#ifdef USE_VM_DETECTION + + if (MACHINE_IS_VM) { + + if (hwc_data.init_ioctls.columns > 76) + hwc_data.init_ioctls.columns = 76; + hwc_data.init_ioctls.tolower = 1; + if (!hwc_data.init_ioctls.delim) + hwc_data.init_ioctls.delim = DEFAULT_CASE_DELIMITER; + } else { + hwc_data.init_ioctls.tolower = 0; + hwc_data.init_ioctls.delim = 0; + } +#endif + retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1); + + hwc_data.kmem_start = (unsigned long) + alloc_bootmem_pages (hwc_data.ioctls.kmem_hwcb * PAGE_SIZE); + hwc_data.kmem_end = hwc_data.kmem_start + + hwc_data.ioctls.kmem_hwcb * PAGE_SIZE - 1; + + ctl_set_bit (0, 9); + +#ifdef BUFFER_STRESS_TEST + + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "use %i bytes for buffering.\n", + hwc_data.ioctls.kmem_hwcb * PAGE_SIZE); + for (i = 0; i < 500; i++) { + hwcb = (init_hwcb_t *) BUF_HWCB; + internal_print ( + DELAYED_WRITE, + HWC_RW_PRINT_HEADER + "This is stress test message #%i, free: %i bytes\n", + i, + MAX_HWCB_ROOM - (hwcb->length + sizeof (mto_t))); + } + +#endif + + return retval; +} + +void +do_hwc_interrupt (void) +{ + + spin_lock (&hwc_data.lock); + + if (!hwc_data.current_servc) { + + unconditional_read_1 (); + + } else { + + switch (hwc_data.current_servc) { + + case HWC_CMDW_WRITEMASK: + + write_event_mask_2 (); + break; + + case HWC_CMDW_WRITEDATA: + + write_event_data_2 (); + break; + + case HWC_CMDW_READDATA: + + unconditional_read_2 (); + break; + } + + write_event_data_1 (); + } + + wake_up_hwc_tty (); + + spin_unlock (&hwc_data.lock); +} + +int +hwc_ioctl (unsigned int cmd, unsigned long arg) +{ + hwc_ioctls_t tmp = hwc_data.ioctls; + int retval = 0; + unsigned long flags; + unsigned int obuf; + + spin_lock_irqsave (&hwc_data.lock, flags); + + switch (cmd) { + + case TIOCHWCSHTAB: + if (get_user (tmp.width_htab, (ioctl_htab_t *) arg)) + goto fault; + break; + + case TIOCHWCSECHO: + if (get_user (tmp.echo, (ioctl_echo_t *) arg)) + goto fault; + break; + + case TIOCHWCSCOLS: + if (get_user (tmp.columns, (ioctl_cols_t *) arg)) + goto fault; + break; + + case TIOCHWCSCODE: + if (get_user (tmp.code, (ioctl_code_t *) arg)) + goto fault; + + break; + + case TIOCHWCSNL: + if (get_user (tmp.final_nl, (ioctl_nl_t *) arg)) + goto fault; + break; + + case TIOCHWCSOBUF: + if (get_user (obuf, (unsigned int *) arg)) + goto fault; + if (obuf & 0xFFF) + tmp.max_hwcb = (((obuf | 0xFFF) + 1) >> 12); + else + tmp.max_hwcb = (obuf >> 12); + break; + + case TIOCHWCSCASE: + if (get_user (tmp.tolower, (ioctl_case_t *) arg)) + goto fault; + break; + + case TIOCHWCSDELIM: + if (get_user (tmp.delim, (ioctl_delim_t *) arg)) + goto fault; + break; + + case TIOCHWCSINIT: + retval = set_hwc_ioctls (&hwc_data.init_ioctls, 1); + break; + + case TIOCHWCGHTAB: + if (put_user (tmp.width_htab, (ioctl_htab_t *) arg)) + goto fault; + break; + + case TIOCHWCGECHO: + if (put_user (tmp.echo, (ioctl_echo_t *) arg)) + goto fault; + break; + + case TIOCHWCGCOLS: + if (put_user (tmp.columns, (ioctl_cols_t *) arg)) + goto fault; + break; + + case TIOCHWCGCODE: + if (put_user (tmp.code, (ioctl_code_t *) arg)) + goto fault; + + break; + + case TIOCHWCGNL: + if (put_user (tmp.final_nl, (ioctl_nl_t *) arg)) + goto fault; + break; + + case TIOCHWCGOBUF: + if (put_user (tmp.max_hwcb, (ioctl_obuf_t *) arg)) + goto fault; + break; + + case TIOCHWCGKBUF: + if (put_user (tmp.kmem_hwcb, (ioctl_obuf_t *) arg)) + goto fault; + break; + + case TIOCHWCGCASE: + if (put_user (tmp.tolower, (ioctl_case_t *) arg)) + goto fault; + break; + + case TIOCHWCGDELIM: + if (put_user (tmp.delim, (ioctl_delim_t *) arg)) + goto fault; + break; +#if 0 + + case TIOCHWCGINIT: + if (put_user (&hwc_data.init_ioctls, (hwc_ioctls_t *) arg)) + goto fault; + break; + + case TIOCHWCGCURR: + if (put_user (&hwc_data.ioctls, (hwc_ioctls_t *) arg)) + goto fault; + break; +#endif + + default: + goto noioctlcmd; + } + + if (_IOC_DIR (cmd) == _IOC_WRITE) + retval = set_hwc_ioctls (&tmp, 0); + + goto out; + + fault: + retval = -EFAULT; + goto out; + noioctlcmd: + retval = -ENOIOCTLCMD; + out: + spin_unlock_irqrestore (&hwc_data.lock, flags); + return retval; +} diff --git a/drivers/s390/char/hwc_rw.h b/drivers/s390/char/hwc_rw.h new file mode 100644 index 000000000..04c939cd8 --- /dev/null +++ b/drivers/s390/char/hwc_rw.h @@ -0,0 +1,113 @@ +/* + * drivers/s390/char/hwc_rw.h + * interface to the HWC-read/write driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke <peschke@fh-brandenburg.de> + */ + +#ifndef __HWC_RW_H__ +#define __HWC_RW_H__ + +#include <linux/ioctl.h> + +#ifndef __HWC_RW_C__ + +extern int hwc_init (void); + +extern int hwc_write (int from_user, const unsigned char *, unsigned int); + +extern unsigned int hwc_chars_in_buffer (unsigned char); + +extern unsigned int hwc_write_room (unsigned char); + +extern void hwc_flush_buffer (unsigned char); + +extern signed int hwc_ioctl (unsigned int, unsigned long); + +extern void do_hwc_interrupt (void); + +extern int hwc_printk (const char *,...); + +#else + +extern void store_hwc_input (unsigned char *, unsigned int); + +extern void wake_up_hwc_tty (void); + +#endif + +#define IN_HWCB 1 +#define IN_WRITE_BUF 2 +#define IN_BUFS_TOTAL (IN_HWCB | IN_WRITE_BUF) + +typedef unsigned short int ioctl_htab_t; +typedef unsigned char ioctl_echo_t; +typedef unsigned short int ioctl_cols_t; +typedef unsigned char ioctl_code_t; +typedef signed char ioctl_nl_t; +typedef unsigned short int ioctl_obuf_t; +typedef unsigned char ioctl_case_t; +typedef unsigned char ioctl_delim_t; + +typedef struct { + ioctl_htab_t width_htab; + ioctl_echo_t echo; + ioctl_cols_t columns; + ioctl_code_t code; + ioctl_nl_t final_nl; + ioctl_obuf_t max_hwcb; + ioctl_obuf_t kmem_hwcb; + ioctl_case_t tolower; + ioctl_delim_t delim; +} hwc_ioctls_t; + +static hwc_ioctls_t _hwc_ioctls; + +#define HWC_IOCTL_LETTER 'B' + +#define TIOCHWCSHTAB _IOW(HWC_IOCTL_LETTER, 0, _hwc_ioctls.width_htab) + +#define TIOCHWCSECHO _IOW(HWC_IOCTL_LETTER, 1, _hwc_ioctls.echo) + +#define TIOCHWCSCOLS _IOW(HWC_IOCTL_LETTER, 2, _hwc_ioctls.columns) + +#define TIOCHWCSCODE _IOW(HWC_IOCTL_LETTER, 3, _hwc_ioctls.code) + +#define TIOCHWCSNL _IOW(HWC_IOCTL_LETTER, 4, _hwc_ioctls.final_nl) + +#define TIOCHWCSOBUF _IOW(HWC_IOCTL_LETTER, 5, _hwc_ioctls.max_hwcb) + +#define TIOCHWCSINIT _IO(HWC_IOCTL_LETTER, 6) + +#define TIOCHWCSCASE _IOW(HWC_IOCTL_LETTER, 7, _hwc_ioctls.tolower) + +#define TIOCHWCSDELIM _IOW(HWC_IOCTL_LETTER, 9, _hwc_ioctls.delim) + +#define TIOCHWCGHTAB _IOR(HWC_IOCTL_LETTER, 10, _hwc_ioctls.width_htab) + +#define TIOCHWCGECHO _IOR(HWC_IOCTL_LETTER, 11, _hwc_ioctls.echo) + +#define TIOCHWCGCOLS _IOR(HWC_IOCTL_LETTER, 12, _hwc_ioctls.columns) + +#define TIOCHWCGCODE _IOR(HWC_IOCTL_LETTER, 13, _hwc_ioctls.code) + +#define TIOCHWCGNL _IOR(HWC_IOCTL_LETTER, 14, _hwc_ioctls.final_nl) + +#define TIOCHWCGOBUF _IOR(HWC_IOCTL_LETTER, 15, _hwc_ioctls.max_hwcb) + +#define TIOCHWCGINIT _IOR(HWC_IOCTL_LETTER, 16, _hwc_ioctls) + +#define TIOCHWCGCASE _IOR(HWC_IOCTL_LETTER, 17, _hwc_ioctls.tolower) + +#define TIOCHWCGDELIM _IOR(HWC_IOCTL_LETTER, 19, _hwc_ioctls.delim) + +#define TIOCHWCGKBUF _IOR(HWC_IOCTL_LETTER, 20, _hwc_ioctls.max_hwcb) + +#define TIOCHWCGCURR _IOR(HWC_IOCTL_LETTER, 21, _hwc_ioctls) + +#define CODE_ASCII 0x0 +#define CODE_EBCDIC 0x1 + +#endif diff --git a/drivers/s390/char/hwc_tty.c b/drivers/s390/char/hwc_tty.c new file mode 100644 index 000000000..d58504168 --- /dev/null +++ b/drivers/s390/char/hwc_tty.c @@ -0,0 +1,265 @@ +/* + * drivers/s390/char/hwc_tty.c + * HWC line mode terminal driver. + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Martin Peschke <peschke@fh-brandenburg.de> + * + * Thanks to Martin Schwidefsky. + */ + +#include <linux/major.h> +#include <linux/termios.h> +#include <linux/tty.h> +#include <linux/tty_driver.h> +#include <linux/sched.h> +#include <linux/mm.h> + +#include <asm/uaccess.h> + +#include "hwc_rw.h" + +#define HWC_TTY_PRINT_HEADER "hwc tty driver: " + +#define HWC_TTY_BUF_SIZE 512 + +typedef struct { + + struct tty_struct *tty; + + unsigned char buf[HWC_TTY_BUF_SIZE]; + + unsigned short int buf_count; + + spinlock_t lock; +} hwc_tty_data_struct; + +static hwc_tty_data_struct hwc_tty_data; +static struct tty_driver hwc_tty_driver; +static struct tty_struct *hwc_tty_table[1]; +static struct termios *hwc_tty_termios[1]; +static struct termios *hwc_tty_termios_locked[1]; +static int hwc_tty_refcount = 0; + +extern struct termios tty_std_termios; + +static int +hwc_tty_open (struct tty_struct *tty, + struct file *filp) +{ + + if (MINOR (tty->device) - tty->driver.minor_start) + return -ENODEV; + + tty->driver_data = &hwc_tty_data; + hwc_tty_data.buf_count = 0; + hwc_tty_data.tty = tty; + tty->low_latency = 0; + + return 0; +} + +void +wake_up_hwc_tty (void) +{ + if (hwc_tty_data.tty == NULL) + return; + if ((hwc_tty_data.tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + hwc_tty_data.tty->ldisc.write_wakeup) + (hwc_tty_data.tty->ldisc.write_wakeup) (hwc_tty_data.tty); + wake_up_interruptible (&hwc_tty_data.tty->write_wait); +} + +static void +hwc_tty_close (struct tty_struct *tty, + struct file *filp) +{ + if (MINOR (tty->device) != tty->driver.minor_start) { + printk (KERN_WARNING HWC_TTY_PRINT_HEADER + "do not close hwc tty because of wrong device number"); + return; + } + hwc_tty_data.tty = NULL; +} + +static int +hwc_tty_write_room (struct tty_struct *tty) +{ + int retval; + + retval = hwc_write_room (IN_BUFS_TOTAL); + return retval; +} + +static int +hwc_tty_write (struct tty_struct *tty, + int from_user, + const unsigned char *buf, + int count) +{ + int retval; + + if (hwc_tty_data.buf_count > 0) { + hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); + hwc_tty_data.buf_count = 0; + } + retval = hwc_write (from_user, buf, count); + return retval; +} + +static void +hwc_tty_put_char (struct tty_struct *tty, + unsigned char ch) +{ + unsigned long flags; + + spin_lock_irqsave (&hwc_tty_data.lock, flags); + if (hwc_tty_data.buf_count >= HWC_TTY_BUF_SIZE) { + hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); + hwc_tty_data.buf_count = 0; + } + hwc_tty_data.buf[hwc_tty_data.buf_count] = ch; + hwc_tty_data.buf_count++; + spin_unlock_irqrestore (&hwc_tty_data.lock, flags); +} + +static void +hwc_tty_flush_chars (struct tty_struct *tty) +{ + unsigned long flags; + + spin_lock_irqsave (&hwc_tty_data.lock, flags); + hwc_write (0, hwc_tty_data.buf, hwc_tty_data.buf_count); + hwc_tty_data.buf_count = 0; + spin_unlock_irqrestore (&hwc_tty_data.lock, flags); +} + +static int +hwc_tty_chars_in_buffer (struct tty_struct *tty) +{ + int retval; + + retval = hwc_chars_in_buffer (IN_BUFS_TOTAL); + return retval; +} + +static void +hwc_tty_flush_buffer (struct tty_struct *tty) +{ + wake_up_hwc_tty (); +} + +static int +hwc_tty_ioctl ( + struct tty_struct *tty, + struct file *file, + unsigned int cmd, + unsigned long arg) +{ + if (tty->flags & (1 << TTY_IO_ERROR)) + return -EIO; + + return hwc_ioctl (cmd, arg); +} + +void +store_hwc_input (unsigned char *buf, unsigned int count) +{ + struct tty_struct *tty = hwc_tty_data.tty; + + if (tty != NULL) { + + if (count == 2 && ( + /* hat is 0xb0 in codepage 037 (US etc.) and thus */ + /* converted to 0x5e in ascii ('^') */ + strncmp (buf, "^c", 2) == 0 || + /* hat is 0xb0 in several other codepages (German, */ + /* UK, ...) and thus converted to ascii octal 252 */ + strncmp (buf, "\0252c", 2) == 0)) { + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = INTR_CHAR (tty); + } else if (count == 2 && ( + strncmp (buf, "^d", 2) == 0 || + strncmp (buf, "\0252d", 2) == 0)) { + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = EOF_CHAR (tty); + } else if (count == 2 && ( + strncmp (buf, "^z", 2) == 0 || + strncmp (buf, "\0252z", 2) == 0)) { + tty->flip.count++; + *tty->flip.flag_buf_ptr++ = TTY_NORMAL; + *tty->flip.char_buf_ptr++ = SUSP_CHAR (tty); + } else { + + memcpy (tty->flip.char_buf_ptr, buf, count); + if (count < 2 || ( + strncmp (buf + count - 2, "^n", 2) || + strncmp (buf + count - 2, "\0252n", 2))) { + tty->flip.char_buf_ptr[count] = '\n'; + count++; + } else + count -= 2; + memset (tty->flip.flag_buf_ptr, TTY_NORMAL, count); + tty->flip.char_buf_ptr += count; + tty->flip.flag_buf_ptr += count; + tty->flip.count += count; + } + tty_flip_buffer_push (tty); + wake_up_hwc_tty (); + } +} + +void +hwc_tty_init (void) +{ + memset (&hwc_tty_driver, 0, sizeof (struct tty_driver)); + memset (&hwc_tty_data, 0, sizeof (hwc_tty_data_struct)); + hwc_tty_driver.magic = TTY_DRIVER_MAGIC; + hwc_tty_driver.driver_name = "tty_hwc"; + hwc_tty_driver.name = "ttyS"; + hwc_tty_driver.name_base = 0; + hwc_tty_driver.major = TTY_MAJOR; + hwc_tty_driver.minor_start = 64; + hwc_tty_driver.num = 1; + hwc_tty_driver.type = TTY_DRIVER_TYPE_SYSTEM; + hwc_tty_driver.subtype = SYSTEM_TYPE_TTY; + hwc_tty_driver.init_termios = tty_std_termios; + hwc_tty_driver.init_termios.c_iflag = IGNBRK | IGNPAR; + hwc_tty_driver.init_termios.c_oflag = ONLCR; + hwc_tty_driver.init_termios.c_lflag = ISIG | ECHO; + hwc_tty_driver.flags = TTY_DRIVER_REAL_RAW; + hwc_tty_driver.refcount = &hwc_tty_refcount; + + hwc_tty_driver.table = hwc_tty_table; + hwc_tty_driver.termios = hwc_tty_termios; + hwc_tty_driver.termios_locked = hwc_tty_termios_locked; + + hwc_tty_driver.open = hwc_tty_open; + hwc_tty_driver.close = NULL /* hwc_tty_close */ ; + hwc_tty_driver.write = hwc_tty_write; + hwc_tty_driver.put_char = hwc_tty_put_char; + hwc_tty_driver.flush_chars = hwc_tty_flush_chars; + hwc_tty_driver.write_room = hwc_tty_write_room; + hwc_tty_driver.chars_in_buffer = hwc_tty_chars_in_buffer; + hwc_tty_driver.flush_buffer = hwc_tty_flush_buffer; + hwc_tty_driver.ioctl = hwc_tty_ioctl; + + hwc_tty_driver.throttle = NULL; + hwc_tty_driver.unthrottle = NULL; + hwc_tty_driver.send_xchar = NULL; + hwc_tty_driver.set_termios = NULL; + hwc_tty_driver.set_ldisc = NULL; + hwc_tty_driver.stop = NULL; + hwc_tty_driver.start = NULL; + hwc_tty_driver.hangup = NULL; + hwc_tty_driver.break_ctl = NULL; + hwc_tty_driver.wait_until_sent = NULL; + hwc_tty_driver.read_proc = NULL; + hwc_tty_driver.write_proc = NULL; + + if (tty_register_driver (&hwc_tty_driver)) + panic ("Couldn't register hwc_tty driver\n"); +} diff --git a/drivers/s390/misc/Makefile b/drivers/s390/misc/Makefile new file mode 100644 index 000000000..3d8c93271 --- /dev/null +++ b/drivers/s390/misc/Makefile @@ -0,0 +1,13 @@ +all: s390-misc.o + +CFLAFS += +O_TARGET := s390-misc.o +O_OBJS := +M_OBJS := + +ifeq ($(CONFIG_CHANDEV),y) + O_OBJS += chandev.o +endif + +include $(TOPDIR)/Rules.make + diff --git a/drivers/s390/misc/chandev.c b/drivers/s390/misc/chandev.c new file mode 100644 index 000000000..4345f1211 --- /dev/null +++ b/drivers/s390/misc/chandev.c @@ -0,0 +1,759 @@ +/* + * drivers/s390/misc/chandev.c + * common channel device layer + * + * S390 version + * Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + */ + +#define __KERNEL_SYSCALLS__ +#include <linux/config.h> +#include <linux/types.h> +#include <linux/ctype.h> +#include <asm/queue.h> +#include <asm/uaccess.h> +#include <linux/slab.h> +#include <asm/irq.h> +#include <linux/init.h> +#include <linux/unistd.h> +#include <asm/chandev.h> +#include <linux/proc_fs.h> +#include <linux/vmalloc.h> + +static chandev_model_info *chandev_models_head=NULL; +static chandev *chandev_head=NULL; +static chandev_noauto_range *chandev_noauto_head=NULL; +static chandev_force *chandev_force_head=NULL; +static chandev_probelist *chandev_probelist_head=NULL; +static int use_devno_names=FALSE; +static int chandev_conf_read=FALSE; + +static void *chandev_alloc_listmember(list **listhead,size_t size) +{ + void *newmember=kmalloc(GFP_KERNEL,size); + if(newmember) + add_to_list(listhead,newmember); + return(newmember); +} + +void chandev_free_listmember(list **listhead,list *member) +{ + if(remove_from_list(listhead,member)) + kfree(member); + else + printk(KERN_CRIT"chandev_free_listmember detected nonexistant" + "listmember listhead=%p member %p\n",listhead,member); +} + +void chandev_free_all(list **listhead) +{ + while(*listhead) + chandev_free_listmember(listhead,*listhead); +} + +void chandev_add_model(chandev_type chan_type,u16 cu_type,u8 cu_model,u8 max_port_no) +{ + chandev_model_info *newmodel; + + if((newmodel=chandev_alloc_listmember( + (list **)&chandev_models_head,sizeof(chandev_model_info)))) + { + newmodel->chan_type=chan_type; + newmodel->cu_type=cu_type; + newmodel->cu_model=cu_model; + newmodel->max_port_no=max_port_no; + } +} + + +void chandev_remove(chandev *member) +{ + chandev_free_listmember((list **)&chandev_head,(list *)member); +} + + +void chandev_remove_all(void) +{ + chandev_free_all((list **)&chandev_head); +} + +void chandev_remove_model(chandev_model_info *model) +{ + chandev *curr_chandev; + for(curr_chandev=chandev_head;curr_chandev!=NULL; + curr_chandev=curr_chandev->next) + if(curr_chandev->model_info==model) + chandev_remove(curr_chandev); + chandev_free_listmember((list **)&chandev_models_head,(list *)model); +} + +void chandev_remove_all_models(void) +{ + while(chandev_models_head) + chandev_remove_model(chandev_models_head); +} + +void chandev_del_model(u16 cu_type,u8 cu_model) +{ + chandev_model_info *curr_model; + for(curr_model=chandev_models_head;curr_model!=NULL; + curr_model=curr_model->next) + if(curr_model->cu_type==cu_type&&curr_model->cu_model==cu_model) + chandev_remove_model(curr_model); +} + +static void chandev_init_default_models(void) +{ + /* P390/Planter 3172 emulation assume maximum 16 to be safe. */ + chandev_add_model(lcs,0x3088,0x1,15); + + /* 3172/2216 Paralell the 2216 allows 16 ports per card the */ + /* the original 3172 only allows 4 we will assume the max of 16 */ + chandev_add_model(lcs|ctc,0x3088,0x8,15); + + /* 3172/2216 Escon serial the 2216 allows 16 ports per card the */ + /* the original 3172 only allows 4 we will assume the max of 16 */ + chandev_add_model(lcs|escon,0x3088,0x1F,15); + + /* Only 2 ports allowed on OSA2 cards model 0x60 */ + chandev_add_model(lcs,0x3088,0x60,1); + + /* Osa-D we currently aren't too emotionally involved with this */ + chandev_add_model(osad,0x3088,0x62,0); +} + +void chandev_add(dev_info_t *newdevinfo,chandev_model_info *newmodelinfo) +{ + chandev *new_chandev; + + if((new_chandev=chandev_alloc_listmember( + (list **)&chandev_head,sizeof(chandev)))) + { + new_chandev->model_info=newmodelinfo; + new_chandev->devno=newdevinfo->devno; + new_chandev->irq=newdevinfo->irq; + } +} + + +void chandev_collect_devices(void) +{ + int curr_irq,loopcnt=0,err; + dev_info_t curr_devinfo; + chandev_model_info *curr_model; + + + for(curr_irq=get_irq_first();curr_irq>=0; curr_irq=get_irq_next(curr_irq)) + { + /* check read chandev + * we had to do the cu_model check also because ctc devices + * have the same cutype & after asking some people + * the model numbers are given out pseudo randomly so + * we can't just take a range of them also the dev_type & models are 0 + */ + loopcnt++; + if(loopcnt>0x10000) + { + printk(KERN_ERR"chandev_collect_devices detected infinite loop bug in get_irq_next\n"); + break; + } + if((err=get_dev_info_by_irq(curr_irq,&curr_devinfo))) + { + printk("chandev_collect_devices get_dev_info_by_irq reported err=%X on irq %d\n" + "should not happen\n",err,curr_irq); + continue; + } + for(curr_model=chandev_models_head;curr_model!=NULL; + curr_model=curr_model->next) + { + if((curr_model->cu_type==curr_devinfo.sid_data.cu_type)&& + (curr_model->cu_model==curr_devinfo.sid_data.cu_model) + &&((curr_devinfo.status&DEVSTAT_DEVICE_OWNED)==0)) + chandev_add(&curr_devinfo,curr_model); + } + } +} + +void chandev_add_force(chandev_type chan_type,s32 devif_num,u16 read_devno, +u16 write_devno,s16 port_no,u8 do_ip_checksumming,u8 use_hw_stats) + +{ + chandev_force *new_chandev_force; + + if((new_chandev_force=chandev_alloc_listmember( + (list **)&chandev_force_head,sizeof(chandev_force)))) + { + new_chandev_force->chan_type=chan_type; + new_chandev_force->devif_num=devif_num; + new_chandev_force->read_devno=read_devno; + new_chandev_force->write_devno=write_devno; + new_chandev_force->port_no=port_no; + new_chandev_force->do_ip_checksumming=do_ip_checksumming; + new_chandev_force->use_hw_stats=use_hw_stats; + } +} + +void chandev_del_force(u16 read_devno) +{ + chandev_force *curr_force; + for(curr_force=chandev_force_head;curr_force!=NULL; + curr_force=curr_force->next) + { + if(curr_force->read_devno==read_devno) + chandev_free_listmember((list **)&chandev_force_head, + (list *)curr_force); + } +} + +void chandev_pack_args(char *str) +{ + char *newstr=str; + while(*str) + { + if(isspace(*str)) + str++; + else + *newstr++=*str++; + } + *newstr=0; +} + +typedef enum +{ + isnull=0, + isstr=1, + isnum=2, + iscomma=4, +} chandev_strval; + +chandev_strval chandev_strcmp(char *teststr,char **str,long *endlong) +{ + char *cur=*str; + chandev_strval retval=isnull; + + int len=strlen(teststr); + if(strncmp(teststr,*str,len)==0) + { + *str+=len; + retval=isstr; + *endlong=simple_strtol(cur,str,0); + if(cur!=*str) + retval|=isnum; + if(**str==',') + retval|=iscomma; + } + return(retval); +} + +static char *argstrs[]= +{ + "noauto", + "lcs", + "ctc", + "escon", + "del_force", + "use_devno_names" + "dont_use_devno_names", + "add_model" + "del_model" + "del_all_models" +}; + +typedef enum +{ + stridx_mult=16, + first_stridx=0, + noauto_stridx=first_stridx, + lcs_stridx, + ctc_stridx, + escon_stridx, + del_force_stridx, + use_devno_names_stridx, + dont_use_devno_names_stridx, + add_model_stridx, + del_model_stridx, + del_all_models_stridx, + last_stridx, +} chandev_str_enum; + +void chandev_add_noauto(u16 lo_devno,u16 hi_devno) +{ + chandev_noauto_range *new_range; + + if((new_range=chandev_alloc_listmember( + (list **)&chandev_noauto_head,sizeof(chandev_noauto_range)))) + { + new_range->lo_devno=lo_devno; + new_range->hi_devno=hi_devno; + } +} + +static char chandev_keydescript[]= +"chan_type key bitfield\nctc=0x1,escon=0x2,lcs=0x4,lcs=0x4,osad=0x8,claw=0x16\n"; + +static void chandev_print_args(void) +{ + printk("valid chandev arguments are" + "<> indicate optional parameters | indicate a choice.\n"); + printk("noauto,<lo_devno>,<hi_devno>\n" + "don't probe a range of device numbers for channel devices\n"); + printk("lcs|ctc|escon<devif_num>,read_devno,write_devno,<port_no>," + "<do_ip_checksumming>,<use_hw_stats>\n"); + printk("e.g. ctc0,0x7c00,0x7c01,-1,0,0\n"); + printk(" tells the channel layer to force ctc0 if detected to use\n" + " cuu's 7c00 & 7c01 port ( rel adapter no ) is invalid for\n" + " ctc's so use -1 don't do checksumming on received ip\n" + " packets & as ctc doesn't have hardware stats ignore this\n" + " parameter\n\n"); + printk("del_force read_devno\n" + "delete a forced channel device from force list.\n"); + printk("use_devno_names, tells the channel layer to assign device\n" + "names based on the read channel cuu number\n" + "e.g. a token ring read channel 0x7c00 would have an interface" + "called tr0x7c00 this avoids name collisions on devices."); + printk("add_model chan_type cu_model max_port no\n" + "tells the channel layer to probe for the device described\n"); + printk("%s use max_port_no of 0 for devices where this field " + "is invalid.\n",chandev_keydescript); + printk("del_model cu_type cu_model\n"); + printk("del_all_models\n"); +} + + +static int chandev_setup(char *str) +{ + chandev_strval val=isnull; + chandev_str_enum stridx; + long endlong; + chandev_type chan_type; +#define CHANDEV_MAX_EXTRA_INTS 5 + int ints[CHANDEV_MAX_EXTRA_INTS+1]; + memset(ints,0,sizeof(ints)); + chandev_pack_args(str); + for(stridx=first_stridx;stridx<last_stridx;stridx++) + if((val=chandev_strcmp(argstrs[stridx],&str,&endlong))) + break; + if(val) + { + if(val&iscomma) + get_options(str,CHANDEV_MAX_EXTRA_INTS,ints); + else + ints[0]=0; + val=(((chandev_strval)stridx)*stridx_mult)+(val&~isstr); + switch(val) + { + case noauto_stridx*stridx_mult: + case (noauto_stridx*stridx_mult)|iscomma: + switch(ints[0]) + { + case 0: + chandev_free_all((list **)&chandev_noauto_head); + chandev_add_noauto(0,0xffff); + break; + case 1: + ints[2]=ints[1]; + case 2: + chandev_add_noauto(ints[1],ints[2]); + + } + break; + case (ctc_stridx*stridx_mult)|isnum|iscomma: + case (escon_stridx*stridx_mult)|isnum|iscomma: + case (lcs_stridx*stridx_mult)|isnum|iscomma: + switch(val) + { + case (ctc_stridx*stridx_mult)|isnum|iscomma: + chan_type=ctc; + break; + case (escon_stridx*stridx_mult)|isnum|iscomma: + chan_type=escon; + break; + case (lcs_stridx*stridx_mult)|isnum|iscomma: + chan_type=lcs; + break; + default: + goto BadArgs; + } + chandev_add_force(chan_type,endlong,ints[1],ints[2], + ints[3],ints[4],ints[5]); + break; + case (del_force_stridx*stridx_mult)|iscomma: + if(ints[0]!=1) + goto BadArgs; + chandev_del_force(ints[1]); + break; + case (use_devno_names_stridx*stridx_mult): + use_devno_names=1; + break; + case (dont_use_devno_names_stridx*stridx_mult): + use_devno_names=0; + case (add_model_stridx*stridx_mult)|iscomma: + if(ints[0]<3) + goto BadArgs; + if(ints[0]==3) + { + ints[0]=4; + ints[4]=-1; + } + chandev_add_model(ints[1],ints[2],ints[3],ints[4]); + break; + case (del_model_stridx*stridx_mult)|iscomma: + if(ints[0]!=2) + goto BadArgs; + chandev_del_model(ints[1],ints[2]); + break; + case del_all_models_stridx*stridx_mult: + chandev_remove_all_models(); + break; + default: + goto BadArgs; + } + } + return(1); + BadArgs: + chandev_print_args(); + return(0); +} + +__setup("chandev=",chandev_setup); + +int chandev_doprobe(chandev_force *force,chandev *read_chandev, +chandev *write_chandev) +{ + chandev_probelist *probe; + chandev_model_info *model_info; + chandev_probeinfo probeinfo; + int retval=-1,hint=-1; + + model_info=read_chandev->model_info; + if(read_chandev->model_info!=write_chandev->model_info|| + (force&&((force->chan_type&model_info->chan_type)==0))) + return(-1); /* inconsistent */ + for(probe=chandev_probelist_head; + probe!=NULL; + probe=probe->next) + { + if(probe->chan_type&model_info->chan_type) + { + if(use_devno_names) + probeinfo.devif_num=read_chandev->devno; + else + probeinfo.devif_num=-1; + probeinfo.read_irq=read_chandev->irq; + probeinfo.write_irq=write_chandev->irq; + + probeinfo.max_port_no=model_info->max_port_no; + if(force) + { + probeinfo.forced_port_no=force->port_no; + if(force->devif_num!=-1) + probeinfo.devif_num=force->devif_num; + probeinfo.do_ip_checksumming=force->do_ip_checksumming; + probeinfo.use_hw_stats=force->use_hw_stats; + + } + else + { + probeinfo.forced_port_no=-1; + probeinfo.do_ip_checksumming=FALSE; + probeinfo.use_hw_stats=FALSE; + if(probe->chan_type&lcs) + { + hint=(read_chandev->devno&0xFF)>>1; + if(hint>model_info->max_port_no) + { + /* The card is possibly emulated e.g P/390 */ + /* or possibly configured to use a shared */ + /* port configured by osa-sf. */ + hint=0; + } + } + } + probeinfo.hint_port_no=hint; + retval=probe->probefunc(&probeinfo); + if(retval==0) + break; + } + } + return(retval); +} + +void chandev_probe(void) +{ + chandev *read_chandev,*write_chandev,*curr_chandev; + chandev_force *curr_force; + chandev_noauto_range *curr_noauto; + + chandev_collect_devices(); + for(curr_force=chandev_force_head;curr_force!=NULL; + curr_force=curr_force->next) + { + for(read_chandev=chandev_head; + read_chandev!=NULL; + read_chandev=read_chandev->next) + if(read_chandev->devno==curr_force->read_devno) + { + for(write_chandev=chandev_head; + write_chandev!=NULL; + write_chandev=write_chandev->next) + if(write_chandev->devno== + curr_force->write_devno) + { + if(chandev_doprobe(curr_force, + read_chandev, + write_chandev)==0) + { + chandev_remove(read_chandev); + chandev_remove(write_chandev); + goto chandev_probe_skip; + } + } + } + chandev_probe_skip: + } + for(curr_chandev=chandev_head; + curr_chandev!=NULL; + curr_chandev=curr_chandev->next) + { + for(curr_noauto=chandev_noauto_head;curr_noauto!=NULL; + curr_noauto=curr_noauto->next) + { + if(curr_chandev->devno>=curr_noauto->lo_devno&& + curr_chandev->devno<=curr_noauto->hi_devno) + { + chandev_remove(curr_chandev); + break; + } + } + } + for(curr_chandev=chandev_head;curr_chandev!=NULL; + curr_chandev=curr_chandev->next) + { + if(curr_chandev->next&&curr_chandev->model_info== + curr_chandev->next->model_info) + { + + chandev_doprobe(NULL,curr_chandev,curr_chandev->next); + curr_chandev=curr_chandev->next; + } + } + chandev_remove_all(); +} + +int chandev_do_setup(char *buff,int size) +{ + int curr,startline=0,comment=FALSE,newline=FALSE,oldnewline=TRUE; + int rc=1; + + buff[size]=0; + for(curr=0;curr<=size;curr++) + { + if(buff[curr]=='#') + { + comment=TRUE; + newline=FALSE; + } + else if(buff[curr]==10||buff[curr]==13||buff[curr]==0) + { + buff[curr]=0; + comment=FALSE; + newline=TRUE; + } + if(comment==FALSE&&curr>startline + &&((oldnewline==TRUE&&newline==FALSE)||curr==size)) + { + if((rc=chandev_setup(&buff[startline]))==0) + break; + startline=curr+1; + } + oldnewline=newline; + } + return(rc); +} +void chandev_read_conf(void) +{ +#define CHANDEV_FILE "/etc/chandev.conf" + struct stat statbuf; + char *buff; + int curr,left,len,fd; + + chandev_conf_read=TRUE; + set_fs(KERNEL_DS); + if(stat(CHANDEV_FILE,&statbuf)==0) + { + set_fs(USER_DS); + buff=vmalloc(statbuf.st_size+1); + if(buff) + { + set_fs(KERNEL_DS); + if((fd=open(CHANDEV_FILE,O_RDONLY,0))!=-1) + { + curr=0; + left=statbuf.st_size; + while((len=read(fd,&buff[curr],left))>0) + { + curr+=len; + left-=len; + } + close(fd); + } + set_fs(USER_DS); + chandev_do_setup(buff,statbuf.st_size); + vfree(buff); + } + } + set_fs(USER_DS); +} + +void chandev_register_and_probe(chandev_probefunc probefunc,chandev_type chan_type) +{ + chandev_probelist *new_probe; + if(!chandev_conf_read) + chandev_read_conf(); + if((new_probe=chandev_alloc_listmember((list **)& + chandev_probelist_head,sizeof(chandev_probelist)))) + { + new_probe->probefunc=probefunc; + new_probe->chan_type=chan_type; + chandev_probe(); + } +} + +void chandev_unregister(chandev_probefunc probefunc) +{ + chandev_probelist *curr_probe=NULL; + + for(curr_probe=chandev_probelist_head;curr_probe!=NULL; + curr_probe=curr_probe->next) + { + if(curr_probe->probefunc==probefunc) + chandev_free_listmember((list **)&chandev_probelist_head, + (list *)curr_probe); + } +} + + +#ifdef CONFIG_PROC_FS +#define chandev_printf(exitchan,args...) \ +splen=sprintf(spbuff,##args); \ +spoffset+=splen; \ +if(spoffset>offset) { \ + spbuff+=splen; \ + currlen+=splen; \ +} \ +if(currlen>=length) \ + goto exitchan; + + + +static int chandev_read_proc(char *page, char **start, off_t offset, + int length, int *eof, void *data) +{ + char *spbuff=*start=page; + int currlen=0,splen; + off_t spoffset=0; + chandev_model_info *curr_model; + chandev_noauto_range *curr_noauto; + chandev_force *curr_force; + + + chandev_printf(chan_exit,"Channels enabled for detection\n"); + chandev_printf(chan_exit,"chan_type cu_type cu_model max_port_no\n"); + chandev_printf(chan_exit,"=================================================\n"); + for(curr_model=chandev_models_head;curr_model!=NULL; + curr_model=curr_model->next) + { + chandev_printf(chan_exit,"0x%02x 0x%04x 0x%02x %d\n", + curr_model->chan_type,(int)curr_model->cu_type, + (int)curr_model->cu_model,(int)curr_model->max_port_no); + } + + chandev_printf(chan_exit,"%s",chandev_keydescript); + chandev_printf(chan_exit,"No auto devno ranges\n"); + chandev_printf(chan_exit," From To \n"); + chandev_printf(chan_exit,"====================\n"); + for(curr_noauto=chandev_noauto_head;curr_noauto!=NULL; + curr_noauto=curr_noauto->next) + { + chandev_printf(chan_exit,"0x%4x 0x%4x\n", + curr_noauto->lo_devno, + curr_noauto->hi_devno); + } + chandev_printf(chan_exit,"\nForced devices\n"); + chandev_printf(chan_exit,"chan_type defif_num read_devno write_devno port_no ip_cksum hw_stats\n"); + chandev_printf(chan_exit,"====================================================================\n"); + for(curr_force=chandev_force_head;curr_force!=NULL; + curr_force=curr_force->next) + { + chandev_printf(chan_exit,"0x%2x %d 0x%4x 0x%4x %4d %1d %1d\n", + curr_force->chan_type,curr_force->devif_num, + curr_force->read_devno,curr_force->write_devno, + curr_force->port_no,curr_force->do_ip_checksumming, + curr_force->use_hw_stats); + } + *eof=TRUE; + chan_exit: + if(currlen>length) { + /* rewind to previous printf so that we are correctly + * aligned if we get called to print another page. + */ + currlen-=splen; + } + return(currlen); +} + + +static int chandev_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + int rc; + char *buff; + + buff=vmalloc(count+1); + if(buff) + { + rc = copy_from_user(buff,buffer,count); + if (rc) + goto chandev_write_exit; + chandev_do_setup(buff,count); + rc=count; + chandev_write_exit: + vfree(buff); + return rc; + } + else + return -ENOMEM; + return(0); +} + +static void __init chandev_create_proc(void) +{ + struct proc_dir_entry *dir_entry= + create_proc_entry("chandev",0644, + &proc_root); + if(dir_entry) + { + dir_entry->read_proc=&chandev_read_proc; + dir_entry->write_proc=&chandev_write_proc; + } +} + + +#endif +static int __init chandev_init(void) +{ + chandev_init_default_models(); +#if CONFIG_PROC_FS + chandev_create_proc(); +#endif + return(0); +} +__initcall(chandev_init); + + + + + + + diff --git a/drivers/s390/net/Makefile b/drivers/s390/net/Makefile new file mode 100644 index 000000000..2c2a182b6 --- /dev/null +++ b/drivers/s390/net/Makefile @@ -0,0 +1,16 @@ +all: s390-net.o + +CFLAFS += +O_TARGET := s390-net.o +O_OBJS := +M_OBJS := + +ifeq ($(CONFIG_CTC),y) + O_OBJS += ctc.o +endif + +ifeq ($(CONFIG_IUCV),y) + O_OBJS += iucv.o +endif + +include $(TOPDIR)/Rules.make diff --git a/drivers/s390/net/ctc.c b/drivers/s390/net/ctc.c new file mode 100644 index 000000000..4acc6e543 --- /dev/null +++ b/drivers/s390/net/ctc.c @@ -0,0 +1,1581 @@ +/* + * drivers/s390/net/ctc.c + * CTC / ESCON network driver + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Dieter Wellerdiek (wel@de.ibm.com) + * + * 2.3 Updates Martin Schwidefsky (schwidefsky@de.ibm.com) + * Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * + * + * Description of the Kernel Parameter + * Normally the CTC driver selects the channels in order (automatic channel + * selection). If your installation needs to use the channels in a different + * order or doesn't want to have automatic channel selection on, you can do + * this with the "ctc= kernel keyword". + * + * ctc=0,0xrrrr,0xwwww,ddddd + * + * Where: + * + * "rrrr" is the read channel address + * "wwww" is the write channel address + * "dddd" is the network device (ctc0 to ctc7 for a parallel channel, escon0 + * to escon7 for ESCON channels). + * + * To switch the automatic channel selection off use the ctc= keyword with + * parameter "noauto". This may be necessary if you 3271 devices or other devices + * which use the ctc device type and model, but operate with a different protocol. + * + * ctc=noauto + * + * Change History + * 0.50 Initial release shipped + * 0.51 Bug fixes + * - CTC / ESCON network device can now handle up to 64 channels + * - 3088-61 info message supperssed - CISCO 7206 - CLAW - ESCON + * - 3088-62 info message suppressed - OSA/D + * - channel: def ffffffed ... error message suppressed + * - CTC / ESCON device was not recoverable after a lost connection with + * IFCONFIG dev DOWN and IFCONFIG dev UP + * - Possibility to switch the automatic selection off + * - Minor bug fixes + */ +#include <linux/version.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/malloc.h> +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/interrupt.h> +#include <linux/timer.h> +#include <linux/sched.h> + +#include <linux/signal.h> +#include <linux/string.h> + +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/ip.h> +#include <linux/if_arp.h> +#include <linux/tcp.h> +#include <linux/skbuff.h> + +#include <asm/io.h> +#include <asm/bitops.h> + +#include <asm/irq.h> + + +//#define DEBUG + +/* Redefine message level, so that all messages occur on 3215 console in DEBUG mode */ +#ifdef DEBUG + #undef KERN_INFO + #undef KERN_WARNING + #undef KERN_DEBUG + #define KERN_INFO KERN_EMERG + #define KERN_WARNING KERN_EMERG + #define KERN_DEBUG KERN_EMERG +#endif +//#undef DEBUG + +#define CCW_CMD_WRITE 0x01 +#define CCW_CMD_READ 0x02 +#define CCW_CMD_SET_EXTENDED 0xc3 +#define CCW_CMD_PREPARE 0xe3 + +#define MAX_CHANNEL_DEVICES 64 +#define MAX_ADAPTERS 8 +#define CTC_DEFAULT_MTU_SIZE 1500 +#define READ 0 +#define WRITE 1 +#define CTC 0 +#define ESCON 1 +#define CHANNEL_MEDIA 2 +#define CTC_BLOCKS 8 /* 8 blocks * 2 times * 64k = 1M */ + +#define TB_TX 0 /* sk buffer handling in process */ +#define TB_STOP 1 /* network device stop in process */ +#define TB_RETRY 2 /* retry in process */ +#define TB_NOBUFFER 3 /* no buffer on free queue */ + +/* state machine codes used in ctc_irq_handler */ +#define CTC_STOP 0 +#define CTC_START_HALT_IO 1 +#define CTC_START_SET_X_MODE 2 +#define CTC_START_SELECT 4 +#define CTC_START_READ_TEST 32 +#define CTC_START_READ 33 +#define CTC_START_WRITE_TEST 64 +#define CTC_START_WRITE 65 + + +typedef enum { + channel_type_none, /* Device is not a channel */ + channel_type_undefined, /* Device is a channel but we don't know anything about it */ + channel_type_ctca, /* Device is a CTC/A and we can deal with it */ + channel_type_escon, /* Device is a ESCON channel and we can deal with it */ + channel_type_unsupported /* Device is a unsupported model */ +} channel_type_t; + + + +/* + * Structures needed in the initial phase + * + */ + +static int channel_tab_initialized = 0; /* channel[] structure initialized */ + +struct devicelist { + unsigned int devno; + __u8 flag; +#define CHANNEL_IN_USE 0x08 /* - Show that channel is in use */ +}; + +static struct { + struct devicelist list[MAX_CHANNEL_DEVICES]; + int count; + int left; +} channel[CHANNEL_MEDIA]; + + + +static int ctc_no_auto = 0; + +struct adapterlist{ + unsigned int devno[2]; + __u16 protocol; +}; + +static struct adapterlist ctc_adapter[CHANNEL_MEDIA][MAX_ADAPTERS]; /* 0 = CTC / 1 = ESCON */ + + +/* + * Structure used after the initial phase + * + */ + +struct buffer { + struct buffer *next; + int packets; + struct block *block; +}; + +#if LINUX_VERSION_CODE>=0x020300 +typedef struct net_device net_device; +#else +typedef struct device net_device; +typedef struct wait_queue* wait_queue_head_t; +#define DECLARE_WAITQUEUE(waitqname,waitqtask) struct wait_queue waitqname = {waitqtask, NULL } +#define init_waitqueue_head(nothing) +#endif + + +struct channel { + unsigned int devno; + int irq; + unsigned long IO_active; + ccw1_t ccw[3]; + __u32 state; + int buffer_count; + struct buffer *free_anchor; + struct buffer *proc_anchor; + devstat_t *devstat; + net_device *dev; /* backward pointer to the network device */ + wait_queue_head_t wait; + struct tq_struct tq; + struct timer_list timer; + unsigned long flag_a; /* atomic flags */ +#define CTC_BH_ACTIVE 0 + __u8 last_dstat; + __u8 flag; +#define CTC_WRITE 0x01 /* - Set if this is a write channel */ +#define CTC_TIMER 0x80 /* - Set if timer made the wake_up */ +}; + + +struct ctc_priv { + struct net_device_stats stats; +#if LINUX_VERSION_CODE>=0x02032D + int tbusy; +#endif + struct channel channel[2]; + __u16 protocol; +}; + +/* + * This structure works as shuttle between two systems + * - A block can contain one or more packets + */ + +#define PACKET_HEADER_LENGTH 6 +struct packet { + __u16 length; + __u16 type; + __u16 unused; + __u8 data; +}; + +#define BLOCK_HEADER_LENGTH 2 +struct block { + __u16 length; + struct packet data; +}; + +#if LINUX_VERSION_CODE>=0x02032D +#define ctc_protect_busy(dev) \ +s390irq_spin_lock(((struct ctc_priv *)dev->priv)->channel[WRITE].irq) +#define ctc_unprotect_busy(dev) \ +s390irq_spin_unlock(((struct ctc_priv *)dev->priv)->channel[WRITE].irq) + +#define ctc_protect_busy_irqsave(dev,flags) \ +s390irq_spin_lock_irqsave(((struct ctc_priv *)dev->priv)->channel[WRITE].irq,flags) +#define ctc_unprotect_busy_irqrestore(dev,flags) \ +s390irq_spin_unlock_irqrestore(((struct ctc_priv *)dev->priv)->channel[WRITE].irq,flags) + +static __inline__ void ctc_set_busy(net_device *dev) +{ + ((struct ctc_priv *)dev->priv)->tbusy=1; + netif_stop_queue(dev); +} + +static __inline__ void ctc_clear_busy(net_device *dev) +{ + ((struct ctc_priv *)dev->priv)->tbusy=0; + netif_start_queue(dev); +} + +static __inline__ int ctc_check_busy(net_device *dev) +{ + eieio(); + return(((struct ctc_priv *)dev->priv)->tbusy); +} + + +static __inline__ void ctc_setbit_busy(int nr,net_device *dev) +{ + set_bit(nr,&(((struct ctc_priv *)dev->priv)->tbusy)); + netif_stop_queue(dev); +} + +static __inline__ void ctc_clearbit_busy(int nr,net_device *dev) +{ + clear_bit(nr,&(((struct ctc_priv *)dev->priv)->tbusy)); + if(((struct ctc_priv *)dev->priv)->tbusy==0) + netif_start_queue(dev); +} + +static __inline__ int ctc_test_and_setbit_busy(int nr,net_device *dev) +{ + netif_stop_queue(dev); + return(test_and_set_bit(nr,&((struct ctc_priv *)dev->priv)->tbusy)); +} +#else + +#define ctc_protect_busy(dev) +#define ctc_unprotect_busy(dev) +#define ctc_protect_busy_irqsave(dev,flags) +#define ctc_unprotect_busy_irqrestore(dev,flags) + +static __inline__ void ctc_set_busy(net_device *dev) +{ + dev->tbusy=1; + eieio(); +} + +static __inline__ void ctc_clear_busy(net_device *dev) +{ + dev->tbusy=0; + eieio(); +} + +static __inline__ int ctc_check_busy(net_device *dev) +{ + eieio(); + return(dev->tbusy); +} + + +static __inline__ void ctc_setbit_busy(int nr,net_device *dev) +{ + set_bit(nr,(void *)&dev->tbusy); +} + +static __inline__ void ctc_clearbit_busy(int nr,net_device *dev) +{ + clear_bit(nr,(void *)&dev->tbusy); +} + +static __inline__ int ctc_test_and_setbit_busy(int nr,net_device *dev) +{ + return(test_and_set_bit(nr,(void *)&dev->tbusy)); +} +#endif + + + + + +/* Interrupt handler */ +static void ctc_irq_handler(int irq, void *initparm, struct pt_regs *regs); +static void ctc_irq_bh(struct channel *ctc); +static void ctc_read_retry (struct channel *ctc); +static void ctc_write_retry (struct channel *ctc); + + +/* Functions for the DEV methods */ +int ctc_probe(net_device *dev); + + +static int ctc_open(net_device *dev); +static void ctc_timer (struct channel *ctc); +static int ctc_release(net_device *dev); +static int ctc_tx(struct sk_buff *skb, net_device *dev); +static int ctc_change_mtu(net_device *dev, int new_mtu); +struct net_device_stats* ctc_stats(net_device *dev); + + +/* + * Channel Routines + * + */ + +static void channel_init(void); +static void channel_scan(void); +static int channel_get(int media, int devno); +static int channel_get_next(int media); +static int channel_free(int media, int devno); +static channel_type_t channel_check_for_type (senseid_t *id); +static void channel_sort(struct devicelist list[], int n); + + +/* + * initialize the channel[].list + */ +static void channel_init(void) +{ + int m; +#ifdef DEBUG + int c; +#endif + + if (!test_and_set_bit(0, (void *)& channel_tab_initialized)){ + channel_scan(); + for (m = 0; m < CHANNEL_MEDIA; m++) { + channel_sort (channel[m].list, MAX_CHANNEL_DEVICES); + channel[m].left = channel[m].count; + } + if (channel[CTC].count == 0 && channel[ESCON].count == 0) + printk(KERN_INFO "channel: no Channel devices recognized\n"); + else + printk(KERN_INFO "channel: %d Parallel channel found - %d ESCON channel found\n", + channel[CTC].count, channel[ESCON].count); +#ifdef DEBUG + for (m = 0; m < CHANNEL_MEDIA; m++) { + for (c = 0; c < MAX_CHANNEL_DEVICES; c++){ + printk(KERN_DEBUG "channel: Adapter=%x Entry=%x devno=%04x\n", + m, c, channel[m].list[c].devno); + } + } +#endif + } +} + + +/* +* scan for all channels and put the device numbers into the channel[].list +*/ +static void channel_scan(void) +{ + int m; + int c; + int irq; + dev_info_t temp; + + for (m = 0; m < CHANNEL_MEDIA; m++) { + for (c = 0; c < MAX_CHANNEL_DEVICES; c++){ + channel[m].list[c].devno = -ENODEV; + } + } + + for (irq = 0; irq < NR_IRQS; irq++) { + /* CTC/A */ + if (channel[CTC].count < MAX_CHANNEL_DEVICES ) { + if (get_dev_info(irq, &temp) == 0 && + channel_check_for_type(&temp.sid_data) == channel_type_ctca) { + channel[CTC].list[channel[CTC].count].devno = temp.devno; + channel[CTC].count++; + } + } + + /* ESCON */ + if (channel[ESCON].count < MAX_CHANNEL_DEVICES ) { + if (get_dev_info(irq, &temp) == 0 && + channel_check_for_type(&temp.sid_data) == channel_type_escon) { + channel[ESCON].list[channel[ESCON].count].devno = temp.devno; + channel[ESCON].count++; + + } + } + } +} + + +/* + * free specific channel from the channel[].list + */ +static int channel_free(int media, int devno) +{ + int i; + + for (i = 0; i < channel[media].count; i++) { + if ((devno == channel[media].list[i].devno) && + ((channel[media].list[i].flag & CHANNEL_IN_USE) != 0x00)) { + channel[media].list[i].flag &= ~CHANNEL_IN_USE; + return 0; + } + } + printk(KERN_WARNING "channel: dev %04x is not a channel or in use\n", devno); + return -ENODEV; +} + + +/* + * get specific channel from the channel[].list + */ +static int channel_get(int media, int devno) +{ + int i; + + for (i = 0; i < channel[media].count; i++) { + if ((devno == channel[media].list[i].devno) && + ((channel[media].list[i].flag & CHANNEL_IN_USE) == 0x00)) { + channel[media].list[i].flag |= CHANNEL_IN_USE; + return channel[media].list[i].devno; + } + } + printk(KERN_WARNING "channel: dev %04x is not a channel or in use\n", devno); + return -ENODEV; + +} + + +/* + * get the next free channel from the channel[].list + */ +static int channel_get_next(int media) +{ + int i; + + for (i = 0; i < channel[media].count; i++) { + if ((channel[media].list[i].flag & CHANNEL_IN_USE) == 0x00) { +#ifdef DEBUG + printk(KERN_DEBUG "channel: picked=%04x\n", channel[media].list[i].devno); +#endif + channel[media].list[i].flag |= CHANNEL_IN_USE; + return channel[media].list[i].devno; + } + } + return -ENODEV; +} + + +/* + * picks the next free channel from the channel[].list + */ +static int channel_left(int media) +{ + return channel[media].left; +} + + +/* + * defines all devices which are channels + */ +static channel_type_t channel_check_for_type (senseid_t *id) + { + channel_type_t type; + + switch (id->cu_type) { + case 0x3088: + + switch (id->cu_model) { + case 0x08: + type = channel_type_ctca; /* 3088-08 ==> CTCA */ + break; + + case 0x1F: + type = channel_type_escon; /* 3088-1F ==> ESCON channel */ + break; + + case 0x01: /* 3088-01 ==> P390 OSA emulation */ + case 0x60: /* 3088-60 ==> OSA/2 adapter */ + case 0x61: /* 3088-61 ==> CISCO 7206 CLAW protocol ESCON connected */ + case 0x62: /* 3088-62 ==> OSA/D device */ + type = channel_type_unsupported; + break; + + default: + type = channel_type_undefined; + printk(KERN_INFO "channel: Unknown model found 3088-%02x\n",id->cu_model); + } + break; + + default: + type = channel_type_none; + + } + return type; +} + + +/* + * sort the channel[].list + */ +static void channel_sort(struct devicelist list[], int n) +{ + int i; + int sorted = 0; + struct devicelist tmp; + + while (!sorted) { + sorted = 1; + + for (i = 0; i < n-1; i++) { + if (list[i].devno > list[i+1].devno) { + tmp = list[i]; + list[i] = list[i+1]; + list[i+1] = tmp; + sorted = 0; + } + } + } +} + + +/* + * General routines + * + */ + +static int inline extract_channel_id(char *name) +{ + if (name[0] == 'c') + return (name[3]-'0'); + else + return (name[5]-'0'); +} + + +static int inline extract_channel_media(char *name) +{ + if (name[0] == 'c') + return CTC; + else + return ESCON; +} + + +static void ctc_tab_init(void) +{ + int m; + int i; + static int t; + + if (t == 0){ + for (m = 0; m < CHANNEL_MEDIA; m++) { + for (i = 0; i < MAX_ADAPTERS; i++) { + ctc_adapter[m][i].devno[WRITE] = -ENODEV; + ctc_adapter[m][i].devno[READ] = -ENODEV; + } + } + t = 1; + } +} + + +static int ctc_buffer_alloc(struct channel *ctc) { + + struct buffer *p; + struct buffer *q; + + p = kmalloc(sizeof(p), GFP_KERNEL); + if (p == NULL) + return -ENOMEM; + else { + p->next = NULL; + p->packets = 0; + p->block = (struct block *) __get_free_pages(GFP_KERNEL+GFP_DMA, 4); + if (p->block == NULL) { + kfree(p); + return -ENOMEM; + } + } + + if (ctc->free_anchor == NULL) + ctc->free_anchor = p; + else { + q = ctc->free_anchor; + while (q->next != NULL) + q = q->next; + q->next = p; + } + ctc->buffer_count++; + return 0; +} + + +static int ctc_buffer_free(struct channel *ctc) { + + struct buffer *p; + + + if (ctc->free_anchor == NULL) + return -ENOMEM; + + p = ctc->free_anchor; + ctc->free_anchor = p->next; + free_pages((__u32)p->block, 4); + kfree(p); + + return 0; +} + + +static int inline ctc_buffer_swap(struct buffer **from, struct buffer **to) { + + struct buffer *p = NULL; + struct buffer *q = NULL; + + if (*from == NULL) + return -ENOMEM; + + p = *from; + *from = p->next; + p->next = NULL; + + if (*to == NULL) + *to = p; + else { + q = *to; + while (q->next != NULL) + q = q->next; + q->next = p; + + } + return 0; +} + + +/* + * ctc_setup function + * this function is called for each ctc= keyword passed into the kernel + * + * valid parameter are: ctc=n,0xnnnn,0xnnnn,ctcx + * where n is the channel protocol always 0 + * 0xnnnn is the cu number read + * 0xnnnn is the cu number write + * ctcx can be ctc0 to ctc7 or escon0 to escon7 + */ +#if LINUX_VERSION_CODE>=0x020300 +static int __init ctc_setup(char *dev_name) +#else +__initfunc(void ctc_setup(char *dev_name,int *ints)) +#endif +{ + struct adapterlist tmp; +#if LINUX_VERSION_CODE>=0x020300 + #define CTC_MAX_PARMS 4 + int ints[CTC_MAX_PARMS+1]; + get_options(dev_name,CTC_MAX_PARMS,ints); + #define ctc_setup_return return(1) +#else + #define ctc_setup_return return +#endif + ctc_tab_init(); + + ctc_no_auto = 1; + + if (!strcmp(dev_name,"noauto")) { + printk(KERN_INFO "ctc: automatic channel selection deactivated\n"); + ctc_setup_return; + } + + tmp.devno[WRITE] = -ENODEV; + tmp.devno[READ] = -ENODEV; + + switch (ints[0]) { + + case 3: /* write channel passed */ + tmp.devno[WRITE] = ints[3]; + + case 2: /* read channel passed */ + tmp.devno[READ] = ints[2]; + if (tmp.devno[WRITE] == -ENODEV) + tmp.devno[WRITE] = tmp.devno[READ] + 1; + + case 1: /* protocol type passed */ + tmp.protocol = ints[1]; + if (tmp.protocol == 0) { + break; + } else { + printk(KERN_WARNING "%s: wrong Channel protocol type passed\n", dev_name); + ctc_setup_return; + } + break; + + default: + printk(KERN_WARNING "ctc: wrong number of parameter passed\n"); + ctc_setup_return; + } + ctc_adapter[extract_channel_media(dev_name)][extract_channel_id(dev_name)] = tmp; +#ifdef DEBUG + printk(DEBUG "%s: protocol=%x read=%04x write=%04x\n", + dev_name, tmp.protocol, tmp.devno[READ], tmp.devno[WRITE]); +#endif + ctc_setup_return; + +} +#if LINUX_VERSION_CODE>=0x020300 +__setup("ctc=", ctc_setup); +#endif + +/* + * ctc_probe + * this function is called for each channel network device, + * which is defined in the /init/main.c + */ +int ctc_probe(net_device *dev) +{ + int rc; + int c; + int i; + int m; + + struct ctc_priv *privptr; + + /* Only the first time the ctc_probe gets control */ + if (channel_tab_initialized == 0) { + channel_init(); + + + } + + ctc_tab_init(); + + m = extract_channel_media(dev->name); + i = extract_channel_id(dev->name); + + if (channel_left(m) <=1) + return -ENODEV; + + if (ctc_no_auto == 1 && (ctc_adapter[m][i].devno[READ] == -ENODEV || ctc_adapter[m][i].devno[WRITE] == -ENODEV)) + return -ENODEV; + + dev->priv = kmalloc(sizeof(struct ctc_priv), GFP_KERNEL); + if (dev->priv == NULL) + return -ENOMEM; + memset(dev->priv, 0, sizeof(struct ctc_priv)); + privptr = (struct ctc_priv *) (dev->priv); + + + for (c = 0; c < 2; c++) { + + privptr->channel[c].devstat = kmalloc(sizeof(devstat_t), GFP_KERNEL); + if (privptr->channel[c].devstat == NULL){ + if (i == WRITE) + kfree(privptr->channel[READ].devstat); + return -ENOMEM; + } + memset(privptr->channel[c].devstat, 0, sizeof(devstat_t)); + + if (ctc_no_auto == 0) + ctc_adapter[m][i].devno[c] = channel_get_next(m); + else + ctc_adapter[m][i].devno[c] = channel_get(m, ctc_adapter[m][i].devno[c]); + + if ( ctc_adapter[m][i].devno[c] != -ENODEV){ + rc = request_irq(get_irq_by_devno(ctc_adapter[m][i].devno[c]), + (void *)ctc_irq_handler, SA_INTERRUPT, dev->name, + privptr->channel[c].devstat); + if (rc) { + printk(KERN_WARNING "%s: requested device busy %02x\n", dev->name, rc); + return -EBUSY; + } + } else { + if (i == WRITE) { + free_irq(get_irq_by_devno(ctc_adapter[m][i].devno[c]), privptr->channel[i].devstat); + channel_free(m, ctc_adapter[m][i].devno[READ]); + kfree(privptr->channel[READ].devstat); + } + kfree(privptr->channel[i].devstat); + return -ENODEV; + } + } + + privptr->channel[READ].devno = ctc_adapter[m][i].devno[READ]; + privptr->channel[READ].irq = get_irq_by_devno(ctc_adapter[m][i].devno[READ]); + privptr->channel[WRITE].devno = ctc_adapter[m][i].devno[WRITE]; + privptr->channel[WRITE].irq = get_irq_by_devno(ctc_adapter[m][i].devno[WRITE]); + privptr->protocol = ctc_adapter[m][i].protocol; + channel[m].left = channel[m].left - 2; + + printk(KERN_INFO "%s: read dev: %04x irq: %04x - write dev: %04x irq: %04x \n", + dev->name, privptr->channel[READ].devno, privptr->channel[READ].irq, + privptr->channel[WRITE].devno, privptr->channel[WRITE].irq); + + dev->mtu = CTC_DEFAULT_MTU_SIZE; + dev->hard_start_xmit = ctc_tx; + dev->open = ctc_open; + dev->stop = ctc_release; + dev->get_stats = ctc_stats; + dev->change_mtu = ctc_change_mtu; + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->type = ARPHRD_SLIP; + dev->tx_queue_len = 100; + dev_init_buffers(dev); + dev->flags = IFF_POINTOPOINT | IFF_NOARP; + + return 0; +} + + +/* + * Interrupt processing + * + */ + +static void inline ccw_check_return_code (net_device *dev, int return_code) +{ + if (return_code != 0) { + switch (return_code) { + case -EBUSY: + printk(KERN_INFO "%s: Busy !\n", dev->name); + break; + case -ENODEV: + printk(KERN_EMERG "%s: Invalid device called for IO\n", dev->name); + break; + case -EIO: + printk(KERN_EMERG "%s: Status pending... \n", dev->name); + break; + default: + printk(KERN_EMERG "%s: Unknown error in Do_IO %04x\n", + dev->name, return_code); + } + } +} + + +static void inline ccw_check_unit_check (net_device *dev, char sense) +{ +#ifdef DEBUG + printk(KERN_INFO "%s: Unit Check with sense code: %02x\n", + dev->name, sense); +#endif + + if (sense & 0x40) { +#ifdef DEBUG + if (sense & 0x01) + printk(KERN_DEBUG "%s: Interface disconnect or Selective reset occurred (remote side)\n", dev->name); + else + printk(KERN_DEBUG "%s: System reset occured (remote side)\n", dev->name); +#endif + } else if (sense & 0x20) { + if (sense & 0x04) + printk(KERN_WARNING "%s: Data-streaming timeout)\n", dev->name); + else + printk(KERN_WARNING "%s: Data-transfer parity error\n", dev->name); + } else if (sense & 0x10) { + if (sense & 0x20) + printk(KERN_WARNING "%s: Hardware malfunction (remote side)\n", dev->name); + else + printk(KERN_WARNING "%s: Read-data parity error (remote side)\n", dev->name); + } + +} + + +static void ctc_irq_handler (int irq, void *initparm, struct pt_regs *regs) +{ + int rc = 0; + __u32 parm; + __u8 flags = 0x00; + struct channel *ctc = NULL; + struct ctc_priv *privptr = NULL; + net_device *dev = NULL; + + ccw1_t ccw_set_x_mode[2] = {{CCW_CMD_SET_EXTENDED, CCW_FLAG_SLI | CCW_FLAG_CC, 0, NULL}, + {CCW_CMD_NOOP, CCW_FLAG_SLI, 0, NULL}}; + + devstat_t *devstat = ((devstat_t *)initparm); + + /* Bypass all 'unsolited interrupts' */ + if (devstat->intparm == 0) { +#ifdef DEBUG + printk(KERN_DEBUG "ctc: unsolited interrupt for device: %04x received c-%02x d-%02x f-%02x\n", + devstat->devno, devstat->cstat, devstat->dstat, devstat->flag); +#endif + /* FIXME - find the related intparm!!! No IO outstanding!!!! */ + return; + } + + ctc = (struct channel *) (devstat->intparm); + dev = (net_device *) ctc->dev; + privptr = dev->priv; + +#ifdef DEBUG + printk(KERN_DEBUG "%s: interrupt for device: %04x received c-%02x d-%02x f-%02x state-%02x\n", + dev->name, ctc->devno, devstat->cstat, devstat->dstat, devstat->flag, ctc->state); +#endif + + /* Check for good subchannel return code, otherwise error message */ + if (devstat->cstat) { + printk(KERN_WARNING "%s: subchannel check for device: %04x - %02x\n", + dev->name, ctc->devno, devstat->cstat); + return; + } + + + /* Check the reason-code of a unit check */ + if (devstat->dstat & DEV_STAT_UNIT_CHECK) + ccw_check_unit_check(dev, devstat->ii.sense.data[0]); + + + /* State machine to bring the connection up / down and to restart */ + + ctc->last_dstat = devstat->dstat; + + switch (ctc->state) { + + case CTC_STOP: /* HALT_IO issued by ctc_release (halt sequence) */ + if (!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + wake_up(&ctc->wait); /* wake up ctc_release */ + return; + + + case CTC_START_HALT_IO: /* HALT_IO issued by ctc_open (start sequence) */ + if (!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + + ctc->state = CTC_START_SET_X_MODE; + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ccw_set_x_mode[0], parm, 0xff, flags); + if (rc != 0) + ccw_check_return_code(dev, rc); + return; + + + case CTC_START_SET_X_MODE: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + if ((devstat->ii.sense.data[0] & 0x41) != 0x41 || + (devstat->ii.sense.data[0] & 0x40) != 0x40) { + wake_up(&ctc->wait); /* wake up ctc_open (READ or WRITE) */ + return; + } + } + if (!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + ctc->state = CTC_START_SELECT; + + + case CTC_START_SELECT: + if (!ctc->flag & CTC_WRITE) { + ctc->state = CTC_START_READ_TEST; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + wake_up(&ctc->wait); /* wake up ctc_open (READ) */ + + } else { + ctc->state = CTC_START_WRITE_TEST; + /* ADD HERE THE RIGHT PACKET TO ISSUE A ROUND TRIP - PART 1 */ + ctc->ccw[1].count = 0; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags); + if (rc != 0) + ccw_check_return_code(dev, rc); + } + return; + + + case CTC_START_READ_TEST: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + if ((devstat->ii.sense.data[0] & 0x41) == 0x41 || + (devstat->ii.sense.data[0] & 0x40) == 0x40 || + devstat->ii.sense.data[0] == 0 ) { + init_timer(&ctc->timer); + ctc->timer.function = (void *)ctc_read_retry; + ctc->timer.data = (__u32)ctc; + ctc->timer.expires = jiffies + 10*HZ; + add_timer(&ctc->timer); +#ifdef DEBUG + printk(KERN_DEBUG "%s: read connection restarted\n",dev->name); +#endif + } + return; + } + + if ((devstat->dstat & ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) { + if ((devstat->dstat & DEV_STAT_ATTENTION) && + (devstat->dstat & DEV_STAT_BUSY)) { + printk(KERN_WARNING "%s: read channel is connected with the remote side read channel\n", dev->name); + } + wake_up(&privptr->channel[WRITE].wait); /* wake up ctc_open (WRITE) */ + return; + } + + ctc->state = CTC_START_READ; + set_bit(0, (void *)&ctc->IO_active); + + /* ADD HERE THE RIGHT PACKET TO ISSUE A ROUND TRIP - PART 2 */ + /* wake_up(&privptr->channel[WRITE].wait);*/ /* wake up ctc_open (WRITE) */ + + + case CTC_START_READ: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + if ((devstat->ii.sense.data[0] & 0x41) == 0x41 || + (devstat->ii.sense.data[0] & 0x40) == 0x40 || + devstat->ii.sense.data[0] == 0 ) { + privptr->stats.rx_errors++; + /* Need protection here cos we are in the read irq */ + /* handler the tbusy is for the write subchannel */ + ctc_protect_busy(dev); + ctc_setbit_busy(TB_RETRY,dev); + ctc_unprotect_busy(dev); + init_timer(&ctc->timer); + ctc->timer.function = (void *)ctc_read_retry; + ctc->timer.data = (__u32)ctc; + ctc->timer.expires = jiffies + 30*HZ; + add_timer(&ctc->timer); + printk(KERN_INFO "%s: connection restarted!! problem on remote side\n",dev->name); + } + return; + } + + if(!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + ctc_protect_busy(dev); + ctc_clearbit_busy(TB_RETRY,dev); + ctc_unprotect_busy(dev); + ctc_buffer_swap(&ctc->free_anchor, &ctc->proc_anchor); + + if (ctc->free_anchor != NULL) { + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + } else { + clear_bit(0, (void *)&ctc->IO_active); +#ifdef DEBUG + printk(KERN_DEBUG "%s: No HOT READ started in IRQ\n",dev->name); +#endif + } + + if (test_and_set_bit(CTC_BH_ACTIVE, (void *)&ctc->flag_a) == 0) { + queue_task(&ctc->tq, &tq_immediate); + mark_bh(IMMEDIATE_BH); + } + return; + + + case CTC_START_WRITE_TEST: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + if ((devstat->ii.sense.data[0] & 0x41) == 0x41 || + (devstat->ii.sense.data[0] & 0x40) == 0x40 || + devstat->ii.sense.data[0] == 0 ) { + init_timer(&ctc->timer); + ctc->timer.function = (void *)ctc_write_retry; + ctc->timer.data = (__u32)ctc; + ctc->timer.expires = jiffies + 10*HZ; + add_timer(&ctc->timer); +#ifdef DEBUG + printk(KERN_DEBUG "%s: write connection restarted\n",dev->name); +#endif + } + return; + } + + ctc->state = CTC_START_WRITE; + wake_up(&ctc->wait); /* wake up ctc_open (WRITE) */ + return; + + + case CTC_START_WRITE: + if (devstat->dstat & DEV_STAT_UNIT_CHECK) { + privptr->stats.tx_errors += ctc->proc_anchor->packets; +#ifdef DEBUG + printk(KERN_DEBUG "%s: Unit Check on write channel\n",dev->name); +#endif + } else { + if (!devstat->flag & DEVSTAT_FINAL_STATUS) + return; + privptr->stats.tx_packets += ctc->proc_anchor->packets; + } + + ctc->proc_anchor->block->length = 0; + ctc_buffer_swap(&ctc->proc_anchor, &ctc->free_anchor); + ctc_clearbit_busy(TB_NOBUFFER,dev); + if (ctc->proc_anchor != NULL) { +#ifdef DEBUG + printk(KERN_DEBUG "%s: IRQ early swap buffer\n",dev->name); +#endif + ctc->ccw[1].count = ctc->proc_anchor->block->length; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->proc_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + dev->trans_start = jiffies; + return; + + } + + if (ctc->free_anchor->block->length != 0) { + if (ctc_test_and_setbit_busy(TB_TX,dev) == 0) { + /* set transmission to busy */ + ctc_buffer_swap(&ctc->free_anchor, &ctc->proc_anchor); + ctc_clearbit_busy(TB_TX,dev); +#ifdef DEBUG + printk(KERN_DEBUG "%s: last buffer move in IRQ\n",dev->name); +#endif + ctc->ccw[1].count = ctc->proc_anchor->block->length; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->proc_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + dev->trans_start = jiffies; + return; + } + } + + clear_bit(0, (void *)&ctc->IO_active); /* set by ctc_tx or ctc_bh */ + return; + + + default: + printk(KERN_WARNING "%s: wrong selection code - irq\n",dev->name); + return; + } +} + + +static void ctc_irq_bh (struct channel *ctc) +{ + int rc = 0; + __u16 data_len; + __u32 parm; + + __u8 flags = 0x00; + __u32 saveflags; + net_device *dev; + struct ctc_priv *privptr; + struct packet *lp; + struct sk_buff *skb; + + dev = (net_device *) ctc->dev; + privptr = (struct ctc_priv *) dev->priv; + +#ifdef DEBUG + printk(KERN_DEBUG "%s: bh routine - state-%02x\n" ,dev->name, ctc->state); +#endif + + while (ctc->proc_anchor != NULL) { + + lp = &ctc->proc_anchor->block->data; + + while ((__u8 *) lp < (__u8 *) &ctc->proc_anchor->block->length + ctc->proc_anchor->block->length) { + data_len = lp->length - PACKET_HEADER_LENGTH; + skb = dev_alloc_skb(data_len); + if (skb) { + memcpy(skb_put(skb, data_len),&lp->data, data_len); + skb->mac.raw = skb->data; + skb->dev = dev; + skb->protocol = htons(ETH_P_IP); + skb->ip_summed = CHECKSUM_UNNECESSARY; /* no UC happened!!! */ + netif_rx(skb); + privptr->stats.rx_packets++; + } else { + privptr->stats.rx_dropped++; + printk(KERN_WARNING "%s: is low on memory\n",dev->name); + } + (__u8 *)lp += lp->length; + } + + s390irq_spin_lock_irqsave(ctc->irq, saveflags); + ctc_buffer_swap(&ctc->proc_anchor, &ctc->free_anchor); + + if (test_and_set_bit(0, (void *)&ctc->IO_active) == 0) { +#ifdef DEBUG + printk(KERN_DEBUG "%s: HOT READ started in bh routine\n" ,dev->name); +#endif + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + if (rc != 0) + ccw_check_return_code(dev, rc); + } + s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); + } + clear_bit(CTC_BH_ACTIVE, (void *)&ctc->flag_a); + return; +} + + +static void ctc_read_retry (struct channel *ctc) +{ + int rc = 0; + __u32 parm; + __u8 flags = 0x00; + __u32 saveflags; + net_device *dev; + + dev = (net_device *) ctc->dev; + +#ifdef DEBUG + printk(KERN_DEBUG "%s: read retry - state-%02x\n" ,dev->name, ctc->state); +#endif + s390irq_spin_lock_irqsave(ctc->irq, saveflags); + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->free_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); + if (rc != 0) + ccw_check_return_code(dev, rc); + return; +} + + +static void ctc_write_retry (struct channel *ctc) +{ + int rc = 0; + __u32 parm; + __u8 flags = 0x00; + __u32 saveflags; + net_device *dev; + + dev = (net_device *) ctc->dev; + +#ifdef DEBUG + printk(KERN_DEBUG "%s: write retry - state-%02x\n" ,dev->name, ctc->state); +#endif + s390irq_spin_lock_irqsave(ctc->irq, saveflags); + ctc->ccw[1].count = 0; + ctc->ccw[1].cda = (char *)virt_to_phys(ctc->proc_anchor->block); + parm = (__u32) ctc; + rc = do_IO (ctc->irq, &ctc->ccw[0], parm, 0xff, flags ); + s390irq_spin_unlock_irqrestore(ctc->irq, saveflags); + if (rc != 0) + ccw_check_return_code(dev, rc); + return; +} + + + +/* + * ctc_open + * + */ +static int ctc_open(net_device *dev) +{ + int rc; + int i; + int j; + __u8 flags = 0x00; + __u32 saveflags; + __u32 parm; + struct ctc_priv *privptr; + DECLARE_WAITQUEUE(wait, current); + struct timer_list timer; + + + ctc_set_busy(dev); + + privptr = (struct ctc_priv *) (dev->priv); + + privptr->channel[READ].flag = 0x00; + privptr->channel[WRITE].flag = CTC_WRITE; + + for (i = 0; i < 2; i++) { + for (j = 0; j < CTC_BLOCKS; j++) { + rc = ctc_buffer_alloc(&privptr->channel[i]); + if (rc != 0) + return -ENOMEM; + } + init_waitqueue_head(&privptr->channel[i].wait); + privptr->channel[i].tq.next = NULL; + privptr->channel[i].tq.sync = 0; + privptr->channel[i].tq.routine = (void *)(void *)ctc_irq_bh; + privptr->channel[i].tq.data = &privptr->channel[i]; + + privptr->channel[i].dev = dev; + + privptr->channel[i].flag_a = 0; + privptr->channel[i].IO_active = 0; + + privptr->channel[i].ccw[0].cmd_code = CCW_CMD_PREPARE; + privptr->channel[i].ccw[0].flags = CCW_FLAG_SLI | CCW_FLAG_CC; + privptr->channel[i].ccw[0].count = 0; + privptr->channel[i].ccw[0].cda = NULL; + if (i == READ) { + privptr->channel[i].ccw[1].cmd_code = CCW_CMD_READ; + privptr->channel[i].ccw[1].flags = CCW_FLAG_SLI; + privptr->channel[i].ccw[1].count = 0xffff; /* MAX size */ + privptr->channel[i].ccw[1].cda = NULL; + } else { + privptr->channel[i].ccw[1].cmd_code = CCW_CMD_WRITE; + privptr->channel[i].ccw[1].flags = CCW_FLAG_SLI | CCW_FLAG_CC; + privptr->channel[i].ccw[1].count = 0; + privptr->channel[i].ccw[1].cda = NULL; + } + privptr->channel[i].ccw[2].cmd_code = CCW_CMD_NOOP; /* jointed CE+DE */ + privptr->channel[i].ccw[2].flags = CCW_FLAG_SLI; + privptr->channel[i].ccw[2].count = 0; + privptr->channel[i].ccw[2].cda = NULL; + + privptr->channel[i].flag &= ~CTC_TIMER; + init_timer(&timer); + timer.function = (void *)ctc_timer; + timer.data = (__u32)&privptr->channel[i]; + timer.expires = jiffies + 150*HZ; /* time to connect with the remote side */ + add_timer(&timer); + + s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); + parm = (unsigned long) &privptr->channel[i]; + privptr->channel[i].state = CTC_START_HALT_IO; + rc = halt_IO(privptr->channel[i].irq, parm, flags); + add_wait_queue(&privptr->channel[i].wait, &wait); + current->state = TASK_INTERRUPTIBLE; + s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); + schedule(); + remove_wait_queue(&privptr->channel[i].wait, &wait); + if(rc != 0) + ccw_check_return_code(dev, rc); + if((privptr->channel[i].flag & CTC_TIMER) == 0x00) + del_timer(&timer); + } + + if ((((privptr->channel[READ].last_dstat | privptr->channel[WRITE].last_dstat) & + ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) || + (((privptr->channel[READ].flag | privptr->channel[WRITE].flag) & CTC_TIMER) != 0x00)) { +#ifdef DEBUG + printk(KERN_DEBUG "%s: channel problems during open - read: %02x - write: %02x\n", + dev->name, privptr->channel[READ].last_dstat, privptr->channel[WRITE].last_dstat); +#endif + printk(KERN_INFO "%s: remote side is currently not ready\n", dev->name); + + for (i = 0; i < 2; i++) { + s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); + parm = (unsigned long) &privptr->channel[i]; + privptr->channel[i].state = CTC_STOP; + rc = halt_IO(privptr->channel[i].irq, parm, flags); + s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); + if (rc != 0) + ccw_check_return_code(dev, rc); + for (j = 0; j < CTC_BLOCKS; j++) + ctc_buffer_free(&privptr->channel[i]); + } + return -EIO; + } + + printk(KERN_INFO "%s: connected with remote side\n",dev->name); + ctc_clear_busy(dev); + return 0; +} + + +static void ctc_timer (struct channel *ctc) +{ +#ifdef DEBUG + net_device *dev; + + dev = (net_device *) ctc->dev; + printk(KERN_DEBUG "%s: timer return\n" ,dev->name); +#endif + ctc->flag |= CTC_TIMER; + wake_up(&ctc->wait); + return; +} + +/* + * ctc_release + * + */ +static int ctc_release(net_device *dev) +{ + int rc; + int i; + int j; + __u8 flags = 0x00; + __u32 saveflags; + __u32 parm; + struct ctc_priv *privptr; + DECLARE_WAITQUEUE(wait, current); + + privptr = (struct ctc_priv *) dev->priv; + + ctc_protect_busy_irqsave(dev,saveflags); + ctc_setbit_busy(TB_STOP,dev); + ctc_unprotect_busy_irqrestore(dev,flags); + for (i = 0; i < 2; i++) { + s390irq_spin_lock_irqsave(privptr->channel[i].irq, saveflags); + privptr->channel[i].state = CTC_STOP; + parm = (__u32) &privptr->channel[i]; + rc = halt_IO (privptr->channel[i].irq, parm, flags ); + add_wait_queue(&privptr->channel[i].wait, &wait); + current->state = TASK_INTERRUPTIBLE; + s390irq_spin_unlock_irqrestore(privptr->channel[i].irq, saveflags); + schedule(); + remove_wait_queue(&privptr->channel[i].wait, &wait); + if (rc != 0) { + ccw_check_return_code(dev, rc); + } + + for (j = 0; j < CTC_BLOCKS; j++) { + ctc_buffer_swap(&privptr->channel[i].proc_anchor, &privptr->channel[i].free_anchor); + ctc_buffer_free(&privptr->channel[i]); + } + } + + if (((privptr->channel[READ].last_dstat | privptr->channel[WRITE].last_dstat) & + ~(DEV_STAT_CHN_END | DEV_STAT_DEV_END)) != 0x00) { + printk(KERN_WARNING "%s: channel problems during close - read: %02x - write: %02x\n", + dev->name, privptr->channel[READ].last_dstat, privptr->channel[WRITE].last_dstat); + return -EIO; + } + + return 0; +} + + +/* + * ctc_tx + * + * + */ +static int ctc_tx(struct sk_buff *skb, net_device *dev) +{ + int rc=0,rc2; + __u32 parm; + __u8 flags = 0x00; + __u32 saveflags; + struct ctc_priv *privptr; + struct packet *lp; + + + privptr = (struct ctc_priv *) (dev->priv); + + if (skb == NULL) { + printk(KERN_WARNING "%s: NULL pointer as sk_buffer passed\n", dev->name); + privptr->stats.tx_dropped++; + return -EIO; + } + + s390irq_spin_lock_irqsave(privptr->channel[WRITE].irq, saveflags); + if (ctc_check_busy(dev)) { + rc=-EBUSY; + goto Done; + } + + if (ctc_test_and_setbit_busy(TB_TX,dev)) { /* set transmission to busy */ + rc=-EBUSY; + goto Done; + } + + if (65535 - privptr->channel[WRITE].free_anchor->block->length - PACKET_HEADER_LENGTH <= skb->len + PACKET_HEADER_LENGTH + 2) { +#ifdef DEBUG + printk(KERN_DEBUG "%s: early swap\n", dev->name); +#endif + + ctc_buffer_swap(&privptr->channel[WRITE].free_anchor, &privptr->channel[WRITE].proc_anchor); + if (privptr->channel[WRITE].free_anchor == NULL){ + ctc_setbit_busy(TB_NOBUFFER,dev); + rc=-EBUSY; + goto Done2; + } + } + + if (privptr->channel[WRITE].free_anchor->block->length == 0) { + privptr->channel[WRITE].free_anchor->block->length = BLOCK_HEADER_LENGTH; + privptr->channel[WRITE].free_anchor->packets = 0; + } + + + (__u8 *)lp = (__u8 *) &privptr->channel[WRITE].free_anchor->block->length + privptr->channel[WRITE].free_anchor->block->length; + privptr->channel[WRITE].free_anchor->block->length += skb->len + PACKET_HEADER_LENGTH; + lp->length = skb->len + PACKET_HEADER_LENGTH; + lp->type = 0x0800; + lp->unused = 0; + memcpy(&lp->data, skb->data, skb->len); + (__u8 *) lp += lp->length; + lp->length = 0; + dev_kfree_skb(skb); + privptr->channel[WRITE].free_anchor->packets++; + + if (test_and_set_bit(0, (void *)&privptr->channel[WRITE].IO_active) == 0) { + ctc_buffer_swap(&privptr->channel[WRITE].free_anchor,&privptr->channel[WRITE].proc_anchor); + privptr->channel[WRITE].ccw[1].count = privptr->channel[WRITE].proc_anchor->block->length; + privptr->channel[WRITE].ccw[1].cda = (char *)virt_to_phys(privptr->channel[WRITE].proc_anchor->block); + parm = (__u32) &privptr->channel[WRITE]; + rc2 = do_IO (privptr->channel[WRITE].irq, &privptr->channel[WRITE].ccw[0], parm, 0xff, flags ); + if (rc2 != 0) + ccw_check_return_code(dev, rc2); + dev->trans_start = jiffies; + } + if (privptr->channel[WRITE].free_anchor == NULL) + ctc_setbit_busy(TB_NOBUFFER,dev); +Done2: + ctc_clearbit_busy(TB_TX,dev); +Done: + s390irq_spin_unlock_irqrestore(privptr->channel[WRITE].irq, saveflags); + return(rc); +} + + +/* + * ctc_change_mtu + * + * S/390 can handle MTU sizes from 576 to 32760 for VM, VSE + * 576 to 65527 for OS/390 + * + */ +static int ctc_change_mtu(net_device *dev, int new_mtu) +{ + if ((new_mtu < 576) || (new_mtu > 65528)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + + +/* + * ctc_stats + * + */ +struct net_device_stats *ctc_stats(net_device *dev) +{ + struct ctc_priv *privptr; + + privptr = dev->priv; + return &privptr->stats; +} + + +/* Module code goes here */ + +/* + free_irq(privptr->channel[i].irq, privptr->channel[i].devstat); + kfree(privptr->channel[i].devstat); + +*/ +/* --- This is the END my friend --- */ diff --git a/drivers/s390/net/iucv.c b/drivers/s390/net/iucv.c new file mode 100644 index 000000000..b8b365753 --- /dev/null +++ b/drivers/s390/net/iucv.c @@ -0,0 +1,1178 @@ +/* + * drivers/s390/net/iucv.c + * Network driver for VM using iucv + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Stefan Hegewald <hegewald@de.ibm.com> + * Hartmut Penner <hpenner@de.ibm.com> + * + * 2.3 Updates Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com) + * Martin Schwidefsky (schwidefsky@de.ibm.com) + * + + */ + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + +#include <linux/version.h> +#include <linux/sched.h> +#include <linux/kernel.h> /* printk() */ +#include <linux/malloc.h> /* kmalloc() */ +#include <linux/errno.h> /* error codes */ +#include <linux/types.h> /* size_t */ +#include <linux/interrupt.h> /* mark_bh */ +#include <linux/netdevice.h> /* struct net_device, and other headers */ +#include <linux/inetdevice.h> /* struct net_device, and other headers */ +#include <linux/if_arp.h> +#include <linux/rtnetlink.h> +#include <linux/ip.h> /* struct iphdr */ +#include <linux/tcp.h> /* struct tcphdr */ +#include <linux/skbuff.h> +#include <linux/init.h> +#include <linux/string.h> +#include <asm/checksum.h> +#include <asm/io.h> +#include <asm/string.h> + +#include "iucv.h" + + + + +#define DEBUG123 +#define MAX_DEVICES 10 + +extern char _ascebc[]; + +/* + * global structures + */ +static char iucv_userid[MAX_DEVICES][8]; +static char iucv_ascii_userid[MAX_DEVICES][8]; +static int iucv_pathid[MAX_DEVICES] = {0}; +static unsigned char iucv_ext_int_buffer[40] __attribute__((aligned (8))) ={0}; +static unsigned char glob_command_buffer[40] __attribute__((aligned (8))); + +#if LINUX_VERSION_CODE>=0x20300 +typedef struct net_device net_device; +#else +typedef struct device net_device; +#endif +net_device iucv_devs[]; + + +/* This structure is private to each device. It is used to pass */ +/* packets in and out, so there is place for a packet */ +struct iucv_priv { + struct net_device_stats stats; + int packetlen; + int status; + u8 *packetdata; + int pathid; /* used device */ + unsigned char command_buffer[40] __attribute__((aligned (8))); + unsigned char ext_int_buffer[40] __attribute__((aligned (8))); + u8* receive_buffer; + int receive_buffer_len; + u8* send_buffer; + int send_buffer_len; + char * new_send_buf; /* send buffer ptr */ + unsigned char recv_buf[2048]; /* size is just a guess */ + unsigned char userid[8]; +}; + +struct iucv_header { + short len; +}; + + + +static __inline__ int netif_is_busy(net_device *dev) +{ +#if LINUX_VERSION_CODE<0x02032D + return(dev->tbusy); +#else + return(test_bit(__LINK_STATE_XOFF,&dev->flags)); +#endif +} + + + +#if LINUX_VERSION_CODE<0x02032D +#define netif_enter_interrupt(dev) dev->interrupt=1 +#define netif_exit_interrupt(dev) dev->interrupt=0 +#define netif_start(dev) dev->start=1 +#define netif_stop(dev) dev->start=0 + +static __inline__ void netif_stop_queue(net_device *dev) +{ + dev->tbusy=1; +} + +static __inline__ void netif_start_queue(net_device *dev) +{ + dev->tbusy=0; +} + +static __inline__ void netif_wake_queue(net_device *dev) +{ + dev->tbusy=0; + mark_bh(NET_BH); +} + +#else +#define netif_enter_interrupt(dev) +#define netif_exit_interrupt(dev) +#define netif_start(dev) +#define netif_stop(dev) +#endif + + + +/* + * Following the iucv primitives + */ + + +extern inline void b2f0(int code,void* parm) +{ + asm volatile ("LR 1,%1\n\tLR 0,%0\n\t.long 0xb2f01000" :: + "d" (code) ,"a" (parm) :"0", "1"); +} + +int iucv_enable(void *parms) +{ + MASK_T *parm = parms; + memset(parms,0,sizeof(parm)); + parm->ipmask = 0xF8; + b2f0(SETMASK,parm); + memset(parms,0,sizeof(parm)); + parm->ipmask = 0xF8; + b2f0(SETCMASK,parm); + return parm->iprcode; +} + + +int iucv_declare_buffer(void *parms, DCLBFR_T *buffer) +{ + DCLBFR_T *parm = parms; + memset(parms,0,sizeof(parm)); + parm->ipflags1= 0x00; + parm->ipbfadr1 = virt_to_phys(buffer); + b2f0(DECLARE_BUFFER, parm); + return parm->iprcode; +} + + +int iucv_retrieve_buffer(void *parms) +{ + DCLBFR_T *parm = parms; + memset(parms,0x0,sizeof(parm)); + parm->iprcode = 0x0; + b2f0(RETRIEVE_BUFFER, parm); + return parm->iprcode; +} + + +int iucv_connect(void *parms, + const char *userid, + const char *host, + const char *ipusr, + unsigned short * used_pathid) +{ + CONNECT_T *parm = parms; /* ipflags was 0x60*/ + memset(parms,0x0,sizeof(parm)); + parm->ipflags1 = 0x80; + parm->ipmsglim = 0x0a; + memcpy(parm->ipvmid,userid,8); + if (ipusr) + memcpy(parm->ipuser,ipusr,16); + memcpy(parm->iptarget,host,8); + b2f0(CONNECT, parm); + *used_pathid = parm->ippathid; + return parm->iprcode; +} + + + +int iucv_accept(void *parms,int pathid) +{ +#ifdef DEBUG + int i=0; +#endif + ACCEPT_T *parm = parms; + memset(parms,0,sizeof(parm)); + parm->ippathid = pathid; + parm->ipflags1 = 0x80; + parm->ipmsglim = 0x0a; +#ifdef DEBUG + printk("iucv: iucv_accept input.\n"); + for (i=0;i<40; i++) + { + printk("%02x ",((char *)parms)[i]); + } + printk("\n"); +#endif + b2f0(ACCEPT, parm); + return parm->iprcode; +} + + + +int iucv_receive(void *parms,void *bufferarray,int len) +{ +#ifdef DEBUG + int i=0; +#endif + RECEIVE_T *parm = parms; + memset(parms,0x0,sizeof(parm)); + /*parm->ipflags1 = 0x42;*/ + parm->ipflags1 = 0x0; + parm->ipmsgid = 0x0; + parm->iptrgcls = 0x0; + parm->ipbfadr1 = (ULONG) virt_to_phys(bufferarray); + parm->ipbfln1f = len; + parm->ipbfln2f = 0x0; + b2f0(RECEIVE, parm); + if (parm->iprcode == 0) + len = parm->ipbfln1f; +// len = len-parm->ipbfln1f; +#ifdef DEBUG + printk("iucv: iucv_receive command input:\n"); + for (i=0;i<40;i++) /* show iucv buffer before send */ + { + printk("%02x ",((char *)parms)[i]); + } + printk("\n"); + + printk("iucv: iucv_receive data buffer:\n"); + for (i=0;i<len;i++) /* show data received */ + { + printk("%02x ",((char *)bufferarray)[i]); + } + printk("\n"); + printk("received length: %02x ",len); + +#endif + return parm->iprcode; +} + + +int iucv_send(void *parms,int pathid,void *bufferarray,int len, + void *recv_buf, int recv_len) +{ +#ifdef DEBUG + int i=0; +#endif + SEND_T *parm = parms; + memset(parms,0x0,sizeof(parm)); + /* parm->ipflags1 = 0x48; ??*/ + parm->ippathid = pathid; + parm->ipflags1 = 0x14; /* any options ?? */ + parm->ipmsgid = 0x0; + parm->iptrgcls = 0x0; + parm->ipbfadr1 = virt_to_phys(bufferarray); + parm->ipbfln1f = len; + parm->ipsrccls = 0x0; + parm->ipmsgtag = 0x0; + parm->ipbfadr2 = virt_to_phys(recv_buf); + parm->ipbfln2f = recv_len; + + +#ifdef DEBUG + printk("iucv: iucv_send command input:\n"); + for (i=0;i<40;i++) /* show iucv buffer before send */ + { + printk("%02x ",((char *)parms)[i]); + } + printk("\n"); + + printk("iucv: iucv_send data buffer:\n"); + for (i=0;i<len;i++) /* show send data before send */ + { + printk("%02x ",((char *)bufferarray)[i]); + } + printk("\n"); +#endif + + b2f0(SEND, parm); + +#ifdef DEBUGXX + printk("iucv: iucv_send buffer after send:\n"); + for (i=0;i<len;i++) /* show send buffer after send */ + { + printk("%1x",((char *)bufferarray)[i]); + } + printk("\n"); +#endif + + return parm->iprcode; +} + + + +int iucv_sever(void *parms) +{ + SEVER_T *parm = parms; + memset(parms,0x0,sizeof(parm)); + parm->ippathid = 0x0; + parm->ipflags1 = 0x0; + parm->iprcode = 0xF; + memset(parm->ipuser,0,16); + b2f0(SEVER, parm); + return parm->iprcode; +} + + +#ifdef DEBUG +/*--------------------------*/ +/* Dump buffer formatted */ +/*--------------------------*/ +static void dumpit(char* buf, int len) +{ + int i; + for (i=0;i<len;i++) { + if (!(i%16)&&i!=0) + printk("\n"); + else if (!(i%4)&&i!=0) + printk(" "); + printk( "%02X",buf[i]); + } + if (len%16) + printk( "\n"); +} +#endif + + + +/*--------------------------*/ +/* Get device from pathid */ +/*--------------------------*/ +net_device * get_device_from_pathid(int pathid) +{ + int i; + for (i=0;i<=MAX_DEVICES;i++) + { + if (iucv_pathid[i] == pathid) + return &iucv_devs[i]; + } + printk("iucv: get_device_from_pathid: no device for pathid %X\n",pathid); + return 0; +} + + + +/*--------------------------*/ +/* Get device from userid */ +/*--------------------------*/ +net_device * get_device_from_userid(char * userid) +{ + int i; + net_device * dev; + struct iucv_priv *privptr; + for (i=0;i<=MAX_DEVICES;i++) + { + dev = &iucv_devs[i]; + privptr = (struct iucv_priv *)(dev->priv); + if (memcmp(privptr->userid,userid,8)==0) + return &iucv_devs[i]; + } + printk("iucv: get_device_from_uid: no device for userid %s\n",userid); + return 0; +} + + +/*--------------------------*/ +/* Open iucv Device Driver */ +/*--------------------------*/ +int iucv_open(net_device *dev) +{ + int rc; + unsigned short iucv_used_pathid; + struct iucv_priv *privptr; + char iucv_host[8] ={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + char vmident[16] ={0xf0,0x40,0x40,0x40,0x40,0x40,0x40,0x40, + 0xf0,0x40,0x40,0x40,0x40,0x40,0x40,0x40}; + +#ifdef DEBUG + printk( "iucv: iucv_open, device: %s\n",dev->name); +#endif + + privptr = (struct iucv_priv *)(dev->priv); + if(privptr->pathid != -1) { + netif_start(dev); + netif_start_queue(dev); + return 0; + } + if ((rc = iucv_connect(privptr->command_buffer, + privptr->userid, + iucv_host, + vmident, + &iucv_used_pathid))!=0) { + printk( "iucv: iucv connect failed with rc %X\n",rc); + iucv_retrieve_buffer(privptr->command_buffer); + return -ENODEV; + } + + privptr->pathid = iucv_used_pathid; + iucv_pathid[dev-iucv_devs]=privptr->pathid; + +#ifdef DEBUG + printk( "iucv: iucv_connect ended with rc: %X\n",rc); + printk( "iucv[%d] pathid %X \n",(int)(dev-iucv_devs),privptr->pathid); +#endif + netif_start(dev); + netif_start_queue(dev); + return 0; +} + + + +/*-----------------------------------------------------------------------*/ +/* Receive a packet: retrieve, encapsulate and pass over to upper levels */ +/*-----------------------------------------------------------------------*/ +void iucv_rx(net_device *dev, int len, unsigned char *buf) +{ + + struct sk_buff *skb; + struct iucv_priv *privptr = (struct iucv_priv *)dev->priv; + +#ifdef DEBUG + printk( "iucv: iucv_rx len: %X, device %s\n",len,dev->name); + printk( "iucv rx: received orig:\n"); + dumpit(buf,len); +#endif + + /* strip iucv header now */ + len = len - 2; /* short header */ + buf = buf + 2; /* short header */ + + skb = dev_alloc_skb(len+2); /* why +2 ? alignment ? */ + if (!skb) { + printk( "iucv rx: low on mem, returning...\n"); + return; + } + skb_reserve(skb, 2); /* align IP on 16B boundary*/ + memcpy(skb_put(skb, len), buf, len); +#ifdef DEBUG + printk( "iucv rx: data before netif_rx()\n"); + dumpit(buf,len); +#endif + + /* Write metadata, and then pass to the receive level */ + skb->mac.raw = skb->data; + skb->pkt_type = PACKET_HOST; + skb->dev = dev; + skb->protocol = htons(ETH_P_IP); + skb->ip_summed = CHECKSUM_UNNECESSARY; /* don't check it*/ + privptr->stats.rx_packets++; + netif_rx(skb); + + return; +} /* end iucv_rx() */ + + + + +/*----------------------------*/ +/* handle interrupts */ +/*----------------------------*/ +void do_iucv_interrupt(void) +{ + int rc; + struct in_device *indev; + struct in_ifaddr *inaddr; + unsigned long len=0; + net_device *dev=0; + struct iucv_priv *privptr; + INTERRUPT_T * extern_int_buffer; + unsigned short iucv_data_len=0; + unsigned short iucv_next=0; + unsigned char * rcvptr; + + /* get own buffer: */ + extern_int_buffer = (INTERRUPT_T*) iucv_ext_int_buffer; + + netif_enter_interrupt(dev); /* lock ! */ + +#ifdef DEBUG + printk( "iucv: do_iucv_interrupt %x received; pathid: %02X\n", + extern_int_buffer->iptype,extern_int_buffer->ippathid); + printk( "iucv: extern_int_buffer:\n"); + dumpit((char *)&extern_int_buffer[0],40); +#endif + + switch (extern_int_buffer->iptype) + { + case 0x01: /* connection pending ext interrrupt */ +#ifdef DEBUG + printk( "iucv: connection pending IRQ.\n"); +#endif + + rc = iucv_accept(glob_command_buffer, + extern_int_buffer->ippathid); + if (rc != 0) { + printk( "iucv: iucv_accept failed with rc: %X\n",rc); + iucv_retrieve_buffer(glob_command_buffer); + break; + } +#ifdef DEBUG + dumpit(&((char *)extern_int_buffer)[8],8); +#endif + dev = get_device_from_userid(&((char*)extern_int_buffer)[8]); + privptr = (struct iucv_priv *)(dev->priv); + privptr->pathid = extern_int_buffer->ippathid; + +#ifdef DEBUG + printk( "iucv: iucv_accept ended with rc: %X\n",rc); + printk( "iucv: device %s found.\n",dev->name); +#endif + break; + + case 0x02: /* connection completed ext interrrupt */ + /* set own global IP address */ + /* & set global routing addr */ +#ifdef DEBUG + printk( "connection completed.\n"); +#endif + + if( extern_int_buffer->ipmsgtag !=0) + { + /* get ptr's to kernel struct with local & broadcast address */ + dev = get_device_from_pathid(extern_int_buffer->ippathid); + privptr = (struct iucv_priv *)(dev->priv); + indev = dev->ip_ptr; + inaddr = (struct in_ifaddr*) indev->ifa_list; + } + break; + + + case 0x03: /* connection severed ext interrrupt */ + /* we do not handle this one at this time */ +#ifdef DEBUG + printk( "connection severed.\n"); +#endif + break; + + + case 0x04: /* connection quiesced ext interrrupt */ + /* we do not handle this one at this time */ +#ifdef DEBUG + printk( "connection quiesced.\n"); +#endif + break; + + + case 0x05: /* connection resumed ext interrrupt */ + /* we do not handle this one at this time */ +#ifdef DEBUG + printk( "connection resumed.\n"); +#endif + break; + + + case 0x06: /* priority message complete ext interrupt */ + case 0x07: /* non priority message complete ext interrupt */ + /* send it to iucv_rx for handling */ +#ifdef DEBUG + printk( "message completed.\n"); +#endif + + if (extern_int_buffer->ipaudit ==0) /* ok case */ + { +#ifdef DEBUG + printk( "iucv: msg complete interrupt successful, rc: %X\n", + (unsigned int)extern_int_buffer->ipaudit); +#endif + ; + } + else + { + printk( "iucv: msg complete interrupt error, rc: %X\n", + (unsigned int)extern_int_buffer->ipaudit); + } + /* a transmission is over: tell we are no more busy */ + dev = get_device_from_pathid(extern_int_buffer->ippathid); + privptr = (struct iucv_priv *)(dev->priv); + privptr->stats.tx_packets++; + netif_wake_queue(dev); /* transmission is no longer busy*/ + break; + + + case 0x08: /* priority message pending */ + case 0x09: /* non priority message pending */ +#ifdef DEBUG + printk( "message pending.\n"); +#endif + dev = get_device_from_pathid(extern_int_buffer->ippathid); + privptr = (struct iucv_priv *)(dev->priv); + rcvptr = &privptr->receive_buffer[0]; + + /* re-set receive buffer */ + memset(privptr->receive_buffer,0,privptr->receive_buffer_len); + len = privptr->receive_buffer_len; + + /* get data now */ + if (extern_int_buffer->ipflags1 & 0x80) + { /* data is in the message */ +#ifdef DEBUG + printk( "iucv: iucv_receive data is in header!\n"); +#endif + memcpy(privptr->receive_buffer, + (char *)extern_int_buffer->iprmmsg1, + (unsigned long)(extern_int_buffer->iprmmsg2)); + } + else /* data is in buffer, do a receive */ + { + rc = iucv_receive(privptr->command_buffer,rcvptr,len); + if (rc != 0 || len == 0) + { + printk( "iucv: iucv_receive failed with rc: %X, length: %lX\n",rc,len); + iucv_retrieve_buffer(privptr->command_buffer); + break; + } + } /* end else */ + + iucv_next = 0; + /* get next packet offset */ + iucv_data_len= *((unsigned short*)rcvptr); + do{ /* until receive buffer is empty, i.e. iucv_next == 0 ! */ + + /* get data length: */ + iucv_data_len= iucv_data_len - iucv_next; + +#ifdef DEBUG + printk( "iucv: iucv_receive: len is %02X, last: %02X\n", + iucv_data_len,iucv_next); +#endif + /* transmit upstairs */ + iucv_rx(dev,(iucv_data_len),rcvptr); + +#ifdef DEBUG + printk( "iucv: transaction complete now.\n"); +#endif + iucv_next = *((unsigned short*)rcvptr); + rcvptr = rcvptr + iucv_data_len; + /* get next packet offset */ + iucv_data_len= *((unsigned short*)rcvptr); + + } while (iucv_data_len != 0); + netif_start_queue(dev); /* transmission is no longer busy*/ + break; + + default: + printk( "unknown iucv interrupt \n"); + break; + + } /* end switch */ + netif_exit_interrupt(dev); /* release lock*/ + +#ifdef DEBUG + printk( "iucv: leaving do_iucv_interrupt.\n"); +#endif + +} /* end do_iucv_interrupt() */ + + + +/*-------------------------------------------*/ +/* Transmit a packet (low level interface) */ +/*-------------------------------------------*/ +int iucv_hw_tx(char *send_buf, int len,net_device *dev) +{ + /* This function deals with hw details. */ + /* This interface strips off the ethernet header details. */ + /* In other words, this function implements the iucv behaviour,*/ + /* while all other procedures are rather device-independent */ + struct iucv_priv *privptr; + int rc, recv_len=2000; + + privptr = (struct iucv_priv *)(dev->priv); + +#ifdef DEBUG + printk( "iucv: iucv_hw_tx, device %s\n",dev->name); + printk( "iucv: hw_TX_data len: %X\n",len); + dumpit(send_buf,len); +#endif + + /* I am paranoid. Ain't I? */ + if (len < sizeof(struct iphdr)) + { + printk( "iucv: Hmm... packet too short (%i octets)\n",len); + return -EINVAL; + } + + /* + * build IUCV header (preceeding halfword offset) + * works as follows: Each packet is preceded by the + * halfword offset to the next one. + * The last packet is followed by an offset of zero. + * E.g., AL2(12),10-byte packet, AL2(34), 32-byte packet, AL2(0) + */ + + memcpy(&privptr->send_buffer[2],send_buf,len+2); + privptr->send_buffer[len+2] = 0; + privptr->send_buffer[len+3] = 0; + *((unsigned short*) &privptr->send_buffer[0]) = len + 2; + +#ifdef DEBUG + printk( "iucv: iucv_hw_tx, device %s\n",dev->name); + printk( "iucv: send len: %X\n",len+4); + dumpit(privptr->send_buffer,len+4); +#endif + *((unsigned short*) &privptr->send_buffer[0]) = len + 2; + + /* Ok, now the packet is ready for transmission: send it. */ + if ((rc = iucv_send(privptr->command_buffer, + privptr->pathid, + &privptr->send_buffer[0],len+4, + privptr->recv_buf,recv_len))!=0) { + printk( "iucv: send_iucv failed, rc: %X\n",rc); + iucv_retrieve_buffer(privptr->command_buffer); + } +#ifdef DEBUG + printk( "iucv: send_iucv ended, rc: %X\n",rc); +#endif + return rc; +} /* end iucv_hw_tx() */ + + + + + + +/*------------------------------------------*/ +/* Transmit a packet (called by the kernel) */ +/*------------------------------------------*/ +int iucv_tx(struct sk_buff *skb, net_device *dev) +{ + int retval=0; + + struct iucv_priv *privptr; + + if (dev == NULL) + { + printk("iucv: NULL dev passed\n"); + return 0; + } + + privptr = (struct iucv_priv *) (dev->priv); + + if (skb == NULL) + { + printk("iucv: %s: NULL buffer passed\n", dev->name); + privptr->stats.tx_errors++; + return 0; + } + +#ifdef DEBUG + printk( "iucv: enter iucv_tx, using %s\n",dev->name); +#endif + + if (netif_is_busy(dev)) /* shouldn't happen */ + { + privptr->stats.tx_errors++; + dev_kfree_skb(skb); + printk("iucv: %s: transmit access conflict ! leaving iucv_tx.\n", dev->name); + } + + netif_stop_queue(dev); /* transmission is busy*/ + dev->trans_start = jiffies; /* save the timestamp*/ + + /* actual deliver of data is device-specific, and not shown here */ + retval = iucv_hw_tx(skb->data, skb->len, dev); + + dev_kfree_skb(skb); /* release it*/ + +#ifdef DEBUG + printk( "iucv:leaving iucv_tx, device %s\n",dev->name); +#endif + + return retval; /* zero == done; nonzero == fail*/ +} /* end iucv_tx( struct sk_buff *skb, struct device *dev) */ + + + + + + +/*---------------*/ +/* iucv_release */ +/*---------------*/ +int iucv_release(net_device *dev) +{ + int rc =0; + struct iucv_priv *privptr; + privptr = (struct iucv_priv *) (dev->priv); + + netif_stop(dev); + netif_stop_queue(dev); /* can't transmit any more*/ + rc = iucv_sever(privptr->command_buffer); + if (rc!=0) + { + printk("iucv: %s: iucv_release pending...rc:%02x\n",dev->name,rc); + } + +#ifdef DEBUG + printk("iucv: iucv_sever ended with rc: %X\n",rc); +#endif + + return rc; +} /* end iucv_release() */ + + + + + +/*-----------------------------------------------*/ +/* Configuration changes (passed on by ifconfig) */ +/*-----------------------------------------------*/ +int iucv_config(net_device *dev, struct ifmap *map) +{ + if (dev->flags & IFF_UP) /* can't act on a running interface*/ + return -EBUSY; + + /* ignore other fields */ + return 0; +} +/* end iucv_config() */ + + + + + +/*----------------*/ +/* Ioctl commands */ +/*----------------*/ +int iucv_ioctl(net_device *dev, struct ifreq *rq, int cmd) +{ +#ifdef DEBUG + printk( "iucv: device %s; iucv_ioctl\n",dev->name); +#endif + return 0; +} + +/*---------------------------------*/ +/* Return statistics to the caller */ +/*---------------------------------*/ +struct net_device_stats *iucv_stats(net_device *dev) +{ + struct iucv_priv *priv = (struct iucv_priv *)dev->priv; +#ifdef DEBUG + printk( "iucv: device %s; iucv_stats\n",dev->name); +#endif + return &priv->stats; +} + + +/* + * iucv_change_mtu + * IUCV can handle MTU sizes from 576 to approx. 32000 + */ + +static int iucv_change_mtu(net_device *dev, int new_mtu) +{ +#ifdef DEBUG + printk( "iucv: device %s; iucv_change_mtu\n",dev->name); +#endif + if ((new_mtu < 64) || (new_mtu > 32000)) + return -EINVAL; + dev->mtu = new_mtu; + return 0; +} + + + + +/*--------------------------------------------*/ +/* The init function (sometimes called probe).*/ +/* It is invoked by register_netdev() */ +/*--------------------------------------------*/ +int iucv_init(net_device *dev) +{ + int rc; + struct iucv_priv *privptr; + +#ifdef DEBUG + printk( "iucv: iucv_init, device: %s\n",dev->name); +#endif + + dev->open = iucv_open; + dev->stop = iucv_release; + dev->set_config = iucv_config; + dev->hard_start_xmit = iucv_tx; + dev->do_ioctl = iucv_ioctl; + dev->get_stats = iucv_stats; + dev->change_mtu = iucv_change_mtu; + + /* keep the default flags, just add NOARP */ + + dev->hard_header_len = 0; + dev->addr_len = 0; + dev->type = ARPHRD_SLIP; + dev->tx_queue_len = 100; + dev->flags = IFF_NOARP|IFF_POINTOPOINT; + dev->mtu = 4092; + + dev_init_buffers(dev); + + /* Then, allocate the priv field. This encloses the statistics */ + /* and a few private fields.*/ + dev->priv = kmalloc(sizeof(struct iucv_priv), GFP_KERNEL); + if (dev->priv == NULL){ + printk( "iucv: no memory for dev->priv.\n"); + return -ENOMEM; + } + memset(dev->priv, 0, sizeof(struct iucv_priv)); + privptr = (struct iucv_priv *)(dev->priv); + + + privptr->send_buffer = (u8*) __get_free_pages(GFP_KERNEL+GFP_DMA,8); + if (privptr->send_buffer == NULL) { + printk(KERN_INFO "%s: could not get pages for send buffer\n", + dev->name); + return -ENOMEM; + } + memset(privptr->send_buffer, 0, 8*PAGE_SIZE); + privptr->send_buffer_len=8*PAGE_SIZE; + + privptr->receive_buffer = (u8*) __get_free_pages(GFP_KERNEL+GFP_DMA,8); + if (privptr->receive_buffer == NULL) { + printk(KERN_INFO "%s: could not get pages for receive buffer\n", + dev->name); + return -ENOMEM; + } + memset(privptr->receive_buffer, 0, 8*PAGE_SIZE); + privptr->receive_buffer_len=8*PAGE_SIZE; + + /* now use the private fields ... */ + /* init pathid */ + privptr->pathid = -1; + + /* init private userid from global userid */ + memcpy(privptr->userid,iucv_userid[dev-iucv_devs],8); + + + /* we can use only ONE buffer for external interrupt ! */ + rc=iucv_declare_buffer(privptr->command_buffer, + (DCLBFR_T *)iucv_ext_int_buffer); + if (rc!=0 && rc!=19) /* ignore existing buffer */ + { + printk( "iucv:iucv_declare failed, rc: %X\n",rc); + return -ENODEV; + } + + rc = iucv_enable(privptr->command_buffer); + if (rc!=0) + { + printk( "iucv:iucv_enable failed, rc: %x\n",rc); + iucv_retrieve_buffer(privptr->command_buffer); + return -ENODEV; + } +#ifdef DEBUG + printk( "iucv: iucv_init endend OK for device %s.\n",dev->name); +#endif + return 0; +} + + +/* + * setup iucv devices + * + * string passed: iucv=userid1,...,useridn + */ +#if LINUX_VERSION_CODE>=0x020300 +static int __init iucv_setup(char *str) +#else +__initfunc(void iucv_setup(char *str,int *ints)) +#endif +{ + int result=0, i=0,j=0, k=0, device_present=0; + char *s = str; + net_device * dev ={0}; + +#ifdef DEBUG + printk( "iucv: start registering device(s)... \n"); +#endif + + /* + * scan device userids + */ + + while(*s != 0x20 && *s != '\0'){ + if(*s == ','){ + /* fill userid up to 8 chars */ + for(k=i;k<8;k++){ + iucv_userid[j][k] = 0x40; + } /* end for */ + /* new device */ + j++; + s++; /* ignore current char */ + i=0; + if (j>MAX_DEVICES) { + printk("iucv: setup devices: max devices %d reached.\n", + MAX_DEVICES); + break; + } /* end if */ + continue; + } /* end if */ + iucv_ascii_userid[j][i] = (int)*s; + iucv_userid[j][i] = _ascebc[(int)*s++]; + i++; + } /* end while */ + + /* + * fill last userid up to 8 chars + */ + for(k=i;k<8;k++) { + iucv_userid[j][k] = 0x40; + } + + /* + * set device name and register + */ + + for (k=0;k<=j;k++) { + memcpy(iucv_devs[k].name, "iucv0", 4); + dev = &iucv_devs[k]; + dev->name[4] = k + '0'; + +#ifdef DEBUGX + printk("iucv: (ASCII- )Userid:%s\n",&iucv_ascii_userid[k][0]); + printk("iucv: (ASCII-)Userid: "); + for (i=0;i<8;i++) { + printk( "%02X ",(int)iucv_ascii_userid[k][i]); + } + printk("\n"); + printk("iucv: (EBCDIC-)Userid: "); + for (i=0;i<8;i++) { + printk( "%02X ",(int)iucv_userid[k][i]); + } + printk("\n"); + printk("iucv: device name :%s\n",iucv_devs[k].name); +#endif + + if ( (result = register_netdev(iucv_devs + k)) ) + printk("iucv: error %i registering device \"%s\"\n", + result, iucv_devs[k].name); + else + { + device_present++; + } + } /* end for */ + +#ifdef DEBUG + printk( "iucv: end register devices, %d devices present\n",device_present); +#endif + /* return device_present ? 0 : -ENODEV; */ +#if LINUX_VERSION_CODE>=0x020300 + return 1; +#else + return; +#endif +} + +#if LINUX_VERSION_CODE>=0x020300 +__setup("iucv=", iucv_setup); +#endif + + +/*-------------*/ +/* The devices */ +/*-------------*/ +char iucv_names[MAX_DEVICES*8]; /* MAX_DEVICES eight-byte buffers */ +net_device iucv_devs[MAX_DEVICES] = { + { + iucv_names, /* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+8,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+16,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+24,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+32,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+40,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+48,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+56,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+64,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + }, + { + iucv_names+72,/* name -- set at load time */ + 0, 0, 0, 0, /* shmem addresses */ + 0x000, /* ioport */ + 0, /* irq line */ + 0, 0, 0, /* various flags: init to 0 */ + NULL, /* next ptr */ + iucv_init, /* init function, fill other fields with NULL's */ + } +}; + diff --git a/drivers/s390/net/iucv.h b/drivers/s390/net/iucv.h new file mode 100644 index 000000000..7905fb49a --- /dev/null +++ b/drivers/s390/net/iucv.h @@ -0,0 +1,146 @@ +/* + * drivers/s390/net/iucv.h + * Network driver for VM using iucv + * + * S390 version + * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation + * Author(s): Stefan Hegewald <hegewald@de.ibm.com> + * Hartmut Penner <hpenner@de.ibm.com> + */ + +#ifndef _IUCV_H +#define _IUCV_H + + +#define UCHAR unsigned char +#define USHORT unsigned short +#define ULONG unsigned long + +#define DEFAULT_BUFFERSIZE 2048 +#define DEFAULT_FN_LENGTH 27 +#define TRANSFERLENGTH 10 + + + +/* function ID's */ +#define RETRIEVE_BUFFER 2 +#define REPLY 3 +#define SEND 4 +#define RECEIVE 5 +#define ACCEPT 10 +#define CONNECT 11 +#define DECLARE_BUFFER 12 +#define SEVER 15 +#define SETMASK 16 +#define SETCMASK 17 +#define PURGE 9999 + +/* structures */ +typedef struct { + USHORT res0; + UCHAR ipflags1; + UCHAR iprcode; + ULONG res1; + ULONG res2; + ULONG ipbfadr1; + ULONG res[6]; +} DCLBFR_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + USHORT ipmsglim; + USHORT res1; + UCHAR ipvmid[8]; + UCHAR ipuser[16]; + UCHAR iptarget[8]; +} CONNECT_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + USHORT ipmsglim; + USHORT res1; + UCHAR res2[8]; + UCHAR ipuser[16]; + UCHAR res3[8]; +} ACCEPT_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + ULONG ipmsgid; + ULONG iptrgcls; + ULONG ipbfadr1; + ULONG ipbfln1f; + ULONG ipsrccls; + ULONG ipmsgtag; + ULONG ipbfadr2; + ULONG ipbfln2f; + ULONG res; +} SEND_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + ULONG ipmsgid; + ULONG iptrgcls; + ULONG iprmmsg1; + ULONG iprmmsg2; + ULONG res1[2]; + ULONG ipbfadr2; + ULONG ipbfln2f; + ULONG res2; +} REPLY_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + ULONG ipmsgid; + ULONG iptrgcls; + ULONG ipbfadr1; + ULONG ipbfln1f; + ULONG res1[3]; + ULONG ipbfln2f; + ULONG res2; +} RECEIVE_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iprcode; + ULONG res1[3]; + UCHAR ipuser[16]; + ULONG res2[2]; +} SEVER_T; + +typedef struct { + UCHAR ipmask; + UCHAR res1[2]; + UCHAR iprcode; + ULONG res2[9]; +} MASK_T; + +typedef struct { + USHORT ippathid; + UCHAR ipflags1; + UCHAR iptype; + ULONG ipmsgid; + ULONG ipaudit; + ULONG iprmmsg1; + ULONG iprmmsg2; + ULONG ipsrccls; + ULONG ipmsgtag; + ULONG ipbfadr2; + ULONG ipbfln2f; + UCHAR ippollfg; + UCHAR res2[3]; +} INTERRUPT_T; + + +#endif diff --git a/drivers/sound/maestro.c b/drivers/sound/maestro.c index 12da6bbc0..81a7d21d2 100644 --- a/drivers/sound/maestro.c +++ b/drivers/sound/maestro.c @@ -2381,8 +2381,20 @@ static unsigned int ess_poll(struct file *file, struct poll_table_struct *wait) struct ess_state *s = (struct ess_state *)file->private_data; unsigned long flags; unsigned int mask = 0; + int ret; VALIDATE_STATE(s); + +/* In 0.14 prog_dmabuf always returns success anyway ... */ + if (file->f_mode & FMODE_WRITE) { + if (!s->dma_dac.ready && (ret = prog_dmabuf(s, 0))) + return POLLERR; + } + if (file->f_mode & FMODE_READ) { + if (!s->dma_adc.ready && (ret = prog_dmabuf(s, 1))) + return POLLERR; + } + if (file->f_mode & FMODE_WRITE) poll_wait(file, &s->dma_dac.wait, wait); if (file->f_mode & FMODE_READ) diff --git a/drivers/sound/via82cxxx_audio.c b/drivers/sound/via82cxxx_audio.c index 1807e3db6..47bac97d8 100644 --- a/drivers/sound/via82cxxx_audio.c +++ b/drivers/sound/via82cxxx_audio.c @@ -11,7 +11,7 @@ */ -#define VIA_VERSION "1.1.5" +#define VIA_VERSION "1.1.6" #include <linux/config.h> @@ -23,6 +23,7 @@ #include <linux/proc_fs.h> #include <linux/spinlock.h> #include <linux/sound.h> +#include <linux/poll.h> #include <linux/soundcard.h> #include <linux/ac97_codec.h> #include <asm/io.h> @@ -30,8 +31,9 @@ #include <asm/uaccess.h> #include <asm/hardirq.h> -#include "sound_config.h" -#include "soundmodule.h" +/* much better to duplicate this value than include + * drivers/sound/sound_config.h just for this definition */ +#define SND_DEV_DSP16 5 #undef VIA_DEBUG /* define to enable debugging output and checks */ @@ -286,7 +288,6 @@ static int via_dsp_release(struct inode *inode, struct file *file); static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg); static void via_ac97_write_reg (struct ac97_codec *codec, u8 reg, u16 value); static u8 via_ac97_wait_idle (struct via_info *card); -static u32 via_ac97_wait_valid (struct via_info *card); static void via_chan_free (struct via_info *card, struct via_channel *chan); static void via_chan_clear (struct via_channel *chan); @@ -403,11 +404,6 @@ static void via_stop_everything (struct via_info *card) static int via_set_rate (struct via_info *card, unsigned rate, int inhale_deeply) { -#if 0 - unsigned long flags; - u32 status; - u8 status8; -#endif DPRINTK ("ENTER, rate = %d, inhale = %s\n", rate, inhale_deeply ? "yes" : "no"); @@ -415,37 +411,12 @@ static int via_set_rate (struct via_info *card, unsigned rate, int inhale_deeply if (rate > 48000) rate = 48000; if (rate < 4000) rate = 4000; -#if 0 - status8 = via_ac97_wait_idle (card); - if (status8 & VIA_CR83_BUSY) { - DPRINTK ("EXIT, status=0x%X, returning -EIO\n", status); - return -EIO; - } - - if (inhale_deeply) { - card->ch_in.rate = rate; - - spin_lock_irqsave (&card->lock, flags); - outl (VIA_SET_RATE_IN + rate, - card->baseaddr + VIA_BASE0_AC97_CTRL); - spin_unlock_irqrestore (&card->lock, flags); - } else { - card->ch_out.rate = rate; - - spin_lock_irqsave (&card->lock, flags); - outl (VIA_SET_RATE_OUT + rate, - card->baseaddr + VIA_BASE0_AC97_CTRL); - spin_unlock_irqrestore (&card->lock, flags); - } - -#else via_ac97_write_reg (&card->ac97, AC97_POWER_CONTROL, (via_ac97_read_reg (&card->ac97, AC97_POWER_CONTROL) & ~0x0200) | 0x0200); via_ac97_write_reg (&card->ac97, AC97_PCM_FRONT_DAC_RATE, rate); via_ac97_write_reg (&card->ac97, AC97_POWER_CONTROL, via_ac97_read_reg (&card->ac97, AC97_POWER_CONTROL) & ~0x0200); -#endif DPRINTK ("EXIT, returning 0\n"); return rate; @@ -769,38 +740,6 @@ static u8 via_ac97_wait_idle (struct via_info *card) } -static u32 via_ac97_wait_valid (struct via_info *card) -{ - u32 tmp; - int counter = VIA_COUNTER_LIMIT; - - DPRINTK ("ENTER\n"); - - assert (card != NULL); - assert (card->pdev != NULL); - - do { - if (current->need_resched) - schedule (); - - spin_lock_irq (&card->lock); - tmp = inl (card->baseaddr + VIA_BASE0_AC97_CTRL); - spin_unlock_irq (&card->lock); - - udelay (10); - - if (tmp & VIA_CR80_FIRST_CODEC_VALID) { - DPRINTK ("EXIT valid, tmp=0x%X, cnt=%d\n", tmp, counter); - return tmp; - } - } while ((tmp & VIA_CR80_BUSY) && (counter-- > 0)); - - DPRINTK ("EXIT, tmp=0x%X, cnt=%d%s\n", tmp, counter, - counter > 0 ? "" : ", counter limit reached"); - return tmp; -} - - static u16 via_ac97_read_reg (struct ac97_codec *codec, u8 reg) { u32 data; @@ -957,6 +896,7 @@ static struct file_operations via_mixer_fops = { }; +#if 0 /* values reasoned from debugging dumps of via's driver */ static struct { u8 reg; u16 data; @@ -976,6 +916,7 @@ static struct { { 0x2, 0x808 }, { 0x18, 0x808 }, }; +#endif static int __init via_ac97_reset (struct via_info *card) @@ -983,7 +924,6 @@ static int __init via_ac97_reset (struct via_info *card) struct pci_dev *pdev = card->pdev; u8 tmp8; u16 tmp16; - size_t idx; DPRINTK ("ENTER\n"); @@ -1015,8 +955,6 @@ static int __init via_ac97_reset (struct via_info *card) } #endif -#if 1 - /* * reset AC97 controller: enable, disable, enable * pause after each command for good luck @@ -1032,35 +970,6 @@ static int __init via_ac97_reset (struct via_info *card) VIA_CR41_AC97_ENABLE | VIA_CR41_PCM_ENABLE | VIA_CR41_VRA | VIA_CR41_AC97_RESET); udelay (100); -#endif - -#if 0 - /* - * reset AC97 controller - */ - pci_read_config_byte(pdev, 0x08, &tmp8); - if ((tmp8 & 0xff) >= 0x20 ) { - pci_read_config_byte(pdev, 0x42, &tmp8); - pci_write_config_byte(pdev, 0x42,(tmp8 & 0x3f)); - } - udelay (100); - - /* init other mixer defaults */ - for (idx = 0; idx < arraysize(mixer_init_vals); idx++) { - via_ac97_write_reg (&card->ac97, - mixer_init_vals[idx].reg, - mixer_init_vals[idx].data); - udelay (20); - } - - pci_write_config_byte (pdev, 0x41, 0xc0); - udelay (10); - pci_read_config_byte (pdev, 0x41, &tmp8); - udelay (10); - pci_write_config_byte (pdev, 0x41, tmp8 | 0x0f); - udelay (10); - -#endif /* disable legacy stuff */ pci_write_config_byte (pdev, 0x42, 0x00); @@ -1073,16 +982,6 @@ static int __init via_ac97_reset (struct via_info *card) /* disable all codec GPI interrupts */ outl (0, pci_resource_start (pdev, 0) + 0x8C); -#if 0 /* ALSA */ - via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, 0x0009); -#if 0 - via_ac97_write_reg (&card->ac97, AC97_POWER_CONTROL, - via_ac97_read_reg (&card->ac97, AC97_POWER_CONTROL) | 0x0300); -#endif - via_ac97_write_reg (&card->ac97, AC97_EXTENDED_STATUS, - via_ac97_read_reg (&card->ac97, AC97_EXTENDED_STATUS) | 0xe800); -#endif - /* enable variable rate */ tmp16 = via_ac97_read_reg (&card->ac97, 0x2A); via_ac97_write_reg (&card->ac97, 0x2A, tmp16 | 0x01); @@ -1836,24 +1735,24 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file, return -EINVAL; if (val > 0) { rc = 0; - spin_lock_irqsave (&card->lock, flags); + spin_lock_irq (&card->lock); if (rc == 0 && rd) rc = via_chan_set_speed (card, &card->ch_in, val); if (rc == 0 && wr) rc = via_chan_set_speed (card, &card->ch_out, val); - spin_unlock_irqrestore (&card->lock, flags); + spin_unlock_irq (&card->lock); if (rc <= 0) return rc ? rc : -EINVAL; val = rc; } else { - spin_lock_irqsave (&card->lock, flags); + spin_lock_irq (&card->lock); if (rd) val = card->ch_in.rate; else if (wr) val = card->ch_out.rate; else val = 0; - spin_unlock_irqrestore (&card->lock, flags); + spin_unlock_irq (&card->lock); } DPRINTK("SPEED EXIT, returning %d\n", val); return put_user (val, (int *)arg); @@ -1868,18 +1767,16 @@ static int via_dsp_ioctl (struct inode *inode, struct file *file, /* stop recording/playback immediately */ case SNDCTL_DSP_RESET: + spin_lock_irq (&card->lock); if (rd) { - spin_lock_irqsave (&card->lock, flags); via_chan_clear (&card->ch_in); via_chan_pcm_fmt (card, &card->ch_in, 1); - spin_unlock_irqrestore (&card->lock, flags); } if (wr) { - spin_lock_irqsave (&card->lock, flags); via_chan_clear (&card->ch_out); via_chan_pcm_fmt (card, &card->ch_out, 1); - spin_unlock_irqrestore (&card->lock, flags); } + spin_unlock_irq (&card->lock); DPRINTK("RESET EXIT, returning 0\n"); return 0; @@ -2109,7 +2006,6 @@ static int via_info_read_proc (char *page, char **start, off_t off, int len = 0; u8 r40, r41, r42, r44; struct via_info *card = data; - u16 tmp16; DPRINTK ("ENTER\n"); @@ -2306,41 +2202,11 @@ static int __init via_init_one (struct pci_dev *pdev, const struct pci_device_id goto err_out; } -#if 0 - /* chipset init copied from via */ - pci_write_config_byte(pdev, 0x41,(0xc0)); - udelay(10); - pci_read_config_byte(pdev, 0x41, &tmp); - udelay(10); - pci_write_config_byte(pdev, 0x41,(tmp | 0x0f)); - udelay(10); - pci_read_config_byte(pdev, 0x42, &tmp); - udelay(10); - pci_write_config_byte(pdev, 0x42,(tmp | 0x3f)); -#endif - if (pci_enable_device (pdev)) { rc = -EIO; goto err_out_none; } -#if 0 - /* chipset init copied from ALSA */ - pci_write_config_byte(pdev, 0x42, 0); - pci_write_config_byte(pdev, 0x41, 0x40); - udelay(100); - pci_write_config_byte(pdev, 0x41, 0x60); - udelay(10); - pci_write_config_byte(pdev, 0x41, 0xCC); - udelay(10); - - { - u32 data = ((AC97_POWER_CONTROL & 0x7F) << 16) | 0x0000; - udelay(100); - outl (data, pci_resource_start (pdev, 0) + VIA_BASE0_AC97_CTRL); - } -#endif - card = kmalloc (sizeof (*card), GFP_KERNEL); if (!card) { printk (KERN_ERR PFX "out of memory, aborting\n"); diff --git a/drivers/usb/Config.in b/drivers/usb/Config.in index 38efbb118..3b376c365 100644 --- a/drivers/usb/Config.in +++ b/drivers/usb/Config.in @@ -43,7 +43,7 @@ comment 'USB Devices' dep_tristate ' USB Kodak DC-2xx Camera support' CONFIG_USB_DC2XX $CONFIG_USB if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then dep_tristate ' USB Mustek MDC800 Digital Camera support (EXPERIMENTAL)' CONFIG_USB_MDC800 $CONFIG_USB - dep_tristate ' USB Mass Storage support (EXPERIMENTAL)' CONFIG_USB_STORAGE $CONFIG_USB m + dep_tristate ' USB Mass Storage support (EXPERIMENTAL)' CONFIG_USB_STORAGE $CONFIG_USB if [ "$CONFIG_USB_STORAGE" != "n" ]; then bool ' USB Mass Storage verbose debug' CONFIG_USB_STORAGE_DEBUG fi diff --git a/drivers/usb/uhci.c b/drivers/usb/uhci.c index 9ce5c07ec..2eaab47ef 100644 --- a/drivers/usb/uhci.c +++ b/drivers/usb/uhci.c @@ -289,10 +289,10 @@ static void uhci_free_td(struct uhci_td *td) if (!list_empty(&td->list)) dbg("td is still in URB list!"); - kmem_cache_free(uhci_td_cachep, td); - if (td->dev) usb_dec_dev_use(td->dev); + + kmem_cache_free(uhci_td_cachep, td); } static struct uhci_qh *uhci_alloc_qh(struct usb_device *dev) @@ -318,10 +318,10 @@ static struct uhci_qh *uhci_alloc_qh(struct usb_device *dev) static void uhci_free_qh(struct uhci_qh *qh) { - kmem_cache_free(uhci_qh_cachep, qh); - if (qh->dev) usb_dec_dev_use(qh->dev); + + kmem_cache_free(uhci_qh_cachep, qh); } static void uhci_insert_qh(struct uhci *uhci, struct uhci_qh *skelqh, struct uhci_qh *qh) diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 6d4c91409..22ef65c26 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -1,7 +1,7 @@ /* * linux/drivers/video/acornfb.c * - * Copyright (C) 1998,1999 Russell King + * Copyright (C) 1998-2000 Russell King * * Frame buffer code for Acorn platforms * @@ -958,9 +958,6 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) else display = &global_disp; - if (!current_par.allow_modeset && con != -1) - return -EINVAL; - err = acornfb_decode_var(var, con, &visual); if (err) return err; @@ -1088,9 +1085,7 @@ acornfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) outl(control, IOMD_VIDCR); #endif acornfb_update_dma(var); - - if (current_par.allow_modeset) - acornfb_set_timing(var); + acornfb_set_timing(var); if (display->cmap.len) cmap = &display->cmap; @@ -1375,37 +1370,49 @@ acornfb_parse_font(char *opt) static void __init acornfb_parse_mon(char *opt) { + char *p = opt; + current_par.montype = -2; - fb_info.monspecs.hfmin = simple_strtoul(opt, &opt, 0); - if (*opt == '-') - fb_info.monspecs.hfmax = simple_strtoul(opt + 1, &opt, 0); + fb_info.monspecs.hfmin = simple_strtoul(p, &p, 0); + if (*p == '-') + fb_info.monspecs.hfmax = simple_strtoul(p + 1, &p, 0); else fb_info.monspecs.hfmax = fb_info.monspecs.hfmin; - if (*opt != ':') - return; + if (*p != ':') + goto bad; - fb_info.monspecs.vfmin = simple_strtoul(opt + 1, &opt, 0); - if (*opt == '-') - fb_info.monspecs.vfmax = simple_strtoul(opt + 1, &opt, 0); + fb_info.monspecs.vfmin = simple_strtoul(p + 1, &p, 0); + if (*p == '-') + fb_info.monspecs.vfmax = simple_strtoul(p + 1, &p, 0); else fb_info.monspecs.vfmax = fb_info.monspecs.vfmin; - if (*opt != ':') - return; + if (*p != ':') + goto check_values; - fb_info.monspecs.dpms = simple_strtoul(opt + 1, &opt, 0); + fb_info.monspecs.dpms = simple_strtoul(p + 1, &p, 0); - if (*opt != ':') - return; + if (*p != ':') + goto check_values; - init_var.width = simple_strtoul(opt + 1, &opt, 0); + init_var.width = simple_strtoul(p + 1, &p, 0); - if (*opt != ':') - return; + if (*p != ':') + goto check_values; + + init_var.height = simple_strtoul(p + 1, NULL, 0); - init_var.height = simple_strtoul(opt + 1, NULL, 0); +check_values: + if (fb_info.monspecs.hfmax < fb_info.monspecs.hfmin || + fb_info.monspecs.vfmax < fb_info.monspecs.vfmin) + goto bad; + return; + +bad: + printk(KERN_ERR "Acornfb: bad monitor settings: %s\n", opt); + current_par.montype = -1; } static void __init @@ -1574,9 +1581,10 @@ acornfb_init(void) if (current_par.montype == -1 || current_par.montype > NR_MONTYPES) current_par.montype = 4; - if (current_par.montype > 0) + if (current_par.montype > 0) { fb_info.monspecs = monspecs[current_par.montype]; - fb_info.monspecs.dpms = current_par.dpms; + fb_info.monspecs.dpms = current_par.dpms; + } /* * Try to select a suitable default mode @@ -1667,7 +1675,6 @@ acornfb_init(void) current_par.screen_size = size; current_par.palette_size = VIDC_PALETTE_SIZE; - current_par.allow_modeset = 1; /* * Lookup the timing for this resolution. If we can't @@ -1683,13 +1690,6 @@ acornfb_init(void) printk("Acornfb: no valid mode found\n"); } - /* - * Again, if this does not succeed, then we disallow - * changes to the resolution parameters. - */ - if (acornfb_set_var(&init_var, -1, &fb_info)) - current_par.allow_modeset = 0; - h_sync = 1953125000 / init_var.pixclock; h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin + init_var.right_margin + init_var.hsync_len); @@ -1703,6 +1703,15 @@ acornfb_init(void) VIDC_NAME, init_var.xres, init_var.yres, h_sync / 1000, h_sync % 1000, v_sync); + printk(KERN_INFO "Acornfb: Monitor: %d.%03d-%d.%03dkHz, %d-%dHz%s\n", + fb_info.monspecs.hfmin / 1000, fb_info.monspecs.hfmin % 1000, + fb_info.monspecs.hfmax / 1000, fb_info.monspecs.hfmax % 1000, + fb_info.monspecs.vfmin, fb_info.monspecs.vfmax, + fb_info.monspecs.dpms ? ", DPMS" : ""); + + if (acornfb_set_var(&init_var, -1, &fb_info)) + printk(KERN_ERR "Acornfb: unable to set display parameters\n"); + if (register_framebuffer(&fb_info) < 0) return -EINVAL; return 0; diff --git a/drivers/video/acornfb.h b/drivers/video/acornfb.h index fdd7d1b02..aca7eb344 100644 --- a/drivers/video/acornfb.h +++ b/drivers/video/acornfb.h @@ -52,7 +52,6 @@ struct acornfb_par { unsigned int palette_size; signed int montype; signed int currcon; - unsigned int allow_modeset : 1; unsigned int using_vram : 1; unsigned int dpms : 1; diff --git a/drivers/video/cyber2000fb.c b/drivers/video/cyber2000fb.c index d43884936..2e87c79d7 100644 --- a/drivers/video/cyber2000fb.c +++ b/drivers/video/cyber2000fb.c @@ -1,11 +1,19 @@ /* - * linux/drivers/video/cyber2000fb.c + * Linux/drivers/video/cyber2000fb.c * * Copyright (C) 1998-2000 Russell King * - * Integraphics Cyber2000 frame buffer device + * Integraphics CyberPro 2000, 2010 and 5000 frame buffer device * - * Based on cyberfb.c + * Based on cyberfb.c. + * + * Note that we now use the new fbcon fix, var and cmap scheme. We do still + * have to check which console is the currently displayed one however, since + * especially for the colourmap stuff. Once fbcon has been fully migrated, + * we can kill the last 5 references to cfb->currcon. + * + * We also use the new hotplug PCI subsystem. This doesn't work fully in + * the case of multiple CyberPro cards yet however. */ #include <linux/config.h> #include <linux/module.h> @@ -31,34 +39,41 @@ #include <video/fbcon-cfb16.h> #include <video/fbcon-cfb24.h> -#define MMIO_SIZE 0x000c0000 +/* + * Define this if you don't want RGB565, but RGB555 for 16bpp displays. + */ /*#define CFB16_IS_CFB15*/ +/* + * This is the offset of the PCI space in physical memory + */ +#ifdef CONFIG_ARCH_FOOTBRIDGE +#define PCI_PHYS_OFFSET 0x80000000 +#else +#define PCI_PHYS_OFFSET 0x00000000 +#endif + static char *CyberRegs; #include "cyber2000fb.h" -static struct display global_disp; -static struct fb_info fb_info; -static struct cyber2000fb_par current_par; -static struct display_switch *dispsw; -static struct fb_var_screeninfo __initdata init_var = {}; +struct cfb_info { + struct fb_info fb; + struct display_switch *dispsw; + struct pci_dev *dev; + signed int currcon; -#if defined(DEBUG) && defined(CONFIG_DEBUG_LL) -static void debug_printf(char *fmt, ...) -{ - char buffer[128]; - va_list ap; + /* + * Clock divisors + */ + u_int divisors[4]; - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); + struct { + u8 red, green, blue; + } palette[NR_PALETTE]; - printascii(buffer); -} -#else -#define debug_printf(x...) do { } while (0) -#endif + u_char mem_ctl2; +}; /* -------------------- Hardware specific routines ------------------------- */ @@ -67,7 +82,7 @@ static void debug_printf(char *fmt, ...) */ static void cyber2000_accel_wait(void) { - int count = 10000; + int count = 100000; while (cyber2000_inb(CO_REG_CONTROL) & 0x80) { if (!count--) { @@ -75,22 +90,24 @@ static void cyber2000_accel_wait(void) cyber2000_outb(0, CO_REG_CONTROL); return; } - udelay(10); + udelay(1); } } -static void -cyber2000_accel_setup(struct display *p) +static void cyber2000_accel_setup(struct display *p) { - dispsw->setup(p); + struct cfb_info *cfb = (struct cfb_info *)p->fb_info; + + cfb->dispsw->setup(p); } static void cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx, - int height, int width) + int height, int width) { - unsigned long src, dst; - unsigned int fh, fw; + struct fb_var_screeninfo *var = &p->fb_info->var; + u_long src, dst; + u_int fh, fw; int cmd = CO_CMD_L_PATTERN_FGCOL; fw = fontwidth(p); @@ -117,15 +134,15 @@ cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx, cmd |= CO_CMD_L_INC_UP; } - src = sx + sy * p->var.xres_virtual; - dst = dx + dy * p->var.xres_virtual; + src = sx + sy * var->xres_virtual; + dst = dx + dy * var->xres_virtual; cyber2000_accel_wait(); cyber2000_outb(0x00, CO_REG_CONTROL); cyber2000_outb(0x03, CO_REG_FORE_MIX); cyber2000_outw(width, CO_REG_WIDTH); - if (p->var.bits_per_pixel != 24) { + if (var->bits_per_pixel != 24) { cyber2000_outl(dst, CO_REG_DEST_PTR); cyber2000_outl(src, CO_REG_SRC_PTR); } else { @@ -141,16 +158,17 @@ cyber2000_accel_bmove(struct display *p, int sy, int sx, int dy, int dx, static void cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx, - int height, int width) + int height, int width) { - unsigned long dst; - unsigned int fw, fh; + struct fb_var_screeninfo *var = &p->fb_info->var; + u_long dst; + u_int fw, fh; u32 bgx = attr_bgcol_ec(p, conp); fw = fontwidth(p); fh = fontheight(p); - dst = sx * fw + sy * p->var.xres_virtual * fh; + dst = sx * fw + sy * var->xres_virtual * fh; width = width * fw - 1; height = height * fh - 1; @@ -160,7 +178,7 @@ cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx, cyber2000_outw(width, CO_REG_WIDTH); cyber2000_outw(height, CO_REG_HEIGHT); - switch (p->var.bits_per_pixel) { + switch (var->bits_per_pixel) { case 15: case 16: bgx = ((u16 *)p->dispsw_data)[bgx]; @@ -181,31 +199,40 @@ cyber2000_accel_clear(struct vc_data *conp, struct display *p, int sy, int sx, } static void -cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) +cyber2000_accel_putc(struct vc_data *conp, struct display *p, int c, + int yy, int xx) { + struct cfb_info *cfb = (struct cfb_info *)p->fb_info; + cyber2000_accel_wait(); - dispsw->putc(conp, p, c, yy, xx); + cfb->dispsw->putc(conp, p, c, yy, xx); } static void cyber2000_accel_putcs(struct vc_data *conp, struct display *p, - const unsigned short *s, int count, int yy, int xx) + const unsigned short *s, int count, int yy, int xx) { + struct cfb_info *cfb = (struct cfb_info *)p->fb_info; + cyber2000_accel_wait(); - dispsw->putcs(conp, p, s, count, yy, xx); + cfb->dispsw->putcs(conp, p, s, count, yy, xx); } -static void -cyber2000_accel_revc(struct display *p, int xx, int yy) +static void cyber2000_accel_revc(struct display *p, int xx, int yy) { + struct cfb_info *cfb = (struct cfb_info *)p->fb_info; + cyber2000_accel_wait(); - dispsw->revc(p, xx, yy); + cfb->dispsw->revc(p, xx, yy); } static void -cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p, int bottom_only) +cyber2000_accel_clear_margins(struct vc_data *conp, struct display *p, + int bottom_only) { - dispsw->clear_margins(conp, p, bottom_only); + struct cfb_info *cfb = (struct cfb_info *)p->fb_info; + + cfb->dispsw->clear_margins(conp, p, bottom_only); } static struct display_switch fbcon_cyber_accel = { @@ -222,50 +249,26 @@ static struct display_switch fbcon_cyber_accel = { }; /* - * Palette - */ -static int -cyber2000_getcolreg(u_int regno, u_int * red, u_int * green, u_int * blue, - u_int * transp, struct fb_info *fb_info) -{ - int t; - - if (regno >= 256) - return 1; - - t = current_par.palette[regno].red; - *red = t << 10 | t << 4 | t >> 2; - - t = current_par.palette[regno].green; - *green = t << 10 | t << 4 | t >> 2; - - t = current_par.palette[regno].blue; - *blue = t << 10 | t << 4 | t >> 2; - - *transp = 0; - - return 0; -} - -/* * Set a single color register. Return != 0 for invalid regno. */ static int cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *fb_info) + u_int transp, struct fb_info *info) { - if (regno > 255) + struct cfb_info *cfb = (struct cfb_info *)info; + + if (regno >= NR_PALETTE) return 1; red >>= 10; green >>= 10; blue >>= 10; - current_par.palette[regno].red = red; - current_par.palette[regno].green = green; - current_par.palette[regno].blue = blue; + cfb->palette[regno].red = red; + cfb->palette[regno].green = green; + cfb->palette[regno].blue = blue; - switch (fb_display[current_par.currcon].var.bits_per_pixel) { + switch (cfb->fb.var.bits_per_pixel) { #ifdef FBCON_HAS_CFB8 case 8: cyber2000_outb(regno, 0x3c8); @@ -281,21 +284,22 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue, if (regno < 64) { /* write green */ cyber2000_outb(regno << 2, 0x3c8); - cyber2000_outb(current_par.palette[regno >> 1].red, 0x3c9); + cyber2000_outb(cfb->palette[regno >> 1].red, 0x3c9); cyber2000_outb(green, 0x3c9); - cyber2000_outb(current_par.palette[regno >> 1].blue, 0x3c9); + cyber2000_outb(cfb->palette[regno >> 1].blue, 0x3c9); } if (regno < 32) { /* write red,blue */ cyber2000_outb(regno << 3, 0x3c8); cyber2000_outb(red, 0x3c9); - cyber2000_outb(current_par.palette[regno << 1].green, 0x3c9); + cyber2000_outb(cfb->palette[regno << 1].green, 0x3c9); cyber2000_outb(blue, 0x3c9); } if (regno < 16) - current_par.c_table.cfb16[regno] = regno | regno << 5 | regno << 11; + ((u16 *)cfb->fb.pseudo_palette)[regno] = + regno | regno << 5 | regno << 11; break; #endif @@ -307,7 +311,8 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue, cyber2000_outb(blue, 0x3c9); } if (regno < 16) - current_par.c_table.cfb16[regno] = regno | regno << 5 | regno << 10; + ((u16 *)cfb->fb.pseudo_palette)[regno] = + regno | regno << 5 | regno << 10; break; #endif @@ -320,7 +325,8 @@ cyber2000_setcolreg(u_int regno, u_int red, u_int green, u_int blue, cyber2000_outb(blue, 0x3c9); if (regno < 16) - current_par.c_table.cfb24[regno] = regno | regno << 8 | regno << 16; + ((u32 *)cfb->fb.pseudo_palette)[regno] = + regno | regno << 8 | regno << 16; break; #endif @@ -335,24 +341,23 @@ struct par_info { /* * Hardware */ - unsigned char clock_mult; - unsigned char clock_div; - unsigned char visualid; - unsigned char pixformat; - unsigned char crtc_ofl; - unsigned char crtc[19]; - unsigned int width; - unsigned int pitch; - unsigned int fetch; + u_char clock_mult; + u_char clock_div; + u_char visualid; + u_char pixformat; + u_char crtc_ofl; + u_char crtc[19]; + u_int width; + u_int pitch; + u_int fetch; /* * Other */ - unsigned int visual; - unsigned char palette_ctrl; + u_char palette_ctrl; }; -static const char crtc_idx[] = { +static const u_char crtc_idx[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18 @@ -360,12 +365,12 @@ static const char crtc_idx[] = { static void cyber2000fb_set_timing(struct par_info *hw) { - unsigned int i; + u_int i; /* * Blank palette */ - for (i = 0; i < 256; i++) { + for (i = 0; i < NR_PALETTE; i++) { cyber2000_outb(i, 0x3c8); cyber2000_outb(0, 0x3c9); cyber2000_outb(0, 0x3c9); @@ -430,7 +435,8 @@ static void cyber2000fb_set_timing(struct par_info *hw) cyber2000_outb(0xff, 0x3c6); cyber2000_grphw(0x14, hw->fetch); - cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) | ((hw->pitch >> 4) & 0x30)); + cyber2000_grphw(0x15, ((hw->fetch >> 8) & 0x03) | + ((hw->pitch >> 4) & 0x30)); cyber2000_grphw(0x77, hw->visualid); cyber2000_grphw(0x33, 0x0c); @@ -443,9 +449,9 @@ static void cyber2000fb_set_timing(struct par_info *hw) } static inline int -cyber2000fb_update_start(struct fb_var_screeninfo *var) +cyber2000fb_update_start(struct cfb_info *cfb, struct fb_var_screeninfo *var) { - unsigned int base; + u_int base; base = var->yoffset * var->xres_virtual + var->xoffset; @@ -454,9 +460,6 @@ cyber2000fb_update_start(struct fb_var_screeninfo *var) if (base >= 1 << 20) return -EINVAL; - /* - * FIXME: need the upper bits of the start offset - */ cyber2000_grphw(0x10, base >> 16 | 0x10); cyber2000_crtcw(0x0c, base >> 8); cyber2000_crtcw(0x0d, base); @@ -480,60 +483,49 @@ static int cyber2000fb_release(struct fb_info *info, int user) } /* - * Get the Colormap - */ -static int -cyber2000fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, - struct fb_info *info) -{ - int err = 0; - - if (con == current_par.currcon) /* current console? */ - err = fb_get_cmap(cmap, kspc, cyber2000_getcolreg, info); - else if (fb_display[con].cmap.len) /* non default colormap? */ - fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); - else - fb_copy_cmap(fb_default_cmap(1 << fb_display[con].var.bits_per_pixel), - cmap, kspc ? 0 : 2); - return err; -} - - -/* - * Set the Colormap + * Set the Colormap */ static int cyber2000fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) { - struct display *disp = &fb_display[con]; + struct cfb_info *cfb = (struct cfb_info *)info; + struct fb_cmap *dcmap = &fb_display[con].cmap; int err = 0; - if (!disp->cmap.len) { /* no colormap allocated? */ + /* no colormap allocated? */ + if (!dcmap->len) { int size; - if (disp->var.bits_per_pixel == 16) + if (cfb->fb.var.bits_per_pixel == 16) size = 32; else size = 256; - err = fb_alloc_cmap(&disp->cmap, size, 0); + err = fb_alloc_cmap(dcmap, size, 0); } - if (!err) { - if (con == current_par.currcon) /* current console? */ - err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg, - info); - else - fb_copy_cmap(cmap, &disp->cmap, kspc ? 0 : 1); + + /* + * we should be able to remove this test once fbcon has been + * "improved" --rmk + */ + if (!err && con == cfb->currcon) { + err = fb_set_cmap(cmap, kspc, cyber2000_setcolreg, &cfb->fb); + dcmap = &cfb->fb.cmap; } + if (!err) + fb_copy_cmap(cmap, dcmap, kspc ? 0 : 1); + return err; } -static int cyber2000fb_decode_crtc(struct par_info *hw, struct fb_var_screeninfo *var) +static int +cyber2000fb_decode_crtc(struct par_info *hw, struct cfb_info *cfb, + struct fb_var_screeninfo *var) { - unsigned int Htotal, Hblankend, Hsyncend; - unsigned int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend; + u_int Htotal, Hblankend, Hsyncend; + u_int Vtotal, Vdispend, Vblankstart, Vblankend, Vsyncstart, Vsyncend; #define BIT(v,b1,m,b2) (((v >> b1) & m) << b2) hw->crtc[13] = hw->pitch; @@ -541,29 +533,31 @@ static int cyber2000fb_decode_crtc(struct par_info *hw, struct fb_var_screeninfo hw->crtc[14] = 0; hw->crtc[8] = 0; - Htotal = var->xres + var->right_margin + var->hsync_len + var->left_margin; + Htotal = var->xres + var->right_margin + + var->hsync_len + var->left_margin; if (Htotal > 2080) return -EINVAL; - hw->crtc[0] = (Htotal >> 3) - 5; /* Htotal */ - hw->crtc[1] = (var->xres >> 3) - 1; /* Hdispend */ - hw->crtc[2] = var->xres >> 3; /* Hblankstart */ - hw->crtc[4] = (var->xres + var->right_margin) >> 3; /* Hsyncstart */ + hw->crtc[0] = (Htotal >> 3) - 5; + hw->crtc[1] = (var->xres >> 3) - 1; + hw->crtc[2] = var->xres >> 3; + hw->crtc[4] = (var->xres + var->right_margin) >> 3; Hblankend = (Htotal - 4*8) >> 3; - hw->crtc[3] = BIT(Hblankend, 0, 0x1f, 0) | /* Hblankend */ + hw->crtc[3] = BIT(Hblankend, 0, 0x1f, 0) | BIT(1, 0, 0x01, 7); Hsyncend = (var->xres + var->right_margin + var->hsync_len) >> 3; - hw->crtc[5] = BIT(Hsyncend, 0, 0x1f, 0) | /* Hsyncend */ + hw->crtc[5] = BIT(Hsyncend, 0, 0x1f, 0) | BIT(Hblankend, 5, 0x01, 7); Vdispend = var->yres - 1; Vsyncstart = var->yres + var->lower_margin; Vsyncend = var->yres + var->lower_margin + var->vsync_len; - Vtotal = var->yres + var->lower_margin + var->vsync_len + var->upper_margin - 2; + Vtotal = var->yres + var->lower_margin + var->vsync_len + + var->upper_margin - 2; if (Vtotal > 2047) return -EINVAL; @@ -592,7 +586,9 @@ static int cyber2000fb_decode_crtc(struct par_info *hw, struct fb_var_screeninfo hw->crtc[18] = 0xff; /* overflow - graphics reg 0x11 */ -/* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10 4=LINECOMP:10 5-IVIDEO 6=FIXCNT */ + /* 0=VTOTAL:10 1=VDEND:10 2=VRSTART:10 3=VBSTART:10 + * 4=LINECOMP:10 5-IVIDEO 6=FIXCNT + */ hw->crtc_ofl = BIT(Vtotal, 10, 0x01, 0) | BIT(Vdispend, 10, 0x01, 1) | @@ -604,9 +600,8 @@ static int cyber2000fb_decode_crtc(struct par_info *hw, struct fb_var_screeninfo } /* - * The following was discovered by a good monitor, - * bit twiddling, theorising and but mostly luck. - * Strangely, it looks like everyone elses' PLL! + * The following was discovered by a good monitor, bit twiddling, theorising + * and but mostly luck. Strangely, it looks like everyone elses' PLL! * * Clock registers: * fclock = fpll / div2 @@ -620,29 +615,23 @@ static int cyber2000fb_decode_crtc(struct par_info *hw, struct fb_var_screeninfo * (8696ps and 3846ps) */ static int -cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var) +cyber2000fb_decode_clock(struct par_info *hw, struct cfb_info *cfb, + struct fb_var_screeninfo *var) { - static unsigned int divisors_2000[] = { 1, 2, 4, 8 }; - static unsigned int divisors_2010[] = { 1, 2, 4, 6 }; - unsigned long pll_ps = var->pixclock; - unsigned long ref_ps = 69842; - unsigned int *divisors; - int div2, div1, mult; + u_long pll_ps = var->pixclock; + const u_long ref_ps = 69842; + u_int div2, t_div1, best_div1, best_mult; + int best_diff; /* * Step 1: * find div2 such that 115MHz < fpll < 260MHz * and 0 <= div2 < 4 */ - if (current_par.dev_id == PCI_DEVICE_ID_INTERG_2010) - divisors = divisors_2010; - else - divisors = divisors_2000; - for (div2 = 0; div2 < 4; div2++) { - unsigned long new_pll; + u_long new_pll; - new_pll = pll_ps / divisors[div2]; + new_pll = pll_ps / cfb->divisors[div2]; if (8696 > new_pll && new_pll > 3846) { pll_ps = new_pll; break; @@ -652,26 +641,56 @@ cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var) if (div2 == 4) return -EINVAL; -#if 0 +#if 1 /* * Step 2: * Given pll_ps and ref_ps, find: * pll_ps * 0.995 < pll_ps_calc < pll_ps * 1.005 - * where { 0 < div1 < 32, 0 < mult < 256 } - * pll_ps_calc = div1 / (ref_ps * mult) - * - * Note! This just picks any old values at the moment, - * and as such I don't trust it. It certainly doesn't - * come out with the values below, so the PLL may become - * unstable under some circumstances (you don't want an - * FM dot clock) + * where { 1 < best_div1 < 32, 1 < best_mult < 256 } + * pll_ps_calc = best_div1 / (ref_ps * best_mult) */ - for (div1 = 32; div1 > 1; div1 -= 1) { - mult = (ref_ps * div1 + pll_ps / 2) / pll_ps; - if (mult < 256) + best_diff = 0x7fffffff; + best_mult = 32; + best_div1 = 255; + for (t_div1 = 32; t_div1 > 1; t_div1 -= 1) { + u_int rr, t_mult, t_pll_ps; + int diff; + + /* + * Find the multiplier for this divisor + */ + rr = ref_ps * t_div1; + t_mult = (rr + pll_ps / 2) / pll_ps; + + /* + * Is the multiplier within the correct range? + */ + if (t_mult > 256 || t_mult < 2) + continue; + + /* + * Calculate the actual clock period from this multiplier + * and divisor, and estimate the error. + */ + t_pll_ps = (rr + t_mult / 2) / t_mult; + diff = pll_ps - t_pll_ps; + if (diff < 0) + diff = -diff; + + if (diff < best_diff) { + best_diff = diff; + best_mult = t_mult; + best_div1 = t_div1; + } + + /* + * If we hit an exact value, there is no point in continuing. + */ + if (diff == 0) break; } #else + /* Note! This table will be killed shortly. --rmk */ /* * 1600x1200 1280x1024 1152x864 1024x768 800x600 640x480 * 5051 5051 yes 76* @@ -708,66 +727,62 @@ cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var) /* /1 /2 /4 /6 /8 */ /* (2010) (2000) */ if (pll_ps >= 4543 && pll_ps <= 4549) { - mult = 169; /*u220.0 110.0 54.99 36.663 27.497 */ - div1 = 11; /* 4546 9092 18184 27276 36367 */ + best_mult = 169; /*u220.0 110.0 54.99 36.663 27.497 */ + best_div1 = 11; /* 4546 9092 18184 27276 36367 */ } else if (pll_ps >= 4596 && pll_ps <= 4602) { - mult = 243; /* 217.5 108.7 54.36 36.243 27.181 */ - div1 = 16; /* 4599 9197 18395 27592 36789 */ + best_mult = 243; /* 217.5 108.7 54.36 36.243 27.181 */ + best_div1 = 16; /* 4599 9197 18395 27592 36789 */ } else if (pll_ps >= 4627 && pll_ps <= 4633) { - mult = 181; /*u216.0, 108.0, 54.00, 36.000 27.000 */ - div1 = 12; /* 4630 9260 18520 27780 37040 */ + best_mult = 181; /*u216.0, 108.0, 54.00, 36.000 27.000 */ + best_div1 = 12; /* 4630 9260 18520 27780 37040 */ } else if (pll_ps >= 4962 && pll_ps <= 4968) { - mult = 211; /*u201.0, 100.5, 50.25, 33.500 25.125 */ - div1 = 15; /* 4965 9930 19860 29790 39720 */ + best_mult = 211; /*u201.0, 100.5, 50.25, 33.500 25.125 */ + best_div1 = 15; /* 4965 9930 19860 29790 39720 */ } else if (pll_ps >= 5005 && pll_ps <= 5011) { - mult = 251; /* 200.0 99.8 49.92 33.280 24.960 */ - div1 = 18; /* 5008 10016 20032 30048 40064 */ + best_mult = 251; /* 200.0 99.8 49.92 33.280 24.960 */ + best_div1 = 18; /* 5008 10016 20032 30048 40064 */ } else if (pll_ps >= 5047 && pll_ps <= 5053) { - mult = 83; /*u198.0, 99.0, 49.50, 33.000 24.750 */ - div1 = 6; /* 5050 10100 20200 30300 40400 */ + best_mult = 83; /*u198.0, 99.0, 49.50, 33.000 24.750 */ + best_div1 = 6; /* 5050 10100 20200 30300 40400 */ } else if (pll_ps >= 5490 && pll_ps <= 5496) { - mult = 89; /* 182.0 91.0 45.51 30.342 22.756 */ - div1 = 7; /* 5493 10986 21972 32958 43944 */ + best_mult = 89; /* 182.0 91.0 45.51 30.342 22.756 */ + best_div1 = 7; /* 5493 10986 21972 32958 43944 */ } else if (pll_ps >= 5567 && pll_ps <= 5573) { - mult = 163; /*u179.5 89.8 44.88 29.921 22.441 */ - div1 = 13; /* 5570 11140 22281 33421 44562 */ + best_mult = 163; /*u179.5 89.8 44.88 29.921 22.441 */ + best_div1 = 13; /* 5570 11140 22281 33421 44562 */ } else if (pll_ps >= 6246 && pll_ps <= 6252) { - mult = 190; /*u160.0, 80.0, 40.00, 26.671 20.003 */ - div1 = 17; /* 6249 12498 24996 37494 49992 */ + best_mult = 190; /*u160.0, 80.0, 40.00, 26.671 20.003 */ + best_div1 = 17; /* 6249 12498 24996 37494 49992 */ } else if (pll_ps >= 6346 && pll_ps <= 6352) { - mult = 209; /*u158.0, 79.0, 39.50, 26.333 19.750 */ - div1 = 19; /* 6349 12698 25396 38094 50792 */ + best_mult = 209; /*u158.0, 79.0, 39.50, 26.333 19.750 */ + best_div1 = 19; /* 6349 12698 25396 38094 50792 */ } else if (pll_ps >= 6648 && pll_ps <= 6655) { - mult = 210; /*u150.3 75.2 37.58 25.057 18.792 */ - div1 = 20; /* 6652 13303 26606 39909 53213 */ + best_mult = 210; /*u150.3 75.2 37.58 25.057 18.792 */ + best_div1 = 20; /* 6652 13303 26606 39909 53213 */ } else if (pll_ps >= 6943 && pll_ps <= 6949) { - mult = 181; /*u144.0 72.0 36.00 23.996 17.997 */ - div1 = 18; /* 6946 13891 27782 41674 55565 */ + best_mult = 181; /*u144.0 72.0 36.00 23.996 17.997 */ + best_div1 = 18; /* 6946 13891 27782 41674 55565 */ } else if (pll_ps >= 7404 && pll_ps <= 7410) { - mult = 198; /*u134.0 67.5 33.75 22.500 16.875 */ - div1 = 21; /* 7407 14815 29630 44445 59260 */ + best_mult = 198; /*u134.0 67.5 33.75 22.500 16.875 */ + best_div1 = 21; /* 7407 14815 29630 44445 59260 */ } else if (pll_ps >= 7689 && pll_ps <= 7695) { - mult = 227; /*u130.0 65.0 32.50 21.667 16.251 */ - div1 = 25; /* 7692 15384 30768 46152 61536 */ + best_mult = 227; /*u130.0 65.0 32.50 21.667 16.251 */ + best_div1 = 25; /* 7692 15384 30768 46152 61536 */ } else if (pll_ps >= 7808 && pll_ps <= 7814) { - mult = 152; /* 128.0 64.0 32.00 21.337 16.003 */ - div1 = 17; /* 7811 15623 31245 46868 62490 */ + best_mult = 152; /* 128.0 64.0 32.00 21.337 16.003 */ + best_div1 = 17; /* 7811 15623 31245 46868 62490 */ } else if (pll_ps >= 7934 && pll_ps <= 7940) { - mult = 44; /*u126.0 63.0 31.498 20.999 15.749 */ - div1 = 5; /* 7937 15874 31748 47622 63494 */ + best_mult = 44; /*u126.0 63.0 31.498 20.999 15.749 */ + best_div1 = 5; /* 7937 15874 31748 47622 63494 */ } else return -EINVAL; - /* 187 13 -> 4855 */ - /* 181 18 -> 6946 */ - /* 163 13 -> 5570 */ - /* 169 11 -> 4545 */ #endif /* * Step 3: * combine values */ - hw->clock_mult = mult - 1; - hw->clock_div = div2 << 6 | (div1 - 1); + hw->clock_mult = best_mult - 1; + hw->clock_div = div2 << 6 | (best_div1 - 1); return 0; } @@ -778,27 +793,16 @@ cyber2000fb_decode_clock(struct par_info *hw, struct fb_var_screeninfo *var) * CRTC registers, and accelerator settings. */ static int -cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, struct par_info *hw) +cyber2000fb_decode_var(struct fb_var_screeninfo *var, struct cfb_info *cfb, + struct par_info *hw) { int err; hw->width = var->xres_virtual; - var->red.msb_right = 0; - var->green.msb_right = 0; - var->blue.msb_right = 0; - switch (var->bits_per_pixel) { #ifdef FBCON_HAS_CFB8 case 8: /* PSEUDOCOLOUR, 256 */ - var->bits_per_pixel = 8; - var->red.offset = 0; - var->red.length = 8; - var->green.offset = 0; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - hw->visual = FB_VISUAL_PSEUDOCOLOR; hw->pixformat = PIXFORMAT_8BPP; hw->visualid = VISUALID_256; hw->pitch = hw->width >> 3; @@ -808,14 +812,6 @@ cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, struct par_info * #ifdef FBCON_HAS_CFB16 case 16:/* DIRECTCOLOUR, 64k */ #ifndef CFB16_IS_CFB15 - var->bits_per_pixel = 16; - var->red.offset = 11; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 6; - var->blue.offset = 0; - var->blue.length = 5; - hw->visual = FB_VISUAL_DIRECTCOLOR; hw->pixformat = PIXFORMAT_16BPP; hw->visualid = VISUALID_64K; hw->pitch = hw->width >> 2; @@ -823,14 +819,6 @@ cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, struct par_info * break; #endif case 15:/* DIRECTCOLOUR, 32k */ - var->bits_per_pixel = 15; - var->red.offset = 10; - var->red.length = 5; - var->green.offset = 5; - var->green.length = 5; - var->blue.offset = 0; - var->blue.length = 5; - hw->visual = FB_VISUAL_DIRECTCOLOR; hw->pixformat = PIXFORMAT_16BPP; hw->visualid = VISUALID_32K; hw->pitch = hw->width >> 2; @@ -840,14 +828,6 @@ cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, struct par_info * #endif #ifdef FBCON_HAS_CFB24 case 24:/* TRUECOLOUR, 16m */ - var->bits_per_pixel = 24; - var->red.offset = 16; - var->red.length = 8; - var->green.offset = 8; - var->green.length = 8; - var->blue.offset = 0; - var->blue.length = 8; - hw->visual = FB_VISUAL_TRUECOLOR; hw->pixformat = PIXFORMAT_24BPP; hw->visualid = VISUALID_16M; hw->width *= 3; @@ -859,29 +839,17 @@ cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, struct par_info * return -EINVAL; } - err = cyber2000fb_decode_clock(hw, var); + err = cyber2000fb_decode_clock(hw, cfb, var); if (err) return err; - err = cyber2000fb_decode_crtc(hw, var); + err = cyber2000fb_decode_crtc(hw, cfb, var); if (err) return err; - debug_printf("Clock: %02X %02X\n", - hw->clock_mult, hw->clock_div); - { - int i; - - for (i = 0; i < 19; i++) - debug_printf("%2d ", i); - debug_printf("\n"); - for (i = 0; i < 18; i++) - debug_printf("%02X ", hw->crtc[i]); - debug_printf("%02X\n", hw->crtc_ofl); - } hw->width -= 1; hw->fetch = hw->pitch; - if (current_par.bus_64bit == 0) + if (!(cfb->mem_ctl2 & MEM_CTL2_64BIT)) hw->fetch <<= 1; hw->fetch += 1; @@ -889,173 +857,170 @@ cyber2000fb_decode_var(struct fb_var_screeninfo *var, int con, struct par_info * } /* - * Get the Fixed Part of the Display - */ -static int -cyber2000fb_get_fix(struct fb_fix_screeninfo *fix, int con, - struct fb_info *fb_info) -{ - struct display *display; - - memset(fix, 0, sizeof(struct fb_fix_screeninfo)); - strcpy(fix->id, current_par.dev_name); - - if (con >= 0) - display = fb_display + con; - else - display = &global_disp; - - fix->smem_start = current_par.screen_base_p; - fix->smem_len = current_par.screen_size; - fix->mmio_start = current_par.regs_base_p; - fix->mmio_len = MMIO_SIZE; - fix->type = display->type; - fix->type_aux = display->type_aux; - fix->xpanstep = 0; - fix->ypanstep = display->ypanstep; - fix->ywrapstep = display->ywrapstep; - fix->visual = display->visual; - fix->line_length = display->line_length; - fix->accel = 22; /*FB_ACCEL_IGS_CYBER2000*/ - - return 0; -} - - -/* - * Get the User Defined Part of the Display - */ -static int -cyber2000fb_get_var(struct fb_var_screeninfo *var, int con, - struct fb_info *fb_info) -{ - if (con == -1) - *var = global_disp.var; - else - *var = fb_display[con].var; - - return 0; -} - -/* * Set the User Defined Part of the Display */ static int -cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { + struct cfb_info *cfb = (struct cfb_info *)info; struct display *display; struct par_info hw; int err, chgvar = 0; - if (con >= 0) - display = fb_display + con; - else - display = &global_disp; + /* + * CONUPDATE and SMOOTH_XPAN are equal. However, + * SMOOTH_XPAN is only used internally by fbcon. + */ + if (var->vmode & FB_VMODE_CONUPDATE) { + var->vmode |= FB_VMODE_YWRAP; + var->xoffset = cfb->fb.var.xoffset; + var->yoffset = cfb->fb.var.yoffset; + } - err = cyber2000fb_decode_var(var, con, &hw); + err = cyber2000fb_decode_var(var, (struct cfb_info *)info, &hw); if (err) return err; - switch (var->activate & FB_ACTIVATE_MASK) { - case FB_ACTIVATE_TEST: + if (var->activate & FB_ACTIVATE_TEST) return 0; - case FB_ACTIVATE_NXTOPEN: - case FB_ACTIVATE_NOW: - break; - - default: + if ((var->activate & FB_ACTIVATE_MASK) != FB_ACTIVATE_NOW) return -EINVAL; - } - if (con >= 0) { - if (display->var.xres != var->xres) - chgvar = 1; - if (display->var.yres != var->yres) - chgvar = 1; - if (display->var.xres_virtual != var->xres_virtual) - chgvar = 1; - if (display->var.yres_virtual != var->yres_virtual) - chgvar = 1; - if (display->var.accel_flags != var->accel_flags) - chgvar = 1; - if (memcmp(&display->var.red, &var->red, sizeof(var->red))) - chgvar = 1; - if (memcmp(&display->var.green, &var->green, sizeof(var->green))) - chgvar = 1; - if (memcmp(&display->var.blue, &var->blue, sizeof(var->green))) - chgvar = 1; + if (cfb->fb.var.xres != var->xres) + chgvar = 1; + if (cfb->fb.var.yres != var->yres) + chgvar = 1; + if (cfb->fb.var.xres_virtual != var->xres_virtual) + chgvar = 1; + if (cfb->fb.var.yres_virtual != var->yres_virtual) + chgvar = 1; + if (cfb->fb.var.bits_per_pixel != var->bits_per_pixel) + chgvar = 1; + + if (con < 0) { + display = cfb->fb.disp; + chgvar = 0; + } else { + display = fb_display + con; } - display->var = *var; - display->var.activate &= ~FB_ACTIVATE_ALL; - - if (var->activate & FB_ACTIVATE_ALL) - global_disp.var = display->var; - - display->screen_base = current_par.screen_base; - display->visual = hw.visual; - display->type = FB_TYPE_PACKED_PIXELS; - display->type_aux = 0; - display->ypanstep = 1; - display->ywrapstep = 0; - display->can_soft_blank = 1; - display->inverse = 0; + var->red.msb_right = 0; + var->green.msb_right = 0; + var->blue.msb_right = 0; - switch (display->var.bits_per_pixel) { + switch (var->bits_per_pixel) { #ifdef FBCON_HAS_CFB8 - case 8: - dispsw = &fbcon_cfb8; - display->dispsw_data = NULL; - display->next_line = var->xres_virtual; + case 8: /* PSEUDOCOLOUR, 256 */ + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 0; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + + cfb->fb.fix.visual = FB_VISUAL_PSEUDOCOLOR; + cfb->dispsw = &fbcon_cfb8; + display->dispsw_data = NULL; + display->next_line = var->xres_virtual; break; #endif #ifdef FBCON_HAS_CFB16 - case 15: - case 16: - dispsw = &fbcon_cfb16; - display->dispsw_data = current_par.c_table.cfb16; - display->next_line = var->xres_virtual * 2; + case 16:/* DIRECTCOLOUR, 64k */ +#ifndef CFB16_IS_CFB15 + var->bits_per_pixel = 15; + var->red.offset = 11; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 6; + var->blue.offset = 0; + var->blue.length = 5; + + cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; + cfb->dispsw = &fbcon_cfb16; + display->dispsw_data = cfb->fb.pseudo_palette; + display->next_line = var->xres_virtual * 2; + break; +#endif + case 15:/* DIRECTCOLOUR, 32k */ + var->bits_per_pixel = 15; + var->red.offset = 10; + var->red.length = 5; + var->green.offset = 5; + var->green.length = 5; + var->blue.offset = 0; + var->blue.length = 5; + + cfb->fb.fix.visual = FB_VISUAL_DIRECTCOLOR; + cfb->dispsw = &fbcon_cfb16; + display->dispsw_data = cfb->fb.pseudo_palette; + display->next_line = var->xres_virtual * 2; break; #endif #ifdef FBCON_HAS_CFB24 - case 24: - dispsw = &fbcon_cfb24; - display->dispsw_data = current_par.c_table.cfb24; - display->next_line = var->xres_virtual * 3; + case 24:/* TRUECOLOUR, 16m */ + var->red.offset = 16; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 0; + var->blue.length = 8; + + cfb->fb.fix.visual = FB_VISUAL_TRUECOLOR; + cfb->dispsw = &fbcon_cfb24; + display->dispsw_data = cfb->fb.pseudo_palette; + display->next_line = var->xres_virtual * 3; break; #endif - default: + default:/* in theory this should never happen */ printk(KERN_WARNING "%s: no support for %dbpp\n", - current_par.dev_name, display->var.bits_per_pixel); - dispsw = &fbcon_dummy; + cfb->fb.fix.id, var->bits_per_pixel); + cfb->dispsw = &fbcon_dummy; break; } - display->line_length = display->next_line; - - if (display->var.accel_flags & FB_ACCELF_TEXT && - dispsw != &fbcon_dummy) + if (var->accel_flags & FB_ACCELF_TEXT && cfb->dispsw != &fbcon_dummy) display->dispsw = &fbcon_cyber_accel; else - display->dispsw = dispsw; + display->dispsw = cfb->dispsw; + + cfb->fb.fix.line_length = display->next_line; + + display->screen_base = cfb->fb.screen_base; + display->line_length = cfb->fb.fix.line_length; + display->visual = cfb->fb.fix.visual; + display->type = cfb->fb.fix.type; + display->type_aux = cfb->fb.fix.type_aux; + display->ypanstep = cfb->fb.fix.ypanstep; + display->ywrapstep = cfb->fb.fix.ywrapstep; + display->can_soft_blank = 1; + display->inverse = 0; + + cfb->fb.var = *var; + cfb->fb.var.activate &= ~FB_ACTIVATE_ALL; - if (chgvar && info && info->changevar) - info->changevar(con); + /* + * Update the old var. The fbcon drivers still use this. + * Once they are using cfb->fb.var, this can be dropped. + * --rmk + */ + display->var = cfb->fb.var; - if (con == current_par.currcon) { - struct fb_cmap *cmap; + /* + * If we are setting all the virtual consoles, also set the + * defaults used to create new consoles. + */ + if (var->activate & FB_ACTIVATE_ALL) + cfb->fb.disp->var = cfb->fb.var; - cyber2000fb_update_start(var); - cyber2000fb_set_timing(&hw); + if (chgvar && info && cfb->fb.changevar) + cfb->fb.changevar(con); - if (display->cmap.len) - cmap = &display->cmap; - else - cmap = fb_default_cmap(current_par.palette_size); + cyber2000fb_update_start(cfb, var); + cyber2000fb_set_timing(&hw); + fb_set_cmap(&cfb->fb.cmap, 1, cyber2000_setcolreg, &cfb->fb); - fb_set_cmap(cmap, 1, cyber2000_setcolreg, info); - } return 0; } @@ -1063,9 +1028,11 @@ cyber2000fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info /* * Pan or Wrap the Display */ -static int cyber2000fb_pan_display(struct fb_var_screeninfo *var, int con, - struct fb_info *info) +static int +cyber2000fb_pan_display(struct fb_var_screeninfo *var, int con, + struct fb_info *info) { + struct cfb_info *cfb = (struct cfb_info *)info; u_int y_bottom; y_bottom = var->yoffset; @@ -1075,25 +1042,27 @@ static int cyber2000fb_pan_display(struct fb_var_screeninfo *var, int con, if (var->xoffset > (var->xres_virtual - var->xres)) return -EINVAL; - if (y_bottom > fb_display[con].var.yres_virtual) + if (y_bottom > cfb->fb.var.yres_virtual) return -EINVAL; - if (cyber2000fb_update_start(var)) + if (cyber2000fb_update_start(cfb, var)) return -EINVAL; - fb_display[con].var.xoffset = var->xoffset; - fb_display[con].var.yoffset = var->yoffset; - if (var->vmode & FB_VMODE_YWRAP) - fb_display[con].var.vmode |= FB_VMODE_YWRAP; - else - fb_display[con].var.vmode &= ~FB_VMODE_YWRAP; + cfb->fb.var.xoffset = var->xoffset; + cfb->fb.var.yoffset = var->yoffset; + if (var->vmode & FB_VMODE_YWRAP) { + cfb->fb.var.vmode |= FB_VMODE_YWRAP; + } else { + cfb->fb.var.vmode &= ~FB_VMODE_YWRAP; + } return 0; } -static int cyber2000fb_ioctl(struct inode *inode, struct file *file, - u_int cmd, u_long arg, int con, struct fb_info *info) +static int +cyber2000fb_ioctl(struct inode *inode, struct file *file, u_int cmd, + u_long arg, int con, struct fb_info *info) { return -EINVAL; } @@ -1105,34 +1074,53 @@ static int cyber2000fb_ioctl(struct inode *inode, struct file *file, * This call looks only at yoffset and the FB_VMODE_YWRAP flag in `var'. * Since it's called by a kernel driver, no range checking is done. */ -static int -cyber2000fb_updatevar(int con, struct fb_info *info) +static int cyber2000fb_updatevar(int con, struct fb_info *info) { - int ret = 0; - - if (con == current_par.currcon) - ret = cyber2000fb_update_start(&fb_display[con].var); + struct cfb_info *cfb = (struct cfb_info *)info; - return ret; + return cyber2000fb_update_start(cfb, &fb_display[con].var); } -static int -cyber2000fb_switch(int con, struct fb_info *info) +static int cyber2000fb_switch(int con, struct fb_info *info) { + struct cfb_info *cfb = (struct cfb_info *)info; + struct display *disp; struct fb_cmap *cmap; - if (current_par.currcon >= 0) { - cmap = &fb_display[current_par.currcon].cmap; + if (cfb->currcon >= 0) { + disp = fb_display + cfb->currcon; - if (cmap->len) - fb_get_cmap(cmap, 1, cyber2000_getcolreg, info); + /* + * Save the old colormap and video mode. + */ + disp->var = cfb->fb.var; + if (disp->cmap.len) + fb_copy_cmap(&cfb->fb.cmap, &disp->cmap, 0); } - current_par.currcon = con; + cfb->currcon = con; + disp = fb_display + con; + + /* + * Install the new colormap and change the video mode. By default, + * fbcon sets all the colormaps and video modes to the default + * values at bootup. + * + * Really, we want to set the colourmap size depending on the + * depth of the new video mode. For now, we leave it at its + * default 256 entry. + */ + if (disp->cmap.len) + cmap = &disp->cmap; + else + cmap = fb_default_cmap(1 << disp->var.bits_per_pixel); + + fb_copy_cmap(cmap, &cfb->fb.cmap, 0); - fb_display[con].var.activate = FB_ACTIVATE_NOW; + cfb->fb.var = disp->var; + cfb->fb.var.activate = FB_ACTIVATE_NOW; - cyber2000fb_set_var(&fb_display[con].var, con, info); + cyber2000fb_set_var(&cfb->fb.var, con, &cfb->fb); return 0; } @@ -1140,38 +1128,69 @@ cyber2000fb_switch(int con, struct fb_info *info) /* * (Un)Blank the display. */ -static void cyber2000fb_blank(int blank, struct fb_info *fb_info) +static void cyber2000fb_blank(int blank, struct fb_info *info) { + struct cfb_info *cfb = (struct cfb_info *)info; int i; if (blank) { - for (i = 0; i < 256; i++) { + for (i = 0; i < NR_PALETTE; i++) { cyber2000_outb(i, 0x3c8); cyber2000_outb(0, 0x3c9); cyber2000_outb(0, 0x3c9); cyber2000_outb(0, 0x3c9); } } else { - for (i = 0; i < 256; i++) { + for (i = 0; i < NR_PALETTE; i++) { cyber2000_outb(i, 0x3c8); - cyber2000_outb(current_par.palette[i].red, 0x3c9); - cyber2000_outb(current_par.palette[i].green, 0x3c9); - cyber2000_outb(current_par.palette[i].blue, 0x3c9); + cyber2000_outb(cfb->palette[i].red, 0x3c9); + cyber2000_outb(cfb->palette[i].green, 0x3c9); + cyber2000_outb(cfb->palette[i].blue, 0x3c9); } } } +/* + * Get the currently displayed virtual consoles colormap. + */ +static int +gen_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info) +{ + fb_copy_cmap(&info->cmap, cmap, kspc ? 0 : 2); + return 0; +} + +/* + * Get the currently displayed virtual consoles fixed part of the display. + */ +static int +gen_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info) +{ + *fix = info->fix; + return 0; +} + +/* + * Get the current user defined part of the display. + */ +static int +gen_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info) +{ + *var = info->var; + return 0; +} + static struct fb_ops cyber2000fb_ops = { - cyber2000fb_open, - cyber2000fb_release, - cyber2000fb_get_fix, - cyber2000fb_get_var, - cyber2000fb_set_var, - cyber2000fb_get_cmap, - cyber2000fb_set_cmap, - cyber2000fb_pan_display, - cyber2000fb_ioctl + fb_open: cyber2000fb_open, + fb_release: cyber2000fb_release, + fb_set_var: cyber2000fb_set_var, + fb_set_cmap: cyber2000fb_set_cmap, + fb_pan_display: cyber2000fb_pan_display, + fb_ioctl: cyber2000fb_ioctl, + fb_get_fix: gen_get_fix, + fb_get_var: gen_get_var, + fb_get_cmap: gen_get_cmap, }; /* @@ -1199,24 +1218,31 @@ static void cyber2000fb_disable_extregs(void) } /* + * This is the only "static" reference to the internal data structures + * of this driver. It is here solely at the moment to support the other + * CyberPro modules external to this driver. + */ +static struct cfb_info *int_cfb_info; + +/* * Attach a capture/tv driver to the core CyberX0X0 driver. */ int cyber2000fb_attach(struct cyberpro_info *info) { - if (current_par.initialised) { - info->dev = current_par.dev; + if (int_cfb_info != NULL) { + info->dev = int_cfb_info->dev; info->regs = CyberRegs; - info->fb = current_par.screen_base; - info->fb_size = current_par.screen_size; + info->fb = int_cfb_info->fb.screen_base; + info->fb_size = int_cfb_info->fb.fix.smem_len; info->enable_extregs = cyber2000fb_enable_extregs; info->disable_extregs = cyber2000fb_disable_extregs; - strncpy(info->dev_name, current_par.dev_name, sizeof(info->dev_name)); + strncpy(info->dev_name, int_cfb_info->fb.fix.id, sizeof(info->dev_name)); MOD_INC_USE_COUNT; } - return current_par.initialised; + return int_cfb_info != NULL; } /* @@ -1234,9 +1260,7 @@ EXPORT_SYMBOL(cyber2000fb_detach); * These parameters give * 640x480, hsync 31.5kHz, vsync 60Hz */ -static struct fb_videomode __initdata -cyber2000fb_default_mode = { - name: NULL, +static struct fb_videomode __devinitdata cyber2000fb_default_mode = { refresh: 60, xres: 640, yres: 480, @@ -1251,336 +1275,364 @@ cyber2000fb_default_mode = { vmode: FB_VMODE_NONINTERLACED }; -static void __init -cyber2000fb_init_fbinfo(void) +int __init cyber2000fb_setup(char *options) { - static int first = 1; + return 0; +} - if (!first) - return; - first = 0; +static char igs_regs[] __devinitdata = { + 0x10, 0x10, 0x12, 0x00, 0x13, 0x00, + 0x31, 0x00, 0x32, 0x00, 0x33, 0x01, + 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, + 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01, + 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, + 0x70, 0x0b, 0x73, 0x30, + 0x74, 0x0b, 0x75, 0x17, 0x76, 0x00, 0x7a, 0xc8 +}; - strcpy(fb_info.modename, "Cyber2000"); - strcpy(fb_info.fontname, "Acorn8x8"); +static inline void cyberpro_init_hw(struct cfb_info *cfb) +{ + int i; - fb_info.node = -1; - fb_info.fbops = &cyber2000fb_ops; - fb_info.disp = &global_disp; - fb_info.changevar = NULL; - fb_info.switch_con = cyber2000fb_switch; - fb_info.updatevar = cyber2000fb_updatevar; - fb_info.blank = cyber2000fb_blank; - fb_info.flags = FBINFO_FLAG_DEFAULT; + /* + * Wake up the CyberPro + */ + cyber2000_outb(0x18, 0x46e8); + cyber2000_outb(0x01, 0x102); + cyber2000_outb(0x08, 0x46e8); /* - * setup initial parameters + * Initialise the CyberPro */ - memset(&init_var, 0, sizeof(init_var)); + for (i = 0; i < sizeof(igs_regs); i += 2) + cyber2000_grphw(igs_regs[i], igs_regs[i+1]); +} - init_var.red.msb_right = 0; - init_var.green.msb_right = 0; - init_var.blue.msb_right = 0; +static struct cfb_info * __devinit +cyberpro_alloc_fb_info(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct cfb_info *cfb; - switch(init_var.bits_per_pixel) { - default: - init_var.bits_per_pixel = 8; - case 8: /* PSEUDOCOLOUR */ - init_var.bits_per_pixel = 8; - init_var.red.offset = 0; - init_var.red.length = 8; - init_var.green.offset = 0; - init_var.green.length = 8; - init_var.blue.offset = 0; - init_var.blue.length = 8; - break; + cfb = kmalloc(sizeof(struct cfb_info) + sizeof(struct display) + + sizeof(u32) * 16, GFP_KERNEL); - case 15: /* RGB555 */ - init_var.bits_per_pixel = 15; - init_var.red.offset = 10; - init_var.red.length = 5; - init_var.green.offset = 5; - init_var.green.length = 5; - init_var.blue.offset = 0; - init_var.blue.length = 5; - break; + if (!cfb) + return NULL; - case 16: /* RGB565 */ - init_var.bits_per_pixel = 16; - init_var.red.offset = 11; - init_var.red.length = 5; - init_var.green.offset = 5; - init_var.green.length = 6; - init_var.blue.offset = 0; - init_var.blue.length = 5; - break; + memset(cfb, 0, sizeof(struct cfb_info) + sizeof(struct display)); - case 24: /* RGB888 */ - init_var.bits_per_pixel = 24; - init_var.red.offset = 16; - init_var.red.length = 8; - init_var.green.offset = 8; - init_var.green.length = 8; - init_var.blue.offset = 0; - init_var.blue.length = 8; - break; - } + cfb->currcon = -1; + cfb->dev = dev; + cfb->divisors[0] = 1; + cfb->divisors[1] = 2; + cfb->divisors[2] = 4; - init_var.nonstd = 0; - init_var.activate = FB_ACTIVATE_NOW; - init_var.height = -1; - init_var.width = -1; - init_var.accel_flags = FB_ACCELF_TEXT; + if (id->driver_data == FB_ACCEL_IGS_CYBER2010) + cfb->divisors[3] = 6; + else + cfb->divisors[3] = 8; + + sprintf(cfb->fb.fix.id, "CyberPro%4X", id->device); + + cfb->fb.fix.type = FB_TYPE_PACKED_PIXELS; + cfb->fb.fix.type_aux = 0; + cfb->fb.fix.xpanstep = 0; + cfb->fb.fix.ypanstep = 1; + cfb->fb.fix.ywrapstep = 0; + cfb->fb.fix.accel = id->driver_data; + + cfb->fb.var.nonstd = 0; + cfb->fb.var.activate = FB_ACTIVATE_NOW; + cfb->fb.var.height = -1; + cfb->fb.var.width = -1; + cfb->fb.var.accel_flags = FB_ACCELF_TEXT; + + strcpy(cfb->fb.modename, cfb->fb.fix.id); + strcpy(cfb->fb.fontname, "Acorn8x8"); + + cfb->fb.fbops = &cyber2000fb_ops; + cfb->fb.changevar = NULL; + cfb->fb.switch_con = cyber2000fb_switch; + cfb->fb.updatevar = cyber2000fb_updatevar; + cfb->fb.blank = cyber2000fb_blank; + cfb->fb.flags = FBINFO_FLAG_DEFAULT; + cfb->fb.disp = (struct display *)(cfb + 1); + cfb->fb.pseudo_palette = (void *)(cfb->fb.disp + 1); + + fb_alloc_cmap(&cfb->fb.cmap, NR_PALETTE, 0); + + return cfb; } -/* - * Cyber2000 options: - * - * font:fontname - * Set the fontname - * - * res:XxY - * Set the default display resolution - */ -static void __init -cyber2000fb_parse_font(char *opt) +static void __devinit +cyberpro_free_fb_info(struct cfb_info *cfb) { - strcpy(fb_info.fontname, opt); -} + if (cfb) { + /* + * Free the colourmap + */ + fb_alloc_cmap(&cfb->fb.cmap, 0, 0); -static struct options { - char *name; - void (*parse)(char *opt); -} opt_table[] __initdata = { - { "font", cyber2000fb_parse_font }, - { NULL, NULL } -}; + kfree(cfb); + } +} -int __init -cyber2000fb_setup(char *options) +/* + * Map in the registers + */ +static int __devinit +cyberpro_map_mmio(struct cfb_info *cfb, struct pci_dev *dev) { - struct options *optp; - char *opt; + u_long mmio_base; - if (!options || !*options) - return 0; + mmio_base = pci_resource_start(dev, 0) + MMIO_OFFSET; - cyber2000fb_init_fbinfo(); + cfb->fb.fix.mmio_start = mmio_base + PCI_PHYS_OFFSET; + cfb->fb.fix.mmio_len = MMIO_SIZE; - for (opt = strtok(options, ","); opt; opt = strtok(NULL, ",")) { - if (!*opt) - continue; - - for (optp = opt_table; optp->name; optp++) { - int optlen; - - optlen = strlen(optp->name); - - if (strncmp(opt, optp->name, optlen) == 0 && - opt[optlen] == ':') { - optp->parse(opt + optlen + 1); - break; - } - } + if (!request_mem_region(mmio_base, MMIO_SIZE, "memory mapped I/O")) { + printk("%s: memory mapped IO in use\n", cfb->fb.fix.id); + return -EBUSY; + } - if (!optp->name) - printk(KERN_ERR "CyberPro20x0: unknown parameter: %s\n", - opt); + CyberRegs = ioremap(mmio_base, MMIO_SIZE); + if (!CyberRegs) { + printk("%s: unable to map memory mapped IO\n", + cfb->fb.fix.id); + return -ENOMEM; } return 0; } -static char igs_regs[] __initdata = { - 0x10, 0x10, 0x12, 0x00, 0x13, 0x00, - 0x31, 0x00, 0x32, 0x00, 0x33, 0x01, - 0x50, 0x00, 0x51, 0x00, 0x52, 0x00, 0x53, 0x00, - 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57, 0x01, - 0x58, 0x00, 0x59, 0x00, 0x5a, 0x00, - 0x70, 0x0b, 0x73, 0x30, - 0x74, 0x0b, 0x75, 0x17, 0x76, 0x00, 0x7a, 0xc8 -}; - -static void __init cyber2000fb_hw_init(void) +/* + * Unmap registers + */ +static void __devinit cyberpro_unmap_mmio(struct cfb_info *cfb) { - int i; + if (cfb && CyberRegs) { + iounmap(CyberRegs); + CyberRegs = NULL; - for (i = 0; i < sizeof(igs_regs); i += 2) - cyber2000_grphw(igs_regs[i], igs_regs[i+1]); + release_mem_region(cfb->fb.fix.mmio_start - PCI_PHYS_OFFSET, + cfb->fb.fix.mmio_len); + } } -static unsigned short device_ids[] __initdata = { - PCI_DEVICE_ID_INTERG_2000, - PCI_DEVICE_ID_INTERG_2010, - PCI_DEVICE_ID_INTERG_5000 -}; - /* - * Initialization + * Map in screen memory */ -int __init cyber2000fb_init(void) +static int __devinit +cyberpro_map_smem(struct cfb_info *cfb, struct pci_dev *dev, u_long smem_len) { - struct pci_dev *dev; - u_int h_sync, v_sync; - u_long mmio_base, smem_base, smem_size; - int err = 0, i; + u_long smem_base; - for (i = 0; i < sizeof(device_ids) / sizeof(device_ids[0]); i++) { - dev = pci_find_device(PCI_VENDOR_ID_INTERG, - device_ids[i], NULL); - if (dev) - break; + smem_base = pci_resource_start(dev, 0); + + cfb->fb.fix.smem_start = smem_base + PCI_PHYS_OFFSET; + cfb->fb.fix.smem_len = smem_len; + + if (!request_mem_region(smem_base, smem_len, "frame buffer")) { + printk("%s: frame buffer in use\n", + cfb->fb.fix.id); + return -EBUSY; } - if (!dev) - return -ENXIO; + cfb->fb.screen_base = ioremap(smem_base, smem_len); + if (!cfb->fb.screen_base) { + printk("%s: unable to map screen memory\n", + cfb->fb.fix.id); + return -ENOMEM; + } - sprintf(current_par.dev_name, "CyberPro%4X", dev->device); + return 0; +} - smem_base = dev->resource[0].start; - mmio_base = dev->resource[0].start + 0x00800000; - current_par.dev = dev; - current_par.dev_id = dev->device; +static void __devinit cyberpro_unmap_smem(struct cfb_info *cfb) +{ + if (cfb && cfb->fb.screen_base) { + iounmap(cfb->fb.screen_base); + cfb->fb.screen_base = NULL; - err = pci_enable_device(dev); - if (err) { - printk("%s: unable to enable device: %d\n", - current_par.dev_name, err); - return err; + release_mem_region(cfb->fb.fix.smem_start - PCI_PHYS_OFFSET, + cfb->fb.fix.smem_len); } +} + +static int __devinit +cyberpro_probe(struct pci_dev *dev, const struct pci_device_id *id) +{ + struct cfb_info *cfb; + u_int h_sync, v_sync; + u_long smem_size; + int err; /* - * Map in the registers + * We can only accept one CyberPro device at the moment. We can + * kill this once int_cfb_info and CyberRegs have been killed. */ - if (!request_mem_region(mmio_base, MMIO_SIZE, "memory mapped I/O")) { - printk("%s: memory mapped IO in use\n", - current_par.dev_name); + if (int_cfb_info) return -EBUSY; - } - CyberRegs = ioremap(mmio_base, MMIO_SIZE); - if (!CyberRegs) { - printk("%s: unable to map memory mapped IO\n", - current_par.dev_name); - err = -ENOMEM; - goto release_mmio_resource; - } + err = pci_enable_device(dev); + if (err) + return err; - cyber2000_outb(0x18, 0x46e8); - cyber2000_outb(0x01, 0x102); - cyber2000_outb(0x08, 0x46e8); + err = -ENOMEM; + cfb = cyberpro_alloc_fb_info(dev, id); + if (!cfb) + goto failed; + + err = cyberpro_map_mmio(cfb, dev); + if (err) + goto failed; + + cyberpro_init_hw(cfb); /* * get the video RAM size and width from the VGA register. * This should have been already initialised by the BIOS, * but if it's garbage, claim default 1MB VRAM (woody) */ - cyber2000_outb(0x72, 0x3ce); - i = cyber2000_inb(0x3cf); - current_par.bus_64bit = i & 4; + cfb->mem_ctl2 = cyber2000_grphr(MEM_CTL2); - switch (i & 3) { - case 2: smem_size = 0x00400000; break; - case 1: smem_size = 0x00200000; break; - default: smem_size = 0x00100000; break; + switch (cfb->mem_ctl2 & MEM_CTL2_SIZE_MASK) { + case MEM_CTL2_SIZE_4MB: smem_size = 0x00400000; break; + case MEM_CTL2_SIZE_2MB: smem_size = 0x00200000; break; + default: smem_size = 0x00100000; break; } - /* - * Map in screen memory - */ - if (!request_mem_region(smem_base, smem_size, "frame buffer")) { - printk("%s: frame buffer in use\n", - current_par.dev_name); - err = -EBUSY; - goto release_mmio; - } + err = cyberpro_map_smem(cfb, dev, smem_size); + if (err) + goto failed; - current_par.screen_base = ioremap(smem_base, smem_size); - if (!current_par.screen_base) { - printk("%s: unable to map screen memory\n", - current_par.dev_name); - err = -ENOMEM; - goto release_smem_resource; + if (!fb_find_mode(&cfb->fb.var, &cfb->fb, NULL, NULL, 0, + &cyber2000fb_default_mode, 8)) { + printk("%s: no valid mode found\n", cfb->fb.fix.id); + goto failed; } - current_par.screen_size = smem_size; - current_par.screen_base_p = smem_base + 0x80000000; - current_par.regs_base_p = mmio_base + 0x80000000; - current_par.currcon = -1; + cfb->fb.var.yres_virtual = cfb->fb.fix.smem_len * 8 / + (cfb->fb.var.bits_per_pixel * cfb->fb.var.xres_virtual); - cyber2000fb_init_fbinfo(); + if (cfb->fb.var.yres_virtual < cfb->fb.var.yres) + cfb->fb.var.yres_virtual = cfb->fb.var.yres; - if (!fb_find_mode(&init_var, &fb_info, NULL, - NULL, 0, &cyber2000fb_default_mode, 8)) { - printk("%s: no valid mode found\n", - current_par.dev_name); - goto release_smem_resource; - } + cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb); + + h_sync = 1953125000 / cfb->fb.var.pixclock; + h_sync = h_sync * 512 / (cfb->fb.var.xres + cfb->fb.var.left_margin + + cfb->fb.var.right_margin + cfb->fb.var.hsync_len); + v_sync = h_sync / (cfb->fb.var.yres + cfb->fb.var.upper_margin + + cfb->fb.var.lower_margin + cfb->fb.var.vsync_len); - init_var.yres_virtual = smem_size * 8 / - (init_var.bits_per_pixel * init_var.xres_virtual); - - if (init_var.yres_virtual < init_var.yres) - init_var.yres_virtual = init_var.yres; - - cyber2000fb_hw_init(); - cyber2000fb_set_var(&init_var, -1, &fb_info); - - h_sync = 1953125000 / init_var.pixclock; - h_sync = h_sync * 512 / (init_var.xres + init_var.left_margin + - init_var.right_margin + init_var.hsync_len); - v_sync = h_sync / (init_var.yres + init_var.upper_margin + - init_var.lower_margin + init_var.vsync_len); - - printk(KERN_INFO "%s: %ldkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n", - current_par.dev_name, - current_par.screen_size >> 10, - init_var.xres, init_var.yres, + printk(KERN_INFO "%s: %dkB VRAM, using %dx%d, %d.%03dkHz, %dHz\n", + cfb->fb.fix.id, cfb->fb.fix.smem_len >> 10, + cfb->fb.var.xres, cfb->fb.var.yres, h_sync / 1000, h_sync % 1000, v_sync); - if (register_framebuffer(&fb_info) < 0) { - err = -EINVAL; - goto release_smem; - } + err = register_framebuffer(&cfb->fb); + if (err < 0) + goto failed; - current_par.initialised = 1; + /* + * Our driver data + */ + dev->driver_data = cfb; + int_cfb_info = cfb; - MOD_INC_USE_COUNT; /* TODO: This driver cannot be unloaded yet */ return 0; -release_smem: - iounmap(current_par.screen_base); -release_smem_resource: - release_mem_region(smem_base, smem_size); -release_mmio: - iounmap(CyberRegs); -release_mmio_resource: - release_mem_region(mmio_base, MMIO_SIZE); +failed: + cyberpro_unmap_smem(cfb); + cyberpro_unmap_mmio(cfb); + cyberpro_free_fb_info(cfb); return err; } -#ifdef MODULE -int __init init_module(void) +static void __devexit cyberpro_remove(struct pci_dev *dev) { - int ret; - - ret = cyber2000fb_init(); - if (ret) - return ret; + struct cfb_info *cfb = (struct cfb_info *)dev->driver_data; + + if (cfb) { + unregister_framebuffer(&cfb->fb); + cyberpro_unmap_smem(cfb); + cyberpro_unmap_mmio(cfb); + cyberpro_free_fb_info(cfb); + + /* + * Ensure that the driver data is no longer + * valid. + */ + dev->driver_data = NULL; + int_cfb_info = NULL; + } +} - return 0; +static void cyberpro_suspend(struct pci_dev *dev) +{ } -void cleanup_module(void) +/* + * Re-initialise the CyberPro hardware + */ +static void cyberpro_resume(struct pci_dev *dev) { - /* Not reached because the usecount will never be - decremented to zero */ - unregister_framebuffer(&fb_info); + struct cfb_info *cfb = (struct cfb_info *)dev->driver_data; + + if (cfb) { + cyberpro_init_hw(cfb); + + /* + * Reprogram the MEM_CTL2 register + */ + cyber2000_grphw(MEM_CTL2, cfb->mem_ctl2); + + /* + * Restore the old video mode and the palette. + * We also need to tell fbcon to redraw the console. + */ + cfb->fb.var.activate = FB_ACTIVATE_NOW; + cyber2000fb_set_var(&cfb->fb.var, -1, &cfb->fb); + } +} + +static struct pci_device_id cyberpro_pci_table[] __devinitdata = { + { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2000, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2000 }, + { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_2010, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER2010 }, + { PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5000, + PCI_ANY_ID, PCI_ANY_ID, 0, 0, FB_ACCEL_IGS_CYBER5000 }, + { 0, } +}; - iounmap(current_par.screen_base); - iounmap(CyberRegs); +MODULE_DEVICE_TABLE(pci, cyberpro_pci_table); - release_mem_region(smem_base, current_par.screen_size); - release_mem_region(mmio_base, MMIO_SIZE); +static struct pci_driver cyberpro_driver = { + name: "CyberPro", + probe: cyberpro_probe, + remove: cyberpro_remove, + suspend: cyberpro_suspend, + resume: cyberpro_resume, + id_table: cyberpro_pci_table +}; + +/* + * I don't think we can use the "module_init" stuff here because + * the fbcon stuff may not be initialised yet. + */ +int __init cyber2000fb_init(void) +{ + return pci_module_init(&cyberpro_driver); } -#endif /* MODULE */ +static void __exit cyberpro_exit(void) +{ + pci_unregister_driver(&cyberpro_driver); +} + +#ifdef MODULE +module_init(cyber2000fb_init); +#endif +module_exit(cyberpro_exit); diff --git a/drivers/video/cyber2000fb.h b/drivers/video/cyber2000fb.h index 734e7e7af..eefc038da 100644 --- a/drivers/video/cyber2000fb.h +++ b/drivers/video/cyber2000fb.h @@ -4,8 +4,6 @@ * Integraphics Cyber2000 frame buffer device */ -#define arraysize(x) (sizeof(x)/sizeof(*(x))) - #define cyber2000_outb(dat,reg) writeb(dat, CyberRegs + reg) #define cyber2000_outw(dat,reg) writew(dat, CyberRegs + reg) #define cyber2000_outl(dat,reg) writel(dat, CyberRegs + reg) @@ -14,6 +12,30 @@ #define cyber2000_inw(reg) readw(CyberRegs + reg) #define cyber2000_inl(reg) readl(CyberRegs + reg) +/* + * Internal CyberPro sizes and offsets. + */ +#define MMIO_OFFSET 0x00800000 +#define MMIO_SIZE 0x000c0000 + +#define NR_PALETTE 256 + +#if defined(DEBUG) && defined(CONFIG_DEBUG_LL) +static void debug_printf(char *fmt, ...) +{ + char buffer[128]; + va_list ap; + + va_start(ap, fmt); + vsprintf(buffer, fmt, ap); + va_end(ap); + + printascii(buffer); +} +#else +#define debug_printf(x...) do { } while (0) +#endif + static inline void cyber2000_crtcw(int reg, int val) { cyber2000_outb(reg, 0x3d4); @@ -46,42 +68,6 @@ static inline void cyber2000_seqw(int reg, int val) cyber2000_outb(val, 0x3c5); } -struct cyber2000fb_par { - char * screen_base; - unsigned long screen_base_p; - unsigned long regs_base; - unsigned long regs_base_p; - unsigned long screen_end; - unsigned long screen_size; - unsigned int palette_size; - signed int currcon; - char dev_name[32]; - struct pci_dev *dev; - unsigned int dev_id; - unsigned int initialised:1; - unsigned int bus_64bit:1; - - /* - * palette - */ - struct { - u8 red; - u8 green; - u8 blue; - } palette[256]; - /* - * colour mapping table - */ - union { -#ifdef FBCON_HAS_CFB16 - u16 cfb16[16]; -#endif -#ifdef FBCON_HAS_CFB24 - u32 cfb24[16]; -#endif - } c_table; -}; - #define PIXFORMAT_8BPP 0 #define PIXFORMAT_16BPP 1 #define PIXFORMAT_24BPP 2 @@ -140,6 +126,12 @@ struct cyber2000fb_par { #define CAP_DDA_Y_INIT 0x6c #define CAP_DDA_Y_INC 0x6e +#define MEM_CTL2 0x72 +#define MEM_CTL2_SIZE_2MB 0x01 +#define MEM_CTL2_SIZE_4MB 0x02 +#define MEM_CTL2_SIZE_MASK 0x03 +#define MEM_CTL2_64BIT 0x04 + #define EXT_FIFO_CTL 0x74 #define CAP_PIP_X_START 0x80 |