summaryrefslogtreecommitdiffstats
path: root/drivers/scsi
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/3w-9xxx.c101
-rw-r--r--drivers/scsi/3w-9xxx.h2
-rw-r--r--drivers/scsi/Kconfig39
-rw-r--r--drivers/scsi/Makefile4
-rw-r--r--drivers/scsi/a2091.c6
-rw-r--r--drivers/scsi/a2091.h3
-rw-r--r--drivers/scsi/a3000.c6
-rw-r--r--drivers/scsi/a3000.h3
-rw-r--r--drivers/scsi/a4000t.c29
-rw-r--r--drivers/scsi/aacraid/aachba.c40
-rw-r--r--drivers/scsi/aacraid/aacraid.h9
-rw-r--r--drivers/scsi/aacraid/comminit.c14
-rw-r--r--drivers/scsi/aacraid/linit.c8
-rw-r--r--drivers/scsi/advansys.c1731
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_core.c12
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_inline.h32
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_osm.h102
-rw-r--r--drivers/scsi/aic7xxx/aic79xx_pci.c8
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_inline.h5
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_osm.h104
-rw-r--r--drivers/scsi/aic7xxx/aic7xxx_pci.c10
-rw-r--r--drivers/scsi/aic7xxx/aiclib.h4
-rw-r--r--drivers/scsi/arm/cumana_2.c5
-rw-r--r--drivers/scsi/arm/eesox.c3
-rw-r--r--drivers/scsi/arm/powertec.c3
-rw-r--r--drivers/scsi/atari_NCR5380.c2
-rw-r--r--drivers/scsi/atari_scsi.c2
-rw-r--r--drivers/scsi/bvme6000_scsi.c29
-rw-r--r--drivers/scsi/ch.c1
-rw-r--r--drivers/scsi/constants.c13
-rw-r--r--drivers/scsi/cxgb3i/Kbuild4
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i.h31
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_ddp.c279
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_ddp.h19
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_init.c31
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_iscsi.c176
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_offload.c244
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_offload.h41
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_pdu.c277
-rw-r--r--drivers/scsi/cxgb3i/cxgb3i_pdu.h2
-rw-r--r--drivers/scsi/device_handler/scsi_dh_alua.c14
-rw-r--r--drivers/scsi/device_handler/scsi_dh_rdac.c49
-rw-r--r--drivers/scsi/fcoe/Makefile8
-rw-r--r--drivers/scsi/fcoe/fc_transport_fcoe.c446
-rw-r--r--drivers/scsi/fcoe/fcoe.c1878
-rw-r--r--drivers/scsi/fcoe/fcoe.h75
-rw-r--r--drivers/scsi/fcoe/fcoe_sw.c494
-rw-r--r--drivers/scsi/fcoe/libfcoe.c2296
-rw-r--r--drivers/scsi/hosts.c3
-rw-r--r--drivers/scsi/hptiop.c4
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.c203
-rw-r--r--drivers/scsi/ibmvscsi/ibmvfc.h20
-rw-r--r--drivers/scsi/ibmvscsi/ibmvscsi.c1
-rw-r--r--drivers/scsi/ipr.c13
-rw-r--r--drivers/scsi/ipr.h4
-rw-r--r--drivers/scsi/ips.c3
-rw-r--r--drivers/scsi/iscsi_tcp.c73
-rw-r--r--drivers/scsi/lasi700.c2
-rw-r--r--drivers/scsi/libfc/fc_disc.c63
-rw-r--r--drivers/scsi/libfc/fc_exch.c38
-rw-r--r--drivers/scsi/libfc/fc_fcp.c141
-rw-r--r--drivers/scsi/libfc/fc_lport.c189
-rw-r--r--drivers/scsi/libfc/fc_rport.c199
-rw-r--r--drivers/scsi/libiscsi.c243
-rw-r--r--drivers/scsi/libiscsi_tcp.c122
-rw-r--r--drivers/scsi/lpfc/lpfc_debugfs.c16
-rw-r--r--drivers/scsi/lpfc/lpfc_els.c1
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c6
-rw-r--r--drivers/scsi/mpt2sas/Kconfig66
-rw-r--r--drivers/scsi/mpt2sas/Makefile7
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2.h1067
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h2151
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_init.h420
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_ioc.h1295
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_raid.h295
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_sas.h282
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_tool.h249
-rw-r--r--drivers/scsi/mpt2sas/mpi/mpi2_type.h61
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.c3435
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_base.h779
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_config.c1873
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.c2516
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_ctl.h416
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_debug.h181
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_scsih.c5687
-rw-r--r--drivers/scsi/mpt2sas/mpt2sas_transport.c1211
-rw-r--r--drivers/scsi/mvme16x_scsi.c29
-rw-r--r--drivers/scsi/osd/Kbuild45
-rw-r--r--drivers/scsi/osd/Kconfig53
-rwxr-xr-xdrivers/scsi/osd/Makefile37
-rw-r--r--drivers/scsi/osd/osd_debug.h30
-rw-r--r--drivers/scsi/osd/osd_initiator.c1663
-rw-r--r--drivers/scsi/osd/osd_uld.c481
-rw-r--r--drivers/scsi/osst.c96
-rw-r--r--drivers/scsi/osst.h2
-rw-r--r--drivers/scsi/ql1040_fw.h2130
-rw-r--r--drivers/scsi/ql12160_fw.h1811
-rw-r--r--drivers/scsi/ql1280_fw.h2048
-rw-r--r--drivers/scsi/qla1280.c114
-rw-r--r--drivers/scsi/qla1280.h6
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c317
-rw-r--r--drivers/scsi/qla2xxx/qla_def.h141
-rw-r--r--drivers/scsi/qla2xxx/qla_devtbl.h2
-rw-r--r--drivers/scsi/qla2xxx/qla_dfs.c4
-rw-r--r--drivers/scsi/qla2xxx/qla_fw.h44
-rw-r--r--drivers/scsi/qla2xxx/qla_gbl.h34
-rw-r--r--drivers/scsi/qla2xxx/qla_init.c160
-rw-r--r--drivers/scsi/qla2xxx/qla_iocb.c37
-rw-r--r--drivers/scsi/qla2xxx/qla_isr.c90
-rw-r--r--drivers/scsi/qla2xxx/qla_mbx.c281
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c34
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c280
-rw-r--r--drivers/scsi/qla2xxx/qla_sup.c105
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/qlogicpti.c63
-rw-r--r--drivers/scsi/qlogicpti_asm.c1160
-rw-r--r--drivers/scsi/scsi.c108
-rw-r--r--drivers/scsi/scsi_debug.c443
-rw-r--r--drivers/scsi/scsi_devinfo.c2
-rw-r--r--drivers/scsi/scsi_error.c34
-rw-r--r--drivers/scsi/scsi_lib.c225
-rw-r--r--drivers/scsi/scsi_proc.c3
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c1
-rw-r--r--drivers/scsi/scsi_transport_fc.c18
-rw-r--r--drivers/scsi/scsi_transport_iscsi.c57
-rw-r--r--drivers/scsi/sd.c388
-rw-r--r--drivers/scsi/sd.h1
-rw-r--r--drivers/scsi/ses.c35
-rw-r--r--drivers/scsi/sg.c528
-rw-r--r--drivers/scsi/sr.c9
-rw-r--r--drivers/scsi/st.c6
-rw-r--r--drivers/scsi/stex.c823
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.c137
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_glue.h6
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.c66
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_hipd.h10
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_malloc.c2
-rw-r--r--drivers/scsi/sym53c8xx_2/sym_misc.h18
-rw-r--r--drivers/scsi/zalon.c2
140 files changed, 32414 insertions, 13840 deletions
diff --git a/drivers/scsi/3w-9xxx.c b/drivers/scsi/3w-9xxx.c
index 5311317c2e4..a12783ebb42 100644
--- a/drivers/scsi/3w-9xxx.c
+++ b/drivers/scsi/3w-9xxx.c
@@ -4,7 +4,7 @@
Written By: Adam Radford <linuxraid@amcc.com>
Modifications By: Tom Couch <linuxraid@amcc.com>
- Copyright (C) 2004-2008 Applied Micro Circuits Corporation.
+ Copyright (C) 2004-2009 Applied Micro Circuits Corporation.
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
@@ -75,6 +75,7 @@
Add MSI support and "use_msi" module parameter.
Fix bug in twa_get_param() on 4GB+.
Use pci_resource_len() for ioremap().
+ 2.26.02.012 - Add power management support.
*/
#include <linux/module.h>
@@ -99,7 +100,7 @@
#include "3w-9xxx.h"
/* Globals */
-#define TW_DRIVER_VERSION "2.26.02.011"
+#define TW_DRIVER_VERSION "2.26.02.012"
static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT];
static unsigned int twa_device_extension_count;
static int twa_major = -1;
@@ -2182,6 +2183,98 @@ static void twa_remove(struct pci_dev *pdev)
twa_device_extension_count--;
} /* End twa_remove() */
+#ifdef CONFIG_PM
+/* This function is called on PCI suspend */
+static int twa_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct Scsi_Host *host = pci_get_drvdata(pdev);
+ TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+
+ printk(KERN_WARNING "3w-9xxx: Suspending host %d.\n", tw_dev->host->host_no);
+
+ TW_DISABLE_INTERRUPTS(tw_dev);
+ free_irq(tw_dev->tw_pci_dev->irq, tw_dev);
+
+ if (test_bit(TW_USING_MSI, &tw_dev->flags))
+ pci_disable_msi(pdev);
+
+ /* Tell the card we are shutting down */
+ if (twa_initconnection(tw_dev, 1, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL)) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x38, "Connection shutdown failed during suspend");
+ } else {
+ printk(KERN_WARNING "3w-9xxx: Suspend complete.\n");
+ }
+ TW_CLEAR_ALL_INTERRUPTS(tw_dev);
+
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, pci_choose_state(pdev, state));
+
+ return 0;
+} /* End twa_suspend() */
+
+/* This function is called on PCI resume */
+static int twa_resume(struct pci_dev *pdev)
+{
+ int retval = 0;
+ struct Scsi_Host *host = pci_get_drvdata(pdev);
+ TW_Device_Extension *tw_dev = (TW_Device_Extension *)host->hostdata;
+
+ printk(KERN_WARNING "3w-9xxx: Resuming host %d.\n", tw_dev->host->host_no);
+ pci_set_power_state(pdev, PCI_D0);
+ pci_enable_wake(pdev, PCI_D0, 0);
+ pci_restore_state(pdev);
+
+ retval = pci_enable_device(pdev);
+ if (retval) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x39, "Enable device failed during resume");
+ return retval;
+ }
+
+ pci_set_master(pdev);
+ pci_try_set_mwi(pdev);
+
+ if (pci_set_dma_mask(pdev, DMA_64BIT_MASK)
+ || pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
+ if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)
+ || pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ TW_PRINTK(host, TW_DRIVER, 0x40, "Failed to set dma mask during resume");
+ retval = -ENODEV;
+ goto out_disable_device;
+ }
+
+ /* Initialize the card */
+ if (twa_reset_sequence(tw_dev, 0)) {
+ retval = -ENODEV;
+ goto out_disable_device;
+ }
+
+ /* Now setup the interrupt handler */
+ retval = request_irq(pdev->irq, twa_interrupt, IRQF_SHARED, "3w-9xxx", tw_dev);
+ if (retval) {
+ TW_PRINTK(tw_dev->host, TW_DRIVER, 0x42, "Error requesting IRQ during resume");
+ retval = -ENODEV;
+ goto out_disable_device;
+ }
+
+ /* Now enable MSI if enabled */
+ if (test_bit(TW_USING_MSI, &tw_dev->flags))
+ pci_enable_msi(pdev);
+
+ /* Re-enable interrupts on the card */
+ TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev);
+
+ printk(KERN_WARNING "3w-9xxx: Resume complete.\n");
+ return 0;
+
+out_disable_device:
+ scsi_remove_host(host);
+ pci_disable_device(pdev);
+
+ return retval;
+} /* End twa_resume() */
+#endif
+
/* PCI Devices supported by this driver */
static struct pci_device_id twa_pci_tbl[] __devinitdata = {
{ PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9000,
@@ -2202,6 +2295,10 @@ static struct pci_driver twa_driver = {
.id_table = twa_pci_tbl,
.probe = twa_probe,
.remove = twa_remove,
+#ifdef CONFIG_PM
+ .suspend = twa_suspend,
+ .resume = twa_resume,
+#endif
.shutdown = twa_shutdown
};
diff --git a/drivers/scsi/3w-9xxx.h b/drivers/scsi/3w-9xxx.h
index 1729a8785fe..2893eec78ed 100644
--- a/drivers/scsi/3w-9xxx.h
+++ b/drivers/scsi/3w-9xxx.h
@@ -4,7 +4,7 @@
Written By: Adam Radford <linuxraid@amcc.com>
Modifications By: Tom Couch <linuxraid@amcc.com>
- Copyright (C) 2004-2008 Applied Micro Circuits Corporation.
+ Copyright (C) 2004-2009 Applied Micro Circuits Corporation.
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
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 256c7bec7bd..8ed2990c826 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -121,10 +121,11 @@ config BLK_DEV_SR
tristate "SCSI CDROM support"
depends on SCSI
---help---
- If you want to use a SCSI or FireWire CD-ROM under Linux,
- say Y and read the SCSI-HOWTO and the CDROM-HOWTO at
- <http://www.tldp.org/docs.html#howto>. Also make sure to say
- Y or M to "ISO 9660 CD-ROM file system support" later.
+ If you want to use a CD or DVD drive attached to your computer
+ by SCSI, FireWire, USB or ATAPI, say Y and read the SCSI-HOWTO
+ and the CDROM-HOWTO at <http://www.tldp.org/docs.html#howto>.
+
+ Make sure to say Y or M to "ISO 9660 CD-ROM file system support".
To compile this driver as a module, choose M here and read
<file:Documentation/scsi/scsi.txt>.
@@ -224,14 +225,15 @@ config SCSI_LOGGING
can enable logging by saying Y to "/proc file system support" and
"Sysctl support" below and executing the command
- echo "scsi log token [level]" > /proc/scsi/scsi
+ echo <bitmask> > /proc/sys/dev/scsi/logging_level
- at boot time after the /proc file system has been mounted.
+ where <bitmask> is a four byte value representing the logging type
+ and logging level for each type of logging selected.
- There are a number of things that can be used for 'token' (you can
- find them in the source: <file:drivers/scsi/scsi.c>), and this
- allows you to select the types of information you want, and the
- level allows you to select the level of verbosity.
+ There are a number of logging types and you can find them in the
+ source at <file:drivers/scsi/scsi_logging.h>. The logging levels
+ are also described in that file and they determine the verbosity of
+ the logging for each logging type.
If you say N here, it may be harder to track down some types of SCSI
problems. If you say Y here your kernel will be somewhat larger, but
@@ -570,6 +572,7 @@ config SCSI_ARCMSR_AER
To enable this function, choose Y here.
source "drivers/scsi/megaraid/Kconfig.megaraid"
+source "drivers/scsi/mpt2sas/Kconfig"
config SCSI_HPTIOP
tristate "HighPoint RocketRAID 3xxx/4xxx Controller support"
@@ -608,13 +611,20 @@ config SCSI_FLASHPOINT
config LIBFC
tristate "LibFC module"
select SCSI_FC_ATTRS
+ select CRC32
---help---
Fibre Channel library module
+config LIBFCOE
+ tristate "LibFCoE module"
+ select LIBFC
+ ---help---
+ Library for Fibre Channel over Ethernet module
+
config FCOE
tristate "FCoE module"
depends on PCI
- select LIBFC
+ select LIBFCOE
---help---
Fibre Channel over Ethernet module
@@ -1377,7 +1387,7 @@ config SCSI_LPFC_DEBUG_FS
bool "Emulex LightPulse Fibre Channel debugfs Support"
depends on SCSI_LPFC && DEBUG_FS
help
- This makes debugging infomation from the lpfc driver
+ This makes debugging information from the lpfc driver
available via the debugfs filesystem.
config SCSI_SIM710
@@ -1385,7 +1395,7 @@ config SCSI_SIM710
depends on (EISA || MCA) && SCSI
select SCSI_SPI_ATTRS
---help---
- This driver for NCR53c710 based SCSI host adapters.
+ This driver is for NCR53c710 based SCSI host adapters.
It currently supports Compaq EISA cards and NCR MCA cards
@@ -1535,6 +1545,7 @@ config SCSI_NSP32
config SCSI_DEBUG
tristate "SCSI debugging host simulator"
depends on SCSI
+ select CRC_T10DIF
help
This is a host adapter simulator that can simulate multiple hosts
each with multiple dummy SCSI devices (disks). It defaults to one
@@ -1803,4 +1814,6 @@ source "drivers/scsi/pcmcia/Kconfig"
source "drivers/scsi/device_handler/Kconfig"
+source "drivers/scsi/osd/Kconfig"
+
endmenu
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 7461eb09a03..e7c861ac417 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -37,6 +37,7 @@ obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o
obj-$(CONFIG_SCSI_DH) += device_handler/
obj-$(CONFIG_LIBFC) += libfc/
+obj-$(CONFIG_LIBFCOE) += fcoe/
obj-$(CONFIG_FCOE) += fcoe/
obj-$(CONFIG_ISCSI_TCP) += libiscsi.o libiscsi_tcp.o iscsi_tcp.o
obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o
@@ -99,6 +100,7 @@ obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
+obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas/
obj-$(CONFIG_SCSI_ACARD) += atp870u.o
obj-$(CONFIG_SCSI_SUNESP) += esp_scsi.o sun_esp.o
obj-$(CONFIG_SCSI_GDTH) += gdth.o
@@ -137,6 +139,8 @@ obj-$(CONFIG_CHR_DEV_SG) += sg.o
obj-$(CONFIG_CHR_DEV_SCH) += ch.o
obj-$(CONFIG_SCSI_ENCLOSURE) += ses.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += osd/
+
# This goes last, so that "real" scsi devices probe earlier
obj-$(CONFIG_SCSI_DEBUG) += scsi_debug.o
diff --git a/drivers/scsi/a2091.c b/drivers/scsi/a2091.c
index 37dd47136fb..4b38c4750f7 100644
--- a/drivers/scsi/a2091.c
+++ b/drivers/scsi/a2091.c
@@ -23,6 +23,8 @@
#define DMA(ptr) ((a2091_scsiregs *)((ptr)->base))
#define HDATA(ptr) ((struct WD33C93_hostdata *)((ptr)->hostdata))
+static int a2091_release(struct Scsi_Host *instance);
+
static irqreturn_t a2091_intr (int irq, void *_instance)
{
unsigned long flags;
@@ -144,7 +146,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
}
}
-int __init a2091_detect(struct scsi_host_template *tpnt)
+static int __init a2091_detect(struct scsi_host_template *tpnt)
{
static unsigned char called = 0;
struct Scsi_Host *instance;
@@ -233,7 +235,7 @@ static struct scsi_host_template driver_template = {
#include "scsi_module.c"
-int a2091_release(struct Scsi_Host *instance)
+static int a2091_release(struct Scsi_Host *instance)
{
#ifdef MODULE
DMA(instance)->CNTR = 0;
diff --git a/drivers/scsi/a2091.h b/drivers/scsi/a2091.h
index fe809bc88d7..252528f2672 100644
--- a/drivers/scsi/a2091.h
+++ b/drivers/scsi/a2091.h
@@ -11,9 +11,6 @@
#include <linux/types.h>
-int a2091_detect(struct scsi_host_template *);
-int a2091_release(struct Scsi_Host *);
-
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
#endif
diff --git a/drivers/scsi/a3000.c b/drivers/scsi/a3000.c
index 8b449d8acac..6970ce82c4a 100644
--- a/drivers/scsi/a3000.c
+++ b/drivers/scsi/a3000.c
@@ -25,6 +25,8 @@
static struct Scsi_Host *a3000_host = NULL;
+static int a3000_release(struct Scsi_Host *instance);
+
static irqreturn_t a3000_intr (int irq, void *dummy)
{
unsigned long flags;
@@ -157,7 +159,7 @@ static void dma_stop(struct Scsi_Host *instance, struct scsi_cmnd *SCpnt,
}
}
-int __init a3000_detect(struct scsi_host_template *tpnt)
+static int __init a3000_detect(struct scsi_host_template *tpnt)
{
wd33c93_regs regs;
@@ -232,7 +234,7 @@ static struct scsi_host_template driver_template = {
#include "scsi_module.c"
-int a3000_release(struct Scsi_Host *instance)
+static int a3000_release(struct Scsi_Host *instance)
{
wd33c93_release();
DMA(instance)->CNTR = 0;
diff --git a/drivers/scsi/a3000.h b/drivers/scsi/a3000.h
index 44a4ec7b465..c7afe16fd6e 100644
--- a/drivers/scsi/a3000.h
+++ b/drivers/scsi/a3000.h
@@ -11,9 +11,6 @@
#include <linux/types.h>
-int a3000_detect(struct scsi_host_template *);
-int a3000_release(struct Scsi_Host *);
-
#ifndef CMD_PER_LUN
#define CMD_PER_LUN 2
#endif
diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c
index d4bda201774..61af3d91ac8 100644
--- a/drivers/scsi/a4000t.c
+++ b/drivers/scsi/a4000t.c
@@ -35,7 +35,7 @@ static struct platform_device *a4000t_scsi_device;
#define A4000T_SCSI_ADDR 0xdd0040
-static int __devinit a4000t_probe(struct device *dev)
+static int __devinit a4000t_probe(struct platform_device *dev)
{
struct Scsi_Host *host;
struct NCR_700_Host_Parameters *hostdata;
@@ -61,7 +61,8 @@ static int __devinit a4000t_probe(struct device *dev)
hostdata->dcntl_extra = EA_710;
/* and register the chip */
- host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev);
+ host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata,
+ &dev->dev);
if (!host) {
printk(KERN_ERR "a4000t-scsi: No host detected; "
"board configuration problem?\n");
@@ -78,7 +79,7 @@ static int __devinit a4000t_probe(struct device *dev)
goto out_put_host;
}
- dev_set_drvdata(dev, host);
+ platform_set_drvdata(dev, host);
scsi_scan_host(host);
return 0;
@@ -93,9 +94,9 @@ static int __devinit a4000t_probe(struct device *dev)
return -ENODEV;
}
-static __devexit int a4000t_device_remove(struct device *dev)
+static __devexit int a4000t_device_remove(struct platform_device *dev)
{
- struct Scsi_Host *host = dev_get_drvdata(dev);
+ struct Scsi_Host *host = platform_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
scsi_remove_host(host);
@@ -108,25 +109,27 @@ static __devexit int a4000t_device_remove(struct device *dev)
return 0;
}
-static struct device_driver a4000t_scsi_driver = {
- .name = "a4000t-scsi",
- .bus = &platform_bus_type,
- .probe = a4000t_probe,
- .remove = __devexit_p(a4000t_device_remove),
+static struct platform_driver a4000t_scsi_driver = {
+ .driver = {
+ .name = "a4000t-scsi",
+ .owner = THIS_MODULE,
+ },
+ .probe = a4000t_probe,
+ .remove = __devexit_p(a4000t_device_remove),
};
static int __init a4000t_scsi_init(void)
{
int err;
- err = driver_register(&a4000t_scsi_driver);
+ err = platform_driver_register(&a4000t_scsi_driver);
if (err)
return err;
a4000t_scsi_device = platform_device_register_simple("a4000t-scsi",
-1, NULL, 0);
if (IS_ERR(a4000t_scsi_device)) {
- driver_unregister(&a4000t_scsi_driver);
+ platform_driver_register(&a4000t_scsi_driver);
return PTR_ERR(a4000t_scsi_device);
}
@@ -136,7 +139,7 @@ static int __init a4000t_scsi_init(void)
static void __exit a4000t_scsi_exit(void)
{
platform_device_unregister(a4000t_scsi_device);
- driver_unregister(&a4000t_scsi_driver);
+ platform_driver_unregister(&a4000t_scsi_driver);
}
module_init(a4000t_scsi_init);
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 90d1d0878cb..21964aaebca 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -143,7 +143,7 @@ static char *aac_get_status_string(u32 status);
*/
static int nondasd = -1;
-static int aac_cache;
+static int aac_cache = 2; /* WCE=0 to avoid performance problems */
static int dacmode = -1;
int aac_msi;
int aac_commit = -1;
@@ -157,7 +157,7 @@ module_param_named(cache, aac_cache, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(cache, "Disable Queue Flush commands:\n"
"\tbit 0 - Disable FUA in WRITE SCSI commands\n"
"\tbit 1 - Disable SYNCHRONIZE_CACHE SCSI command\n"
- "\tbit 2 - Disable only if Battery not protecting Cache");
+ "\tbit 2 - Disable only if Battery is protecting Cache");
module_param(dacmode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC."
" 0=off, 1=on");
@@ -217,6 +217,14 @@ int aac_reset_devices;
module_param_named(reset_devices, aac_reset_devices, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(reset_devices, "Force an adapter reset at initialization.");
+int aac_wwn = 1;
+module_param_named(wwn, aac_wwn, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(wwn, "Select a WWN type for the arrays:\n"
+ "\t0 - Disable\n"
+ "\t1 - Array Meta Data Signature (default)\n"
+ "\t2 - Adapter Serial Number");
+
+
static inline int aac_valid_context(struct scsi_cmnd *scsicmd,
struct fib *fibptr) {
struct scsi_device *device;
@@ -1206,9 +1214,8 @@ static int aac_scsi_32(struct fib * fib, struct scsi_cmnd * cmd)
static int aac_scsi_32_64(struct fib * fib, struct scsi_cmnd * cmd)
{
- if ((sizeof(dma_addr_t) > 4) &&
- (num_physpages > (0xFFFFFFFFULL >> PAGE_SHIFT)) &&
- (fib->dev->adapter_info.options & AAC_OPT_SGMAP_HOST64))
+ if ((sizeof(dma_addr_t) > 4) && fib->dev->needs_dac &&
+ (fib->dev->adapter_info.options & AAC_OPT_SGMAP_HOST64))
return FAILED;
return aac_scsi_32(fib, cmd);
}
@@ -1371,8 +1378,11 @@ int aac_get_adapter_info(struct aac_dev* dev)
if (dev->nondasd_support && !dev->in_reset)
printk(KERN_INFO "%s%d: Non-DASD support enabled.\n",dev->name, dev->id);
+ if (dma_get_required_mask(&dev->pdev->dev) > DMA_32BIT_MASK)
+ dev->needs_dac = 1;
dev->dac_support = 0;
- if( (sizeof(dma_addr_t) > 4) && (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){
+ if ((sizeof(dma_addr_t) > 4) && dev->needs_dac &&
+ (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)) {
if (!dev->in_reset)
printk(KERN_INFO "%s%d: 64bit support enabled.\n",
dev->name, dev->id);
@@ -1382,6 +1392,15 @@ int aac_get_adapter_info(struct aac_dev* dev)
if(dacmode != -1) {
dev->dac_support = (dacmode!=0);
}
+
+ /* avoid problems with AAC_QUIRK_SCSI_32 controllers */
+ if (dev->dac_support && (aac_get_driver_ident(dev->cardtype)->quirks
+ & AAC_QUIRK_SCSI_32)) {
+ dev->nondasd_support = 0;
+ dev->jbod = 0;
+ expose_physicals = 0;
+ }
+
if(dev->dac_support != 0) {
if (!pci_set_dma_mask(dev->pdev, DMA_64BIT_MASK) &&
!pci_set_consistent_dma_mask(dev->pdev, DMA_64BIT_MASK)) {
@@ -2058,7 +2077,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", cid));
memset(&inq_data, 0, sizeof (struct inquiry_data));
- if (scsicmd->cmnd[1] & 0x1) {
+ if ((scsicmd->cmnd[1] & 0x1) && aac_wwn) {
char *arr = (char *)&inq_data;
/* EVPD bit set */
@@ -2081,7 +2100,12 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
arr[1] = scsicmd->cmnd[2];
scsi_sg_copy_from_buffer(scsicmd, &inq_data,
sizeof(inq_data));
- return aac_get_container_serial(scsicmd);
+ if (aac_wwn != 2)
+ return aac_get_container_serial(
+ scsicmd);
+ /* SLES 10 SP1 special */
+ scsicmd->result = DID_OK << 16 |
+ COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
} else {
/* vpd page not implemented */
scsicmd->result = DID_OK << 16 |
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index 73916adb8f8..cdbdec9f4fb 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -12,7 +12,7 @@
*----------------------------------------------------------------------------*/
#ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 2456
+# define AAC_DRIVER_BUILD 2461
# define AAC_DRIVER_BRANCH "-ms"
#endif
#define MAXIMUM_NUM_CONTAINERS 32
@@ -865,7 +865,11 @@ struct aac_supplement_adapter_info
u8 MfgPcbaSerialNo[12];
u8 MfgWWNName[8];
__le32 SupportedOptions2;
- __le32 ReservedGrowth[1];
+ __le32 StructExpansion;
+ /* StructExpansion == 1 */
+ __le32 FeatureBits3;
+ __le32 SupportedPerformanceModes;
+ __le32 ReservedForFutureGrowth[80];
};
#define AAC_FEATURE_FALCON cpu_to_le32(0x00000010)
#define AAC_FEATURE_JBOD cpu_to_le32(0x08000000)
@@ -1020,6 +1024,7 @@ struct aac_dev
u8 jbod;
u8 cache_protected;
u8 dac_support;
+ u8 needs_dac;
u8 raid_scsi_mode;
u8 comm_interface;
# define AAC_COMM_PRODUCER 0
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 16310443b55..d598eba630d 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -54,6 +54,7 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
const unsigned long printfbufsiz = 256;
struct aac_init *init;
dma_addr_t phys;
+ unsigned long aac_max_hostphysmempages;
size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz;
@@ -90,7 +91,18 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
init->AdapterFibsSize = cpu_to_le32(fibsize);
init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
- init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
+ /*
+ * number of 4k pages of host physical memory. The aacraid fw needs
+ * this number to be less than 4gb worth of pages. New firmware doesn't
+ * have any issues with the mapping system, but older Firmware did, and
+ * had *troubles* dealing with the math overloading past 32 bits, thus
+ * we must limit this field.
+ */
+ aac_max_hostphysmempages = dma_get_required_mask(&dev->pdev->dev) >> 12;
+ if (aac_max_hostphysmempages < AAC_MAX_HOSTPHYSMEMPAGES)
+ init->HostPhysMemPages = cpu_to_le32(aac_max_hostphysmempages);
+ else
+ init->HostPhysMemPages = cpu_to_le32(AAC_MAX_HOSTPHYSMEMPAGES);
init->InitFlags = 0;
if (dev->comm_interface == AAC_COMM_MESSAGE) {
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index 36d8aab97ef..c507719c0d4 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -86,7 +86,13 @@ char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
*
* Note: The last field is used to index into aac_drivers below.
*/
-static struct pci_device_id aac_pci_tbl[] = {
+#ifdef DECLARE_PCI_DEVICE_TABLE
+static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = {
+#elif defined(__devinitconst)
+static const struct pci_device_id aac_pci_tbl[] __devinitconst = {
+#else
+static const struct pci_device_id aac_pci_tbl[] __devinitdata = {
+#endif
{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */
{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */
{ 0x1028, 0x0003, 0x1028, 0x0003, 0, 0, 2 }, /* PERC 3/Si (SlimFast/PERC3Si */
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 7507d8bc57a..b756041f0b2 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -38,6 +38,7 @@
#include <linux/pci.h>
#include <linux/spinlock.h>
#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
#include <asm/io.h>
#include <asm/system.h>
@@ -4519,8 +4520,8 @@ static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val)
* and is maintained in little-endian order when written to LRAM.
*/
static void
-AscMemWordCopyPtrToLram(PortAddr iop_base,
- ushort s_addr, uchar *s_buffer, int words)
+AscMemWordCopyPtrToLram(PortAddr iop_base, ushort s_addr,
+ const uchar *s_buffer, int words)
{
int i;
@@ -4642,8 +4643,8 @@ static ushort AscInitLram(ASC_DVC_VAR *asc_dvc)
}
static ASC_DCNT
-AscLoadMicroCode(PortAddr iop_base,
- ushort s_addr, uchar *mcode_buf, ushort mcode_size)
+AscLoadMicroCode(PortAddr iop_base, ushort s_addr,
+ const uchar *mcode_buf, ushort mcode_size)
{
ASC_DCNT chksum;
ushort mcode_word_size;
@@ -4668,1618 +4669,6 @@ AscLoadMicroCode(PortAddr iop_base,
return chksum;
}
-/* Microcode buffer is kept after initialization for error recovery. */
-static uchar _asc_mcode_buf[] = {
- 0x01, 0x03, 0x01, 0x19, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC3, 0x12, 0x0D, 0x05,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xFF, 0x80, 0xFF, 0xFF, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x23, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0xE4, 0x88, 0x00, 0x00, 0x00, 0x00, 0x80, 0x73, 0x48, 0x04,
- 0x36, 0x00, 0x00, 0xA2, 0xC2, 0x00, 0x80, 0x73, 0x03, 0x23, 0x36, 0x40,
- 0xB6, 0x00, 0x36, 0x00, 0x05, 0xD6, 0x0C, 0xD2, 0x12, 0xDA, 0x00, 0xA2,
- 0xC2, 0x00, 0x92, 0x80, 0x1E, 0x98, 0x50, 0x00, 0xF5, 0x00, 0x48, 0x98,
- 0xDF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x4F, 0x00, 0xF5, 0x00,
- 0x48, 0x98, 0xEF, 0x23, 0x36, 0x60, 0xB6, 0x00, 0x92, 0x80, 0x80, 0x62,
- 0x92, 0x80, 0x00, 0x46, 0x15, 0xEE, 0x13, 0xEA, 0x02, 0x01, 0x09, 0xD8,
- 0xCD, 0x04, 0x4D, 0x00, 0x00, 0xA3, 0xD6, 0x00, 0xA6, 0x97, 0x7F, 0x23,
- 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84, 0xD2, 0xC1, 0x80, 0x73, 0xCD, 0x04,
- 0x4D, 0x00, 0x00, 0xA3, 0xDA, 0x01, 0xA6, 0x97, 0xC6, 0x81, 0xC2, 0x88,
- 0x80, 0x73, 0x80, 0x77, 0x00, 0x01, 0x01, 0xA1, 0xFE, 0x00, 0x4F, 0x00,
- 0x84, 0x97, 0x07, 0xA6, 0x08, 0x01, 0x00, 0x33, 0x03, 0x00, 0xC2, 0x88,
- 0x03, 0x03, 0x01, 0xDE, 0xC2, 0x88, 0xCE, 0x00, 0x69, 0x60, 0xCE, 0x00,
- 0x02, 0x03, 0x4A, 0x60, 0x00, 0xA2, 0x78, 0x01, 0x80, 0x63, 0x07, 0xA6,
- 0x24, 0x01, 0x78, 0x81, 0x03, 0x03, 0x80, 0x63, 0xE2, 0x00, 0x07, 0xA6,
- 0x34, 0x01, 0x00, 0x33, 0x04, 0x00, 0xC2, 0x88, 0x03, 0x07, 0x02, 0x01,
- 0x04, 0xCA, 0x0D, 0x23, 0x68, 0x98, 0x4D, 0x04, 0x04, 0x85, 0x05, 0xD8,
- 0x0D, 0x23, 0x68, 0x98, 0xCD, 0x04, 0x15, 0x23, 0xF8, 0x88, 0xFB, 0x23,
- 0x02, 0x61, 0x82, 0x01, 0x80, 0x63, 0x02, 0x03, 0x06, 0xA3, 0x62, 0x01,
- 0x00, 0x33, 0x0A, 0x00, 0xC2, 0x88, 0x4E, 0x00, 0x07, 0xA3, 0x6E, 0x01,
- 0x00, 0x33, 0x0B, 0x00, 0xC2, 0x88, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33,
- 0x1A, 0x00, 0xC2, 0x88, 0x50, 0x04, 0x88, 0x81, 0x06, 0xAB, 0x82, 0x01,
- 0x88, 0x81, 0x4E, 0x00, 0x07, 0xA3, 0x92, 0x01, 0x50, 0x00, 0x00, 0xA3,
- 0x3C, 0x01, 0x00, 0x05, 0x7C, 0x81, 0x46, 0x97, 0x02, 0x01, 0x05, 0xC6,
- 0x04, 0x23, 0xA0, 0x01, 0x15, 0x23, 0xA1, 0x01, 0xBE, 0x81, 0xFD, 0x23,
- 0x02, 0x61, 0x82, 0x01, 0x0A, 0xDA, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA0,
- 0xB4, 0x01, 0x80, 0x63, 0xCD, 0x04, 0x36, 0x2D, 0x00, 0x33, 0x1B, 0x00,
- 0xC2, 0x88, 0x06, 0x23, 0x68, 0x98, 0xCD, 0x04, 0xE6, 0x84, 0x06, 0x01,
- 0x00, 0xA2, 0xD4, 0x01, 0x57, 0x60, 0x00, 0xA0, 0xDA, 0x01, 0xE6, 0x84,
- 0x80, 0x23, 0xA0, 0x01, 0xE6, 0x84, 0x80, 0x73, 0x4B, 0x00, 0x06, 0x61,
- 0x00, 0xA2, 0x00, 0x02, 0x04, 0x01, 0x0C, 0xDE, 0x02, 0x01, 0x03, 0xCC,
- 0x4F, 0x00, 0x84, 0x97, 0xFC, 0x81, 0x08, 0x23, 0x02, 0x41, 0x82, 0x01,
- 0x4F, 0x00, 0x62, 0x97, 0x48, 0x04, 0x84, 0x80, 0xF0, 0x97, 0x00, 0x46,
- 0x56, 0x00, 0x03, 0xC0, 0x01, 0x23, 0xE8, 0x00, 0x81, 0x73, 0x06, 0x29,
- 0x03, 0x42, 0x06, 0xE2, 0x03, 0xEE, 0x6B, 0xEB, 0x11, 0x23, 0xF8, 0x88,
- 0x04, 0x98, 0xF0, 0x80, 0x80, 0x73, 0x80, 0x77, 0x07, 0xA4, 0x2A, 0x02,
- 0x7C, 0x95, 0x06, 0xA6, 0x34, 0x02, 0x03, 0xA6, 0x4C, 0x04, 0x46, 0x82,
- 0x04, 0x01, 0x03, 0xD8, 0xB4, 0x98, 0x6A, 0x96, 0x46, 0x82, 0xFE, 0x95,
- 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0xB6, 0x2D, 0x02, 0xA6, 0x6C, 0x02,
- 0x07, 0xA6, 0x5A, 0x02, 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x62, 0x02,
- 0xC2, 0x88, 0x7C, 0x95, 0x48, 0x82, 0x60, 0x96, 0x48, 0x82, 0x04, 0x23,
- 0xA0, 0x01, 0x14, 0x23, 0xA1, 0x01, 0x3C, 0x84, 0x04, 0x01, 0x0C, 0xDC,
- 0xE0, 0x23, 0x25, 0x61, 0xEF, 0x00, 0x14, 0x01, 0x4F, 0x04, 0xA8, 0x01,
- 0x6F, 0x00, 0xA5, 0x01, 0x03, 0x23, 0xA4, 0x01, 0x06, 0x23, 0x9C, 0x01,
- 0x24, 0x2B, 0x1C, 0x01, 0x02, 0xA6, 0xAA, 0x02, 0x07, 0xA6, 0x5A, 0x02,
- 0x06, 0xA6, 0x5E, 0x02, 0x03, 0xA6, 0x20, 0x04, 0x01, 0xA6, 0xB4, 0x02,
- 0x00, 0xA6, 0xB4, 0x02, 0x00, 0x33, 0x12, 0x00, 0xC2, 0x88, 0x00, 0x0E,
- 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0x8C, 0x02, 0x4D, 0x04, 0x04, 0x01,
- 0x0B, 0xDC, 0xE7, 0x23, 0x04, 0x61, 0x84, 0x01, 0x10, 0x31, 0x12, 0x35,
- 0x14, 0x01, 0xEC, 0x00, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0xEA, 0x82,
- 0x18, 0x23, 0x04, 0x61, 0x18, 0xA0, 0xE2, 0x02, 0x04, 0x01, 0xA2, 0xC8,
- 0x00, 0x33, 0x1F, 0x00, 0xC2, 0x88, 0x08, 0x31, 0x0A, 0x35, 0x0C, 0x39,
- 0x0E, 0x3D, 0x7E, 0x98, 0xB6, 0x2D, 0x01, 0xA6, 0x14, 0x03, 0x00, 0xA6,
- 0x14, 0x03, 0x07, 0xA6, 0x0C, 0x03, 0x06, 0xA6, 0x10, 0x03, 0x03, 0xA6,
- 0x20, 0x04, 0x02, 0xA6, 0x6C, 0x02, 0x00, 0x33, 0x33, 0x00, 0xC2, 0x88,
- 0x7C, 0x95, 0xEE, 0x82, 0x60, 0x96, 0xEE, 0x82, 0x82, 0x98, 0x80, 0x42,
- 0x7E, 0x98, 0x64, 0xE4, 0x04, 0x01, 0x2D, 0xC8, 0x31, 0x05, 0x07, 0x01,
- 0x00, 0xA2, 0x54, 0x03, 0x00, 0x43, 0x87, 0x01, 0x05, 0x05, 0x86, 0x98,
- 0x7E, 0x98, 0x00, 0xA6, 0x16, 0x03, 0x07, 0xA6, 0x4C, 0x03, 0x03, 0xA6,
- 0x3C, 0x04, 0x06, 0xA6, 0x50, 0x03, 0x01, 0xA6, 0x16, 0x03, 0x00, 0x33,
- 0x25, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x32, 0x83, 0x60, 0x96, 0x32, 0x83,
- 0x04, 0x01, 0x10, 0xCE, 0x07, 0xC8, 0x05, 0x05, 0xEB, 0x04, 0x00, 0x33,
- 0x00, 0x20, 0xC0, 0x20, 0x81, 0x62, 0x72, 0x83, 0x00, 0x01, 0x05, 0x05,
- 0xFF, 0xA2, 0x7A, 0x03, 0xB1, 0x01, 0x08, 0x23, 0xB2, 0x01, 0x2E, 0x83,
- 0x05, 0x05, 0x15, 0x01, 0x00, 0xA2, 0x9A, 0x03, 0xEC, 0x00, 0x6E, 0x00,
- 0x95, 0x01, 0x6C, 0x38, 0x00, 0x3F, 0x00, 0x00, 0x01, 0xA6, 0x96, 0x03,
- 0x00, 0xA6, 0x96, 0x03, 0x10, 0x84, 0x80, 0x42, 0x7E, 0x98, 0x01, 0xA6,
- 0xA4, 0x03, 0x00, 0xA6, 0xBC, 0x03, 0x10, 0x84, 0xA8, 0x98, 0x80, 0x42,
- 0x01, 0xA6, 0xA4, 0x03, 0x07, 0xA6, 0xB2, 0x03, 0xD4, 0x83, 0x7C, 0x95,
- 0xA8, 0x83, 0x00, 0x33, 0x2F, 0x00, 0xC2, 0x88, 0xA8, 0x98, 0x80, 0x42,
- 0x00, 0xA6, 0xBC, 0x03, 0x07, 0xA6, 0xCA, 0x03, 0xD4, 0x83, 0x7C, 0x95,
- 0xC0, 0x83, 0x00, 0x33, 0x26, 0x00, 0xC2, 0x88, 0x38, 0x2B, 0x80, 0x32,
- 0x80, 0x36, 0x04, 0x23, 0xA0, 0x01, 0x12, 0x23, 0xA1, 0x01, 0x10, 0x84,
- 0x07, 0xF0, 0x06, 0xA4, 0xF4, 0x03, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23,
- 0x83, 0x03, 0x80, 0x63, 0x03, 0xA6, 0x0E, 0x04, 0x07, 0xA6, 0x06, 0x04,
- 0x06, 0xA6, 0x0A, 0x04, 0x00, 0x33, 0x17, 0x00, 0xC2, 0x88, 0x7C, 0x95,
- 0xF4, 0x83, 0x60, 0x96, 0xF4, 0x83, 0x20, 0x84, 0x07, 0xF0, 0x06, 0xA4,
- 0x20, 0x04, 0x80, 0x6B, 0x80, 0x67, 0x05, 0x23, 0x83, 0x03, 0x80, 0x63,
- 0xB6, 0x2D, 0x03, 0xA6, 0x3C, 0x04, 0x07, 0xA6, 0x34, 0x04, 0x06, 0xA6,
- 0x38, 0x04, 0x00, 0x33, 0x30, 0x00, 0xC2, 0x88, 0x7C, 0x95, 0x20, 0x84,
- 0x60, 0x96, 0x20, 0x84, 0x1D, 0x01, 0x06, 0xCC, 0x00, 0x33, 0x00, 0x84,
- 0xC0, 0x20, 0x00, 0x23, 0xEA, 0x00, 0x81, 0x62, 0xA2, 0x0D, 0x80, 0x63,
- 0x07, 0xA6, 0x5A, 0x04, 0x00, 0x33, 0x18, 0x00, 0xC2, 0x88, 0x03, 0x03,
- 0x80, 0x63, 0xA3, 0x01, 0x07, 0xA4, 0x64, 0x04, 0x23, 0x01, 0x00, 0xA2,
- 0x86, 0x04, 0x0A, 0xA0, 0x76, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1D, 0x00,
- 0xC2, 0x88, 0x0B, 0xA0, 0x82, 0x04, 0xE0, 0x00, 0x00, 0x33, 0x1E, 0x00,
- 0xC2, 0x88, 0x42, 0x23, 0xF8, 0x88, 0x00, 0x23, 0x22, 0xA3, 0xE6, 0x04,
- 0x08, 0x23, 0x22, 0xA3, 0xA2, 0x04, 0x28, 0x23, 0x22, 0xA3, 0xAE, 0x04,
- 0x02, 0x23, 0x22, 0xA3, 0xC4, 0x04, 0x42, 0x23, 0xF8, 0x88, 0x4A, 0x00,
- 0x06, 0x61, 0x00, 0xA0, 0xAE, 0x04, 0x45, 0x23, 0xF8, 0x88, 0x04, 0x98,
- 0x00, 0xA2, 0xC0, 0x04, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x82, 0xC0, 0x20,
- 0x81, 0x62, 0xE8, 0x81, 0x47, 0x23, 0xF8, 0x88, 0x04, 0x01, 0x0B, 0xDE,
- 0x04, 0x98, 0xB4, 0x98, 0x00, 0x33, 0x00, 0x81, 0xC0, 0x20, 0x81, 0x62,
- 0x14, 0x01, 0x00, 0xA0, 0x00, 0x02, 0x43, 0x23, 0xF8, 0x88, 0x04, 0x23,
- 0xA0, 0x01, 0x44, 0x23, 0xA1, 0x01, 0x80, 0x73, 0x4D, 0x00, 0x03, 0xA3,
- 0xF4, 0x04, 0x00, 0x33, 0x27, 0x00, 0xC2, 0x88, 0x04, 0x01, 0x04, 0xDC,
- 0x02, 0x23, 0xA2, 0x01, 0x04, 0x23, 0xA0, 0x01, 0x04, 0x98, 0x26, 0x95,
- 0x4B, 0x00, 0xF6, 0x00, 0x4F, 0x04, 0x4F, 0x00, 0x00, 0xA3, 0x22, 0x05,
- 0x00, 0x05, 0x76, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x1C, 0x05, 0x0A, 0x85,
- 0x46, 0x97, 0xCD, 0x04, 0x24, 0x85, 0x48, 0x04, 0x84, 0x80, 0x02, 0x01,
- 0x03, 0xDA, 0x80, 0x23, 0x82, 0x01, 0x34, 0x85, 0x02, 0x23, 0xA0, 0x01,
- 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x40, 0x05, 0x1D, 0x01, 0x04, 0xD6,
- 0xFF, 0x23, 0x86, 0x41, 0x4B, 0x60, 0xCB, 0x00, 0xFF, 0x23, 0x80, 0x01,
- 0x49, 0x00, 0x81, 0x01, 0x04, 0x01, 0x02, 0xC8, 0x30, 0x01, 0x80, 0x01,
- 0xF7, 0x04, 0x03, 0x01, 0x49, 0x04, 0x80, 0x01, 0xC9, 0x00, 0x00, 0x05,
- 0x00, 0x01, 0xFF, 0xA0, 0x60, 0x05, 0x77, 0x04, 0x01, 0x23, 0xEA, 0x00,
- 0x5D, 0x00, 0xFE, 0xC7, 0x00, 0x62, 0x00, 0x23, 0xEA, 0x00, 0x00, 0x63,
- 0x07, 0xA4, 0xF8, 0x05, 0x03, 0x03, 0x02, 0xA0, 0x8E, 0x05, 0xF4, 0x85,
- 0x00, 0x33, 0x2D, 0x00, 0xC2, 0x88, 0x04, 0xA0, 0xB8, 0x05, 0x80, 0x63,
- 0x00, 0x23, 0xDF, 0x00, 0x4A, 0x00, 0x06, 0x61, 0x00, 0xA2, 0xA4, 0x05,
- 0x1D, 0x01, 0x06, 0xD6, 0x02, 0x23, 0x02, 0x41, 0x82, 0x01, 0x50, 0x00,
- 0x62, 0x97, 0x04, 0x85, 0x04, 0x23, 0x02, 0x41, 0x82, 0x01, 0x04, 0x85,
- 0x08, 0xA0, 0xBE, 0x05, 0xF4, 0x85, 0x03, 0xA0, 0xC4, 0x05, 0xF4, 0x85,
- 0x01, 0xA0, 0xCE, 0x05, 0x88, 0x00, 0x80, 0x63, 0xCC, 0x86, 0x07, 0xA0,
- 0xEE, 0x05, 0x5F, 0x00, 0x00, 0x2B, 0xDF, 0x08, 0x00, 0xA2, 0xE6, 0x05,
- 0x80, 0x67, 0x80, 0x63, 0x01, 0xA2, 0x7A, 0x06, 0x7C, 0x85, 0x06, 0x23,
- 0x68, 0x98, 0x48, 0x23, 0xF8, 0x88, 0x07, 0x23, 0x80, 0x00, 0x06, 0x87,
- 0x80, 0x63, 0x7C, 0x85, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63, 0x4A, 0x00,
- 0x06, 0x61, 0x00, 0xA2, 0x36, 0x06, 0x1D, 0x01, 0x16, 0xD4, 0xC0, 0x23,
- 0x07, 0x41, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x1C, 0x06, 0x00, 0x33,
- 0x37, 0x00, 0xC2, 0x88, 0x1D, 0x01, 0x01, 0xD6, 0x20, 0x23, 0x63, 0x60,
- 0x83, 0x03, 0x80, 0x63, 0x02, 0x23, 0xDF, 0x00, 0x07, 0xA6, 0x7C, 0x05,
- 0xEF, 0x04, 0x6F, 0x00, 0x00, 0x63, 0x4B, 0x00, 0x06, 0x41, 0xCB, 0x00,
- 0x52, 0x00, 0x06, 0x61, 0x00, 0xA2, 0x4E, 0x06, 0x1D, 0x01, 0x03, 0xCA,
- 0xC0, 0x23, 0x07, 0x41, 0x00, 0x63, 0x1D, 0x01, 0x04, 0xCC, 0x00, 0x33,
- 0x00, 0x83, 0xC0, 0x20, 0x81, 0x62, 0x80, 0x23, 0x07, 0x41, 0x00, 0x63,
- 0x80, 0x67, 0x08, 0x23, 0x83, 0x03, 0x80, 0x63, 0x00, 0x63, 0x01, 0x23,
- 0xDF, 0x00, 0x06, 0xA6, 0x84, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67,
- 0x80, 0x63, 0x00, 0x33, 0x00, 0x40, 0xC0, 0x20, 0x81, 0x62, 0x00, 0x63,
- 0x00, 0x00, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6, 0x94, 0x06,
- 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x00, 0x01, 0xA0, 0x14, 0x07, 0x00, 0x2B,
- 0x40, 0x0E, 0x80, 0x63, 0x01, 0x00, 0x06, 0xA6, 0xAA, 0x06, 0x07, 0xA6,
- 0x7C, 0x05, 0x40, 0x0E, 0x80, 0x63, 0x00, 0x43, 0x00, 0xA0, 0xA2, 0x06,
- 0x06, 0xA6, 0xBC, 0x06, 0x07, 0xA6, 0x7C, 0x05, 0x80, 0x67, 0x40, 0x0E,
- 0x80, 0x63, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x23, 0xDF, 0x00, 0x00, 0x63,
- 0x07, 0xA6, 0xD6, 0x06, 0x00, 0x33, 0x2A, 0x00, 0xC2, 0x88, 0x03, 0x03,
- 0x80, 0x63, 0x89, 0x00, 0x0A, 0x2B, 0x07, 0xA6, 0xE8, 0x06, 0x00, 0x33,
- 0x29, 0x00, 0xC2, 0x88, 0x00, 0x43, 0x00, 0xA2, 0xF4, 0x06, 0xC0, 0x0E,
- 0x80, 0x63, 0xDE, 0x86, 0xC0, 0x0E, 0x00, 0x33, 0x00, 0x80, 0xC0, 0x20,
- 0x81, 0x62, 0x04, 0x01, 0x02, 0xDA, 0x80, 0x63, 0x7C, 0x85, 0x80, 0x7B,
- 0x80, 0x63, 0x06, 0xA6, 0x8C, 0x06, 0x00, 0x33, 0x2C, 0x00, 0xC2, 0x88,
- 0x0C, 0xA2, 0x2E, 0x07, 0xFE, 0x95, 0x83, 0x03, 0x80, 0x63, 0x06, 0xA6,
- 0x2C, 0x07, 0x07, 0xA6, 0x7C, 0x05, 0x00, 0x33, 0x3D, 0x00, 0xC2, 0x88,
- 0x00, 0x00, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63, 0x0C, 0xA0, 0x44, 0x07,
- 0x07, 0xA6, 0x7C, 0x05, 0xBF, 0x23, 0x04, 0x61, 0x84, 0x01, 0xE6, 0x84,
- 0x00, 0x63, 0xF0, 0x04, 0x01, 0x01, 0xF1, 0x00, 0x00, 0x01, 0xF2, 0x00,
- 0x01, 0x05, 0x80, 0x01, 0x72, 0x04, 0x71, 0x00, 0x81, 0x01, 0x70, 0x04,
- 0x80, 0x05, 0x81, 0x05, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04,
- 0x01, 0x01, 0xF1, 0x00, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04, 0x71, 0x00,
- 0x81, 0x01, 0x72, 0x00, 0x80, 0x01, 0x71, 0x04, 0x70, 0x00, 0x80, 0x01,
- 0x70, 0x04, 0x00, 0x63, 0xF0, 0x04, 0xF2, 0x00, 0x72, 0x04, 0x00, 0x01,
- 0xF1, 0x00, 0x70, 0x00, 0x80, 0x01, 0x70, 0x04, 0x71, 0x00, 0x80, 0x01,
- 0x72, 0x00, 0x81, 0x01, 0x71, 0x04, 0x70, 0x00, 0x81, 0x01, 0x70, 0x04,
- 0x00, 0x63, 0x00, 0x23, 0xB3, 0x01, 0x83, 0x05, 0xA3, 0x01, 0xA2, 0x01,
- 0xA1, 0x01, 0x01, 0x23, 0xA0, 0x01, 0x00, 0x01, 0xC8, 0x00, 0x03, 0xA1,
- 0xC4, 0x07, 0x00, 0x33, 0x07, 0x00, 0xC2, 0x88, 0x80, 0x05, 0x81, 0x05,
- 0x04, 0x01, 0x11, 0xC8, 0x48, 0x00, 0xB0, 0x01, 0xB1, 0x01, 0x08, 0x23,
- 0xB2, 0x01, 0x05, 0x01, 0x48, 0x04, 0x00, 0x43, 0x00, 0xA2, 0xE4, 0x07,
- 0x00, 0x05, 0xDA, 0x87, 0x00, 0x01, 0xC8, 0x00, 0xFF, 0x23, 0x80, 0x01,
- 0x05, 0x05, 0x00, 0x63, 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04,
- 0x00, 0x02, 0x80, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04, 0x00, 0x63,
- 0xF7, 0x04, 0x1A, 0x09, 0xF6, 0x08, 0x6E, 0x04, 0x00, 0x02, 0x00, 0xA0,
- 0x14, 0x08, 0x16, 0x88, 0x00, 0x43, 0x76, 0x08, 0x80, 0x02, 0x77, 0x04,
- 0x00, 0x63, 0xF3, 0x04, 0x00, 0x23, 0xF4, 0x00, 0x74, 0x00, 0x80, 0x43,
- 0xF4, 0x00, 0xCF, 0x40, 0x00, 0xA2, 0x44, 0x08, 0x74, 0x04, 0x02, 0x01,
- 0xF7, 0xC9, 0xF6, 0xD9, 0x00, 0x01, 0x01, 0xA1, 0x24, 0x08, 0x04, 0x98,
- 0x26, 0x95, 0x24, 0x88, 0x73, 0x04, 0x00, 0x63, 0xF3, 0x04, 0x75, 0x04,
- 0x5A, 0x88, 0x02, 0x01, 0x04, 0xD8, 0x46, 0x97, 0x04, 0x98, 0x26, 0x95,
- 0x4A, 0x88, 0x75, 0x00, 0x00, 0xA3, 0x64, 0x08, 0x00, 0x05, 0x4E, 0x88,
- 0x73, 0x04, 0x00, 0x63, 0x80, 0x7B, 0x80, 0x63, 0x06, 0xA6, 0x76, 0x08,
- 0x00, 0x33, 0x3E, 0x00, 0xC2, 0x88, 0x80, 0x67, 0x83, 0x03, 0x80, 0x63,
- 0x00, 0x63, 0x38, 0x2B, 0x9C, 0x88, 0x38, 0x2B, 0x92, 0x88, 0x32, 0x09,
- 0x31, 0x05, 0x92, 0x98, 0x05, 0x05, 0xB2, 0x09, 0x00, 0x63, 0x00, 0x32,
- 0x00, 0x36, 0x00, 0x3A, 0x00, 0x3E, 0x00, 0x63, 0x80, 0x32, 0x80, 0x36,
- 0x80, 0x3A, 0x80, 0x3E, 0xB4, 0x3D, 0x00, 0x63, 0x38, 0x2B, 0x40, 0x32,
- 0x40, 0x36, 0x40, 0x3A, 0x40, 0x3E, 0x00, 0x63, 0x5A, 0x20, 0xC9, 0x40,
- 0x00, 0xA0, 0xB4, 0x08, 0x5D, 0x00, 0xFE, 0xC3, 0x00, 0x63, 0x80, 0x73,
- 0xE6, 0x20, 0x02, 0x23, 0xE8, 0x00, 0x82, 0x73, 0xFF, 0xFD, 0x80, 0x73,
- 0x13, 0x23, 0xF8, 0x88, 0x66, 0x20, 0xC0, 0x20, 0x04, 0x23, 0xA0, 0x01,
- 0xA1, 0x23, 0xA1, 0x01, 0x81, 0x62, 0xE2, 0x88, 0x80, 0x73, 0x80, 0x77,
- 0x68, 0x00, 0x00, 0xA2, 0x80, 0x00, 0x03, 0xC2, 0xF1, 0xC7, 0x41, 0x23,
- 0xF8, 0x88, 0x11, 0x23, 0xA1, 0x01, 0x04, 0x23, 0xA0, 0x01, 0xE6, 0x84,
-};
-
-static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf);
-static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL;
-
-/* Microcode buffer is kept after initialization for error recovery. */
-static unsigned char _adv_asc3550_buf[] = {
- 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0x16, 0x18, 0xe4, 0x00, 0xfc,
- 0x01, 0x00, 0x48, 0xe4, 0xbe, 0x18, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00,
- 0x00, 0xfa, 0xff, 0xff, 0x28, 0x0e, 0x9e, 0xe7, 0xff, 0x00, 0x82, 0xe7,
- 0x00, 0xea, 0x00, 0xf6, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0, 0x01, 0xf6,
- 0x01, 0xfa, 0x08, 0x00, 0x03, 0x00, 0x04, 0x00, 0x18, 0xf4, 0x10, 0x00,
- 0x00, 0xec, 0x85, 0xf0, 0xbc, 0x00, 0xd5, 0xf0, 0x8e, 0x0c, 0x38, 0x54,
- 0x00, 0xe6, 0x1e, 0xf0, 0x86, 0xf0, 0xb4, 0x00, 0x98, 0x57, 0xd0, 0x01,
- 0x0c, 0x1c, 0x3e, 0x1c, 0x0c, 0x00, 0xbb, 0x00, 0xaa, 0x18, 0x02, 0x80,
- 0x32, 0xf0, 0x01, 0xfc, 0x88, 0x0c, 0xc6, 0x12, 0x02, 0x13, 0x18, 0x40,
- 0x00, 0x57, 0x01, 0xea, 0x3c, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
- 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
- 0x3e, 0x01, 0xda, 0x0f, 0x22, 0x10, 0x08, 0x12, 0x02, 0x4a, 0xb9, 0x54,
- 0x03, 0x58, 0x1b, 0x80, 0x30, 0xe4, 0x4b, 0xe4, 0x20, 0x00, 0x32, 0x00,
- 0x3e, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
- 0x70, 0x01, 0x72, 0x01, 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x62, 0x0a,
- 0x92, 0x0c, 0x2c, 0x10, 0x2e, 0x10, 0x06, 0x13, 0x4c, 0x1c, 0xbb, 0x55,
- 0x3c, 0x56, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0, 0xb1, 0xf0,
- 0x03, 0xf7, 0x06, 0xf7, 0x03, 0xfc, 0x0f, 0x00, 0x40, 0x00, 0xbe, 0x00,
- 0x00, 0x01, 0xb0, 0x08, 0x30, 0x13, 0x64, 0x15, 0x32, 0x1c, 0x38, 0x1c,
- 0x4e, 0x1c, 0x10, 0x44, 0x02, 0x48, 0x00, 0x4c, 0x04, 0xea, 0x5d, 0xf0,
- 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00,
- 0xcc, 0x00, 0x20, 0x01, 0x4e, 0x01, 0x4e, 0x0b, 0x1e, 0x0e, 0x0c, 0x10,
- 0x0a, 0x12, 0x04, 0x13, 0x40, 0x13, 0x30, 0x1c, 0x00, 0x4e, 0xbd, 0x56,
- 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xa7, 0xf0,
- 0xb8, 0xf0, 0x0e, 0xf7, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00,
- 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00,
- 0xde, 0x03, 0x56, 0x0a, 0x14, 0x0e, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10,
- 0x36, 0x10, 0x0a, 0x13, 0x12, 0x13, 0x52, 0x13, 0x10, 0x15, 0x14, 0x15,
- 0xac, 0x16, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44,
- 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x83, 0x55,
- 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0, 0x0c, 0xf0,
- 0x5c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8, 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa,
- 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x1c, 0x00,
- 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0x22, 0x01,
- 0x26, 0x01, 0x79, 0x01, 0x7a, 0x01, 0xc0, 0x01, 0xc2, 0x01, 0x7c, 0x02,
- 0x5a, 0x03, 0xea, 0x04, 0xe8, 0x07, 0x68, 0x08, 0x69, 0x08, 0xba, 0x08,
- 0xe9, 0x09, 0x06, 0x0b, 0x3a, 0x0e, 0x00, 0x10, 0x1a, 0x10, 0xed, 0x10,
- 0xf1, 0x10, 0x06, 0x12, 0x0c, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x82, 0x13,
- 0x42, 0x14, 0xd6, 0x14, 0x8a, 0x15, 0xc6, 0x17, 0xd2, 0x17, 0x6b, 0x18,
- 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40, 0x0e, 0x47, 0x48, 0x47,
- 0x41, 0x48, 0x89, 0x48, 0x80, 0x4c, 0x00, 0x54, 0x44, 0x55, 0xe5, 0x55,
- 0x14, 0x56, 0x77, 0x57, 0xbf, 0x57, 0x40, 0x5c, 0x06, 0x80, 0x08, 0x90,
- 0x03, 0xa1, 0xfe, 0x9c, 0xf0, 0x29, 0x02, 0xfe, 0xb8, 0x0c, 0xff, 0x10,
- 0x00, 0x00, 0xd0, 0xfe, 0xcc, 0x18, 0x00, 0xcf, 0xfe, 0x80, 0x01, 0xff,
- 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
- 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x48, 0x00, 0x4f, 0xff, 0x04, 0x00,
- 0x00, 0x10, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
- 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x0f,
- 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
- 0xfe, 0x04, 0xf7, 0xcf, 0x2a, 0x67, 0x0b, 0x01, 0xfe, 0xce, 0x0e, 0xfe,
- 0x04, 0xf7, 0xcf, 0x67, 0x0b, 0x3c, 0x2a, 0xfe, 0x3d, 0xf0, 0xfe, 0x02,
- 0x02, 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x91, 0xf0, 0xfe, 0xf0, 0x01, 0xfe,
- 0x90, 0xf0, 0xfe, 0xf0, 0x01, 0xfe, 0x8f, 0xf0, 0x9c, 0x05, 0x51, 0x3b,
- 0x02, 0xfe, 0xd4, 0x0c, 0x01, 0xfe, 0x44, 0x0d, 0xfe, 0xdd, 0x12, 0xfe,
- 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x05, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
- 0x47, 0x18, 0xfe, 0xa6, 0x00, 0xb5, 0xfe, 0x48, 0xf0, 0xfe, 0x86, 0x02,
- 0xfe, 0x49, 0xf0, 0xfe, 0xa0, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xbe, 0x02,
- 0xfe, 0x46, 0xf0, 0xfe, 0x50, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x56, 0x02,
- 0xfe, 0x43, 0xf0, 0xfe, 0x44, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x48, 0x02,
- 0xfe, 0x45, 0xf0, 0xfe, 0x4c, 0x02, 0x17, 0x0b, 0xa0, 0x17, 0x06, 0x18,
- 0x96, 0x02, 0x29, 0xfe, 0x00, 0x1c, 0xde, 0xfe, 0x02, 0x1c, 0xdd, 0xfe,
- 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x20, 0x17, 0xfe, 0xe7, 0x10,
- 0xfe, 0x06, 0xfc, 0xc7, 0x0a, 0x6b, 0x01, 0x9e, 0x02, 0x29, 0x14, 0x4d,
- 0x37, 0x97, 0x01, 0xfe, 0x64, 0x0f, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xbd,
- 0x10, 0x0a, 0x6b, 0x01, 0x82, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
- 0x58, 0x1c, 0x17, 0x06, 0x18, 0x96, 0x2a, 0x25, 0x29, 0xfe, 0x3d, 0xf0,
- 0xfe, 0x02, 0x02, 0x21, 0xfe, 0x94, 0x02, 0xfe, 0x5a, 0x1c, 0xea, 0xfe,
- 0x14, 0x1c, 0x14, 0xfe, 0x30, 0x00, 0x37, 0x97, 0x01, 0xfe, 0x54, 0x0f,
- 0x17, 0x06, 0x18, 0x96, 0x02, 0xd0, 0x1e, 0x20, 0x07, 0x10, 0x34, 0xfe,
- 0x69, 0x10, 0x17, 0x06, 0x18, 0x96, 0xfe, 0x04, 0xec, 0x20, 0x46, 0x3d,
- 0x12, 0x20, 0xfe, 0x05, 0xf6, 0xc7, 0x01, 0xfe, 0x52, 0x16, 0x09, 0x4a,
- 0x4c, 0x35, 0x11, 0x2d, 0x3c, 0x8a, 0x01, 0xe6, 0x02, 0x29, 0x0a, 0x40,
- 0x01, 0x0e, 0x07, 0x00, 0x5d, 0x01, 0x6f, 0xfe, 0x18, 0x10, 0xfe, 0x41,
- 0x58, 0x0a, 0x99, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x64, 0xfe, 0x0c, 0x03,
- 0x01, 0xe6, 0x02, 0x29, 0x2a, 0x46, 0xfe, 0x02, 0xe8, 0x27, 0xf8, 0xfe,
- 0x9e, 0x43, 0xf7, 0xfe, 0x27, 0xf0, 0xfe, 0xdc, 0x01, 0xfe, 0x07, 0x4b,
- 0xfe, 0x20, 0xf0, 0x9c, 0xfe, 0x40, 0x1c, 0x25, 0xd2, 0xfe, 0x26, 0xf0,
- 0xfe, 0x56, 0x03, 0xfe, 0xa0, 0xf0, 0xfe, 0x44, 0x03, 0xfe, 0x11, 0xf0,
- 0x9c, 0xfe, 0xef, 0x10, 0xfe, 0x9f, 0xf0, 0xfe, 0x64, 0x03, 0xeb, 0x0f,
- 0xfe, 0x11, 0x00, 0x02, 0x5a, 0x2a, 0xfe, 0x48, 0x1c, 0xeb, 0x09, 0x04,
- 0x1d, 0xfe, 0x18, 0x13, 0x23, 0x1e, 0x98, 0xac, 0x12, 0x98, 0x0a, 0x40,
- 0x01, 0x0e, 0xac, 0x75, 0x01, 0xfe, 0xbc, 0x15, 0x11, 0xca, 0x25, 0xd2,
- 0xfe, 0x01, 0xf0, 0xd2, 0xfe, 0x82, 0xf0, 0xfe, 0x92, 0x03, 0xec, 0x11,
- 0xfe, 0xe4, 0x00, 0x65, 0xfe, 0xa4, 0x03, 0x25, 0x32, 0x1f, 0xfe, 0xb4,
- 0x03, 0x01, 0x43, 0xfe, 0x06, 0xf0, 0xfe, 0xc4, 0x03, 0x8d, 0x81, 0xfe,
- 0x0a, 0xf0, 0xfe, 0x7a, 0x06, 0x02, 0x22, 0x05, 0x6b, 0x28, 0x16, 0xfe,
- 0xf6, 0x04, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02, 0xd1,
- 0xeb, 0x2a, 0x67, 0x1a, 0xfe, 0x67, 0x1b, 0xf8, 0xf7, 0xfe, 0x48, 0x1c,
- 0x70, 0x01, 0x6e, 0x87, 0x0a, 0x40, 0x01, 0x0e, 0x07, 0x00, 0x16, 0xd3,
- 0x0a, 0xca, 0x01, 0x0e, 0x74, 0x60, 0x59, 0x76, 0x27, 0x05, 0x6b, 0x28,
- 0xfe, 0x10, 0x12, 0x14, 0x2c, 0x01, 0x33, 0x8f, 0xfe, 0x66, 0x02, 0x02,
- 0xd1, 0xbc, 0x7d, 0xbd, 0x7f, 0x25, 0x22, 0x65, 0xfe, 0x3c, 0x04, 0x1f,
- 0xfe, 0x38, 0x04, 0x68, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
- 0x12, 0x2b, 0xff, 0x02, 0x00, 0x10, 0x01, 0x08, 0x1f, 0xfe, 0xe0, 0x04,
- 0x2b, 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd5, 0xfe, 0x4c, 0x44, 0xfe,
- 0x4c, 0x12, 0x60, 0xfe, 0x44, 0x48, 0x13, 0x2c, 0xfe, 0x4c, 0x54, 0x64,
- 0xd3, 0x46, 0x76, 0x27, 0xfa, 0xef, 0xfe, 0x62, 0x13, 0x09, 0x04, 0x1d,
- 0xfe, 0x2a, 0x13, 0x2f, 0x07, 0x7e, 0xa5, 0xfe, 0x20, 0x10, 0x13, 0x2c,
- 0xfe, 0x4c, 0x54, 0x64, 0xd3, 0xfa, 0xef, 0x86, 0x09, 0x04, 0x1d, 0xfe,
- 0x08, 0x13, 0x2f, 0x07, 0x7e, 0x6e, 0x09, 0x04, 0x1d, 0xfe, 0x1c, 0x12,
- 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b, 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe,
- 0x70, 0x0c, 0x02, 0x22, 0x2b, 0x11, 0xfe, 0xe6, 0x00, 0xfe, 0x1c, 0x90,
- 0xf9, 0x03, 0x14, 0x92, 0x01, 0x33, 0x02, 0x29, 0xfe, 0x42, 0x5b, 0x67,
- 0x1a, 0xfe, 0x46, 0x59, 0xf8, 0xf7, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4,
- 0x4f, 0x09, 0x04, 0x0b, 0xfe, 0x78, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x1a,
- 0xfe, 0x70, 0x12, 0x49, 0x04, 0x06, 0xfe, 0x60, 0x13, 0x05, 0xfe, 0xa2,
- 0x00, 0x28, 0x16, 0xfe, 0x80, 0x05, 0xfe, 0x31, 0xe4, 0x6a, 0x49, 0x04,
- 0x0b, 0xfe, 0x4a, 0x13, 0x05, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x42, 0x12,
- 0x5e, 0x01, 0x08, 0x25, 0x32, 0xf1, 0x01, 0x08, 0x26, 0xfe, 0x98, 0x05,
- 0x11, 0xfe, 0xe3, 0x00, 0x23, 0x49, 0xfe, 0x4a, 0xf0, 0xfe, 0x6a, 0x05,
- 0xfe, 0x49, 0xf0, 0xfe, 0x64, 0x05, 0x83, 0x24, 0xfe, 0x21, 0x00, 0xa1,
- 0x24, 0xfe, 0x22, 0x00, 0xa0, 0x24, 0x4c, 0xfe, 0x09, 0x48, 0x01, 0x08,
- 0x26, 0xfe, 0x98, 0x05, 0xfe, 0xe2, 0x08, 0x49, 0x04, 0xc5, 0x3b, 0x01,
- 0x86, 0x24, 0x06, 0x12, 0xcc, 0x37, 0xfe, 0x27, 0x01, 0x09, 0x04, 0x1d,
- 0xfe, 0x22, 0x12, 0x47, 0x01, 0xa7, 0x14, 0x92, 0x09, 0x04, 0x06, 0x3b,
- 0x14, 0xc4, 0x01, 0x33, 0x8f, 0xfe, 0x70, 0x0c, 0x02, 0x22, 0x05, 0xfe,
- 0x9c, 0x00, 0x28, 0xfe, 0x3e, 0x12, 0x05, 0x50, 0x28, 0xfe, 0x36, 0x13,
- 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x08, 0x06, 0x0a, 0x06, 0x49, 0x04, 0x19,
- 0xfe, 0x02, 0x12, 0x5f, 0x01, 0xfe, 0xaa, 0x14, 0x1f, 0xfe, 0xfe, 0x05,
- 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x50, 0xb4, 0x0c,
- 0x50, 0x05, 0xc6, 0x28, 0xfe, 0x62, 0x12, 0x05, 0x3f, 0x28, 0xfe, 0x5a,
- 0x13, 0x01, 0xfe, 0x14, 0x18, 0x01, 0xfe, 0x66, 0x18, 0xfe, 0x43, 0x48,
- 0xb7, 0x19, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d,
- 0x85, 0xb7, 0x69, 0x47, 0x01, 0xa7, 0x26, 0xfe, 0x72, 0x06, 0x49, 0x04,
- 0x1b, 0xdf, 0x89, 0x0a, 0x4d, 0x01, 0xfe, 0xd8, 0x14, 0x1f, 0xfe, 0x68,
- 0x06, 0x11, 0x9a, 0x01, 0x43, 0x11, 0xfe, 0xe5, 0x00, 0x05, 0x3f, 0xb4,
- 0x0c, 0x3f, 0x17, 0x06, 0x01, 0xa7, 0xec, 0x72, 0x70, 0x01, 0x6e, 0x87,
- 0x11, 0xfe, 0xe2, 0x00, 0x01, 0x08, 0x25, 0x32, 0xfe, 0x0a, 0xf0, 0xfe,
- 0xa6, 0x06, 0x8c, 0xfe, 0x5c, 0x07, 0xfe, 0x06, 0xf0, 0xfe, 0x64, 0x07,
- 0x8d, 0x81, 0x02, 0x22, 0x09, 0x04, 0x0b, 0xfe, 0x2e, 0x12, 0x15, 0x1a,
- 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00,
- 0x01, 0x08, 0xfe, 0x99, 0xa4, 0x01, 0x08, 0x15, 0x00, 0x02, 0xfe, 0x32,
- 0x08, 0x61, 0x04, 0x1b, 0xfe, 0x38, 0x12, 0x09, 0x04, 0x1b, 0x6e, 0x15,
- 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x00, 0x01,
- 0x08, 0x15, 0x00, 0x01, 0x08, 0x15, 0x06, 0x01, 0x08, 0x15, 0x00, 0x02,
- 0xd9, 0x66, 0x4c, 0xfe, 0x3a, 0x55, 0x5f, 0xfe, 0x9a, 0x81, 0x4b, 0x1d,
- 0xba, 0xfe, 0x32, 0x07, 0x0a, 0x1d, 0xfe, 0x09, 0x6f, 0xaf, 0xfe, 0xca,
- 0x45, 0xfe, 0x32, 0x12, 0x62, 0x2c, 0x85, 0x66, 0x7b, 0x01, 0x08, 0x25,
- 0x32, 0xfe, 0x0a, 0xf0, 0xfe, 0x32, 0x07, 0x8d, 0x81, 0x8c, 0xfe, 0x5c,
- 0x07, 0x02, 0x22, 0x01, 0x43, 0x02, 0xfe, 0x8a, 0x06, 0x15, 0x19, 0x02,
- 0xfe, 0x8a, 0x06, 0xfe, 0x9c, 0xf7, 0xd4, 0xfe, 0x2c, 0x90, 0xfe, 0xae,
- 0x90, 0x77, 0xfe, 0xca, 0x07, 0x0c, 0x54, 0x18, 0x55, 0x09, 0x4a, 0x6a,
- 0x35, 0x1e, 0x20, 0x07, 0x10, 0xfe, 0x0e, 0x12, 0x74, 0xfe, 0x80, 0x80,
- 0x37, 0x20, 0x63, 0x27, 0xfe, 0x06, 0x10, 0xfe, 0x83, 0xe7, 0xc4, 0xa1,
- 0xfe, 0x03, 0x40, 0x09, 0x4a, 0x4f, 0x35, 0x01, 0xa8, 0xad, 0xfe, 0x1f,
- 0x40, 0x12, 0x58, 0x01, 0xa5, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
- 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x83, 0xfb, 0xfe, 0x8a, 0x90, 0x0c, 0x52,
- 0x18, 0x53, 0xfe, 0x0c, 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe,
- 0xc2, 0x50, 0x0c, 0x39, 0x18, 0x3a, 0xfe, 0x4a, 0x10, 0x09, 0x04, 0x6a,
- 0xfe, 0x2a, 0x12, 0xfe, 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x54, 0x18,
- 0x55, 0x09, 0x04, 0x4f, 0x85, 0x01, 0xa8, 0xfe, 0x1f, 0x80, 0x12, 0x58,
- 0xfe, 0x44, 0x90, 0xfe, 0xc6, 0x90, 0x0c, 0x56, 0x18, 0x57, 0xfb, 0xfe,
- 0x8a, 0x90, 0x0c, 0x52, 0x18, 0x53, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90,
- 0x0c, 0x39, 0x18, 0x3a, 0x0c, 0x38, 0x18, 0x4e, 0x09, 0x4a, 0x19, 0x35,
- 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x48, 0x08, 0xfe, 0x9e, 0xf0,
- 0xfe, 0x5c, 0x08, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0xfe, 0x80,
- 0x08, 0xb9, 0xfe, 0x9e, 0x08, 0x8c, 0xfe, 0x74, 0x08, 0xfe, 0x06, 0xf0,
- 0xfe, 0x7a, 0x08, 0x8d, 0x81, 0x02, 0x22, 0x01, 0x43, 0xfe, 0xc9, 0x10,
- 0x15, 0x19, 0xfe, 0xc9, 0x10, 0x61, 0x04, 0x06, 0xfe, 0x10, 0x12, 0x61,
- 0x04, 0x0b, 0x45, 0x09, 0x04, 0x0b, 0xfe, 0x68, 0x12, 0xfe, 0x2e, 0x1c,
- 0x02, 0xfe, 0x24, 0x0a, 0x61, 0x04, 0x06, 0x45, 0x61, 0x04, 0x0b, 0xfe,
- 0x52, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0x1e, 0x09, 0xfe,
- 0xac, 0xf0, 0xfe, 0xbe, 0x08, 0xfe, 0x8a, 0x10, 0xaa, 0xfe, 0xf3, 0x10,
- 0xfe, 0xad, 0xf0, 0xfe, 0xca, 0x08, 0x02, 0xfe, 0x24, 0x0a, 0xab, 0xfe,
- 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0x9d, 0xe9, 0x1c, 0xfe, 0x00, 0xfe, 0xfe,
- 0x1c, 0x12, 0xb5, 0xfe, 0xd2, 0xf0, 0x9d, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
- 0x16, 0x9d, 0x05, 0xcb, 0x1c, 0x06, 0x16, 0x9d, 0xb8, 0x6d, 0xb9, 0x6d,
- 0xaa, 0xab, 0xfe, 0xb1, 0x10, 0x70, 0x5e, 0x2b, 0x14, 0x92, 0x01, 0x33,
- 0x0f, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x5a, 0x0f, 0x7c, 0x02, 0x5a,
- 0xfe, 0x74, 0x18, 0x1c, 0xfe, 0x00, 0xf8, 0x16, 0x6d, 0x67, 0x1b, 0x01,
- 0xfe, 0x44, 0x0d, 0x3b, 0x01, 0xe6, 0x1e, 0x27, 0x74, 0x67, 0x1a, 0x02,
- 0x6d, 0x09, 0x04, 0x0b, 0x21, 0xfe, 0x06, 0x0a, 0x09, 0x04, 0x6a, 0xfe,
- 0x82, 0x12, 0x09, 0x04, 0x19, 0xfe, 0x66, 0x13, 0x1e, 0x58, 0xac, 0xfc,
- 0xfe, 0x83, 0x80, 0xfe, 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91,
- 0xfe, 0x86, 0x91, 0x63, 0x27, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x77,
- 0xd7, 0x05, 0x54, 0x31, 0x55, 0x0c, 0x7b, 0x18, 0x7c, 0xbe, 0x54, 0xbf,
- 0x55, 0x01, 0xa8, 0xad, 0x63, 0x27, 0x12, 0x58, 0xc0, 0x38, 0xc1, 0x4e,
- 0x79, 0x56, 0x68, 0x57, 0xf4, 0xf5, 0xfe, 0x04, 0xfa, 0x38, 0xfe, 0x05,
- 0xfa, 0x4e, 0x01, 0xa5, 0xa2, 0x23, 0x0c, 0x7b, 0x0c, 0x7c, 0x79, 0x56,
- 0x68, 0x57, 0xfe, 0x12, 0x10, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x79, 0x39,
- 0x68, 0x3a, 0x09, 0x04, 0xfe, 0xf7, 0x00, 0x35, 0x05, 0x52, 0x31, 0x53,
- 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59,
- 0x02, 0x6d, 0x09, 0x04, 0x19, 0x16, 0xd7, 0x09, 0x04, 0xfe, 0xf7, 0x00,
- 0x35, 0xfe, 0x3a, 0x55, 0xfe, 0x19, 0x81, 0x5f, 0xfe, 0x10, 0x90, 0xfe,
- 0x92, 0x90, 0xfe, 0xd7, 0x10, 0x2f, 0x07, 0x9b, 0x16, 0xfe, 0xc6, 0x08,
- 0x11, 0x9b, 0x09, 0x04, 0x0b, 0xfe, 0x14, 0x13, 0x05, 0x39, 0x31, 0x3a,
- 0x77, 0xfe, 0xc6, 0x08, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x6d,
- 0x23, 0x47, 0xfe, 0x19, 0x80, 0xde, 0x09, 0x04, 0x0b, 0xfe, 0x1a, 0x12,
- 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41, 0xe9, 0xb5, 0xfe, 0xd1, 0xf0, 0xd9,
- 0x14, 0x7a, 0x01, 0x33, 0x0f, 0xfe, 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe,
- 0x6c, 0x19, 0xbe, 0x39, 0xfe, 0xed, 0x19, 0xbf, 0x3a, 0xfe, 0x0c, 0x51,
- 0xfe, 0x8e, 0x51, 0xe9, 0x1c, 0xfe, 0x00, 0xff, 0x34, 0xfe, 0x74, 0x10,
- 0xb5, 0xfe, 0xd2, 0xf0, 0xfe, 0xb2, 0x0a, 0xfe, 0x76, 0x18, 0x1c, 0x1a,
- 0x84, 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0x08, 0x13, 0x0f, 0xfe, 0x16, 0x00,
- 0x02, 0x5a, 0xfe, 0xd1, 0xf0, 0xfe, 0xc4, 0x0a, 0x14, 0x7a, 0x01, 0x33,
- 0x0f, 0xfe, 0x17, 0x00, 0xfe, 0x42, 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xca,
- 0x0a, 0xfe, 0x3c, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xd6, 0x0a, 0x0f, 0xfe,
- 0x22, 0x00, 0x02, 0x5a, 0xfe, 0xcb, 0xf0, 0xfe, 0xe2, 0x0a, 0x0f, 0xfe,
- 0x24, 0x00, 0x02, 0x5a, 0xfe, 0xd0, 0xf0, 0xfe, 0xec, 0x0a, 0x0f, 0x93,
- 0xdc, 0xfe, 0xcf, 0xf0, 0xfe, 0xf6, 0x0a, 0x0f, 0x4c, 0xfe, 0x10, 0x10,
- 0xfe, 0xcc, 0xf0, 0xd9, 0x61, 0x04, 0x19, 0x3b, 0x0f, 0xfe, 0x12, 0x00,
- 0x2a, 0x13, 0xfe, 0x4e, 0x11, 0x65, 0xfe, 0x0c, 0x0b, 0xfe, 0x9e, 0xf0,
- 0xfe, 0x20, 0x0b, 0xb1, 0x16, 0x32, 0x2a, 0x73, 0xdd, 0xb8, 0x22, 0xb9,
- 0x22, 0x2a, 0xec, 0x65, 0xfe, 0x2c, 0x0b, 0x25, 0x32, 0x8c, 0xfe, 0x48,
- 0x0b, 0x8d, 0x81, 0xb8, 0xd4, 0xb9, 0xd4, 0x02, 0x22, 0x01, 0x43, 0xfe,
- 0xdb, 0x10, 0x11, 0xfe, 0xe8, 0x00, 0xaa, 0xab, 0x70, 0xbc, 0x7d, 0xbd,
- 0x7f, 0xfe, 0x89, 0xf0, 0x22, 0x30, 0x2e, 0xd8, 0xbc, 0x7d, 0xbd, 0x7f,
- 0x01, 0x08, 0x1f, 0x22, 0x30, 0x2e, 0xd6, 0xb1, 0x45, 0x0f, 0xfe, 0x42,
- 0x00, 0x02, 0x5a, 0x78, 0x06, 0xfe, 0x81, 0x49, 0x16, 0xfe, 0x38, 0x0c,
- 0x09, 0x04, 0x0b, 0xfe, 0x44, 0x13, 0x0f, 0x00, 0x4b, 0x0b, 0xfe, 0x54,
- 0x12, 0x4b, 0xfe, 0x28, 0x00, 0x21, 0xfe, 0xa6, 0x0c, 0x0a, 0x40, 0x01,
- 0x0e, 0x07, 0x00, 0x5d, 0x3e, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01,
- 0xe7, 0x01, 0xe8, 0x0a, 0x99, 0x01, 0xfe, 0x32, 0x0e, 0x59, 0x11, 0x2d,
- 0x01, 0x6f, 0x02, 0x29, 0x0f, 0xfe, 0x44, 0x00, 0x4b, 0x0b, 0xdf, 0x3e,
- 0x0b, 0xfe, 0xb4, 0x10, 0x01, 0x86, 0x3e, 0x0b, 0xfe, 0xaa, 0x10, 0x01,
- 0x86, 0xfe, 0x19, 0x82, 0xfe, 0x34, 0x46, 0xa3, 0x3e, 0x0b, 0x0f, 0xfe,
- 0x43, 0x00, 0xfe, 0x96, 0x10, 0x09, 0x4a, 0x0b, 0x35, 0x01, 0xe7, 0x01,
- 0xe8, 0x59, 0x11, 0x2d, 0x01, 0x6f, 0x67, 0x0b, 0x59, 0x3c, 0x8a, 0x02,
- 0xfe, 0x2a, 0x03, 0x09, 0x04, 0x0b, 0x84, 0x3e, 0x0b, 0x0f, 0x00, 0xfe,
- 0x5c, 0x10, 0x61, 0x04, 0x1b, 0xfe, 0x58, 0x12, 0x09, 0x04, 0x1b, 0xfe,
- 0x50, 0x13, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x5c, 0x0c, 0xfe,
- 0x1c, 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x62, 0x0c, 0x09, 0x4a, 0x1b, 0x35,
- 0xfe, 0xa9, 0x10, 0x0f, 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0b, 0x5f,
- 0x5c, 0x0f, 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x0f, 0xfe, 0x47, 0x00,
- 0xa1, 0x0f, 0xfe, 0x41, 0x00, 0xa0, 0x0f, 0xfe, 0x24, 0x00, 0x87, 0xaa,
- 0xab, 0x70, 0x05, 0x6b, 0x28, 0x21, 0xd1, 0x5f, 0xfe, 0x04, 0xe6, 0x1b,
- 0xfe, 0x9d, 0x41, 0xfe, 0x1c, 0x42, 0x59, 0x01, 0xda, 0x02, 0x29, 0xea,
- 0x14, 0x0b, 0x37, 0x95, 0xa9, 0x14, 0xfe, 0x31, 0x00, 0x37, 0x97, 0x01,
- 0xfe, 0x54, 0x0f, 0x02, 0xd0, 0x3c, 0xfe, 0x06, 0xec, 0xc9, 0xee, 0x3e,
- 0x1d, 0xfe, 0xce, 0x45, 0x34, 0x3c, 0xfe, 0x06, 0xea, 0xc9, 0xfe, 0x47,
- 0x4b, 0x89, 0xfe, 0x75, 0x57, 0x05, 0x51, 0xfe, 0x98, 0x56, 0xfe, 0x38,
- 0x12, 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x44, 0x48, 0x46, 0x09, 0x04, 0x1d,
- 0xfe, 0x1a, 0x13, 0x0a, 0x40, 0x01, 0x0e, 0x47, 0xfe, 0x41, 0x58, 0x0a,
- 0x99, 0x01, 0x0e, 0xfe, 0x49, 0x54, 0x8e, 0xfe, 0x2a, 0x0d, 0x02, 0xfe,
- 0x2a, 0x03, 0x0a, 0x51, 0xfe, 0xee, 0x14, 0xee, 0x3e, 0x1d, 0xfe, 0xce,
- 0x45, 0x34, 0x3c, 0xfe, 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x29, 0x1e,
- 0x20, 0x07, 0x10, 0xfe, 0x9e, 0x12, 0x23, 0x12, 0x4d, 0x12, 0x94, 0x12,
- 0xce, 0x1e, 0x2d, 0x47, 0x37, 0x2d, 0xb1, 0xe0, 0xfe, 0xbc, 0xf0, 0xfe,
- 0xec, 0x0d, 0x13, 0x06, 0x12, 0x4d, 0x01, 0xfe, 0xe2, 0x15, 0x05, 0xfe,
- 0x38, 0x01, 0x31, 0xfe, 0x3a, 0x01, 0x77, 0xfe, 0xf0, 0x0d, 0xfe, 0x02,
- 0xec, 0xce, 0x62, 0x00, 0x5d, 0xfe, 0x04, 0xec, 0x20, 0x46, 0xfe, 0x05,
- 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x52, 0x16, 0xfb, 0xfe, 0x48, 0xf4,
- 0x0d, 0xfe, 0x18, 0x13, 0xaf, 0xfe, 0x02, 0xea, 0xce, 0x62, 0x7a, 0xfe,
- 0xc5, 0x13, 0x14, 0x1b, 0x37, 0x95, 0xa9, 0x5c, 0x05, 0xfe, 0x38, 0x01,
- 0x1c, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x05, 0xfe, 0x3a, 0x01,
- 0x0c, 0xfe, 0x62, 0x01, 0x3d, 0x12, 0x20, 0x24, 0x06, 0x12, 0x2d, 0x11,
- 0x2d, 0x8a, 0x13, 0x06, 0x03, 0x23, 0x03, 0x1e, 0x4d, 0xfe, 0xf7, 0x12,
- 0x1e, 0x94, 0xac, 0x12, 0x94, 0x07, 0x7a, 0xfe, 0x71, 0x13, 0xfe, 0x24,
- 0x1c, 0x14, 0x1a, 0x37, 0x95, 0xa9, 0xfe, 0xd9, 0x10, 0xb6, 0xfe, 0x03,
- 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xb6, 0xfe, 0x03, 0xdc,
- 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x23,
- 0xfe, 0x00, 0xcc, 0x03, 0xfe, 0x03, 0x57, 0xb6, 0x75, 0x03, 0x09, 0x04,
- 0x4c, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
- 0xfe, 0x1e, 0x80, 0xe1, 0xfe, 0x1d, 0x80, 0xa4, 0xfe, 0x0c, 0x90, 0xfe,
- 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xa3, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
- 0x0b, 0xfe, 0x3c, 0x50, 0xa0, 0x01, 0xfe, 0x82, 0x16, 0x2f, 0x07, 0x2d,
- 0xe0, 0x01, 0xfe, 0xbc, 0x15, 0x09, 0x04, 0x1d, 0x45, 0x01, 0xe7, 0x01,
- 0xe8, 0x11, 0xfe, 0xe9, 0x00, 0x09, 0x04, 0x4c, 0xfe, 0x2c, 0x13, 0x01,
- 0xfe, 0x14, 0x16, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
- 0x0c, 0xfe, 0x64, 0x01, 0x18, 0xfe, 0x66, 0x01, 0x09, 0x04, 0x4f, 0xfe,
- 0x12, 0x12, 0xfe, 0x03, 0x80, 0x74, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
- 0x40, 0x12, 0x20, 0x63, 0x27, 0x11, 0xc8, 0x59, 0x1e, 0x20, 0xed, 0x76,
- 0x20, 0x03, 0xfe, 0x08, 0x1c, 0x05, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
- 0x05, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x05, 0xfe, 0xb0, 0x00, 0xfe,
- 0x08, 0x58, 0x05, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
- 0x24, 0x69, 0x12, 0xc9, 0x23, 0x0c, 0x50, 0x0c, 0x3f, 0x13, 0x40, 0x48,
- 0x5f, 0x17, 0x1d, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x21, 0xfe, 0x08,
- 0x0f, 0x3e, 0x10, 0x13, 0x42, 0x48, 0x17, 0x4c, 0xfe, 0x90, 0x4d, 0xfe,
- 0x91, 0x54, 0x21, 0xfe, 0x1e, 0x0f, 0x24, 0x10, 0x12, 0x20, 0x78, 0x2c,
- 0x46, 0x1e, 0x20, 0xed, 0x76, 0x20, 0x11, 0xc8, 0xf6, 0xfe, 0xd6, 0xf0,
- 0xfe, 0x32, 0x0f, 0xea, 0x70, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
- 0x18, 0x1c, 0x03, 0x3c, 0xfe, 0x0c, 0x14, 0xee, 0xfe, 0x07, 0xe6, 0x1d,
- 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x03, 0x01, 0x86, 0x78, 0x2c, 0x46,
- 0xfa, 0xef, 0xfe, 0x42, 0x13, 0x2f, 0x07, 0x2d, 0xfe, 0x34, 0x13, 0x0a,
- 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x36, 0x12, 0xf0, 0xfe, 0x45, 0x48, 0x01,
- 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13, 0x3d, 0x75, 0x07, 0x10,
- 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xfe, 0x80, 0x5c, 0x01, 0x6f, 0xfe, 0x0e,
- 0x10, 0x07, 0x7e, 0x45, 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x6c, 0x0f, 0x03,
- 0xfe, 0x44, 0x58, 0x74, 0xfe, 0x01, 0xec, 0x97, 0xfe, 0x9e, 0x40, 0xfe,
- 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x1b, 0x76, 0x27, 0x01, 0xda, 0xfe,
- 0xdd, 0x10, 0x2a, 0xbc, 0x7d, 0xbd, 0x7f, 0x30, 0x2e, 0xd5, 0x07, 0x1b,
- 0xfe, 0x48, 0x12, 0x07, 0x0b, 0xfe, 0x56, 0x12, 0x07, 0x1a, 0xfe, 0x30,
- 0x12, 0x07, 0xc2, 0x16, 0xfe, 0x3e, 0x11, 0x07, 0xfe, 0x23, 0x00, 0x16,
- 0xfe, 0x4a, 0x11, 0x07, 0x06, 0x16, 0xfe, 0xa8, 0x11, 0x07, 0x19, 0xfe,
- 0x12, 0x12, 0x07, 0x00, 0x16, 0x22, 0x14, 0xc2, 0x01, 0x33, 0x9f, 0x2b,
- 0x01, 0x08, 0x8c, 0x43, 0x03, 0x2b, 0xfe, 0x62, 0x08, 0x0a, 0xca, 0x01,
- 0xfe, 0x32, 0x0e, 0x11, 0x7e, 0x02, 0x29, 0x2b, 0x2f, 0x07, 0x9b, 0xfe,
- 0xd9, 0x13, 0x79, 0x39, 0x68, 0x3a, 0x77, 0xfe, 0xfc, 0x10, 0x09, 0x04,
- 0x6a, 0xfe, 0x72, 0x12, 0xc0, 0x38, 0xc1, 0x4e, 0xf4, 0xf5, 0x8e, 0xfe,
- 0xc6, 0x10, 0x1e, 0x58, 0xfe, 0x26, 0x13, 0x05, 0x7b, 0x31, 0x7c, 0x77,
- 0xfe, 0x82, 0x0c, 0x0c, 0x54, 0x18, 0x55, 0x23, 0x0c, 0x7b, 0x0c, 0x7c,
- 0x01, 0xa8, 0x24, 0x69, 0x73, 0x12, 0x58, 0x01, 0xa5, 0xc0, 0x38, 0xc1,
- 0x4e, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x38, 0xfe,
- 0x05, 0xfa, 0x4e, 0xfe, 0x91, 0x10, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x40,
- 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x56, 0x18, 0x57, 0x83, 0xc0, 0x38, 0xc1,
- 0x4e, 0xf4, 0xf5, 0x05, 0x52, 0x31, 0x53, 0xfe, 0x00, 0x56, 0xfe, 0xa1,
- 0x56, 0x0c, 0x52, 0x18, 0x53, 0x09, 0x04, 0x6a, 0xfe, 0x1e, 0x12, 0x1e,
- 0x58, 0xfe, 0x1f, 0x40, 0x05, 0x54, 0x31, 0x55, 0xfe, 0x2c, 0x50, 0xfe,
- 0xae, 0x50, 0x05, 0x56, 0x31, 0x57, 0xfe, 0x44, 0x50, 0xfe, 0xc6, 0x50,
- 0x05, 0x52, 0x31, 0x53, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x05, 0x39,
- 0x31, 0x3a, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x02, 0x5c, 0x24, 0x06,
- 0x12, 0xcd, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x1f, 0x44, 0x30, 0x2e, 0xd5,
- 0x07, 0x06, 0x21, 0x44, 0x2f, 0x07, 0x9b, 0x21, 0x5b, 0x01, 0x6e, 0x1c,
- 0x3d, 0x16, 0x44, 0x09, 0x04, 0x0b, 0xe2, 0x79, 0x39, 0x68, 0x3a, 0xfe,
- 0x0a, 0x55, 0x34, 0xfe, 0x8b, 0x55, 0xbe, 0x39, 0xbf, 0x3a, 0xfe, 0x0c,
- 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x5b, 0xfe, 0x19, 0x81, 0xaf, 0xfe, 0x19,
- 0x41, 0x02, 0x5b, 0x2b, 0x01, 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e,
- 0xd8, 0x4b, 0x1a, 0xfe, 0xa6, 0x12, 0x4b, 0x0b, 0x3b, 0x02, 0x44, 0x01,
- 0x08, 0x25, 0x32, 0x1f, 0xa2, 0x30, 0x2e, 0xd6, 0x07, 0x1a, 0x21, 0x44,
- 0x01, 0x08, 0x1f, 0xa2, 0x30, 0x2e, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49,
- 0x60, 0x05, 0xfe, 0x9c, 0x00, 0x28, 0x84, 0x49, 0x04, 0x19, 0x34, 0x9f,
- 0xfe, 0xbb, 0x45, 0x4b, 0x00, 0x45, 0x3e, 0x06, 0x78, 0x3d, 0xfe, 0xda,
- 0x14, 0x01, 0x6e, 0x87, 0xfe, 0x4b, 0x45, 0xe2, 0x2f, 0x07, 0x9a, 0xe1,
- 0x05, 0xc6, 0x28, 0x84, 0x05, 0x3f, 0x28, 0x34, 0x5e, 0x02, 0x5b, 0xfe,
- 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17, 0x05, 0x50, 0xb4, 0x0c,
- 0x50, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe, 0xaa, 0x14, 0x02,
- 0x5c, 0x01, 0x08, 0x25, 0x32, 0x1f, 0x44, 0x30, 0x2e, 0xd6, 0x07, 0x06,
- 0x21, 0x44, 0x01, 0xfe, 0x8e, 0x13, 0xfe, 0x42, 0x58, 0xfe, 0x82, 0x14,
- 0xfe, 0xa4, 0x14, 0x87, 0xfe, 0x4a, 0xf4, 0x0b, 0x16, 0x44, 0xfe, 0x4a,
- 0xf4, 0x06, 0xfe, 0x0c, 0x12, 0x2f, 0x07, 0x9a, 0x85, 0x02, 0x5b, 0x05,
- 0x3f, 0xb4, 0x0c, 0x3f, 0x5e, 0x2b, 0x01, 0x08, 0x26, 0x5c, 0x01, 0xfe,
- 0xd8, 0x14, 0x02, 0x5c, 0x13, 0x06, 0x65, 0xfe, 0xca, 0x12, 0x26, 0xfe,
- 0xe0, 0x12, 0x72, 0xf1, 0x01, 0x08, 0x23, 0x72, 0x03, 0x8f, 0xfe, 0xdc,
- 0x12, 0x25, 0xfe, 0xdc, 0x12, 0x1f, 0xfe, 0xca, 0x12, 0x5e, 0x2b, 0x01,
- 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
- 0x1c, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x03, 0x13,
- 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0x1c, 0x3d, 0xfe, 0x30, 0x56,
- 0xfe, 0x00, 0x5c, 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b,
- 0x03, 0x13, 0x6c, 0xff, 0x02, 0x00, 0x57, 0x48, 0x8b, 0xfe, 0x0b, 0x58,
- 0x03, 0x0a, 0x50, 0x01, 0x82, 0x0a, 0x3f, 0x01, 0x82, 0x03, 0xfc, 0x1c,
- 0x10, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x19, 0x48, 0xfe, 0x00,
- 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c, 0x63, 0x27,
- 0x0c, 0x52, 0x18, 0x53, 0xbe, 0x56, 0xbf, 0x57, 0x03, 0xfe, 0x62, 0x08,
- 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x74, 0x03, 0x01,
- 0xfe, 0x14, 0x18, 0xfe, 0x42, 0x48, 0x5f, 0x60, 0x89, 0x01, 0x08, 0x1f,
- 0xfe, 0xa2, 0x14, 0x30, 0x2e, 0xd8, 0x01, 0x08, 0x1f, 0xfe, 0xa2, 0x14,
- 0x30, 0x2e, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x05, 0xc6, 0x28, 0xfe,
- 0xcc, 0x12, 0x49, 0x04, 0x1b, 0xfe, 0xc4, 0x13, 0x23, 0x62, 0x1b, 0xe2,
- 0x4b, 0xc3, 0x64, 0xfe, 0xe8, 0x13, 0x3b, 0x13, 0x06, 0x17, 0xc3, 0x78,
- 0xdb, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xa1, 0xff, 0x02, 0x83,
- 0x55, 0x62, 0x1a, 0xa4, 0xbb, 0xfe, 0x30, 0x00, 0x8e, 0xe4, 0x17, 0x2c,
- 0x13, 0x06, 0xfe, 0x56, 0x10, 0x62, 0x0b, 0xe1, 0xbb, 0xfe, 0x64, 0x00,
- 0x8e, 0xe4, 0x0a, 0xfe, 0x64, 0x00, 0x17, 0x93, 0x13, 0x06, 0xfe, 0x28,
- 0x10, 0x62, 0x06, 0xfe, 0x60, 0x13, 0xbb, 0xfe, 0xc8, 0x00, 0x8e, 0xe4,
- 0x0a, 0xfe, 0xc8, 0x00, 0x17, 0x4d, 0x13, 0x06, 0x83, 0xbb, 0xfe, 0x90,
- 0x01, 0xba, 0xfe, 0x4e, 0x14, 0x89, 0xfe, 0x12, 0x10, 0xfe, 0x43, 0xf4,
- 0x94, 0xfe, 0x56, 0xf0, 0xfe, 0x60, 0x14, 0xfe, 0x04, 0xf4, 0x6c, 0xfe,
- 0x43, 0xf4, 0x93, 0xfe, 0xf3, 0x10, 0xf9, 0x01, 0xfe, 0x22, 0x13, 0x1c,
- 0x3d, 0xfe, 0x10, 0x13, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x69, 0xba,
- 0xfe, 0x9c, 0x14, 0xb7, 0x69, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe,
- 0x4d, 0xe4, 0x19, 0xba, 0xfe, 0x9c, 0x14, 0xb7, 0x19, 0x83, 0x60, 0x23,
- 0xfe, 0x4d, 0xf4, 0x00, 0xdf, 0x89, 0x13, 0x06, 0xfe, 0xb4, 0x56, 0xfe,
- 0xc3, 0x58, 0x03, 0x60, 0x13, 0x0b, 0x03, 0x15, 0x06, 0x01, 0x08, 0x26,
- 0xe5, 0x15, 0x0b, 0x01, 0x08, 0x26, 0xe5, 0x15, 0x1a, 0x01, 0x08, 0x26,
- 0xe5, 0x72, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x03, 0x15, 0x06, 0x01, 0x08,
- 0x26, 0xa6, 0x15, 0x1a, 0x01, 0x08, 0x26, 0xa6, 0x15, 0x06, 0x01, 0x08,
- 0x26, 0xa6, 0xfe, 0x89, 0x49, 0x01, 0x08, 0x26, 0xa6, 0x72, 0xfe, 0x89,
- 0x4a, 0x01, 0x08, 0x03, 0x60, 0x03, 0x1e, 0xcc, 0x07, 0x06, 0xfe, 0x44,
- 0x13, 0xad, 0x12, 0xcc, 0xfe, 0x49, 0xf4, 0x00, 0x3b, 0x72, 0x9f, 0x5e,
- 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xf1, 0x01, 0x08, 0x2f, 0x07, 0xfe,
- 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1f, 0xfe, 0x5a, 0x15, 0x23, 0x12, 0xcd,
- 0x01, 0x43, 0x1e, 0xcd, 0x07, 0x06, 0x45, 0x09, 0x4a, 0x06, 0x35, 0x03,
- 0x0a, 0x42, 0x01, 0x0e, 0xed, 0x88, 0x07, 0x10, 0xa4, 0x0a, 0x80, 0x01,
- 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03, 0x0a, 0x80, 0x01, 0x0e, 0x88,
- 0xfe, 0x80, 0xe7, 0x10, 0x07, 0x10, 0x84, 0xfe, 0x45, 0x58, 0x01, 0xe3,
- 0x88, 0x03, 0x0a, 0x42, 0x01, 0x0e, 0x88, 0x0a, 0x51, 0x01, 0x9e, 0x03,
- 0x0a, 0x42, 0x01, 0x0e, 0xfe, 0x80, 0x80, 0xf2, 0xfe, 0x49, 0xe4, 0x10,
- 0xa4, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x0a, 0x51, 0x01, 0x82, 0x03, 0x17,
- 0x10, 0x71, 0x66, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde,
- 0xfe, 0x24, 0x1c, 0xfe, 0x1d, 0xf7, 0x1d, 0x90, 0xfe, 0xf6, 0x15, 0x01,
- 0xfe, 0xfc, 0x16, 0xe0, 0x91, 0x1d, 0x66, 0xfe, 0x2c, 0x01, 0xfe, 0x2f,
- 0x19, 0x03, 0xae, 0x21, 0xfe, 0xe6, 0x15, 0xfe, 0xda, 0x10, 0x17, 0x10,
- 0x71, 0x05, 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x19, 0xfe, 0x18, 0x58,
- 0x05, 0xfe, 0x66, 0x01, 0xfe, 0x19, 0x58, 0x91, 0x19, 0xfe, 0x3c, 0x90,
- 0xfe, 0x30, 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x66, 0xfe, 0x38, 0x00, 0xfe,
- 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x19, 0x90, 0xfe, 0x40, 0x16, 0xfe, 0xb6,
- 0x14, 0x34, 0x03, 0xae, 0x21, 0xfe, 0x18, 0x16, 0xfe, 0x9c, 0x10, 0x17,
- 0x10, 0x71, 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe,
- 0x1d, 0xf7, 0x38, 0x90, 0xfe, 0x62, 0x16, 0xfe, 0x94, 0x14, 0xfe, 0x10,
- 0x13, 0x91, 0x38, 0x66, 0x1b, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00,
- 0x03, 0xae, 0x21, 0xfe, 0x56, 0x16, 0xfe, 0x6c, 0x10, 0x17, 0x10, 0x71,
- 0xfe, 0x30, 0xbc, 0xfe, 0xb2, 0xbc, 0x91, 0xc5, 0x66, 0x1b, 0xfe, 0x0f,
- 0x79, 0xfe, 0x1c, 0xf7, 0xc5, 0x90, 0xfe, 0x9a, 0x16, 0xfe, 0x5c, 0x14,
- 0x34, 0x03, 0xae, 0x21, 0xfe, 0x86, 0x16, 0xfe, 0x42, 0x10, 0xfe, 0x02,
- 0xf6, 0x10, 0x71, 0xfe, 0x18, 0xfe, 0x54, 0xfe, 0x19, 0xfe, 0x55, 0xfc,
- 0xfe, 0x1d, 0xf7, 0x4f, 0x90, 0xfe, 0xc0, 0x16, 0xfe, 0x36, 0x14, 0xfe,
- 0x1c, 0x13, 0x91, 0x4f, 0x47, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe,
- 0x80, 0xe7, 0x10, 0xfe, 0x81, 0xe7, 0x10, 0x11, 0xfe, 0xdd, 0x00, 0x63,
- 0x27, 0x03, 0x63, 0x27, 0xfe, 0x12, 0x45, 0x21, 0xfe, 0xb0, 0x16, 0x14,
- 0x06, 0x37, 0x95, 0xa9, 0x02, 0x29, 0xfe, 0x39, 0xf0, 0xfe, 0x04, 0x17,
- 0x23, 0x03, 0xfe, 0x7e, 0x18, 0x1c, 0x1a, 0x5d, 0x13, 0x0d, 0x03, 0x71,
- 0x05, 0xcb, 0x1c, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x78, 0x2c,
- 0x46, 0x2f, 0x07, 0x2d, 0xfe, 0x3c, 0x13, 0xfe, 0x82, 0x14, 0xfe, 0x42,
- 0x13, 0x3c, 0x8a, 0x0a, 0x42, 0x01, 0x0e, 0xb0, 0xfe, 0x3e, 0x12, 0xf0,
- 0xfe, 0x45, 0x48, 0x01, 0xe3, 0xfe, 0x00, 0xcc, 0xb0, 0xfe, 0xf3, 0x13,
- 0x3d, 0x75, 0x07, 0x10, 0xa3, 0x0a, 0x80, 0x01, 0x0e, 0xf2, 0x01, 0x6f,
- 0xfe, 0x16, 0x10, 0x07, 0x7e, 0x85, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12,
- 0xf6, 0xfe, 0xd6, 0xf0, 0xfe, 0x24, 0x17, 0x17, 0x0b, 0x03, 0xfe, 0x9c,
- 0xe7, 0x0b, 0x0f, 0xfe, 0x15, 0x00, 0x59, 0x76, 0x27, 0x01, 0xda, 0x17,
- 0x06, 0x03, 0x3c, 0x8a, 0x09, 0x4a, 0x1d, 0x35, 0x11, 0x2d, 0x01, 0x6f,
- 0x17, 0x06, 0x03, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x79, 0xc7, 0x68,
- 0xc8, 0xfe, 0x48, 0x55, 0x34, 0xfe, 0xc9, 0x55, 0x03, 0x1e, 0x98, 0x73,
- 0x12, 0x98, 0x03, 0x0a, 0x99, 0x01, 0x0e, 0xf0, 0x0a, 0x40, 0x01, 0x0e,
- 0xfe, 0x49, 0x44, 0x16, 0xfe, 0xf0, 0x17, 0x73, 0x75, 0x03, 0x0a, 0x42,
- 0x01, 0x0e, 0x07, 0x10, 0x45, 0x0a, 0x51, 0x01, 0x9e, 0x0a, 0x40, 0x01,
- 0x0e, 0x73, 0x75, 0x03, 0xfe, 0x4e, 0xe4, 0x1a, 0x64, 0xfe, 0x24, 0x18,
- 0x05, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0x5b, 0xfe, 0x4e, 0xe4, 0xc2,
- 0x64, 0xfe, 0x36, 0x18, 0x05, 0xfe, 0x92, 0x00, 0xfe, 0x02, 0xe6, 0x1b,
- 0xdc, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x64, 0xfe, 0x48, 0x18, 0x05,
- 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x19, 0xfe, 0x08, 0x10, 0x05, 0xfe,
- 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x2c, 0xfe, 0x4e, 0x45, 0xfe, 0x0c, 0x12,
- 0xaf, 0xff, 0x04, 0x68, 0x54, 0xde, 0x1c, 0x69, 0x03, 0x07, 0x7a, 0xfe,
- 0x5a, 0xf0, 0xfe, 0x74, 0x18, 0x24, 0xfe, 0x09, 0x00, 0xfe, 0x34, 0x10,
- 0x07, 0x1b, 0xfe, 0x5a, 0xf0, 0xfe, 0x82, 0x18, 0x24, 0xc3, 0xfe, 0x26,
- 0x10, 0x07, 0x1a, 0x5d, 0x24, 0x2c, 0xdc, 0x07, 0x0b, 0x5d, 0x24, 0x93,
- 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x5d, 0x24, 0x4d, 0x9f, 0xad, 0x03, 0x14,
- 0xfe, 0x09, 0x00, 0x01, 0x33, 0xfe, 0x04, 0xfe, 0x7d, 0x05, 0x7f, 0xf9,
- 0x03, 0x25, 0xfe, 0xca, 0x18, 0xfe, 0x14, 0xf0, 0x08, 0x65, 0xfe, 0xc6,
- 0x18, 0x03, 0xff, 0x1a, 0x00, 0x00,
-};
-
-static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */
-static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */
-
-/* Microcode buffer is kept after initialization for error recovery. */
-static unsigned char _adv_asc38C0800_buf[] = {
- 0x00, 0x00, 0x00, 0xf2, 0x00, 0xf0, 0x00, 0xfc, 0x00, 0x16, 0x18, 0xe4,
- 0x01, 0x00, 0x48, 0xe4, 0x18, 0x80, 0x03, 0xf6, 0x02, 0x00, 0xce, 0x19,
- 0x00, 0xfa, 0xff, 0xff, 0x1c, 0x0f, 0x00, 0xf6, 0x9e, 0xe7, 0xff, 0x00,
- 0x82, 0xe7, 0x00, 0xea, 0x01, 0xfa, 0x01, 0xe6, 0x09, 0xe7, 0x55, 0xf0,
- 0x01, 0xf6, 0x03, 0x00, 0x04, 0x00, 0x10, 0x00, 0x1e, 0xf0, 0x85, 0xf0,
- 0x18, 0xf4, 0x08, 0x00, 0xbc, 0x00, 0x38, 0x54, 0x00, 0xec, 0xd5, 0xf0,
- 0x82, 0x0d, 0x00, 0xe6, 0x86, 0xf0, 0xb1, 0xf0, 0x98, 0x57, 0x01, 0xfc,
- 0xb4, 0x00, 0xd4, 0x01, 0x0c, 0x1c, 0x3e, 0x1c, 0x3c, 0x00, 0xbb, 0x00,
- 0x00, 0x10, 0xba, 0x19, 0x02, 0x80, 0x32, 0xf0, 0x7c, 0x0d, 0x02, 0x13,
- 0xba, 0x13, 0x18, 0x40, 0x00, 0x57, 0x01, 0xea, 0x02, 0xfc, 0x03, 0xfc,
- 0x3e, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x74, 0x01, 0x76, 0x01, 0xb9, 0x54,
- 0x3e, 0x57, 0x00, 0x80, 0x03, 0xe6, 0xb6, 0x00, 0xc0, 0x00, 0x01, 0x01,
- 0x3e, 0x01, 0x7a, 0x01, 0xca, 0x08, 0xce, 0x10, 0x16, 0x11, 0x04, 0x12,
- 0x08, 0x12, 0x02, 0x4a, 0xbb, 0x55, 0x3c, 0x56, 0x03, 0x58, 0x1b, 0x80,
- 0x30, 0xe4, 0x4b, 0xe4, 0x5d, 0xf0, 0x02, 0xfa, 0x20, 0x00, 0x32, 0x00,
- 0x40, 0x00, 0x80, 0x00, 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01,
- 0x70, 0x01, 0x72, 0x01, 0x78, 0x01, 0x7c, 0x01, 0x62, 0x0a, 0x86, 0x0d,
- 0x06, 0x13, 0x4c, 0x1c, 0x04, 0x80, 0x4a, 0xe4, 0x02, 0xee, 0x5b, 0xf0,
- 0x03, 0xf7, 0x0c, 0x00, 0x0f, 0x00, 0x47, 0x00, 0xbe, 0x00, 0x00, 0x01,
- 0x20, 0x11, 0x5c, 0x16, 0x32, 0x1c, 0x38, 0x1c, 0x4e, 0x1c, 0x10, 0x44,
- 0x00, 0x4c, 0x04, 0xea, 0x5c, 0xf0, 0xa7, 0xf0, 0x04, 0xf6, 0x03, 0xfa,
- 0x05, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0xcc, 0x00, 0x20, 0x01,
- 0x4e, 0x01, 0x4a, 0x0b, 0x42, 0x0c, 0x12, 0x0f, 0x0c, 0x10, 0x22, 0x11,
- 0x0a, 0x12, 0x04, 0x13, 0x30, 0x1c, 0x02, 0x48, 0x00, 0x4e, 0x42, 0x54,
- 0x44, 0x55, 0xbd, 0x56, 0x06, 0x83, 0x00, 0xdc, 0x05, 0xf0, 0x09, 0xf0,
- 0x59, 0xf0, 0xb8, 0xf0, 0x4b, 0xf4, 0x06, 0xf7, 0x0e, 0xf7, 0x04, 0xfc,
- 0x05, 0xfc, 0x06, 0x00, 0x19, 0x00, 0x33, 0x00, 0x9b, 0x00, 0xa4, 0x00,
- 0xb5, 0x00, 0xba, 0x00, 0xd0, 0x00, 0xe1, 0x00, 0xe7, 0x00, 0xe2, 0x03,
- 0x08, 0x0f, 0x02, 0x10, 0x04, 0x10, 0x0a, 0x10, 0x0a, 0x13, 0x0c, 0x13,
- 0x12, 0x13, 0x24, 0x14, 0x34, 0x14, 0x04, 0x16, 0x08, 0x16, 0xa4, 0x17,
- 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44,
- 0x0a, 0x45, 0x48, 0x46, 0x01, 0x48, 0x68, 0x54, 0x3a, 0x55, 0x83, 0x55,
- 0xe5, 0x55, 0xb0, 0x57, 0x01, 0x58, 0x83, 0x59, 0x05, 0xe6, 0x0b, 0xf0,
- 0x0c, 0xf0, 0x04, 0xf8, 0x05, 0xf8, 0x07, 0x00, 0x0a, 0x00, 0x1c, 0x00,
- 0x1e, 0x00, 0x9e, 0x00, 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00,
- 0x22, 0x01, 0x26, 0x01, 0x79, 0x01, 0x7e, 0x01, 0xc4, 0x01, 0xc6, 0x01,
- 0x80, 0x02, 0x5e, 0x03, 0xee, 0x04, 0x9a, 0x06, 0xf8, 0x07, 0x62, 0x08,
- 0x68, 0x08, 0x69, 0x08, 0xd6, 0x08, 0xe9, 0x09, 0xfa, 0x0b, 0x2e, 0x0f,
- 0x12, 0x10, 0x1a, 0x10, 0xed, 0x10, 0xf1, 0x10, 0x2a, 0x11, 0x06, 0x12,
- 0x0c, 0x12, 0x3e, 0x12, 0x10, 0x13, 0x16, 0x13, 0x1e, 0x13, 0x46, 0x14,
- 0x76, 0x14, 0x82, 0x14, 0x36, 0x15, 0xca, 0x15, 0x6b, 0x18, 0xbe, 0x18,
- 0xca, 0x18, 0xe6, 0x19, 0x12, 0x1c, 0x46, 0x1c, 0x9c, 0x32, 0x00, 0x40,
- 0x0e, 0x47, 0xfe, 0x9c, 0xf0, 0x2b, 0x02, 0xfe, 0xac, 0x0d, 0xff, 0x10,
- 0x00, 0x00, 0xd7, 0xfe, 0xe8, 0x19, 0x00, 0xd6, 0xfe, 0x84, 0x01, 0xff,
- 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
- 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x5b, 0xff, 0x04, 0x00,
- 0x00, 0x11, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
- 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x11,
- 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
- 0xfe, 0x04, 0xf7, 0xd6, 0x2c, 0x99, 0x0a, 0x01, 0xfe, 0xc2, 0x0f, 0xfe,
- 0x04, 0xf7, 0xd6, 0x99, 0x0a, 0x42, 0x2c, 0xfe, 0x3d, 0xf0, 0xfe, 0x06,
- 0x02, 0xfe, 0x20, 0xf0, 0xa7, 0xfe, 0x91, 0xf0, 0xfe, 0xf4, 0x01, 0xfe,
- 0x90, 0xf0, 0xfe, 0xf4, 0x01, 0xfe, 0x8f, 0xf0, 0xa7, 0x03, 0x5d, 0x4d,
- 0x02, 0xfe, 0xc8, 0x0d, 0x01, 0xfe, 0x38, 0x0e, 0xfe, 0xdd, 0x12, 0xfe,
- 0xfc, 0x10, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd3, 0x12,
- 0x41, 0x14, 0xfe, 0xa6, 0x00, 0xc2, 0xfe, 0x48, 0xf0, 0xfe, 0x8a, 0x02,
- 0xfe, 0x49, 0xf0, 0xfe, 0xa4, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc2, 0x02,
- 0xfe, 0x46, 0xf0, 0xfe, 0x54, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x5a, 0x02,
- 0xfe, 0x43, 0xf0, 0xfe, 0x48, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x4c, 0x02,
- 0xfe, 0x45, 0xf0, 0xfe, 0x50, 0x02, 0x18, 0x0a, 0xaa, 0x18, 0x06, 0x14,
- 0xa1, 0x02, 0x2b, 0xfe, 0x00, 0x1c, 0xe7, 0xfe, 0x02, 0x1c, 0xe6, 0xfe,
- 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0xfe, 0x18, 0x18, 0xfe, 0xe7, 0x10,
- 0xfe, 0x06, 0xfc, 0xce, 0x09, 0x70, 0x01, 0xa8, 0x02, 0x2b, 0x15, 0x59,
- 0x39, 0xa2, 0x01, 0xfe, 0x58, 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xbd,
- 0x10, 0x09, 0x70, 0x01, 0x87, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c, 0xfe,
- 0x58, 0x1c, 0x18, 0x06, 0x14, 0xa1, 0x2c, 0x1c, 0x2b, 0xfe, 0x3d, 0xf0,
- 0xfe, 0x06, 0x02, 0x23, 0xfe, 0x98, 0x02, 0xfe, 0x5a, 0x1c, 0xf8, 0xfe,
- 0x14, 0x1c, 0x15, 0xfe, 0x30, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10,
- 0x18, 0x06, 0x14, 0xa1, 0x02, 0xd7, 0x22, 0x20, 0x07, 0x11, 0x35, 0xfe,
- 0x69, 0x10, 0x18, 0x06, 0x14, 0xa1, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0x43,
- 0x13, 0x20, 0xfe, 0x05, 0xf6, 0xce, 0x01, 0xfe, 0x4a, 0x17, 0x08, 0x54,
- 0x58, 0x37, 0x12, 0x2f, 0x42, 0x92, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b,
- 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66, 0x01, 0x73, 0xfe, 0x18, 0x10,
- 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0xc8, 0x54, 0x6b, 0xfe,
- 0x10, 0x03, 0x01, 0xfe, 0x82, 0x16, 0x02, 0x2b, 0x2c, 0x4f, 0xfe, 0x02,
- 0xe8, 0x2a, 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe,
- 0x27, 0xf0, 0xfe, 0xe0, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xa7,
- 0xfe, 0x40, 0x1c, 0x1c, 0xd9, 0xfe, 0x26, 0xf0, 0xfe, 0x5a, 0x03, 0xfe,
- 0xa0, 0xf0, 0xfe, 0x48, 0x03, 0xfe, 0x11, 0xf0, 0xa7, 0xfe, 0xef, 0x10,
- 0xfe, 0x9f, 0xf0, 0xfe, 0x68, 0x03, 0xf9, 0x10, 0xfe, 0x11, 0x00, 0x02,
- 0x65, 0x2c, 0xfe, 0x48, 0x1c, 0xf9, 0x08, 0x05, 0x1b, 0xfe, 0x18, 0x13,
- 0x21, 0x22, 0xa3, 0xb7, 0x13, 0xa3, 0x09, 0x46, 0x01, 0x0e, 0xb7, 0x78,
- 0x01, 0xfe, 0xb4, 0x16, 0x12, 0xd1, 0x1c, 0xd9, 0xfe, 0x01, 0xf0, 0xd9,
- 0xfe, 0x82, 0xf0, 0xfe, 0x96, 0x03, 0xfa, 0x12, 0xfe, 0xe4, 0x00, 0x27,
- 0xfe, 0xa8, 0x03, 0x1c, 0x34, 0x1d, 0xfe, 0xb8, 0x03, 0x01, 0x4b, 0xfe,
- 0x06, 0xf0, 0xfe, 0xc8, 0x03, 0x95, 0x86, 0xfe, 0x0a, 0xf0, 0xfe, 0x8a,
- 0x06, 0x02, 0x24, 0x03, 0x70, 0x28, 0x17, 0xfe, 0xfa, 0x04, 0x15, 0x6d,
- 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02, 0xd8, 0xf9, 0x2c, 0x99, 0x19,
- 0xfe, 0x67, 0x1b, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c,
- 0x74, 0x01, 0xaf, 0x8c, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x17, 0xda,
- 0x09, 0xd1, 0x01, 0x0e, 0x8d, 0x51, 0x64, 0x79, 0x2a, 0x03, 0x70, 0x28,
- 0xfe, 0x10, 0x12, 0x15, 0x6d, 0x01, 0x36, 0x7b, 0xfe, 0x6a, 0x02, 0x02,
- 0xd8, 0xc7, 0x81, 0xc8, 0x83, 0x1c, 0x24, 0x27, 0xfe, 0x40, 0x04, 0x1d,
- 0xfe, 0x3c, 0x04, 0x3b, 0xfe, 0xa0, 0x00, 0xfe, 0x9b, 0x57, 0xfe, 0x4e,
- 0x12, 0x2d, 0xff, 0x02, 0x00, 0x10, 0x01, 0x0b, 0x1d, 0xfe, 0xe4, 0x04,
- 0x2d, 0x01, 0x0b, 0x1d, 0x24, 0x33, 0x31, 0xde, 0xfe, 0x4c, 0x44, 0xfe,
- 0x4c, 0x12, 0x51, 0xfe, 0x44, 0x48, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b,
- 0xda, 0x4f, 0x79, 0x2a, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x62,
- 0x13, 0x08, 0x05, 0x1b, 0xfe, 0x2a, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x52,
- 0x13, 0xfe, 0x20, 0x10, 0x0f, 0x6f, 0xfe, 0x4c, 0x54, 0x6b, 0xda, 0xfe,
- 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x40, 0x13, 0x08, 0x05, 0x1b, 0xfe,
- 0x08, 0x13, 0x32, 0x07, 0x82, 0xfe, 0x30, 0x13, 0x08, 0x05, 0x1b, 0xfe,
- 0x1c, 0x12, 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00,
- 0x01, 0x36, 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x2d, 0x12, 0xfe, 0xe6,
- 0x00, 0xfe, 0x1c, 0x90, 0xfe, 0x40, 0x5c, 0x04, 0x15, 0x9d, 0x01, 0x36,
- 0x02, 0x2b, 0xfe, 0x42, 0x5b, 0x99, 0x19, 0xfe, 0x46, 0x59, 0xfe, 0xbf,
- 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x87, 0x80, 0xfe, 0x31, 0xe4, 0x5b, 0x08,
- 0x05, 0x0a, 0xfe, 0x84, 0x13, 0xfe, 0x20, 0x80, 0x07, 0x19, 0xfe, 0x7c,
- 0x12, 0x53, 0x05, 0x06, 0xfe, 0x6c, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x28,
- 0x17, 0xfe, 0x90, 0x05, 0xfe, 0x31, 0xe4, 0x5a, 0x53, 0x05, 0x0a, 0xfe,
- 0x56, 0x13, 0x03, 0xfe, 0xa0, 0x00, 0x28, 0xfe, 0x4e, 0x12, 0x67, 0xff,
- 0x02, 0x00, 0x10, 0x27, 0xfe, 0x48, 0x05, 0x1c, 0x34, 0xfe, 0x89, 0x48,
- 0xff, 0x02, 0x00, 0x10, 0x27, 0xfe, 0x56, 0x05, 0x26, 0xfe, 0xa8, 0x05,
- 0x12, 0xfe, 0xe3, 0x00, 0x21, 0x53, 0xfe, 0x4a, 0xf0, 0xfe, 0x76, 0x05,
- 0xfe, 0x49, 0xf0, 0xfe, 0x70, 0x05, 0x88, 0x25, 0xfe, 0x21, 0x00, 0xab,
- 0x25, 0xfe, 0x22, 0x00, 0xaa, 0x25, 0x58, 0xfe, 0x09, 0x48, 0xff, 0x02,
- 0x00, 0x10, 0x27, 0xfe, 0x86, 0x05, 0x26, 0xfe, 0xa8, 0x05, 0xfe, 0xe2,
- 0x08, 0x53, 0x05, 0xcb, 0x4d, 0x01, 0xb0, 0x25, 0x06, 0x13, 0xd3, 0x39,
- 0xfe, 0x27, 0x01, 0x08, 0x05, 0x1b, 0xfe, 0x22, 0x12, 0x41, 0x01, 0xb2,
- 0x15, 0x9d, 0x08, 0x05, 0x06, 0x4d, 0x15, 0xfe, 0x0d, 0x00, 0x01, 0x36,
- 0x7b, 0xfe, 0x64, 0x0d, 0x02, 0x24, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0xeb,
- 0x03, 0x5c, 0x28, 0xfe, 0x36, 0x13, 0x41, 0x01, 0xb2, 0x26, 0xfe, 0x18,
- 0x06, 0x09, 0x06, 0x53, 0x05, 0x1f, 0xfe, 0x02, 0x12, 0x50, 0x01, 0xfe,
- 0x9e, 0x15, 0x1d, 0xfe, 0x0e, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12, 0xfe,
- 0xe5, 0x00, 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x03, 0xcd, 0x28, 0xfe, 0x62,
- 0x12, 0x03, 0x45, 0x28, 0xfe, 0x5a, 0x13, 0x01, 0xfe, 0x0c, 0x19, 0x01,
- 0xfe, 0x76, 0x19, 0xfe, 0x43, 0x48, 0xc4, 0xcc, 0x0f, 0x71, 0xff, 0x02,
- 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0x8b, 0xc4, 0x6e, 0x41, 0x01, 0xb2,
- 0x26, 0xfe, 0x82, 0x06, 0x53, 0x05, 0x1a, 0xe9, 0x91, 0x09, 0x59, 0x01,
- 0xfe, 0xcc, 0x15, 0x1d, 0xfe, 0x78, 0x06, 0x12, 0xa5, 0x01, 0x4b, 0x12,
- 0xfe, 0xe5, 0x00, 0x03, 0x45, 0xc1, 0x0c, 0x45, 0x18, 0x06, 0x01, 0xb2,
- 0xfa, 0x76, 0x74, 0x01, 0xaf, 0x8c, 0x12, 0xfe, 0xe2, 0x00, 0x27, 0xdb,
- 0x1c, 0x34, 0xfe, 0x0a, 0xf0, 0xfe, 0xb6, 0x06, 0x94, 0xfe, 0x6c, 0x07,
- 0xfe, 0x06, 0xf0, 0xfe, 0x74, 0x07, 0x95, 0x86, 0x02, 0x24, 0x08, 0x05,
- 0x0a, 0xfe, 0x2e, 0x12, 0x16, 0x19, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b,
- 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0xfe, 0x99, 0xa4, 0x01,
- 0x0b, 0x16, 0x00, 0x02, 0xfe, 0x42, 0x08, 0x68, 0x05, 0x1a, 0xfe, 0x38,
- 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x30, 0x13, 0x16, 0xfe, 0x1b, 0x00, 0x01,
- 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01, 0x0b, 0x16, 0x00, 0x01,
- 0x0b, 0x16, 0x06, 0x01, 0x0b, 0x16, 0x00, 0x02, 0xe2, 0x6c, 0x58, 0xbe,
- 0x50, 0xfe, 0x9a, 0x81, 0x55, 0x1b, 0x7a, 0xfe, 0x42, 0x07, 0x09, 0x1b,
- 0xfe, 0x09, 0x6f, 0xba, 0xfe, 0xca, 0x45, 0xfe, 0x32, 0x12, 0x69, 0x6d,
- 0x8b, 0x6c, 0x7f, 0x27, 0xfe, 0x54, 0x07, 0x1c, 0x34, 0xfe, 0x0a, 0xf0,
- 0xfe, 0x42, 0x07, 0x95, 0x86, 0x94, 0xfe, 0x6c, 0x07, 0x02, 0x24, 0x01,
- 0x4b, 0x02, 0xdb, 0x16, 0x1f, 0x02, 0xdb, 0xfe, 0x9c, 0xf7, 0xdc, 0xfe,
- 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x56, 0xfe, 0xda, 0x07, 0x0c, 0x60, 0x14,
- 0x61, 0x08, 0x54, 0x5a, 0x37, 0x22, 0x20, 0x07, 0x11, 0xfe, 0x0e, 0x12,
- 0x8d, 0xfe, 0x80, 0x80, 0x39, 0x20, 0x6a, 0x2a, 0xfe, 0x06, 0x10, 0xfe,
- 0x83, 0xe7, 0xfe, 0x48, 0x00, 0xab, 0xfe, 0x03, 0x40, 0x08, 0x54, 0x5b,
- 0x37, 0x01, 0xb3, 0xb8, 0xfe, 0x1f, 0x40, 0x13, 0x62, 0x01, 0xef, 0xfe,
- 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe, 0x44, 0x51, 0xfe, 0xc6, 0x51, 0x88,
- 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90, 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x0c,
- 0x90, 0xfe, 0x8e, 0x90, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x0c, 0x3d,
- 0x14, 0x3e, 0xfe, 0x4a, 0x10, 0x08, 0x05, 0x5a, 0xfe, 0x2a, 0x12, 0xfe,
- 0x2c, 0x90, 0xfe, 0xae, 0x90, 0x0c, 0x60, 0x14, 0x61, 0x08, 0x05, 0x5b,
- 0x8b, 0x01, 0xb3, 0xfe, 0x1f, 0x80, 0x13, 0x62, 0xfe, 0x44, 0x90, 0xfe,
- 0xc6, 0x90, 0x0c, 0x3f, 0x14, 0x40, 0xfe, 0x08, 0x90, 0xfe, 0x8a, 0x90,
- 0x0c, 0x5e, 0x14, 0x5f, 0xfe, 0x40, 0x90, 0xfe, 0xc2, 0x90, 0x0c, 0x3d,
- 0x14, 0x3e, 0x0c, 0x2e, 0x14, 0x3c, 0x21, 0x0c, 0x49, 0x0c, 0x63, 0x08,
- 0x54, 0x1f, 0x37, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27, 0xdd, 0xfe, 0x9e,
- 0xf0, 0xfe, 0x76, 0x08, 0xbc, 0x17, 0x34, 0x2c, 0x77, 0xe6, 0xc5, 0xfe,
- 0x9a, 0x08, 0xc6, 0xfe, 0xb8, 0x08, 0x94, 0xfe, 0x8e, 0x08, 0xfe, 0x06,
- 0xf0, 0xfe, 0x94, 0x08, 0x95, 0x86, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xc9,
- 0x10, 0x16, 0x1f, 0xfe, 0xc9, 0x10, 0x68, 0x05, 0x06, 0xfe, 0x10, 0x12,
- 0x68, 0x05, 0x0a, 0x4e, 0x08, 0x05, 0x0a, 0xfe, 0x90, 0x12, 0xfe, 0x2e,
- 0x1c, 0x02, 0xfe, 0x18, 0x0b, 0x68, 0x05, 0x06, 0x4e, 0x68, 0x05, 0x0a,
- 0xfe, 0x7a, 0x12, 0xfe, 0x2c, 0x1c, 0xfe, 0xaa, 0xf0, 0xfe, 0xd2, 0x09,
- 0xfe, 0xac, 0xf0, 0xfe, 0x00, 0x09, 0x02, 0xfe, 0xde, 0x09, 0xfe, 0xb7,
- 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0x02, 0xf6, 0x1a, 0x50, 0xfe, 0x70, 0x18,
- 0xfe, 0xf1, 0x18, 0xfe, 0x40, 0x55, 0xfe, 0xe1, 0x55, 0xfe, 0x10, 0x58,
- 0xfe, 0x91, 0x58, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x1c, 0x85, 0xfe,
- 0x8c, 0xf0, 0xfe, 0xfc, 0x08, 0xfe, 0xac, 0xf0, 0xfe, 0xf0, 0x08, 0xb5,
- 0xfe, 0xcb, 0x10, 0xfe, 0xad, 0xf0, 0xfe, 0x0c, 0x09, 0x02, 0xfe, 0x18,
- 0x0b, 0xb6, 0xfe, 0xbf, 0x10, 0xfe, 0x2b, 0xf0, 0x85, 0xf4, 0x1e, 0xfe,
- 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xc2, 0xfe, 0xd2, 0xf0, 0x85, 0xfe, 0x76,
- 0x18, 0x1e, 0x19, 0x17, 0x85, 0x03, 0xd2, 0x1e, 0x06, 0x17, 0x85, 0xc5,
- 0x4a, 0xc6, 0x4a, 0xb5, 0xb6, 0xfe, 0x89, 0x10, 0x74, 0x67, 0x2d, 0x15,
- 0x9d, 0x01, 0x36, 0x10, 0xfe, 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x65, 0x10,
- 0x80, 0x02, 0x65, 0xfe, 0x98, 0x80, 0xfe, 0x19, 0xe4, 0x0a, 0xfe, 0x1a,
- 0x12, 0x51, 0xfe, 0x19, 0x82, 0xfe, 0x6c, 0x18, 0xfe, 0x44, 0x54, 0xbe,
- 0xfe, 0x19, 0x81, 0xfe, 0x74, 0x18, 0x8f, 0x90, 0x17, 0xfe, 0xce, 0x08,
- 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xec, 0x03, 0x2e, 0x29, 0x3c, 0x0c, 0x3f,
- 0x14, 0x40, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x6c, 0x18, 0xfe, 0xed, 0x18,
- 0xfe, 0x44, 0x54, 0xfe, 0xe5, 0x54, 0x3a, 0x3f, 0x3b, 0x40, 0x03, 0x49,
- 0x29, 0x63, 0x8f, 0xfe, 0xe3, 0x54, 0xfe, 0x74, 0x18, 0xfe, 0xf5, 0x18,
- 0x8f, 0xfe, 0xe3, 0x54, 0x90, 0xc0, 0x56, 0xfe, 0xce, 0x08, 0x02, 0x4a,
- 0xfe, 0x37, 0xf0, 0xfe, 0xda, 0x09, 0xfe, 0x8b, 0xf0, 0xfe, 0x60, 0x09,
- 0x02, 0x4a, 0x08, 0x05, 0x0a, 0x23, 0xfe, 0xfa, 0x0a, 0x3a, 0x49, 0x3b,
- 0x63, 0x56, 0xfe, 0x3e, 0x0a, 0x0f, 0xfe, 0xc0, 0x07, 0x41, 0x98, 0x00,
- 0xad, 0xfe, 0x01, 0x59, 0xfe, 0x52, 0xf0, 0xfe, 0x0c, 0x0a, 0x8f, 0x7a,
- 0xfe, 0x24, 0x0a, 0x3a, 0x49, 0x8f, 0xfe, 0xe3, 0x54, 0x57, 0x49, 0x7d,
- 0x63, 0xfe, 0x14, 0x58, 0xfe, 0x95, 0x58, 0x02, 0x4a, 0x3a, 0x49, 0x3b,
- 0x63, 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0xbe, 0x57, 0x49, 0x57, 0x63,
- 0x02, 0x4a, 0x08, 0x05, 0x5a, 0xfe, 0x82, 0x12, 0x08, 0x05, 0x1f, 0xfe,
- 0x66, 0x13, 0x22, 0x62, 0xb7, 0xfe, 0x03, 0xa1, 0xfe, 0x83, 0x80, 0xfe,
- 0xc8, 0x44, 0xfe, 0x2e, 0x13, 0xfe, 0x04, 0x91, 0xfe, 0x86, 0x91, 0x6a,
- 0x2a, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x56, 0xe0, 0x03, 0x60, 0x29,
- 0x61, 0x0c, 0x7f, 0x14, 0x80, 0x57, 0x60, 0x7d, 0x61, 0x01, 0xb3, 0xb8,
- 0x6a, 0x2a, 0x13, 0x62, 0x9b, 0x2e, 0x9c, 0x3c, 0x3a, 0x3f, 0x3b, 0x40,
- 0x90, 0xc0, 0xfe, 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0x01, 0xef,
- 0xfe, 0x36, 0x10, 0x21, 0x0c, 0x7f, 0x0c, 0x80, 0x3a, 0x3f, 0x3b, 0x40,
- 0xe4, 0x08, 0x05, 0x1f, 0x17, 0xe0, 0x3a, 0x3d, 0x3b, 0x3e, 0x08, 0x05,
- 0xfe, 0xf7, 0x00, 0x37, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x10, 0x58, 0xfe,
- 0x91, 0x58, 0x57, 0x49, 0x7d, 0x63, 0x02, 0xfe, 0xf4, 0x09, 0x08, 0x05,
- 0x1f, 0x17, 0xe0, 0x08, 0x05, 0xfe, 0xf7, 0x00, 0x37, 0xbe, 0xfe, 0x19,
- 0x81, 0x50, 0xfe, 0x10, 0x90, 0xfe, 0x92, 0x90, 0xfe, 0xd3, 0x10, 0x32,
- 0x07, 0xa6, 0x17, 0xfe, 0x08, 0x09, 0x12, 0xa6, 0x08, 0x05, 0x0a, 0xfe,
- 0x14, 0x13, 0x03, 0x3d, 0x29, 0x3e, 0x56, 0xfe, 0x08, 0x09, 0xfe, 0x0c,
- 0x58, 0xfe, 0x8d, 0x58, 0x02, 0x4a, 0x21, 0x41, 0xfe, 0x19, 0x80, 0xe7,
- 0x08, 0x05, 0x0a, 0xfe, 0x1a, 0x12, 0xfe, 0x6c, 0x19, 0xfe, 0x19, 0x41,
- 0xf4, 0xc2, 0xfe, 0xd1, 0xf0, 0xe2, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe,
- 0x44, 0x00, 0xfe, 0x8e, 0x10, 0xfe, 0x6c, 0x19, 0x57, 0x3d, 0xfe, 0xed,
- 0x19, 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0xf4, 0x1e, 0xfe,
- 0x00, 0xff, 0x35, 0xfe, 0x74, 0x10, 0xc2, 0xfe, 0xd2, 0xf0, 0xfe, 0xa6,
- 0x0b, 0xfe, 0x76, 0x18, 0x1e, 0x19, 0x8a, 0x03, 0xd2, 0x1e, 0x06, 0xfe,
- 0x08, 0x13, 0x10, 0xfe, 0x16, 0x00, 0x02, 0x65, 0xfe, 0xd1, 0xf0, 0xfe,
- 0xb8, 0x0b, 0x15, 0x7e, 0x01, 0x36, 0x10, 0xfe, 0x17, 0x00, 0xfe, 0x42,
- 0x10, 0xfe, 0xce, 0xf0, 0xfe, 0xbe, 0x0b, 0xfe, 0x3c, 0x10, 0xfe, 0xcd,
- 0xf0, 0xfe, 0xca, 0x0b, 0x10, 0xfe, 0x22, 0x00, 0x02, 0x65, 0xfe, 0xcb,
- 0xf0, 0xfe, 0xd6, 0x0b, 0x10, 0xfe, 0x24, 0x00, 0x02, 0x65, 0xfe, 0xd0,
- 0xf0, 0xfe, 0xe0, 0x0b, 0x10, 0x9e, 0xe5, 0xfe, 0xcf, 0xf0, 0xfe, 0xea,
- 0x0b, 0x10, 0x58, 0xfe, 0x10, 0x10, 0xfe, 0xcc, 0xf0, 0xe2, 0x68, 0x05,
- 0x1f, 0x4d, 0x10, 0xfe, 0x12, 0x00, 0x2c, 0x0f, 0xfe, 0x4e, 0x11, 0x27,
- 0xfe, 0x00, 0x0c, 0xfe, 0x9e, 0xf0, 0xfe, 0x14, 0x0c, 0xbc, 0x17, 0x34,
- 0x2c, 0x77, 0xe6, 0xc5, 0x24, 0xc6, 0x24, 0x2c, 0xfa, 0x27, 0xfe, 0x20,
- 0x0c, 0x1c, 0x34, 0x94, 0xfe, 0x3c, 0x0c, 0x95, 0x86, 0xc5, 0xdc, 0xc6,
- 0xdc, 0x02, 0x24, 0x01, 0x4b, 0xfe, 0xdb, 0x10, 0x12, 0xfe, 0xe8, 0x00,
- 0xb5, 0xb6, 0x74, 0xc7, 0x81, 0xc8, 0x83, 0xfe, 0x89, 0xf0, 0x24, 0x33,
- 0x31, 0xe1, 0xc7, 0x81, 0xc8, 0x83, 0x27, 0xfe, 0x66, 0x0c, 0x1d, 0x24,
- 0x33, 0x31, 0xdf, 0xbc, 0x4e, 0x10, 0xfe, 0x42, 0x00, 0x02, 0x65, 0x7c,
- 0x06, 0xfe, 0x81, 0x49, 0x17, 0xfe, 0x2c, 0x0d, 0x08, 0x05, 0x0a, 0xfe,
- 0x44, 0x13, 0x10, 0x00, 0x55, 0x0a, 0xfe, 0x54, 0x12, 0x55, 0xfe, 0x28,
- 0x00, 0x23, 0xfe, 0x9a, 0x0d, 0x09, 0x46, 0x01, 0x0e, 0x07, 0x00, 0x66,
- 0x44, 0xfe, 0x28, 0x00, 0xfe, 0xe2, 0x10, 0x01, 0xf5, 0x01, 0xf6, 0x09,
- 0xa4, 0x01, 0xfe, 0x26, 0x0f, 0x64, 0x12, 0x2f, 0x01, 0x73, 0x02, 0x2b,
- 0x10, 0xfe, 0x44, 0x00, 0x55, 0x0a, 0xe9, 0x44, 0x0a, 0xfe, 0xb4, 0x10,
- 0x01, 0xb0, 0x44, 0x0a, 0xfe, 0xaa, 0x10, 0x01, 0xb0, 0xfe, 0x19, 0x82,
- 0xfe, 0x34, 0x46, 0xac, 0x44, 0x0a, 0x10, 0xfe, 0x43, 0x00, 0xfe, 0x96,
- 0x10, 0x08, 0x54, 0x0a, 0x37, 0x01, 0xf5, 0x01, 0xf6, 0x64, 0x12, 0x2f,
- 0x01, 0x73, 0x99, 0x0a, 0x64, 0x42, 0x92, 0x02, 0xfe, 0x2e, 0x03, 0x08,
- 0x05, 0x0a, 0x8a, 0x44, 0x0a, 0x10, 0x00, 0xfe, 0x5c, 0x10, 0x68, 0x05,
- 0x1a, 0xfe, 0x58, 0x12, 0x08, 0x05, 0x1a, 0xfe, 0x50, 0x13, 0xfe, 0x1c,
- 0x1c, 0xfe, 0x9d, 0xf0, 0xfe, 0x50, 0x0d, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d,
- 0xf0, 0xfe, 0x56, 0x0d, 0x08, 0x54, 0x1a, 0x37, 0xfe, 0xa9, 0x10, 0x10,
- 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0a, 0x50, 0xfe, 0x2e, 0x10, 0x10,
- 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x10, 0x6f, 0xab, 0x10, 0xfe, 0x41,
- 0x00, 0xaa, 0x10, 0xfe, 0x24, 0x00, 0x8c, 0xb5, 0xb6, 0x74, 0x03, 0x70,
- 0x28, 0x23, 0xd8, 0x50, 0xfe, 0x04, 0xe6, 0x1a, 0xfe, 0x9d, 0x41, 0xfe,
- 0x1c, 0x42, 0x64, 0x01, 0xe3, 0x02, 0x2b, 0xf8, 0x15, 0x0a, 0x39, 0xa0,
- 0xb4, 0x15, 0xfe, 0x31, 0x00, 0x39, 0xa2, 0x01, 0xfe, 0x48, 0x10, 0x02,
- 0xd7, 0x42, 0xfe, 0x06, 0xec, 0xd0, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45,
- 0x35, 0x42, 0xfe, 0x06, 0xea, 0xd0, 0xfe, 0x47, 0x4b, 0x91, 0xfe, 0x75,
- 0x57, 0x03, 0x5d, 0xfe, 0x98, 0x56, 0xfe, 0x38, 0x12, 0x09, 0x48, 0x01,
- 0x0e, 0xfe, 0x44, 0x48, 0x4f, 0x08, 0x05, 0x1b, 0xfe, 0x1a, 0x13, 0x09,
- 0x46, 0x01, 0x0e, 0x41, 0xfe, 0x41, 0x58, 0x09, 0xa4, 0x01, 0x0e, 0xfe,
- 0x49, 0x54, 0x96, 0xfe, 0x1e, 0x0e, 0x02, 0xfe, 0x2e, 0x03, 0x09, 0x5d,
- 0xfe, 0xee, 0x14, 0xfc, 0x44, 0x1b, 0xfe, 0xce, 0x45, 0x35, 0x42, 0xfe,
- 0xce, 0x47, 0xfe, 0xad, 0x13, 0x02, 0x2b, 0x22, 0x20, 0x07, 0x11, 0xfe,
- 0x9e, 0x12, 0x21, 0x13, 0x59, 0x13, 0x9f, 0x13, 0xd5, 0x22, 0x2f, 0x41,
- 0x39, 0x2f, 0xbc, 0xad, 0xfe, 0xbc, 0xf0, 0xfe, 0xe0, 0x0e, 0x0f, 0x06,
- 0x13, 0x59, 0x01, 0xfe, 0xda, 0x16, 0x03, 0xfe, 0x38, 0x01, 0x29, 0xfe,
- 0x3a, 0x01, 0x56, 0xfe, 0xe4, 0x0e, 0xfe, 0x02, 0xec, 0xd5, 0x69, 0x00,
- 0x66, 0xfe, 0x04, 0xec, 0x20, 0x4f, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01,
- 0x01, 0xfe, 0x4a, 0x17, 0xfe, 0x08, 0x90, 0xfe, 0x48, 0xf4, 0x0d, 0xfe,
- 0x18, 0x13, 0xba, 0xfe, 0x02, 0xea, 0xd5, 0x69, 0x7e, 0xfe, 0xc5, 0x13,
- 0x15, 0x1a, 0x39, 0xa0, 0xb4, 0xfe, 0x2e, 0x10, 0x03, 0xfe, 0x38, 0x01,
- 0x1e, 0xfe, 0xf0, 0xff, 0x0c, 0xfe, 0x60, 0x01, 0x03, 0xfe, 0x3a, 0x01,
- 0x0c, 0xfe, 0x62, 0x01, 0x43, 0x13, 0x20, 0x25, 0x06, 0x13, 0x2f, 0x12,
- 0x2f, 0x92, 0x0f, 0x06, 0x04, 0x21, 0x04, 0x22, 0x59, 0xfe, 0xf7, 0x12,
- 0x22, 0x9f, 0xb7, 0x13, 0x9f, 0x07, 0x7e, 0xfe, 0x71, 0x13, 0xfe, 0x24,
- 0x1c, 0x15, 0x19, 0x39, 0xa0, 0xb4, 0xfe, 0xd9, 0x10, 0xc3, 0xfe, 0x03,
- 0xdc, 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xc3, 0xfe, 0x03, 0xdc,
- 0xfe, 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x21,
- 0xfe, 0x00, 0xcc, 0x04, 0xfe, 0x03, 0x57, 0xc3, 0x78, 0x04, 0x08, 0x05,
- 0x58, 0xfe, 0x22, 0x13, 0xfe, 0x1c, 0x80, 0x07, 0x06, 0xfe, 0x1a, 0x13,
- 0xfe, 0x1e, 0x80, 0xed, 0xfe, 0x1d, 0x80, 0xae, 0xfe, 0x0c, 0x90, 0xfe,
- 0x0e, 0x13, 0xfe, 0x0e, 0x90, 0xac, 0xfe, 0x3c, 0x90, 0xfe, 0x30, 0xf4,
- 0x0a, 0xfe, 0x3c, 0x50, 0xaa, 0x01, 0xfe, 0x7a, 0x17, 0x32, 0x07, 0x2f,
- 0xad, 0x01, 0xfe, 0xb4, 0x16, 0x08, 0x05, 0x1b, 0x4e, 0x01, 0xf5, 0x01,
- 0xf6, 0x12, 0xfe, 0xe9, 0x00, 0x08, 0x05, 0x58, 0xfe, 0x2c, 0x13, 0x01,
- 0xfe, 0x0c, 0x17, 0xfe, 0x1e, 0x1c, 0xfe, 0x14, 0x90, 0xfe, 0x96, 0x90,
- 0x0c, 0xfe, 0x64, 0x01, 0x14, 0xfe, 0x66, 0x01, 0x08, 0x05, 0x5b, 0xfe,
- 0x12, 0x12, 0xfe, 0x03, 0x80, 0x8d, 0xfe, 0x01, 0xec, 0x20, 0xfe, 0x80,
- 0x40, 0x13, 0x20, 0x6a, 0x2a, 0x12, 0xcf, 0x64, 0x22, 0x20, 0xfb, 0x79,
- 0x20, 0x04, 0xfe, 0x08, 0x1c, 0x03, 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58,
- 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07, 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe,
- 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00, 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c,
- 0x25, 0x6e, 0x13, 0xd0, 0x21, 0x0c, 0x5c, 0x0c, 0x45, 0x0f, 0x46, 0x52,
- 0x50, 0x18, 0x1b, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x23, 0xfe, 0xfc,
- 0x0f, 0x44, 0x11, 0x0f, 0x48, 0x52, 0x18, 0x58, 0xfe, 0x90, 0x4d, 0xfe,
- 0x91, 0x54, 0x23, 0xe4, 0x25, 0x11, 0x13, 0x20, 0x7c, 0x6f, 0x4f, 0x22,
- 0x20, 0xfb, 0x79, 0x20, 0x12, 0xcf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
- 0xfe, 0x26, 0x10, 0xf8, 0x74, 0xfe, 0x14, 0x1c, 0xfe, 0x10, 0x1c, 0xfe,
- 0x18, 0x1c, 0x04, 0x42, 0xfe, 0x0c, 0x14, 0xfc, 0xfe, 0x07, 0xe6, 0x1b,
- 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x04, 0x01, 0xb0, 0x7c, 0x6f, 0x4f,
- 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42, 0x13, 0x32, 0x07, 0x2f,
- 0xfe, 0x34, 0x13, 0x09, 0x48, 0x01, 0x0e, 0xbb, 0xfe, 0x36, 0x12, 0xfe,
- 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01, 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe,
- 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11, 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe,
- 0x80, 0x5c, 0x01, 0x73, 0xfe, 0x0e, 0x10, 0x07, 0x82, 0x4e, 0xfe, 0x14,
- 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x60, 0x10, 0x04, 0xfe, 0x44, 0x58, 0x8d,
- 0xfe, 0x01, 0xec, 0xa2, 0xfe, 0x9e, 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe,
- 0x9c, 0xe7, 0x1a, 0x79, 0x2a, 0x01, 0xe3, 0xfe, 0xdd, 0x10, 0x2c, 0xc7,
- 0x81, 0xc8, 0x83, 0x33, 0x31, 0xde, 0x07, 0x1a, 0xfe, 0x48, 0x12, 0x07,
- 0x0a, 0xfe, 0x56, 0x12, 0x07, 0x19, 0xfe, 0x30, 0x12, 0x07, 0xc9, 0x17,
- 0xfe, 0x32, 0x12, 0x07, 0xfe, 0x23, 0x00, 0x17, 0xeb, 0x07, 0x06, 0x17,
- 0xfe, 0x9c, 0x12, 0x07, 0x1f, 0xfe, 0x12, 0x12, 0x07, 0x00, 0x17, 0x24,
- 0x15, 0xc9, 0x01, 0x36, 0xa9, 0x2d, 0x01, 0x0b, 0x94, 0x4b, 0x04, 0x2d,
- 0xdd, 0x09, 0xd1, 0x01, 0xfe, 0x26, 0x0f, 0x12, 0x82, 0x02, 0x2b, 0x2d,
- 0x32, 0x07, 0xa6, 0xfe, 0xd9, 0x13, 0x3a, 0x3d, 0x3b, 0x3e, 0x56, 0xfe,
- 0xf0, 0x11, 0x08, 0x05, 0x5a, 0xfe, 0x72, 0x12, 0x9b, 0x2e, 0x9c, 0x3c,
- 0x90, 0xc0, 0x96, 0xfe, 0xba, 0x11, 0x22, 0x62, 0xfe, 0x26, 0x13, 0x03,
- 0x7f, 0x29, 0x80, 0x56, 0xfe, 0x76, 0x0d, 0x0c, 0x60, 0x14, 0x61, 0x21,
- 0x0c, 0x7f, 0x0c, 0x80, 0x01, 0xb3, 0x25, 0x6e, 0x77, 0x13, 0x62, 0x01,
- 0xef, 0x9b, 0x2e, 0x9c, 0x3c, 0xfe, 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe,
- 0x04, 0xfa, 0x2e, 0xfe, 0x05, 0xfa, 0x3c, 0xfe, 0x91, 0x10, 0x03, 0x3f,
- 0x29, 0x40, 0xfe, 0x40, 0x56, 0xfe, 0xe1, 0x56, 0x0c, 0x3f, 0x14, 0x40,
- 0x88, 0x9b, 0x2e, 0x9c, 0x3c, 0x90, 0xc0, 0x03, 0x5e, 0x29, 0x5f, 0xfe,
- 0x00, 0x56, 0xfe, 0xa1, 0x56, 0x0c, 0x5e, 0x14, 0x5f, 0x08, 0x05, 0x5a,
- 0xfe, 0x1e, 0x12, 0x22, 0x62, 0xfe, 0x1f, 0x40, 0x03, 0x60, 0x29, 0x61,
- 0xfe, 0x2c, 0x50, 0xfe, 0xae, 0x50, 0x03, 0x3f, 0x29, 0x40, 0xfe, 0x44,
- 0x50, 0xfe, 0xc6, 0x50, 0x03, 0x5e, 0x29, 0x5f, 0xfe, 0x08, 0x50, 0xfe,
- 0x8a, 0x50, 0x03, 0x3d, 0x29, 0x3e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50,
- 0x02, 0x89, 0x25, 0x06, 0x13, 0xd4, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1d,
- 0x4c, 0x33, 0x31, 0xde, 0x07, 0x06, 0x23, 0x4c, 0x32, 0x07, 0xa6, 0x23,
- 0x72, 0x01, 0xaf, 0x1e, 0x43, 0x17, 0x4c, 0x08, 0x05, 0x0a, 0xee, 0x3a,
- 0x3d, 0x3b, 0x3e, 0xfe, 0x0a, 0x55, 0x35, 0xfe, 0x8b, 0x55, 0x57, 0x3d,
- 0x7d, 0x3e, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x02, 0x72, 0xfe, 0x19,
- 0x81, 0xba, 0xfe, 0x19, 0x41, 0x02, 0x72, 0x2d, 0x01, 0x0b, 0x1c, 0x34,
- 0x1d, 0xe8, 0x33, 0x31, 0xe1, 0x55, 0x19, 0xfe, 0xa6, 0x12, 0x55, 0x0a,
- 0x4d, 0x02, 0x4c, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0xe8, 0x33, 0x31, 0xdf,
- 0x07, 0x19, 0x23, 0x4c, 0x01, 0x0b, 0x1d, 0xe8, 0x33, 0x31, 0xfe, 0xe8,
- 0x09, 0xfe, 0xc2, 0x49, 0x51, 0x03, 0xfe, 0x9c, 0x00, 0x28, 0x8a, 0x53,
- 0x05, 0x1f, 0x35, 0xa9, 0xfe, 0xbb, 0x45, 0x55, 0x00, 0x4e, 0x44, 0x06,
- 0x7c, 0x43, 0xfe, 0xda, 0x14, 0x01, 0xaf, 0x8c, 0xfe, 0x4b, 0x45, 0xee,
- 0x32, 0x07, 0xa5, 0xed, 0x03, 0xcd, 0x28, 0x8a, 0x03, 0x45, 0x28, 0x35,
- 0x67, 0x02, 0x72, 0xfe, 0xc0, 0x5d, 0xfe, 0xf8, 0x14, 0xfe, 0x03, 0x17,
- 0x03, 0x5c, 0xc1, 0x0c, 0x5c, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01,
- 0xfe, 0x9e, 0x15, 0x02, 0x89, 0x01, 0x0b, 0x1c, 0x34, 0x1d, 0x4c, 0x33,
- 0x31, 0xdf, 0x07, 0x06, 0x23, 0x4c, 0x01, 0xf1, 0xfe, 0x42, 0x58, 0xf1,
- 0xfe, 0xa4, 0x14, 0x8c, 0xfe, 0x4a, 0xf4, 0x0a, 0x17, 0x4c, 0xfe, 0x4a,
- 0xf4, 0x06, 0xea, 0x32, 0x07, 0xa5, 0x8b, 0x02, 0x72, 0x03, 0x45, 0xc1,
- 0x0c, 0x45, 0x67, 0x2d, 0x01, 0x0b, 0x26, 0x89, 0x01, 0xfe, 0xcc, 0x15,
- 0x02, 0x89, 0x0f, 0x06, 0x27, 0xfe, 0xbe, 0x13, 0x26, 0xfe, 0xd4, 0x13,
- 0x76, 0xfe, 0x89, 0x48, 0x01, 0x0b, 0x21, 0x76, 0x04, 0x7b, 0xfe, 0xd0,
- 0x13, 0x1c, 0xfe, 0xd0, 0x13, 0x1d, 0xfe, 0xbe, 0x13, 0x67, 0x2d, 0x01,
- 0x0b, 0xfe, 0xd5, 0x10, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
- 0x1e, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x04, 0x0f,
- 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0x1e, 0x43, 0xfe, 0x30, 0x56,
- 0xfe, 0x00, 0x5c, 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93,
- 0x04, 0x0f, 0x71, 0xff, 0x02, 0x00, 0x57, 0x52, 0x93, 0xfe, 0x0b, 0x58,
- 0x04, 0x09, 0x5c, 0x01, 0x87, 0x09, 0x45, 0x01, 0x87, 0x04, 0xfe, 0x03,
- 0xa1, 0x1e, 0x11, 0xff, 0x03, 0x00, 0x54, 0xfe, 0x00, 0xf4, 0x1f, 0x52,
- 0xfe, 0x00, 0x7d, 0xfe, 0x01, 0x7d, 0xfe, 0x02, 0x7d, 0xfe, 0x03, 0x7c,
- 0x6a, 0x2a, 0x0c, 0x5e, 0x14, 0x5f, 0x57, 0x3f, 0x7d, 0x40, 0x04, 0xdd,
- 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x8d, 0x04, 0x01,
- 0xfe, 0x0c, 0x19, 0xfe, 0x42, 0x48, 0x50, 0x51, 0x91, 0x01, 0x0b, 0x1d,
- 0xfe, 0x96, 0x15, 0x33, 0x31, 0xe1, 0x01, 0x0b, 0x1d, 0xfe, 0x96, 0x15,
- 0x33, 0x31, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0xcd, 0x28, 0xfe,
- 0xcc, 0x12, 0x53, 0x05, 0x1a, 0xfe, 0xc4, 0x13, 0x21, 0x69, 0x1a, 0xee,
- 0x55, 0xca, 0x6b, 0xfe, 0xdc, 0x14, 0x4d, 0x0f, 0x06, 0x18, 0xca, 0x7c,
- 0x30, 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xab, 0xff, 0x02, 0x83,
- 0x55, 0x69, 0x19, 0xae, 0x98, 0xfe, 0x30, 0x00, 0x96, 0xf2, 0x18, 0x6d,
- 0x0f, 0x06, 0xfe, 0x56, 0x10, 0x69, 0x0a, 0xed, 0x98, 0xfe, 0x64, 0x00,
- 0x96, 0xf2, 0x09, 0xfe, 0x64, 0x00, 0x18, 0x9e, 0x0f, 0x06, 0xfe, 0x28,
- 0x10, 0x69, 0x06, 0xfe, 0x60, 0x13, 0x98, 0xfe, 0xc8, 0x00, 0x96, 0xf2,
- 0x09, 0xfe, 0xc8, 0x00, 0x18, 0x59, 0x0f, 0x06, 0x88, 0x98, 0xfe, 0x90,
- 0x01, 0x7a, 0xfe, 0x42, 0x15, 0x91, 0xe4, 0xfe, 0x43, 0xf4, 0x9f, 0xfe,
- 0x56, 0xf0, 0xfe, 0x54, 0x15, 0xfe, 0x04, 0xf4, 0x71, 0xfe, 0x43, 0xf4,
- 0x9e, 0xfe, 0xf3, 0x10, 0xfe, 0x40, 0x5c, 0x01, 0xfe, 0x16, 0x14, 0x1e,
- 0x43, 0xec, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4, 0x6e, 0x7a, 0xfe, 0x90,
- 0x15, 0xc4, 0x6e, 0xfe, 0x1c, 0x10, 0xfe, 0x00, 0x17, 0xfe, 0x4d, 0xe4,
- 0xcc, 0x7a, 0xfe, 0x90, 0x15, 0xc4, 0xcc, 0x88, 0x51, 0x21, 0xfe, 0x4d,
- 0xf4, 0x00, 0xe9, 0x91, 0x0f, 0x06, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58,
- 0x04, 0x51, 0x0f, 0x0a, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xf3, 0x16,
- 0x0a, 0x01, 0x0b, 0x26, 0xf3, 0x16, 0x19, 0x01, 0x0b, 0x26, 0xf3, 0x76,
- 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x04, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
- 0x16, 0x19, 0x01, 0x0b, 0x26, 0xb1, 0x16, 0x06, 0x01, 0x0b, 0x26, 0xb1,
- 0xfe, 0x89, 0x49, 0x01, 0x0b, 0x26, 0xb1, 0x76, 0xfe, 0x89, 0x4a, 0x01,
- 0x0b, 0x04, 0x51, 0x04, 0x22, 0xd3, 0x07, 0x06, 0xfe, 0x48, 0x13, 0xb8,
- 0x13, 0xd3, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x76, 0xa9, 0x67, 0xfe, 0x01,
- 0xec, 0xfe, 0x27, 0x01, 0xfe, 0x89, 0x48, 0xff, 0x02, 0x00, 0x10, 0x27,
- 0xfe, 0x2e, 0x16, 0x32, 0x07, 0xfe, 0xe3, 0x00, 0xfe, 0x20, 0x13, 0x1d,
- 0xfe, 0x52, 0x16, 0x21, 0x13, 0xd4, 0x01, 0x4b, 0x22, 0xd4, 0x07, 0x06,
- 0x4e, 0x08, 0x54, 0x06, 0x37, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfb, 0x8e,
- 0x07, 0x11, 0xae, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0x09, 0x5d, 0x01, 0xa8,
- 0x04, 0x09, 0x84, 0x01, 0x0e, 0x8e, 0xfe, 0x80, 0xe7, 0x11, 0x07, 0x11,
- 0x8a, 0xfe, 0x45, 0x58, 0x01, 0xf0, 0x8e, 0x04, 0x09, 0x48, 0x01, 0x0e,
- 0x8e, 0x09, 0x5d, 0x01, 0xa8, 0x04, 0x09, 0x48, 0x01, 0x0e, 0xfe, 0x80,
- 0x80, 0xfe, 0x80, 0x4c, 0xfe, 0x49, 0xe4, 0x11, 0xae, 0x09, 0x84, 0x01,
- 0x0e, 0xfe, 0x80, 0x4c, 0x09, 0x5d, 0x01, 0x87, 0x04, 0x18, 0x11, 0x75,
- 0x6c, 0xfe, 0x60, 0x01, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24,
- 0x1c, 0xfe, 0x1d, 0xf7, 0x1b, 0x97, 0xfe, 0xee, 0x16, 0x01, 0xfe, 0xf4,
- 0x17, 0xad, 0x9a, 0x1b, 0x6c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x04,
- 0xb9, 0x23, 0xfe, 0xde, 0x16, 0xfe, 0xda, 0x10, 0x18, 0x11, 0x75, 0x03,
- 0xfe, 0x64, 0x01, 0xfe, 0x00, 0xf4, 0x1f, 0xfe, 0x18, 0x58, 0x03, 0xfe,
- 0x66, 0x01, 0xfe, 0x19, 0x58, 0x9a, 0x1f, 0xfe, 0x3c, 0x90, 0xfe, 0x30,
- 0xf4, 0x06, 0xfe, 0x3c, 0x50, 0x6c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79,
- 0xfe, 0x1c, 0xf7, 0x1f, 0x97, 0xfe, 0x38, 0x17, 0xfe, 0xb6, 0x14, 0x35,
- 0x04, 0xb9, 0x23, 0xfe, 0x10, 0x17, 0xfe, 0x9c, 0x10, 0x18, 0x11, 0x75,
- 0xfe, 0x83, 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7,
- 0x2e, 0x97, 0xfe, 0x5a, 0x17, 0xfe, 0x94, 0x14, 0xec, 0x9a, 0x2e, 0x6c,
- 0x1a, 0xfe, 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x04, 0xb9, 0x23, 0xfe,
- 0x4e, 0x17, 0xfe, 0x6c, 0x10, 0x18, 0x11, 0x75, 0xfe, 0x30, 0xbc, 0xfe,
- 0xb2, 0xbc, 0x9a, 0xcb, 0x6c, 0x1a, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7,
- 0xcb, 0x97, 0xfe, 0x92, 0x17, 0xfe, 0x5c, 0x14, 0x35, 0x04, 0xb9, 0x23,
- 0xfe, 0x7e, 0x17, 0xfe, 0x42, 0x10, 0xfe, 0x02, 0xf6, 0x11, 0x75, 0xfe,
- 0x18, 0xfe, 0x60, 0xfe, 0x19, 0xfe, 0x61, 0xfe, 0x03, 0xa1, 0xfe, 0x1d,
- 0xf7, 0x5b, 0x97, 0xfe, 0xb8, 0x17, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13,
- 0x9a, 0x5b, 0x41, 0xfe, 0x83, 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7,
- 0x11, 0xfe, 0x81, 0xe7, 0x11, 0x12, 0xfe, 0xdd, 0x00, 0x6a, 0x2a, 0x04,
- 0x6a, 0x2a, 0xfe, 0x12, 0x45, 0x23, 0xfe, 0xa8, 0x17, 0x15, 0x06, 0x39,
- 0xa0, 0xb4, 0x02, 0x2b, 0xfe, 0x39, 0xf0, 0xfe, 0xfc, 0x17, 0x21, 0x04,
- 0xfe, 0x7e, 0x18, 0x1e, 0x19, 0x66, 0x0f, 0x0d, 0x04, 0x75, 0x03, 0xd2,
- 0x1e, 0x06, 0xfe, 0xef, 0x12, 0xfe, 0xe1, 0x10, 0x7c, 0x6f, 0x4f, 0x32,
- 0x07, 0x2f, 0xfe, 0x3c, 0x13, 0xf1, 0xfe, 0x42, 0x13, 0x42, 0x92, 0x09,
- 0x48, 0x01, 0x0e, 0xbb, 0xeb, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
- 0xf0, 0xfe, 0x00, 0xcc, 0xbb, 0xfe, 0xf3, 0x13, 0x43, 0x78, 0x07, 0x11,
- 0xac, 0x09, 0x84, 0x01, 0x0e, 0xfe, 0x80, 0x4c, 0x01, 0x73, 0xfe, 0x16,
- 0x10, 0x07, 0x82, 0x8b, 0xfe, 0x40, 0x14, 0xfe, 0x24, 0x12, 0xfe, 0x14,
- 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x1c, 0x18, 0x18, 0x0a, 0x04, 0xfe, 0x9c,
- 0xe7, 0x0a, 0x10, 0xfe, 0x15, 0x00, 0x64, 0x79, 0x2a, 0x01, 0xe3, 0x18,
- 0x06, 0x04, 0x42, 0x92, 0x08, 0x54, 0x1b, 0x37, 0x12, 0x2f, 0x01, 0x73,
- 0x18, 0x06, 0x04, 0xfe, 0x38, 0x90, 0xfe, 0xba, 0x90, 0x3a, 0xce, 0x3b,
- 0xcf, 0xfe, 0x48, 0x55, 0x35, 0xfe, 0xc9, 0x55, 0x04, 0x22, 0xa3, 0x77,
- 0x13, 0xa3, 0x04, 0x09, 0xa4, 0x01, 0x0e, 0xfe, 0x41, 0x48, 0x09, 0x46,
- 0x01, 0x0e, 0xfe, 0x49, 0x44, 0x17, 0xfe, 0xe8, 0x18, 0x77, 0x78, 0x04,
- 0x09, 0x48, 0x01, 0x0e, 0x07, 0x11, 0x4e, 0x09, 0x5d, 0x01, 0xa8, 0x09,
- 0x46, 0x01, 0x0e, 0x77, 0x78, 0x04, 0xfe, 0x4e, 0xe4, 0x19, 0x6b, 0xfe,
- 0x1c, 0x19, 0x03, 0xfe, 0x90, 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10,
- 0xfe, 0x4e, 0xe4, 0xc9, 0x6b, 0xfe, 0x2e, 0x19, 0x03, 0xfe, 0x92, 0x00,
- 0xfe, 0x02, 0xe6, 0x1a, 0xe5, 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x6b,
- 0xfe, 0x40, 0x19, 0x03, 0xfe, 0x94, 0x00, 0xfe, 0x02, 0xe6, 0x1f, 0xfe,
- 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xfe, 0x02, 0xe6, 0x6d, 0xfe, 0x4e,
- 0x45, 0xea, 0xba, 0xff, 0x04, 0x68, 0x54, 0xe7, 0x1e, 0x6e, 0xfe, 0x08,
- 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c, 0xfe, 0x1a, 0xf4, 0xfe, 0x00,
- 0x04, 0xea, 0xfe, 0x48, 0xf4, 0x19, 0x7a, 0xfe, 0x74, 0x19, 0x0f, 0x19,
- 0x04, 0x07, 0x7e, 0xfe, 0x5a, 0xf0, 0xfe, 0x84, 0x19, 0x25, 0xfe, 0x09,
- 0x00, 0xfe, 0x34, 0x10, 0x07, 0x1a, 0xfe, 0x5a, 0xf0, 0xfe, 0x92, 0x19,
- 0x25, 0xca, 0xfe, 0x26, 0x10, 0x07, 0x19, 0x66, 0x25, 0x6d, 0xe5, 0x07,
- 0x0a, 0x66, 0x25, 0x9e, 0xfe, 0x0e, 0x10, 0x07, 0x06, 0x66, 0x25, 0x59,
- 0xa9, 0xb8, 0x04, 0x15, 0xfe, 0x09, 0x00, 0x01, 0x36, 0xfe, 0x04, 0xfe,
- 0x81, 0x03, 0x83, 0xfe, 0x40, 0x5c, 0x04, 0x1c, 0xf7, 0xfe, 0x14, 0xf0,
- 0x0b, 0x27, 0xfe, 0xd6, 0x19, 0x1c, 0xf7, 0x7b, 0xf7, 0xfe, 0x82, 0xf0,
- 0xfe, 0xda, 0x19, 0x04, 0xff, 0xcc, 0x00, 0x00,
-};
-
-static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */
-static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */
-
-/* Microcode buffer is kept after initialization for error recovery. */
-static unsigned char _adv_asc38C1600_buf[] = {
- 0x00, 0x00, 0x00, 0xf2, 0x00, 0x16, 0x00, 0xfc, 0x00, 0x10, 0x00, 0xf0,
- 0x18, 0xe4, 0x01, 0x00, 0x04, 0x1e, 0x48, 0xe4, 0x03, 0xf6, 0xf7, 0x13,
- 0x2e, 0x1e, 0x02, 0x00, 0x07, 0x17, 0xc0, 0x5f, 0x00, 0xfa, 0xff, 0xff,
- 0x04, 0x00, 0x00, 0xf6, 0x09, 0xe7, 0x82, 0xe7, 0x85, 0xf0, 0x86, 0xf0,
- 0x4e, 0x10, 0x9e, 0xe7, 0xff, 0x00, 0x55, 0xf0, 0x01, 0xf6, 0x03, 0x00,
- 0x98, 0x57, 0x01, 0xe6, 0x00, 0xea, 0x00, 0xec, 0x01, 0xfa, 0x18, 0xf4,
- 0x08, 0x00, 0xf0, 0x1d, 0x38, 0x54, 0x32, 0xf0, 0x10, 0x00, 0xc2, 0x0e,
- 0x1e, 0xf0, 0xd5, 0xf0, 0xbc, 0x00, 0x4b, 0xe4, 0x00, 0xe6, 0xb1, 0xf0,
- 0xb4, 0x00, 0x02, 0x13, 0x3e, 0x1c, 0xc8, 0x47, 0x3e, 0x00, 0xd8, 0x01,
- 0x06, 0x13, 0x0c, 0x1c, 0x5e, 0x1e, 0x00, 0x57, 0xc8, 0x57, 0x01, 0xfc,
- 0xbc, 0x0e, 0xa2, 0x12, 0xb9, 0x54, 0x00, 0x80, 0x62, 0x0a, 0x5a, 0x12,
- 0xc8, 0x15, 0x3e, 0x1e, 0x18, 0x40, 0xbd, 0x56, 0x03, 0xe6, 0x01, 0xea,
- 0x5c, 0xf0, 0x0f, 0x00, 0x20, 0x00, 0x6c, 0x01, 0x6e, 0x01, 0x04, 0x12,
- 0x04, 0x13, 0xbb, 0x55, 0x3c, 0x56, 0x3e, 0x57, 0x03, 0x58, 0x4a, 0xe4,
- 0x40, 0x00, 0xb6, 0x00, 0xbb, 0x00, 0xc0, 0x00, 0x00, 0x01, 0x01, 0x01,
- 0x3e, 0x01, 0x58, 0x0a, 0x44, 0x10, 0x0a, 0x12, 0x4c, 0x1c, 0x4e, 0x1c,
- 0x02, 0x4a, 0x30, 0xe4, 0x05, 0xe6, 0x0c, 0x00, 0x3c, 0x00, 0x80, 0x00,
- 0x24, 0x01, 0x3c, 0x01, 0x68, 0x01, 0x6a, 0x01, 0x70, 0x01, 0x72, 0x01,
- 0x74, 0x01, 0x76, 0x01, 0x78, 0x01, 0x7c, 0x01, 0xc6, 0x0e, 0x0c, 0x10,
- 0xac, 0x12, 0xae, 0x12, 0x16, 0x1a, 0x32, 0x1c, 0x6e, 0x1e, 0x02, 0x48,
- 0x3a, 0x55, 0xc9, 0x57, 0x02, 0xee, 0x5b, 0xf0, 0x03, 0xf7, 0x06, 0xf7,
- 0x03, 0xfc, 0x06, 0x00, 0x1e, 0x00, 0xbe, 0x00, 0xe1, 0x00, 0x0c, 0x12,
- 0x18, 0x1a, 0x70, 0x1a, 0x30, 0x1c, 0x38, 0x1c, 0x10, 0x44, 0x00, 0x4c,
- 0xb0, 0x57, 0x40, 0x5c, 0x4d, 0xe4, 0x04, 0xea, 0x5d, 0xf0, 0xa7, 0xf0,
- 0x04, 0xf6, 0x02, 0xfc, 0x05, 0x00, 0x09, 0x00, 0x19, 0x00, 0x32, 0x00,
- 0x33, 0x00, 0x34, 0x00, 0x36, 0x00, 0x98, 0x00, 0x9e, 0x00, 0xcc, 0x00,
- 0x20, 0x01, 0x4e, 0x01, 0x79, 0x01, 0x3c, 0x09, 0x68, 0x0d, 0x02, 0x10,
- 0x04, 0x10, 0x3a, 0x10, 0x08, 0x12, 0x0a, 0x13, 0x40, 0x16, 0x50, 0x16,
- 0x00, 0x17, 0x4a, 0x19, 0x00, 0x4e, 0x00, 0x54, 0x01, 0x58, 0x00, 0xdc,
- 0x05, 0xf0, 0x09, 0xf0, 0x59, 0xf0, 0xb8, 0xf0, 0x48, 0xf4, 0x0e, 0xf7,
- 0x0a, 0x00, 0x9b, 0x00, 0x9c, 0x00, 0xa4, 0x00, 0xb5, 0x00, 0xba, 0x00,
- 0xd0, 0x00, 0xe7, 0x00, 0xf0, 0x03, 0x69, 0x08, 0xe9, 0x09, 0x5c, 0x0c,
- 0xb6, 0x12, 0xbc, 0x19, 0xd8, 0x1b, 0x20, 0x1c, 0x34, 0x1c, 0x36, 0x1c,
- 0x42, 0x1d, 0x08, 0x44, 0x38, 0x44, 0x91, 0x44, 0x0a, 0x45, 0x48, 0x46,
- 0x89, 0x48, 0x68, 0x54, 0x83, 0x55, 0x83, 0x59, 0x31, 0xe4, 0x02, 0xe6,
- 0x07, 0xf0, 0x08, 0xf0, 0x0b, 0xf0, 0x0c, 0xf0, 0x4b, 0xf4, 0x04, 0xf8,
- 0x05, 0xf8, 0x02, 0xfa, 0x03, 0xfa, 0x04, 0xfc, 0x05, 0xfc, 0x07, 0x00,
- 0xa8, 0x00, 0xaa, 0x00, 0xb9, 0x00, 0xe0, 0x00, 0xe5, 0x00, 0x22, 0x01,
- 0x26, 0x01, 0x60, 0x01, 0x7a, 0x01, 0x82, 0x01, 0xc8, 0x01, 0xca, 0x01,
- 0x86, 0x02, 0x6a, 0x03, 0x18, 0x05, 0xb2, 0x07, 0x68, 0x08, 0x10, 0x0d,
- 0x06, 0x10, 0x0a, 0x10, 0x0e, 0x10, 0x12, 0x10, 0x60, 0x10, 0xed, 0x10,
- 0xf3, 0x10, 0x06, 0x12, 0x10, 0x12, 0x1e, 0x12, 0x0c, 0x13, 0x0e, 0x13,
- 0x10, 0x13, 0xfe, 0x9c, 0xf0, 0x35, 0x05, 0xfe, 0xec, 0x0e, 0xff, 0x10,
- 0x00, 0x00, 0xe9, 0xfe, 0x34, 0x1f, 0x00, 0xe8, 0xfe, 0x88, 0x01, 0xff,
- 0x03, 0x00, 0x00, 0xfe, 0x93, 0x15, 0xfe, 0x0f, 0x05, 0xff, 0x38, 0x00,
- 0x00, 0xfe, 0x57, 0x24, 0x00, 0xfe, 0x4c, 0x00, 0x65, 0xff, 0x04, 0x00,
- 0x00, 0x1a, 0xff, 0x09, 0x00, 0x00, 0xff, 0x08, 0x01, 0x01, 0xff, 0x08,
- 0xff, 0xff, 0xff, 0x27, 0x00, 0x00, 0xff, 0x10, 0xff, 0xff, 0xff, 0x13,
- 0x00, 0x00, 0xfe, 0x78, 0x56, 0xfe, 0x34, 0x12, 0xff, 0x21, 0x00, 0x00,
- 0xfe, 0x04, 0xf7, 0xe8, 0x37, 0x7d, 0x0d, 0x01, 0xfe, 0x4a, 0x11, 0xfe,
- 0x04, 0xf7, 0xe8, 0x7d, 0x0d, 0x51, 0x37, 0xfe, 0x3d, 0xf0, 0xfe, 0x0c,
- 0x02, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x91, 0xf0, 0xfe, 0xf8, 0x01, 0xfe,
- 0x90, 0xf0, 0xfe, 0xf8, 0x01, 0xfe, 0x8f, 0xf0, 0xbc, 0x03, 0x67, 0x4d,
- 0x05, 0xfe, 0x08, 0x0f, 0x01, 0xfe, 0x78, 0x0f, 0xfe, 0xdd, 0x12, 0x05,
- 0xfe, 0x0e, 0x03, 0xfe, 0x28, 0x1c, 0x03, 0xfe, 0xa6, 0x00, 0xfe, 0xd1,
- 0x12, 0x3e, 0x22, 0xfe, 0xa6, 0x00, 0xac, 0xfe, 0x48, 0xf0, 0xfe, 0x90,
- 0x02, 0xfe, 0x49, 0xf0, 0xfe, 0xaa, 0x02, 0xfe, 0x4a, 0xf0, 0xfe, 0xc8,
- 0x02, 0xfe, 0x46, 0xf0, 0xfe, 0x5a, 0x02, 0xfe, 0x47, 0xf0, 0xfe, 0x60,
- 0x02, 0xfe, 0x43, 0xf0, 0xfe, 0x4e, 0x02, 0xfe, 0x44, 0xf0, 0xfe, 0x52,
- 0x02, 0xfe, 0x45, 0xf0, 0xfe, 0x56, 0x02, 0x1c, 0x0d, 0xa2, 0x1c, 0x07,
- 0x22, 0xb7, 0x05, 0x35, 0xfe, 0x00, 0x1c, 0xfe, 0xf1, 0x10, 0xfe, 0x02,
- 0x1c, 0xf5, 0xfe, 0x1e, 0x1c, 0xfe, 0xe9, 0x10, 0x01, 0x5f, 0xfe, 0xe7,
- 0x10, 0xfe, 0x06, 0xfc, 0xde, 0x0a, 0x81, 0x01, 0xa3, 0x05, 0x35, 0x1f,
- 0x95, 0x47, 0xb8, 0x01, 0xfe, 0xe4, 0x11, 0x0a, 0x81, 0x01, 0x5c, 0xfe,
- 0xbd, 0x10, 0x0a, 0x81, 0x01, 0x5c, 0xfe, 0xad, 0x10, 0xfe, 0x16, 0x1c,
- 0xfe, 0x58, 0x1c, 0x1c, 0x07, 0x22, 0xb7, 0x37, 0x2a, 0x35, 0xfe, 0x3d,
- 0xf0, 0xfe, 0x0c, 0x02, 0x2b, 0xfe, 0x9e, 0x02, 0xfe, 0x5a, 0x1c, 0xfe,
- 0x12, 0x1c, 0xfe, 0x14, 0x1c, 0x1f, 0xfe, 0x30, 0x00, 0x47, 0xb8, 0x01,
- 0xfe, 0xd4, 0x11, 0x1c, 0x07, 0x22, 0xb7, 0x05, 0xe9, 0x21, 0x2c, 0x09,
- 0x1a, 0x31, 0xfe, 0x69, 0x10, 0x1c, 0x07, 0x22, 0xb7, 0xfe, 0x04, 0xec,
- 0x2c, 0x60, 0x01, 0xfe, 0x1e, 0x1e, 0x20, 0x2c, 0xfe, 0x05, 0xf6, 0xde,
- 0x01, 0xfe, 0x62, 0x1b, 0x01, 0x0c, 0x61, 0x4a, 0x44, 0x15, 0x56, 0x51,
- 0x01, 0xfe, 0x9e, 0x1e, 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x0a, 0x57,
- 0x01, 0x18, 0x09, 0x00, 0x36, 0x01, 0x85, 0xfe, 0x18, 0x10, 0xfe, 0x41,
- 0x58, 0x0a, 0xba, 0x01, 0x18, 0xfe, 0xc8, 0x54, 0x7b, 0xfe, 0x1c, 0x03,
- 0x01, 0xfe, 0x96, 0x1a, 0x05, 0x35, 0x37, 0x60, 0xfe, 0x02, 0xe8, 0x30,
- 0xfe, 0xbf, 0x57, 0xfe, 0x9e, 0x43, 0xfe, 0x77, 0x57, 0xfe, 0x27, 0xf0,
- 0xfe, 0xe4, 0x01, 0xfe, 0x07, 0x4b, 0xfe, 0x20, 0xf0, 0xbc, 0xfe, 0x40,
- 0x1c, 0x2a, 0xeb, 0xfe, 0x26, 0xf0, 0xfe, 0x66, 0x03, 0xfe, 0xa0, 0xf0,
- 0xfe, 0x54, 0x03, 0xfe, 0x11, 0xf0, 0xbc, 0xfe, 0xef, 0x10, 0xfe, 0x9f,
- 0xf0, 0xfe, 0x74, 0x03, 0xfe, 0x46, 0x1c, 0x19, 0xfe, 0x11, 0x00, 0x05,
- 0x70, 0x37, 0xfe, 0x48, 0x1c, 0xfe, 0x46, 0x1c, 0x01, 0x0c, 0x06, 0x28,
- 0xfe, 0x18, 0x13, 0x26, 0x21, 0xb9, 0xc7, 0x20, 0xb9, 0x0a, 0x57, 0x01,
- 0x18, 0xc7, 0x89, 0x01, 0xfe, 0xc8, 0x1a, 0x15, 0xe1, 0x2a, 0xeb, 0xfe,
- 0x01, 0xf0, 0xeb, 0xfe, 0x82, 0xf0, 0xfe, 0xa4, 0x03, 0xfe, 0x9c, 0x32,
- 0x15, 0xfe, 0xe4, 0x00, 0x2f, 0xfe, 0xb6, 0x03, 0x2a, 0x3c, 0x16, 0xfe,
- 0xc6, 0x03, 0x01, 0x41, 0xfe, 0x06, 0xf0, 0xfe, 0xd6, 0x03, 0xaf, 0xa0,
- 0xfe, 0x0a, 0xf0, 0xfe, 0xa2, 0x07, 0x05, 0x29, 0x03, 0x81, 0x1e, 0x1b,
- 0xfe, 0x24, 0x05, 0x1f, 0x63, 0x01, 0x42, 0x8f, 0xfe, 0x70, 0x02, 0x05,
- 0xea, 0xfe, 0x46, 0x1c, 0x37, 0x7d, 0x1d, 0xfe, 0x67, 0x1b, 0xfe, 0xbf,
- 0x57, 0xfe, 0x77, 0x57, 0xfe, 0x48, 0x1c, 0x75, 0x01, 0xa6, 0x86, 0x0a,
- 0x57, 0x01, 0x18, 0x09, 0x00, 0x1b, 0xec, 0x0a, 0xe1, 0x01, 0x18, 0x77,
- 0x50, 0x40, 0x8d, 0x30, 0x03, 0x81, 0x1e, 0xf8, 0x1f, 0x63, 0x01, 0x42,
- 0x8f, 0xfe, 0x70, 0x02, 0x05, 0xea, 0xd7, 0x99, 0xd8, 0x9c, 0x2a, 0x29,
- 0x2f, 0xfe, 0x4e, 0x04, 0x16, 0xfe, 0x4a, 0x04, 0x7e, 0xfe, 0xa0, 0x00,
- 0xfe, 0x9b, 0x57, 0xfe, 0x54, 0x12, 0x32, 0xff, 0x02, 0x00, 0x10, 0x01,
- 0x08, 0x16, 0xfe, 0x02, 0x05, 0x32, 0x01, 0x08, 0x16, 0x29, 0x27, 0x25,
- 0xee, 0xfe, 0x4c, 0x44, 0xfe, 0x58, 0x12, 0x50, 0xfe, 0x44, 0x48, 0x13,
- 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x60, 0x8d, 0x30, 0x01, 0xfe, 0x4e,
- 0x1e, 0xfe, 0x48, 0x47, 0xfe, 0x7c, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xfe,
- 0x32, 0x13, 0x01, 0x43, 0x09, 0x9b, 0xfe, 0x68, 0x13, 0xfe, 0x26, 0x10,
- 0x13, 0x34, 0xfe, 0x4c, 0x54, 0x7b, 0xec, 0x01, 0xfe, 0x4e, 0x1e, 0xfe,
- 0x48, 0x47, 0xfe, 0x54, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xa5, 0x01, 0x43,
- 0x09, 0x9b, 0xfe, 0x40, 0x13, 0x01, 0x0c, 0x06, 0x28, 0xf9, 0x1f, 0x7f,
- 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42, 0x8f,
- 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x32, 0x15, 0xfe, 0xe6, 0x00, 0x0f, 0xfe,
- 0x1c, 0x90, 0x04, 0xfe, 0x9c, 0x93, 0x3a, 0x0b, 0x0e, 0x8b, 0x02, 0x1f,
- 0x7f, 0x01, 0x42, 0x05, 0x35, 0xfe, 0x42, 0x5b, 0x7d, 0x1d, 0xfe, 0x46,
- 0x59, 0xfe, 0xbf, 0x57, 0xfe, 0x77, 0x57, 0x0f, 0xfe, 0x87, 0x80, 0x04,
- 0xfe, 0x87, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xd0, 0x65, 0x01, 0x0c,
- 0x06, 0x0d, 0xfe, 0x98, 0x13, 0x0f, 0xfe, 0x20, 0x80, 0x04, 0xfe, 0xa0,
- 0x83, 0x33, 0x0b, 0x0e, 0x09, 0x1d, 0xfe, 0x84, 0x12, 0x01, 0x38, 0x06,
- 0x07, 0xfe, 0x70, 0x13, 0x03, 0xfe, 0xa2, 0x00, 0x1e, 0x1b, 0xfe, 0xda,
- 0x05, 0xd0, 0x54, 0x01, 0x38, 0x06, 0x0d, 0xfe, 0x58, 0x13, 0x03, 0xfe,
- 0xa0, 0x00, 0x1e, 0xfe, 0x50, 0x12, 0x5e, 0xff, 0x02, 0x00, 0x10, 0x2f,
- 0xfe, 0x90, 0x05, 0x2a, 0x3c, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe,
- 0x9e, 0x05, 0x17, 0xfe, 0xf4, 0x05, 0x15, 0xfe, 0xe3, 0x00, 0x26, 0x01,
- 0x38, 0xfe, 0x4a, 0xf0, 0xfe, 0xc0, 0x05, 0xfe, 0x49, 0xf0, 0xfe, 0xba,
- 0x05, 0x71, 0x2e, 0xfe, 0x21, 0x00, 0xf1, 0x2e, 0xfe, 0x22, 0x00, 0xa2,
- 0x2e, 0x4a, 0xfe, 0x09, 0x48, 0xff, 0x02, 0x00, 0x10, 0x2f, 0xfe, 0xd0,
- 0x05, 0x17, 0xfe, 0xf4, 0x05, 0xfe, 0xe2, 0x08, 0x01, 0x38, 0x06, 0xfe,
- 0x1c, 0x00, 0x4d, 0x01, 0xa7, 0x2e, 0x07, 0x20, 0xe4, 0x47, 0xfe, 0x27,
- 0x01, 0x01, 0x0c, 0x06, 0x28, 0xfe, 0x24, 0x12, 0x3e, 0x01, 0x84, 0x1f,
- 0x7f, 0x01, 0x0c, 0x06, 0x07, 0x4d, 0x1f, 0xfe, 0x0d, 0x00, 0x01, 0x42,
- 0x8f, 0xfe, 0xa4, 0x0e, 0x05, 0x29, 0x03, 0xe6, 0x1e, 0xfe, 0xca, 0x13,
- 0x03, 0xb6, 0x1e, 0xfe, 0x40, 0x12, 0x03, 0x66, 0x1e, 0xfe, 0x38, 0x13,
- 0x3e, 0x01, 0x84, 0x17, 0xfe, 0x72, 0x06, 0x0a, 0x07, 0x01, 0x38, 0x06,
- 0x24, 0xfe, 0x02, 0x12, 0x4f, 0x01, 0xfe, 0x56, 0x19, 0x16, 0xfe, 0x68,
- 0x06, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x03, 0x66, 0x8a, 0x10, 0x66,
- 0x03, 0x9a, 0x1e, 0xfe, 0x70, 0x12, 0x03, 0x55, 0x1e, 0xfe, 0x68, 0x13,
- 0x01, 0xc6, 0x09, 0x12, 0x48, 0xfe, 0x92, 0x06, 0x2e, 0x12, 0x01, 0xfe,
- 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0x13, 0x58, 0xff, 0x02, 0x00,
- 0x57, 0x52, 0xad, 0x23, 0x3f, 0x4e, 0x62, 0x49, 0x3e, 0x01, 0x84, 0x17,
- 0xfe, 0xea, 0x06, 0x01, 0x38, 0x06, 0x12, 0xf7, 0x45, 0x0a, 0x95, 0x01,
- 0xfe, 0x84, 0x19, 0x16, 0xfe, 0xe0, 0x06, 0x15, 0x82, 0x01, 0x41, 0x15,
- 0xe2, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x1c, 0x07, 0x01, 0x84, 0xfe, 0xae,
- 0x10, 0x03, 0x6f, 0x1e, 0xfe, 0x9e, 0x13, 0x3e, 0x01, 0x84, 0x03, 0x9a,
- 0x1e, 0xfe, 0x1a, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfc, 0x01, 0xc6, 0x01,
- 0xfe, 0xac, 0x1d, 0xfe, 0x43, 0x48, 0x62, 0x80, 0xf0, 0x45, 0x0a, 0x95,
- 0x03, 0xb6, 0x1e, 0xf8, 0x01, 0x38, 0x06, 0x24, 0x36, 0xfe, 0x02, 0xf6,
- 0x07, 0x71, 0x78, 0x8c, 0x00, 0x4d, 0x62, 0x49, 0x3e, 0x2d, 0x93, 0x4e,
- 0xd0, 0x0d, 0x17, 0xfe, 0x9a, 0x07, 0x01, 0xfe, 0xc0, 0x19, 0x16, 0xfe,
- 0x90, 0x07, 0x26, 0x20, 0x9e, 0x15, 0x82, 0x01, 0x41, 0x15, 0xe2, 0x21,
- 0x9e, 0x09, 0x07, 0xfb, 0x03, 0xe6, 0xfe, 0x58, 0x57, 0x10, 0xe6, 0x05,
- 0xfe, 0x2a, 0x06, 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x1c, 0x07, 0x01, 0x84,
- 0xfe, 0x9c, 0x32, 0x5f, 0x75, 0x01, 0xa6, 0x86, 0x15, 0xfe, 0xe2, 0x00,
- 0x2f, 0xed, 0x2a, 0x3c, 0xfe, 0x0a, 0xf0, 0xfe, 0xce, 0x07, 0xae, 0xfe,
- 0x96, 0x08, 0xfe, 0x06, 0xf0, 0xfe, 0x9e, 0x08, 0xaf, 0xa0, 0x05, 0x29,
- 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x2e, 0x12, 0x14, 0x1d, 0x01, 0x08, 0x14,
- 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0xfe,
- 0x99, 0xa4, 0x01, 0x08, 0x14, 0x00, 0x05, 0xfe, 0xc6, 0x09, 0x01, 0x76,
- 0x06, 0x12, 0xfe, 0x3a, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x30, 0x13,
- 0x14, 0xfe, 0x1b, 0x00, 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x00,
- 0x01, 0x08, 0x14, 0x00, 0x01, 0x08, 0x14, 0x07, 0x01, 0x08, 0x14, 0x00,
- 0x05, 0xef, 0x7c, 0x4a, 0x78, 0x4f, 0x0f, 0xfe, 0x9a, 0x81, 0x04, 0xfe,
- 0x9a, 0x83, 0xfe, 0xcb, 0x47, 0x0b, 0x0e, 0x2d, 0x28, 0x48, 0xfe, 0x6c,
- 0x08, 0x0a, 0x28, 0xfe, 0x09, 0x6f, 0xca, 0xfe, 0xca, 0x45, 0xfe, 0x32,
- 0x12, 0x53, 0x63, 0x4e, 0x7c, 0x97, 0x2f, 0xfe, 0x7e, 0x08, 0x2a, 0x3c,
- 0xfe, 0x0a, 0xf0, 0xfe, 0x6c, 0x08, 0xaf, 0xa0, 0xae, 0xfe, 0x96, 0x08,
- 0x05, 0x29, 0x01, 0x41, 0x05, 0xed, 0x14, 0x24, 0x05, 0xed, 0xfe, 0x9c,
- 0xf7, 0x9f, 0x01, 0xfe, 0xae, 0x1e, 0xfe, 0x18, 0x58, 0x01, 0xfe, 0xbe,
- 0x1e, 0xfe, 0x99, 0x58, 0xfe, 0x78, 0x18, 0xfe, 0xf9, 0x18, 0x8e, 0xfe,
- 0x16, 0x09, 0x10, 0x6a, 0x22, 0x6b, 0x01, 0x0c, 0x61, 0x54, 0x44, 0x21,
- 0x2c, 0x09, 0x1a, 0xf8, 0x77, 0x01, 0xfe, 0x7e, 0x1e, 0x47, 0x2c, 0x7a,
- 0x30, 0xf0, 0xfe, 0x83, 0xe7, 0xfe, 0x3f, 0x00, 0x71, 0xfe, 0x03, 0x40,
- 0x01, 0x0c, 0x61, 0x65, 0x44, 0x01, 0xc2, 0xc8, 0xfe, 0x1f, 0x40, 0x20,
- 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0xfe,
- 0x44, 0x51, 0xfe, 0xc6, 0x51, 0xfe, 0x10, 0x10, 0x01, 0xfe, 0xce, 0x1e,
- 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x01, 0xfe, 0xee, 0x1e,
- 0x01, 0xfe, 0xfe, 0x1e, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x10, 0x4b,
- 0x22, 0x4c, 0xfe, 0x8a, 0x10, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x50, 0x12,
- 0x01, 0xfe, 0xae, 0x1e, 0x01, 0xfe, 0xbe, 0x1e, 0x10, 0x6a, 0x22, 0x6b,
- 0x01, 0x0c, 0x06, 0x65, 0x4e, 0x01, 0xc2, 0x0f, 0xfe, 0x1f, 0x80, 0x04,
- 0xfe, 0x9f, 0x83, 0x33, 0x0b, 0x0e, 0x20, 0x6e, 0x0f, 0xfe, 0x44, 0x90,
- 0x04, 0xfe, 0xc4, 0x93, 0x3a, 0x0b, 0xfe, 0xc6, 0x90, 0x04, 0xfe, 0xc6,
- 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x6c, 0x22, 0x6d, 0x01, 0xfe, 0xce, 0x1e,
- 0x01, 0xfe, 0xde, 0x1e, 0x10, 0x68, 0x22, 0x69, 0x0f, 0xfe, 0x40, 0x90,
- 0x04, 0xfe, 0xc0, 0x93, 0x3a, 0x0b, 0xfe, 0xc2, 0x90, 0x04, 0xfe, 0xc2,
- 0x93, 0x79, 0x0b, 0x0e, 0x10, 0x4b, 0x22, 0x4c, 0x10, 0x64, 0x22, 0x34,
- 0x01, 0x0c, 0x61, 0x24, 0x44, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe,
- 0xde, 0x09, 0xfe, 0x9e, 0xf0, 0xfe, 0xf2, 0x09, 0xfe, 0x01, 0x48, 0x1b,
- 0x3c, 0x37, 0x88, 0xf5, 0xd4, 0xfe, 0x1e, 0x0a, 0xd5, 0xfe, 0x42, 0x0a,
- 0xd2, 0xfe, 0x1e, 0x0a, 0xd3, 0xfe, 0x42, 0x0a, 0xae, 0xfe, 0x12, 0x0a,
- 0xfe, 0x06, 0xf0, 0xfe, 0x18, 0x0a, 0xaf, 0xa0, 0x05, 0x29, 0x01, 0x41,
- 0xfe, 0xc1, 0x10, 0x14, 0x24, 0xfe, 0xc1, 0x10, 0x01, 0x76, 0x06, 0x07,
- 0xfe, 0x14, 0x12, 0x01, 0x76, 0x06, 0x0d, 0x5d, 0x01, 0x0c, 0x06, 0x0d,
- 0xfe, 0x74, 0x12, 0xfe, 0x2e, 0x1c, 0x05, 0xfe, 0x1a, 0x0c, 0x01, 0x76,
- 0x06, 0x07, 0x5d, 0x01, 0x76, 0x06, 0x0d, 0x41, 0xfe, 0x2c, 0x1c, 0xfe,
- 0xaa, 0xf0, 0xfe, 0xce, 0x0a, 0xfe, 0xac, 0xf0, 0xfe, 0x66, 0x0a, 0xfe,
- 0x92, 0x10, 0xc4, 0xf6, 0xfe, 0xad, 0xf0, 0xfe, 0x72, 0x0a, 0x05, 0xfe,
- 0x1a, 0x0c, 0xc5, 0xfe, 0xe7, 0x10, 0xfe, 0x2b, 0xf0, 0xbf, 0xfe, 0x6b,
- 0x18, 0x23, 0xfe, 0x00, 0xfe, 0xfe, 0x1c, 0x12, 0xac, 0xfe, 0xd2, 0xf0,
- 0xbf, 0xfe, 0x76, 0x18, 0x23, 0x1d, 0x1b, 0xbf, 0x03, 0xe3, 0x23, 0x07,
- 0x1b, 0xbf, 0xd4, 0x5b, 0xd5, 0x5b, 0xd2, 0x5b, 0xd3, 0x5b, 0xc4, 0xc5,
- 0xfe, 0xa9, 0x10, 0x75, 0x5e, 0x32, 0x1f, 0x7f, 0x01, 0x42, 0x19, 0xfe,
- 0x35, 0x00, 0xfe, 0x01, 0xf0, 0x70, 0x19, 0x98, 0x05, 0x70, 0xfe, 0x74,
- 0x18, 0x23, 0xfe, 0x00, 0xf8, 0x1b, 0x5b, 0x7d, 0x12, 0x01, 0xfe, 0x78,
- 0x0f, 0x4d, 0x01, 0xfe, 0x96, 0x1a, 0x21, 0x30, 0x77, 0x7d, 0x1d, 0x05,
- 0x5b, 0x01, 0x0c, 0x06, 0x0d, 0x2b, 0xfe, 0xe2, 0x0b, 0x01, 0x0c, 0x06,
- 0x54, 0xfe, 0xa6, 0x12, 0x01, 0x0c, 0x06, 0x24, 0xfe, 0x88, 0x13, 0x21,
- 0x6e, 0xc7, 0x01, 0xfe, 0x1e, 0x1f, 0x0f, 0xfe, 0x83, 0x80, 0x04, 0xfe,
- 0x83, 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0xfe, 0xc8, 0x44, 0xfe, 0x42,
- 0x13, 0x0f, 0xfe, 0x04, 0x91, 0x04, 0xfe, 0x84, 0x93, 0xfe, 0xca, 0x57,
- 0x0b, 0xfe, 0x86, 0x91, 0x04, 0xfe, 0x86, 0x93, 0xfe, 0xcb, 0x57, 0x0b,
- 0x0e, 0x7a, 0x30, 0xfe, 0x40, 0x59, 0xfe, 0xc1, 0x59, 0x8e, 0x40, 0x03,
- 0x6a, 0x3b, 0x6b, 0x10, 0x97, 0x22, 0x98, 0xd9, 0x6a, 0xda, 0x6b, 0x01,
- 0xc2, 0xc8, 0x7a, 0x30, 0x20, 0x6e, 0xdb, 0x64, 0xdc, 0x34, 0x91, 0x6c,
- 0x7e, 0x6d, 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xfe, 0x04, 0xfa, 0x64,
- 0xfe, 0x05, 0xfa, 0x34, 0x01, 0xfe, 0x6a, 0x16, 0xa3, 0x26, 0x10, 0x97,
- 0x10, 0x98, 0x91, 0x6c, 0x7e, 0x6d, 0xfe, 0x14, 0x10, 0x01, 0x0c, 0x06,
- 0x24, 0x1b, 0x40, 0x91, 0x4b, 0x7e, 0x4c, 0x01, 0x0c, 0x06, 0xfe, 0xf7,
- 0x00, 0x44, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x10, 0x58, 0xfe, 0x91, 0x58,
- 0xfe, 0x14, 0x59, 0xfe, 0x95, 0x59, 0x05, 0x5b, 0x01, 0x0c, 0x06, 0x24,
- 0x1b, 0x40, 0x01, 0x0c, 0x06, 0xfe, 0xf7, 0x00, 0x44, 0x78, 0x01, 0xfe,
- 0x8e, 0x1e, 0x4f, 0x0f, 0xfe, 0x10, 0x90, 0x04, 0xfe, 0x90, 0x93, 0x3a,
- 0x0b, 0xfe, 0x92, 0x90, 0x04, 0xfe, 0x92, 0x93, 0x79, 0x0b, 0x0e, 0xfe,
- 0xbd, 0x10, 0x01, 0x43, 0x09, 0xbb, 0x1b, 0xfe, 0x6e, 0x0a, 0x15, 0xbb,
- 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x14, 0x13, 0x03, 0x4b, 0x3b, 0x4c, 0x8e,
- 0xfe, 0x6e, 0x0a, 0xfe, 0x0c, 0x58, 0xfe, 0x8d, 0x58, 0x05, 0x5b, 0x26,
- 0x3e, 0x0f, 0xfe, 0x19, 0x80, 0x04, 0xfe, 0x99, 0x83, 0x33, 0x0b, 0x0e,
- 0xfe, 0xe5, 0x10, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1a, 0x12, 0xfe, 0x6c,
- 0x19, 0xfe, 0x19, 0x41, 0xfe, 0x6b, 0x18, 0xac, 0xfe, 0xd1, 0xf0, 0xef,
- 0x1f, 0x92, 0x01, 0x42, 0x19, 0xfe, 0x44, 0x00, 0xfe, 0x90, 0x10, 0xfe,
- 0x6c, 0x19, 0xd9, 0x4b, 0xfe, 0xed, 0x19, 0xda, 0x4c, 0xfe, 0x0c, 0x51,
- 0xfe, 0x8e, 0x51, 0xfe, 0x6b, 0x18, 0x23, 0xfe, 0x00, 0xff, 0x31, 0xfe,
- 0x76, 0x10, 0xac, 0xfe, 0xd2, 0xf0, 0xfe, 0xba, 0x0c, 0xfe, 0x76, 0x18,
- 0x23, 0x1d, 0x5d, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0x08, 0x13, 0x19, 0xfe,
- 0x16, 0x00, 0x05, 0x70, 0xfe, 0xd1, 0xf0, 0xfe, 0xcc, 0x0c, 0x1f, 0x92,
- 0x01, 0x42, 0x19, 0xfe, 0x17, 0x00, 0x5c, 0xfe, 0xce, 0xf0, 0xfe, 0xd2,
- 0x0c, 0xfe, 0x3e, 0x10, 0xfe, 0xcd, 0xf0, 0xfe, 0xde, 0x0c, 0x19, 0xfe,
- 0x22, 0x00, 0x05, 0x70, 0xfe, 0xcb, 0xf0, 0xfe, 0xea, 0x0c, 0x19, 0xfe,
- 0x24, 0x00, 0x05, 0x70, 0xfe, 0xd0, 0xf0, 0xfe, 0xf4, 0x0c, 0x19, 0x94,
- 0xfe, 0x1c, 0x10, 0xfe, 0xcf, 0xf0, 0xfe, 0xfe, 0x0c, 0x19, 0x4a, 0xf3,
- 0xfe, 0xcc, 0xf0, 0xef, 0x01, 0x76, 0x06, 0x24, 0x4d, 0x19, 0xfe, 0x12,
- 0x00, 0x37, 0x13, 0xfe, 0x4e, 0x11, 0x2f, 0xfe, 0x16, 0x0d, 0xfe, 0x9e,
- 0xf0, 0xfe, 0x2a, 0x0d, 0xfe, 0x01, 0x48, 0x1b, 0x3c, 0x37, 0x88, 0xf5,
- 0xd4, 0x29, 0xd5, 0x29, 0xd2, 0x29, 0xd3, 0x29, 0x37, 0xfe, 0x9c, 0x32,
- 0x2f, 0xfe, 0x3e, 0x0d, 0x2a, 0x3c, 0xae, 0xfe, 0x62, 0x0d, 0xaf, 0xa0,
- 0xd4, 0x9f, 0xd5, 0x9f, 0xd2, 0x9f, 0xd3, 0x9f, 0x05, 0x29, 0x01, 0x41,
- 0xfe, 0xd3, 0x10, 0x15, 0xfe, 0xe8, 0x00, 0xc4, 0xc5, 0x75, 0xd7, 0x99,
- 0xd8, 0x9c, 0xfe, 0x89, 0xf0, 0x29, 0x27, 0x25, 0xbe, 0xd7, 0x99, 0xd8,
- 0x9c, 0x2f, 0xfe, 0x8c, 0x0d, 0x16, 0x29, 0x27, 0x25, 0xbd, 0xfe, 0x01,
- 0x48, 0xa4, 0x19, 0xfe, 0x42, 0x00, 0x05, 0x70, 0x90, 0x07, 0xfe, 0x81,
- 0x49, 0x1b, 0xfe, 0x64, 0x0e, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x44, 0x13,
- 0x19, 0x00, 0x2d, 0x0d, 0xfe, 0x54, 0x12, 0x2d, 0xfe, 0x28, 0x00, 0x2b,
- 0xfe, 0xda, 0x0e, 0x0a, 0x57, 0x01, 0x18, 0x09, 0x00, 0x36, 0x46, 0xfe,
- 0x28, 0x00, 0xfe, 0xfa, 0x10, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00,
- 0x1d, 0x0a, 0xba, 0x01, 0xfe, 0x58, 0x10, 0x40, 0x15, 0x56, 0x01, 0x85,
- 0x05, 0x35, 0x19, 0xfe, 0x44, 0x00, 0x2d, 0x0d, 0xf7, 0x46, 0x0d, 0xfe,
- 0xcc, 0x10, 0x01, 0xa7, 0x46, 0x0d, 0xfe, 0xc2, 0x10, 0x01, 0xa7, 0x0f,
- 0xfe, 0x19, 0x82, 0x04, 0xfe, 0x99, 0x83, 0xfe, 0xcc, 0x47, 0x0b, 0x0e,
- 0xfe, 0x34, 0x46, 0xa5, 0x46, 0x0d, 0x19, 0xfe, 0x43, 0x00, 0xfe, 0xa2,
- 0x10, 0x01, 0x0c, 0x61, 0x0d, 0x44, 0x01, 0xfe, 0xf4, 0x1c, 0x01, 0xfe,
- 0x00, 0x1d, 0x40, 0x15, 0x56, 0x01, 0x85, 0x7d, 0x0d, 0x40, 0x51, 0x01,
- 0xfe, 0x9e, 0x1e, 0x05, 0xfe, 0x3a, 0x03, 0x01, 0x0c, 0x06, 0x0d, 0x5d,
- 0x46, 0x0d, 0x19, 0x00, 0xfe, 0x62, 0x10, 0x01, 0x76, 0x06, 0x12, 0xfe,
- 0x5c, 0x12, 0x01, 0x0c, 0x06, 0x12, 0xfe, 0x52, 0x13, 0xfe, 0x1c, 0x1c,
- 0xfe, 0x9d, 0xf0, 0xfe, 0x8e, 0x0e, 0xfe, 0x1c, 0x1c, 0xfe, 0x9d, 0xf0,
- 0xfe, 0x94, 0x0e, 0x01, 0x0c, 0x61, 0x12, 0x44, 0xfe, 0x9f, 0x10, 0x19,
- 0xfe, 0x15, 0x00, 0xfe, 0x04, 0xe6, 0x0d, 0x4f, 0xfe, 0x2e, 0x10, 0x19,
- 0xfe, 0x13, 0x00, 0xfe, 0x10, 0x10, 0x19, 0xfe, 0x47, 0x00, 0xf1, 0x19,
- 0xfe, 0x41, 0x00, 0xa2, 0x19, 0xfe, 0x24, 0x00, 0x86, 0xc4, 0xc5, 0x75,
- 0x03, 0x81, 0x1e, 0x2b, 0xea, 0x4f, 0xfe, 0x04, 0xe6, 0x12, 0xfe, 0x9d,
- 0x41, 0xfe, 0x1c, 0x42, 0x40, 0x01, 0xf4, 0x05, 0x35, 0xfe, 0x12, 0x1c,
- 0x1f, 0x0d, 0x47, 0xb5, 0xc3, 0x1f, 0xfe, 0x31, 0x00, 0x47, 0xb8, 0x01,
- 0xfe, 0xd4, 0x11, 0x05, 0xe9, 0x51, 0xfe, 0x06, 0xec, 0xe0, 0xfe, 0x0e,
- 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0x06, 0xea, 0xe0,
- 0xfe, 0x47, 0x4b, 0x45, 0xfe, 0x75, 0x57, 0x03, 0x67, 0xfe, 0x98, 0x56,
- 0xfe, 0x38, 0x12, 0x0a, 0x5a, 0x01, 0x18, 0xfe, 0x44, 0x48, 0x60, 0x01,
- 0x0c, 0x06, 0x28, 0xfe, 0x18, 0x13, 0x0a, 0x57, 0x01, 0x18, 0x3e, 0xfe,
- 0x41, 0x58, 0x0a, 0xba, 0xfe, 0xfa, 0x14, 0xfe, 0x49, 0x54, 0xb0, 0xfe,
- 0x5e, 0x0f, 0x05, 0xfe, 0x3a, 0x03, 0x0a, 0x67, 0xfe, 0xe0, 0x14, 0xfe,
- 0x0e, 0x47, 0x46, 0x28, 0xfe, 0xce, 0x45, 0x31, 0x51, 0xfe, 0xce, 0x47,
- 0xfe, 0xad, 0x13, 0x05, 0x35, 0x21, 0x2c, 0x09, 0x1a, 0xfe, 0x98, 0x12,
- 0x26, 0x20, 0x96, 0x20, 0xe7, 0xfe, 0x08, 0x1c, 0xfe, 0x7c, 0x19, 0xfe,
- 0xfd, 0x19, 0xfe, 0x0a, 0x1c, 0x03, 0xe5, 0xfe, 0x48, 0x55, 0xa5, 0x3b,
- 0xfe, 0x62, 0x01, 0xfe, 0xc9, 0x55, 0x31, 0xfe, 0x74, 0x10, 0x01, 0xfe,
- 0xf0, 0x1a, 0x03, 0xfe, 0x38, 0x01, 0x3b, 0xfe, 0x3a, 0x01, 0x8e, 0xfe,
- 0x1e, 0x10, 0xfe, 0x02, 0xec, 0xe7, 0x53, 0x00, 0x36, 0xfe, 0x04, 0xec,
- 0x2c, 0x60, 0xfe, 0x05, 0xf6, 0xfe, 0x34, 0x01, 0x01, 0xfe, 0x62, 0x1b,
- 0x01, 0xfe, 0xce, 0x1e, 0xb2, 0x11, 0xfe, 0x18, 0x13, 0xca, 0xfe, 0x02,
- 0xea, 0xe7, 0x53, 0x92, 0xfe, 0xc3, 0x13, 0x1f, 0x12, 0x47, 0xb5, 0xc3,
- 0xfe, 0x2a, 0x10, 0x03, 0xfe, 0x38, 0x01, 0x23, 0xfe, 0xf0, 0xff, 0x10,
- 0xe5, 0x03, 0xfe, 0x3a, 0x01, 0x10, 0xfe, 0x62, 0x01, 0x01, 0xfe, 0x1e,
- 0x1e, 0x20, 0x2c, 0x15, 0x56, 0x01, 0xfe, 0x9e, 0x1e, 0x13, 0x07, 0x02,
- 0x26, 0x02, 0x21, 0x96, 0xc7, 0x20, 0x96, 0x09, 0x92, 0xfe, 0x79, 0x13,
- 0x1f, 0x1d, 0x47, 0xb5, 0xc3, 0xfe, 0xe1, 0x10, 0xcf, 0xfe, 0x03, 0xdc,
- 0xfe, 0x73, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xcf, 0xfe, 0x03, 0xdc, 0xfe,
- 0x5b, 0x57, 0xfe, 0x80, 0x5d, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x26, 0xfe,
- 0x00, 0xcc, 0x02, 0xfe, 0x03, 0x57, 0xcf, 0x89, 0x02, 0x01, 0x0c, 0x06,
- 0x4a, 0xfe, 0x4e, 0x13, 0x0f, 0xfe, 0x1c, 0x80, 0x04, 0xfe, 0x9c, 0x83,
- 0x33, 0x0b, 0x0e, 0x09, 0x07, 0xfe, 0x3a, 0x13, 0x0f, 0xfe, 0x1e, 0x80,
- 0x04, 0xfe, 0x9e, 0x83, 0x33, 0x0b, 0x0e, 0xfe, 0x2a, 0x13, 0x0f, 0xfe,
- 0x1d, 0x80, 0x04, 0xfe, 0x9d, 0x83, 0xfe, 0xf9, 0x13, 0x0e, 0xfe, 0x1c,
- 0x13, 0x01, 0xfe, 0xee, 0x1e, 0xac, 0xfe, 0x14, 0x13, 0x01, 0xfe, 0xfe,
- 0x1e, 0xfe, 0x81, 0x58, 0xfa, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4,
- 0x0d, 0xfe, 0x3c, 0x50, 0xa2, 0x01, 0xfe, 0x92, 0x1b, 0x01, 0x43, 0x09,
- 0x56, 0xfb, 0x01, 0xfe, 0xc8, 0x1a, 0x01, 0x0c, 0x06, 0x28, 0xa4, 0x01,
- 0xfe, 0xf4, 0x1c, 0x01, 0xfe, 0x00, 0x1d, 0x15, 0xfe, 0xe9, 0x00, 0x01,
- 0x0c, 0x06, 0x4a, 0xfe, 0x4e, 0x13, 0x01, 0xfe, 0x22, 0x1b, 0xfe, 0x1e,
- 0x1c, 0x0f, 0xfe, 0x14, 0x90, 0x04, 0xfe, 0x94, 0x93, 0x3a, 0x0b, 0xfe,
- 0x96, 0x90, 0x04, 0xfe, 0x96, 0x93, 0x79, 0x0b, 0x0e, 0x10, 0xfe, 0x64,
- 0x01, 0x22, 0xfe, 0x66, 0x01, 0x01, 0x0c, 0x06, 0x65, 0xf9, 0x0f, 0xfe,
- 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x0e, 0x77, 0xfe, 0x01,
- 0xec, 0x2c, 0xfe, 0x80, 0x40, 0x20, 0x2c, 0x7a, 0x30, 0x15, 0xdf, 0x40,
- 0x21, 0x2c, 0xfe, 0x00, 0x40, 0x8d, 0x2c, 0x02, 0xfe, 0x08, 0x1c, 0x03,
- 0xfe, 0xac, 0x00, 0xfe, 0x06, 0x58, 0x03, 0xfe, 0xae, 0x00, 0xfe, 0x07,
- 0x58, 0x03, 0xfe, 0xb0, 0x00, 0xfe, 0x08, 0x58, 0x03, 0xfe, 0xb2, 0x00,
- 0xfe, 0x09, 0x58, 0xfe, 0x0a, 0x1c, 0x2e, 0x49, 0x20, 0xe0, 0x26, 0x10,
- 0x66, 0x10, 0x55, 0x10, 0x6f, 0x13, 0x57, 0x52, 0x4f, 0x1c, 0x28, 0xfe,
- 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe, 0x88, 0x11, 0x46, 0x1a, 0x13,
- 0x5a, 0x52, 0x1c, 0x4a, 0xfe, 0x90, 0x4d, 0xfe, 0x91, 0x54, 0x2b, 0xfe,
- 0x9e, 0x11, 0x2e, 0x1a, 0x20, 0x2c, 0x90, 0x34, 0x60, 0x21, 0x2c, 0xfe,
- 0x00, 0x40, 0x8d, 0x2c, 0x15, 0xdf, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0,
- 0xfe, 0xb2, 0x11, 0xfe, 0x12, 0x1c, 0x75, 0xfe, 0x14, 0x1c, 0xfe, 0x10,
- 0x1c, 0xfe, 0x18, 0x1c, 0x02, 0x51, 0xfe, 0x0c, 0x14, 0xfe, 0x0e, 0x47,
- 0xfe, 0x07, 0xe6, 0x28, 0xfe, 0xce, 0x47, 0xfe, 0xf5, 0x13, 0x02, 0x01,
- 0xa7, 0x90, 0x34, 0x60, 0xfe, 0x06, 0x80, 0xfe, 0x48, 0x47, 0xfe, 0x42,
- 0x13, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x34, 0x13, 0x0a, 0x5a, 0x01,
- 0x18, 0xcb, 0xfe, 0x36, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48, 0x01,
- 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f, 0x89,
- 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x5c, 0x01, 0x85,
- 0xf2, 0x09, 0x9b, 0xa4, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0xec,
- 0x11, 0x02, 0xfe, 0x44, 0x58, 0x77, 0xfe, 0x01, 0xec, 0xb8, 0xfe, 0x9e,
- 0x40, 0xfe, 0x9d, 0xe7, 0x00, 0xfe, 0x9c, 0xe7, 0x12, 0x8d, 0x30, 0x01,
- 0xf4, 0xfe, 0xdd, 0x10, 0x37, 0xd7, 0x99, 0xd8, 0x9c, 0x27, 0x25, 0xee,
- 0x09, 0x12, 0xfe, 0x48, 0x12, 0x09, 0x0d, 0xfe, 0x56, 0x12, 0x09, 0x1d,
- 0xfe, 0x30, 0x12, 0x09, 0xdd, 0x1b, 0xfe, 0xc4, 0x13, 0x09, 0xfe, 0x23,
- 0x00, 0x1b, 0xfe, 0xd0, 0x13, 0x09, 0x07, 0x1b, 0xfe, 0x34, 0x14, 0x09,
- 0x24, 0xfe, 0x12, 0x12, 0x09, 0x00, 0x1b, 0x29, 0x1f, 0xdd, 0x01, 0x42,
- 0xa1, 0x32, 0x01, 0x08, 0xae, 0x41, 0x02, 0x32, 0xfe, 0x62, 0x08, 0x0a,
- 0xe1, 0x01, 0xfe, 0x58, 0x10, 0x15, 0x9b, 0x05, 0x35, 0x32, 0x01, 0x43,
- 0x09, 0xbb, 0xfe, 0xd7, 0x13, 0x91, 0x4b, 0x7e, 0x4c, 0x8e, 0xfe, 0x80,
- 0x13, 0x01, 0x0c, 0x06, 0x54, 0xfe, 0x72, 0x12, 0xdb, 0x64, 0xdc, 0x34,
- 0xfe, 0x44, 0x55, 0xfe, 0xe5, 0x55, 0xb0, 0xfe, 0x4a, 0x13, 0x21, 0x6e,
- 0xfe, 0x26, 0x13, 0x03, 0x97, 0x3b, 0x98, 0x8e, 0xfe, 0xb6, 0x0e, 0x10,
- 0x6a, 0x22, 0x6b, 0x26, 0x10, 0x97, 0x10, 0x98, 0x01, 0xc2, 0x2e, 0x49,
- 0x88, 0x20, 0x6e, 0x01, 0xfe, 0x6a, 0x16, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
- 0x04, 0x55, 0xfe, 0xa5, 0x55, 0xfe, 0x04, 0xfa, 0x64, 0xfe, 0x05, 0xfa,
- 0x34, 0xfe, 0x8f, 0x10, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x40, 0x56, 0xfe,
- 0xe1, 0x56, 0x10, 0x6c, 0x22, 0x6d, 0x71, 0xdb, 0x64, 0xdc, 0x34, 0xfe,
- 0x44, 0x55, 0xfe, 0xe5, 0x55, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x00, 0x56,
- 0xfe, 0xa1, 0x56, 0x10, 0x68, 0x22, 0x69, 0x01, 0x0c, 0x06, 0x54, 0xf9,
- 0x21, 0x6e, 0xfe, 0x1f, 0x40, 0x03, 0x6a, 0x3b, 0x6b, 0xfe, 0x2c, 0x50,
- 0xfe, 0xae, 0x50, 0x03, 0x6c, 0x3b, 0x6d, 0xfe, 0x44, 0x50, 0xfe, 0xc6,
- 0x50, 0x03, 0x68, 0x3b, 0x69, 0xfe, 0x08, 0x50, 0xfe, 0x8a, 0x50, 0x03,
- 0x4b, 0x3b, 0x4c, 0xfe, 0x40, 0x50, 0xfe, 0xc2, 0x50, 0x05, 0x73, 0x2e,
- 0x07, 0x20, 0x9e, 0x05, 0x72, 0x32, 0x01, 0x08, 0x16, 0x3d, 0x27, 0x25,
- 0xee, 0x09, 0x07, 0x2b, 0x3d, 0x01, 0x43, 0x09, 0xbb, 0x2b, 0x72, 0x01,
- 0xa6, 0x23, 0x3f, 0x1b, 0x3d, 0x01, 0x0c, 0x06, 0x0d, 0xfe, 0x1e, 0x13,
- 0x91, 0x4b, 0x7e, 0x4c, 0xfe, 0x0a, 0x55, 0x31, 0xfe, 0x8b, 0x55, 0xd9,
- 0x4b, 0xda, 0x4c, 0xfe, 0x0c, 0x51, 0xfe, 0x8e, 0x51, 0x05, 0x72, 0x01,
- 0xfe, 0x8e, 0x1e, 0xca, 0xfe, 0x19, 0x41, 0x05, 0x72, 0x32, 0x01, 0x08,
- 0x2a, 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbe, 0x2d, 0x1d, 0xc0, 0x2d, 0x0d,
- 0x83, 0x2d, 0x7f, 0x1b, 0xfe, 0x66, 0x15, 0x05, 0x3d, 0x01, 0x08, 0x2a,
- 0x3c, 0x16, 0xc0, 0x27, 0x25, 0xbd, 0x09, 0x1d, 0x2b, 0x3d, 0x01, 0x08,
- 0x16, 0xc0, 0x27, 0x25, 0xfe, 0xe8, 0x09, 0xfe, 0xc2, 0x49, 0x50, 0x03,
- 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa1, 0xfe, 0xbb, 0x45,
- 0x2d, 0x00, 0xa4, 0x46, 0x07, 0x90, 0x3f, 0x01, 0xfe, 0xf8, 0x15, 0x01,
- 0xa6, 0x86, 0xfe, 0x4b, 0x45, 0xfe, 0x20, 0x13, 0x01, 0x43, 0x09, 0x82,
- 0xfe, 0x16, 0x13, 0x03, 0x9a, 0x1e, 0x5d, 0x03, 0x55, 0x1e, 0x31, 0x5e,
- 0x05, 0x72, 0xfe, 0xc0, 0x5d, 0x01, 0xa7, 0xfe, 0x03, 0x17, 0x03, 0x66,
- 0x8a, 0x10, 0x66, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01, 0xfe, 0x56,
- 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d, 0x27, 0x25, 0xbd,
- 0x09, 0x07, 0x2b, 0x3d, 0x01, 0xfe, 0xbe, 0x16, 0xfe, 0x42, 0x58, 0xfe,
- 0xe8, 0x14, 0x01, 0xa6, 0x86, 0xfe, 0x4a, 0xf4, 0x0d, 0x1b, 0x3d, 0xfe,
- 0x4a, 0xf4, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05,
- 0x72, 0x03, 0x55, 0x8a, 0x10, 0x55, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73,
- 0x01, 0xfe, 0x84, 0x19, 0x05, 0x73, 0x01, 0x08, 0x2a, 0x3c, 0x16, 0x3d,
- 0x27, 0x25, 0xbd, 0x09, 0x12, 0x2b, 0x3d, 0x01, 0xfe, 0xe8, 0x17, 0x8b,
- 0xfe, 0xaa, 0x14, 0xfe, 0xb6, 0x14, 0x86, 0xa8, 0xb2, 0x0d, 0x1b, 0x3d,
- 0xb2, 0x07, 0xfe, 0x0e, 0x12, 0x01, 0x43, 0x09, 0x82, 0x4e, 0x05, 0x72,
- 0x03, 0x6f, 0x8a, 0x10, 0x6f, 0x5e, 0x32, 0x01, 0x08, 0x17, 0x73, 0x01,
- 0xfe, 0xc0, 0x19, 0x05, 0x73, 0x13, 0x07, 0x2f, 0xfe, 0xcc, 0x15, 0x17,
- 0xfe, 0xe2, 0x15, 0x5f, 0xcc, 0x01, 0x08, 0x26, 0x5f, 0x02, 0x8f, 0xfe,
- 0xde, 0x15, 0x2a, 0xfe, 0xde, 0x15, 0x16, 0xfe, 0xcc, 0x15, 0x5e, 0x32,
- 0x01, 0x08, 0xfe, 0xd5, 0x10, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
- 0xad, 0x23, 0xfe, 0xff, 0x7f, 0xfe, 0x30, 0x56, 0xfe, 0x00, 0x5c, 0x02,
- 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0x23, 0x3f, 0xfe, 0x30,
- 0x56, 0xfe, 0x00, 0x5c, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52,
- 0xad, 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xfe, 0x00, 0x5e,
- 0x02, 0x13, 0x58, 0xff, 0x02, 0x00, 0x57, 0x52, 0xad, 0xfe, 0x0b, 0x58,
- 0x02, 0x0a, 0x66, 0x01, 0x5c, 0x0a, 0x55, 0x01, 0x5c, 0x0a, 0x6f, 0x01,
- 0x5c, 0x02, 0x01, 0xfe, 0x1e, 0x1f, 0x23, 0x1a, 0xff, 0x03, 0x00, 0x54,
- 0xfe, 0x00, 0xf4, 0x24, 0x52, 0x0f, 0xfe, 0x00, 0x7c, 0x04, 0xfe, 0x07,
- 0x7c, 0x3a, 0x0b, 0x0e, 0xfe, 0x00, 0x71, 0xfe, 0xf9, 0x18, 0xfe, 0x7a,
- 0x19, 0xfe, 0xfb, 0x19, 0xfe, 0x1a, 0xf7, 0x00, 0xfe, 0x1b, 0xf7, 0x00,
- 0x7a, 0x30, 0x10, 0x68, 0x22, 0x69, 0xd9, 0x6c, 0xda, 0x6d, 0x02, 0xfe,
- 0x62, 0x08, 0xfe, 0x82, 0x4a, 0xfe, 0xe1, 0x1a, 0xfe, 0x83, 0x5a, 0x77,
- 0x02, 0x01, 0xc6, 0xfe, 0x42, 0x48, 0x4f, 0x50, 0x45, 0x01, 0x08, 0x16,
- 0xfe, 0xe0, 0x17, 0x27, 0x25, 0xbe, 0x01, 0x08, 0x16, 0xfe, 0xe0, 0x17,
- 0x27, 0x25, 0xfe, 0xe8, 0x0a, 0xfe, 0xc1, 0x59, 0x03, 0x9a, 0x1e, 0xfe,
- 0xda, 0x12, 0x01, 0x38, 0x06, 0x12, 0xfe, 0xd0, 0x13, 0x26, 0x53, 0x12,
- 0x48, 0xfe, 0x08, 0x17, 0xd1, 0x12, 0x53, 0x12, 0xfe, 0x1e, 0x13, 0x2d,
- 0xb4, 0x7b, 0xfe, 0x26, 0x17, 0x4d, 0x13, 0x07, 0x1c, 0xb4, 0x90, 0x04,
- 0xfe, 0x78, 0x10, 0xff, 0x02, 0x83, 0x55, 0xf1, 0xff, 0x02, 0x83, 0x55,
- 0x53, 0x1d, 0xfe, 0x12, 0x13, 0xd6, 0xfe, 0x30, 0x00, 0xb0, 0xfe, 0x80,
- 0x17, 0x1c, 0x63, 0x13, 0x07, 0xfe, 0x56, 0x10, 0x53, 0x0d, 0xfe, 0x16,
- 0x13, 0xd6, 0xfe, 0x64, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0x64,
- 0x00, 0x1c, 0x94, 0x13, 0x07, 0xfe, 0x28, 0x10, 0x53, 0x07, 0xfe, 0x60,
- 0x13, 0xd6, 0xfe, 0xc8, 0x00, 0xb0, 0xfe, 0x80, 0x17, 0x0a, 0xfe, 0xc8,
- 0x00, 0x1c, 0x95, 0x13, 0x07, 0x71, 0xd6, 0xfe, 0x90, 0x01, 0x48, 0xfe,
- 0x8c, 0x17, 0x45, 0xf3, 0xfe, 0x43, 0xf4, 0x96, 0xfe, 0x56, 0xf0, 0xfe,
- 0x9e, 0x17, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x43, 0xf4, 0x94, 0xf6, 0x8b,
- 0x01, 0xfe, 0x24, 0x16, 0x23, 0x3f, 0xfc, 0xa8, 0x8c, 0x49, 0x48, 0xfe,
- 0xda, 0x17, 0x62, 0x49, 0xfe, 0x1c, 0x10, 0xa8, 0x8c, 0x80, 0x48, 0xfe,
- 0xda, 0x17, 0x62, 0x80, 0x71, 0x50, 0x26, 0xfe, 0x4d, 0xf4, 0x00, 0xf7,
- 0x45, 0x13, 0x07, 0xfe, 0xb4, 0x56, 0xfe, 0xc3, 0x58, 0x02, 0x50, 0x13,
- 0x0d, 0x02, 0x50, 0x3e, 0x78, 0x4f, 0x45, 0x01, 0x08, 0x16, 0xa9, 0x27,
- 0x25, 0xbe, 0xfe, 0x03, 0xea, 0xfe, 0x7e, 0x01, 0x01, 0x08, 0x16, 0xa9,
- 0x27, 0x25, 0xfe, 0xe9, 0x0a, 0x01, 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe,
- 0xe9, 0x0a, 0xfe, 0x05, 0xea, 0xfe, 0x7f, 0x01, 0x01, 0x08, 0x16, 0xa9,
- 0x27, 0x25, 0xfe, 0x69, 0x09, 0xfe, 0x02, 0xea, 0xfe, 0x80, 0x01, 0x01,
- 0x08, 0x16, 0xa9, 0x27, 0x25, 0xfe, 0xe8, 0x08, 0x47, 0xfe, 0x81, 0x01,
- 0x03, 0xb6, 0x1e, 0x83, 0x01, 0x38, 0x06, 0x24, 0x31, 0xa2, 0x78, 0xf2,
- 0x53, 0x07, 0x36, 0xfe, 0x34, 0xf4, 0x3f, 0xa1, 0x78, 0x03, 0x9a, 0x1e,
- 0x83, 0x01, 0x38, 0x06, 0x12, 0x31, 0xf0, 0x4f, 0x45, 0xfe, 0x90, 0x10,
- 0xfe, 0x40, 0x5a, 0x23, 0x3f, 0xfb, 0x8c, 0x49, 0x48, 0xfe, 0xaa, 0x18,
- 0x62, 0x49, 0x71, 0x8c, 0x80, 0x48, 0xfe, 0xaa, 0x18, 0x62, 0x80, 0xfe,
- 0xb4, 0x56, 0xfe, 0x40, 0x5d, 0x01, 0xc6, 0x01, 0xfe, 0xac, 0x1d, 0xfe,
- 0x02, 0x17, 0xfe, 0xc8, 0x45, 0xfe, 0x5a, 0xf0, 0xfe, 0xc0, 0x18, 0xfe,
- 0x43, 0x48, 0x2d, 0x93, 0x36, 0xfe, 0x34, 0xf4, 0xfe, 0x00, 0x11, 0xfe,
- 0x40, 0x10, 0x2d, 0xb4, 0x36, 0xfe, 0x34, 0xf4, 0x04, 0xfe, 0x34, 0x10,
- 0x2d, 0xfe, 0x0b, 0x00, 0x36, 0x46, 0x63, 0xfe, 0x28, 0x10, 0xfe, 0xc0,
- 0x49, 0xff, 0x02, 0x00, 0x54, 0xb2, 0xfe, 0x90, 0x01, 0x48, 0xfe, 0xfa,
- 0x18, 0x45, 0xfe, 0x1c, 0xf4, 0x3f, 0xf3, 0xfe, 0x40, 0xf4, 0x96, 0xfe,
- 0x56, 0xf0, 0xfe, 0x0c, 0x19, 0xfe, 0x04, 0xf4, 0x58, 0xfe, 0x40, 0xf4,
- 0x94, 0xf6, 0x3e, 0x2d, 0x93, 0x4e, 0xd0, 0x0d, 0x21, 0xfe, 0x7f, 0x01,
- 0xfe, 0xc8, 0x46, 0xfe, 0x24, 0x13, 0x8c, 0x00, 0x5d, 0x26, 0x21, 0xfe,
- 0x7e, 0x01, 0xfe, 0xc8, 0x45, 0xfe, 0x14, 0x13, 0x21, 0xfe, 0x80, 0x01,
- 0xfe, 0x48, 0x45, 0xfa, 0x21, 0xfe, 0x81, 0x01, 0xfe, 0xc8, 0x44, 0x4e,
- 0x26, 0x02, 0x13, 0x07, 0x02, 0x78, 0x45, 0x50, 0x13, 0x0d, 0x02, 0x14,
- 0x07, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x14, 0x0d, 0x01, 0x08, 0x17,
- 0xfe, 0x82, 0x19, 0x14, 0x1d, 0x01, 0x08, 0x17, 0xfe, 0x82, 0x19, 0x5f,
- 0xfe, 0x89, 0x49, 0x01, 0x08, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
- 0x14, 0x1d, 0x01, 0x08, 0x17, 0xc1, 0x14, 0x07, 0x01, 0x08, 0x17, 0xc1,
- 0xfe, 0x89, 0x49, 0x01, 0x08, 0x17, 0xc1, 0x5f, 0xfe, 0x89, 0x4a, 0x01,
- 0x08, 0x02, 0x50, 0x02, 0x14, 0x07, 0x01, 0x08, 0x17, 0x74, 0x14, 0x7f,
- 0x01, 0x08, 0x17, 0x74, 0x14, 0x12, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x89,
- 0x49, 0x01, 0x08, 0x17, 0x74, 0x14, 0x00, 0x01, 0x08, 0x17, 0x74, 0xfe,
- 0x89, 0x4a, 0x01, 0x08, 0x17, 0x74, 0xfe, 0x09, 0x49, 0x01, 0x08, 0x17,
- 0x74, 0x5f, 0xcc, 0x01, 0x08, 0x02, 0x21, 0xe4, 0x09, 0x07, 0xfe, 0x4c,
- 0x13, 0xc8, 0x20, 0xe4, 0xfe, 0x49, 0xf4, 0x00, 0x4d, 0x5f, 0xa1, 0x5e,
- 0xfe, 0x01, 0xec, 0xfe, 0x27, 0x01, 0xcc, 0xff, 0x02, 0x00, 0x10, 0x2f,
- 0xfe, 0x3e, 0x1a, 0x01, 0x43, 0x09, 0xfe, 0xe3, 0x00, 0xfe, 0x22, 0x13,
- 0x16, 0xfe, 0x64, 0x1a, 0x26, 0x20, 0x9e, 0x01, 0x41, 0x21, 0x9e, 0x09,
- 0x07, 0x5d, 0x01, 0x0c, 0x61, 0x07, 0x44, 0x02, 0x0a, 0x5a, 0x01, 0x18,
- 0xfe, 0x00, 0x40, 0xaa, 0x09, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01,
- 0x18, 0xaa, 0x0a, 0x67, 0x01, 0xa3, 0x02, 0x0a, 0x9d, 0x01, 0x18, 0xaa,
- 0xfe, 0x80, 0xe7, 0x1a, 0x09, 0x1a, 0x5d, 0xfe, 0x45, 0x58, 0x01, 0xfe,
- 0xb2, 0x16, 0xaa, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0xaa, 0x0a, 0x67, 0x01,
- 0xa3, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x01, 0xfe, 0x7e, 0x1e, 0xfe, 0x80,
- 0x4c, 0xfe, 0x49, 0xe4, 0x1a, 0xfe, 0x12, 0x13, 0x0a, 0x9d, 0x01, 0x18,
- 0xfe, 0x80, 0x4c, 0x0a, 0x67, 0x01, 0x5c, 0x02, 0x1c, 0x1a, 0x87, 0x7c,
- 0xe5, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x24, 0x1c, 0xfe, 0x1d,
- 0xf7, 0x28, 0xb1, 0xfe, 0x04, 0x1b, 0x01, 0xfe, 0x2a, 0x1c, 0xfa, 0xb3,
- 0x28, 0x7c, 0xfe, 0x2c, 0x01, 0xfe, 0x2f, 0x19, 0x02, 0xc9, 0x2b, 0xfe,
- 0xf4, 0x1a, 0xfe, 0xfa, 0x10, 0x1c, 0x1a, 0x87, 0x03, 0xfe, 0x64, 0x01,
- 0xfe, 0x00, 0xf4, 0x24, 0xfe, 0x18, 0x58, 0x03, 0xfe, 0x66, 0x01, 0xfe,
- 0x19, 0x58, 0xb3, 0x24, 0x01, 0xfe, 0x0e, 0x1f, 0xfe, 0x30, 0xf4, 0x07,
- 0xfe, 0x3c, 0x50, 0x7c, 0xfe, 0x38, 0x00, 0xfe, 0x0f, 0x79, 0xfe, 0x1c,
- 0xf7, 0x24, 0xb1, 0xfe, 0x50, 0x1b, 0xfe, 0xd4, 0x14, 0x31, 0x02, 0xc9,
- 0x2b, 0xfe, 0x26, 0x1b, 0xfe, 0xba, 0x10, 0x1c, 0x1a, 0x87, 0xfe, 0x83,
- 0x5a, 0xfe, 0x18, 0xdf, 0xfe, 0x19, 0xde, 0xfe, 0x1d, 0xf7, 0x54, 0xb1,
- 0xfe, 0x72, 0x1b, 0xfe, 0xb2, 0x14, 0xfc, 0xb3, 0x54, 0x7c, 0x12, 0xfe,
- 0xaf, 0x19, 0xfe, 0x98, 0xe7, 0x00, 0x02, 0xc9, 0x2b, 0xfe, 0x66, 0x1b,
- 0xfe, 0x8a, 0x10, 0x1c, 0x1a, 0x87, 0x8b, 0x0f, 0xfe, 0x30, 0x90, 0x04,
- 0xfe, 0xb0, 0x93, 0x3a, 0x0b, 0xfe, 0x18, 0x58, 0xfe, 0x32, 0x90, 0x04,
- 0xfe, 0xb2, 0x93, 0x3a, 0x0b, 0xfe, 0x19, 0x58, 0x0e, 0xa8, 0xb3, 0x4a,
- 0x7c, 0x12, 0xfe, 0x0f, 0x79, 0xfe, 0x1c, 0xf7, 0x4a, 0xb1, 0xfe, 0xc6,
- 0x1b, 0xfe, 0x5e, 0x14, 0x31, 0x02, 0xc9, 0x2b, 0xfe, 0x96, 0x1b, 0x5c,
- 0xfe, 0x02, 0xf6, 0x1a, 0x87, 0xfe, 0x18, 0xfe, 0x6a, 0xfe, 0x19, 0xfe,
- 0x6b, 0x01, 0xfe, 0x1e, 0x1f, 0xfe, 0x1d, 0xf7, 0x65, 0xb1, 0xfe, 0xee,
- 0x1b, 0xfe, 0x36, 0x14, 0xfe, 0x1c, 0x13, 0xb3, 0x65, 0x3e, 0xfe, 0x83,
- 0x58, 0xfe, 0xaf, 0x19, 0xfe, 0x80, 0xe7, 0x1a, 0xfe, 0x81, 0xe7, 0x1a,
- 0x15, 0xfe, 0xdd, 0x00, 0x7a, 0x30, 0x02, 0x7a, 0x30, 0xfe, 0x12, 0x45,
- 0x2b, 0xfe, 0xdc, 0x1b, 0x1f, 0x07, 0x47, 0xb5, 0xc3, 0x05, 0x35, 0xfe,
- 0x39, 0xf0, 0x75, 0x26, 0x02, 0xfe, 0x7e, 0x18, 0x23, 0x1d, 0x36, 0x13,
- 0x11, 0x02, 0x87, 0x03, 0xe3, 0x23, 0x07, 0xfe, 0xef, 0x12, 0xfe, 0xe1,
- 0x10, 0x90, 0x34, 0x60, 0xfe, 0x02, 0x80, 0x09, 0x56, 0xfe, 0x3c, 0x13,
- 0xfe, 0x82, 0x14, 0xfe, 0x42, 0x13, 0x51, 0xfe, 0x06, 0x83, 0x0a, 0x5a,
- 0x01, 0x18, 0xcb, 0xfe, 0x3e, 0x12, 0xfe, 0x41, 0x48, 0xfe, 0x45, 0x48,
- 0x01, 0xfe, 0xb2, 0x16, 0xfe, 0x00, 0xcc, 0xcb, 0xfe, 0xf3, 0x13, 0x3f,
- 0x89, 0x09, 0x1a, 0xa5, 0x0a, 0x9d, 0x01, 0x18, 0xfe, 0x80, 0x4c, 0x01,
- 0x85, 0xfe, 0x16, 0x10, 0x09, 0x9b, 0x4e, 0xfe, 0x40, 0x14, 0xfe, 0x24,
- 0x12, 0xfe, 0x14, 0x56, 0xfe, 0xd6, 0xf0, 0xfe, 0x52, 0x1c, 0x1c, 0x0d,
- 0x02, 0xfe, 0x9c, 0xe7, 0x0d, 0x19, 0xfe, 0x15, 0x00, 0x40, 0x8d, 0x30,
- 0x01, 0xf4, 0x1c, 0x07, 0x02, 0x51, 0xfe, 0x06, 0x83, 0xfe, 0x18, 0x80,
- 0x61, 0x28, 0x44, 0x15, 0x56, 0x01, 0x85, 0x1c, 0x07, 0x02, 0xfe, 0x38,
- 0x90, 0xfe, 0xba, 0x90, 0x91, 0xde, 0x7e, 0xdf, 0xfe, 0x48, 0x55, 0x31,
- 0xfe, 0xc9, 0x55, 0x02, 0x21, 0xb9, 0x88, 0x20, 0xb9, 0x02, 0x0a, 0xba,
- 0x01, 0x18, 0xfe, 0x41, 0x48, 0x0a, 0x57, 0x01, 0x18, 0xfe, 0x49, 0x44,
- 0x1b, 0xfe, 0x1e, 0x1d, 0x88, 0x89, 0x02, 0x0a, 0x5a, 0x01, 0x18, 0x09,
- 0x1a, 0xa4, 0x0a, 0x67, 0x01, 0xa3, 0x0a, 0x57, 0x01, 0x18, 0x88, 0x89,
- 0x02, 0xfe, 0x4e, 0xe4, 0x1d, 0x7b, 0xfe, 0x52, 0x1d, 0x03, 0xfe, 0x90,
- 0x00, 0xfe, 0x3a, 0x45, 0xfe, 0x2c, 0x10, 0xfe, 0x4e, 0xe4, 0xdd, 0x7b,
- 0xfe, 0x64, 0x1d, 0x03, 0xfe, 0x92, 0x00, 0xd1, 0x12, 0xfe, 0x1a, 0x10,
- 0xfe, 0x4e, 0xe4, 0xfe, 0x0b, 0x00, 0x7b, 0xfe, 0x76, 0x1d, 0x03, 0xfe,
- 0x94, 0x00, 0xd1, 0x24, 0xfe, 0x08, 0x10, 0x03, 0xfe, 0x96, 0x00, 0xd1,
- 0x63, 0xfe, 0x4e, 0x45, 0x83, 0xca, 0xff, 0x04, 0x68, 0x54, 0xfe, 0xf1,
- 0x10, 0x23, 0x49, 0xfe, 0x08, 0x1c, 0xfe, 0x67, 0x19, 0xfe, 0x0a, 0x1c,
- 0xfe, 0x1a, 0xf4, 0xfe, 0x00, 0x04, 0x83, 0xb2, 0x1d, 0x48, 0xfe, 0xaa,
- 0x1d, 0x13, 0x1d, 0x02, 0x09, 0x92, 0xfe, 0x5a, 0xf0, 0xfe, 0xba, 0x1d,
- 0x2e, 0x93, 0xfe, 0x34, 0x10, 0x09, 0x12, 0xfe, 0x5a, 0xf0, 0xfe, 0xc8,
- 0x1d, 0x2e, 0xb4, 0xfe, 0x26, 0x10, 0x09, 0x1d, 0x36, 0x2e, 0x63, 0xfe,
- 0x1a, 0x10, 0x09, 0x0d, 0x36, 0x2e, 0x94, 0xf2, 0x09, 0x07, 0x36, 0x2e,
- 0x95, 0xa1, 0xc8, 0x02, 0x1f, 0x93, 0x01, 0x42, 0xfe, 0x04, 0xfe, 0x99,
- 0x03, 0x9c, 0x8b, 0x02, 0x2a, 0xfe, 0x1c, 0x1e, 0xfe, 0x14, 0xf0, 0x08,
- 0x2f, 0xfe, 0x0c, 0x1e, 0x2a, 0xfe, 0x1c, 0x1e, 0x8f, 0xfe, 0x1c, 0x1e,
- 0xfe, 0x82, 0xf0, 0xfe, 0x10, 0x1e, 0x02, 0x0f, 0x3f, 0x04, 0xfe, 0x80,
- 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x18, 0x80, 0x04, 0xfe, 0x98,
- 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x02, 0x80, 0x04, 0xfe, 0x82,
- 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06, 0x80, 0x04, 0xfe, 0x86,
- 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x1b, 0x80, 0x04, 0xfe, 0x9b,
- 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x04, 0x80, 0x04, 0xfe, 0x84,
- 0x83, 0x33, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x80, 0x80, 0x04, 0xfe, 0x80,
- 0x83, 0xfe, 0xc9, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x19, 0x81, 0x04,
- 0xfe, 0x99, 0x83, 0xfe, 0xca, 0x47, 0x0b, 0x0e, 0x02, 0x0f, 0xfe, 0x06,
- 0x83, 0x04, 0xfe, 0x86, 0x83, 0xfe, 0xce, 0x47, 0x0b, 0x0e, 0x02, 0x0f,
- 0xfe, 0x2c, 0x90, 0x04, 0xfe, 0xac, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
- 0xfe, 0xae, 0x90, 0x04, 0xfe, 0xae, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
- 0xfe, 0x08, 0x90, 0x04, 0xfe, 0x88, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
- 0xfe, 0x8a, 0x90, 0x04, 0xfe, 0x8a, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
- 0xfe, 0x0c, 0x90, 0x04, 0xfe, 0x8c, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x0f,
- 0xfe, 0x8e, 0x90, 0x04, 0xfe, 0x8e, 0x93, 0x79, 0x0b, 0x0e, 0x02, 0x0f,
- 0xfe, 0x3c, 0x90, 0x04, 0xfe, 0xbc, 0x93, 0x3a, 0x0b, 0x0e, 0x02, 0x8b,
- 0x0f, 0xfe, 0x03, 0x80, 0x04, 0xfe, 0x83, 0x83, 0x33, 0x0b, 0x77, 0x0e,
- 0xa8, 0x02, 0xff, 0x66, 0x00, 0x00,
-};
-
-static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */
-static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */
-
static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc)
{
PortAddr iop_base;
@@ -6362,6 +4751,10 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc)
static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
{
+ const struct firmware *fw;
+ const char fwname[] = "advansys/mcode.bin";
+ int err;
+ unsigned long chksum;
ushort warn_code;
PortAddr iop_base;
@@ -6383,12 +4776,29 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
warn_code |= AscInitLram(asc_dvc);
if (asc_dvc->err_code != 0)
return UW_ERR;
- ASC_DBG(1, "_asc_mcode_chksum 0x%lx\n", (ulong)_asc_mcode_chksum);
- if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf,
- _asc_mcode_size) != _asc_mcode_chksum) {
+
+ err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev);
+ if (err) {
+ printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ fwname, err);
+ return err;
+ }
+ if (fw->size < 4) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, fwname);
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ chksum = (fw->data[3] << 24) | (fw->data[2] << 16) |
+ (fw->data[1] << 8) | fw->data[0];
+ ASC_DBG(1, "_asc_mcode_chksum 0x%lx\n", (ulong)chksum);
+ if (AscLoadMicroCode(iop_base, 0, &fw->data[4],
+ fw->size - 4) != chksum) {
asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM;
+ release_firmware(fw);
return warn_code;
}
+ release_firmware(fw);
warn_code |= AscInitMicroCodeVar(asc_dvc);
asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC;
AscEnableInterrupt(iop_base);
@@ -6417,8 +4827,8 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc)
*
* Returns 0 or an error if the checksum doesn't match
*/
-static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size,
- int memsize, int chksum)
+static int AdvLoadMicrocode(AdvPortAddr iop_base, const unsigned char *buf,
+ int size, int memsize, int chksum)
{
int i, j, end, len = 0;
ADV_DCNT sum;
@@ -6627,6 +5037,8 @@ static int AdvResetSB(ADV_DVC_VAR *asc_dvc)
*/
static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
{
+ const struct firmware *fw;
+ const char fwname[] = "advansys/3550.bin";
AdvPortAddr iop_base;
ushort warn_code;
int begin_addr;
@@ -6634,6 +5046,8 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
ushort code_sum;
int word;
int i;
+ int err;
+ unsigned long chksum;
ushort scsi_cfg1;
uchar tid;
ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */
@@ -6692,9 +5106,24 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
max_cmd[tid]);
}
- asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf,
- _adv_asc3550_size, ADV_3550_MEMSIZE,
- _adv_asc3550_chksum);
+ err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev);
+ if (err) {
+ printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ fwname, err);
+ return err;
+ }
+ if (fw->size < 4) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, fwname);
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ chksum = (fw->data[3] << 24) | (fw->data[2] << 16) |
+ (fw->data[1] << 8) | fw->data[0];
+ asc_dvc->err_code = AdvLoadMicrocode(iop_base, &fw->data[4],
+ fw->size - 4, ADV_3550_MEMSIZE,
+ chksum);
+ release_firmware(fw);
if (asc_dvc->err_code)
return ADV_ERROR;
@@ -7065,6 +5494,8 @@ static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc)
*/
static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
{
+ const struct firmware *fw;
+ const char fwname[] = "advansys/38C0800.bin";
AdvPortAddr iop_base;
ushort warn_code;
int begin_addr;
@@ -7072,6 +5503,8 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
ushort code_sum;
int word;
int i;
+ int err;
+ unsigned long chksum;
ushort scsi_cfg1;
uchar byte;
uchar tid;
@@ -7187,9 +5620,24 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
/* We need to reset back to normal mode after LRAM test passes. */
AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
- asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf,
- _adv_asc38C0800_size, ADV_38C0800_MEMSIZE,
- _adv_asc38C0800_chksum);
+ err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev);
+ if (err) {
+ printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ fwname, err);
+ return err;
+ }
+ if (fw->size < 4) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, fwname);
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ chksum = (fw->data[3] << 24) | (fw->data[2] << 16) |
+ (fw->data[1] << 8) | fw->data[0];
+ asc_dvc->err_code = AdvLoadMicrocode(iop_base, &fw->data[4],
+ fw->size - 4, ADV_38C0800_MEMSIZE,
+ chksum);
+ release_firmware(fw);
if (asc_dvc->err_code)
return ADV_ERROR;
@@ -7544,6 +5992,8 @@ static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc)
*/
static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
{
+ const struct firmware *fw;
+ const char fwname[] = "advansys/38C1600.bin";
AdvPortAddr iop_base;
ushort warn_code;
int begin_addr;
@@ -7551,6 +6001,8 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
ushort code_sum;
long word;
int i;
+ int err;
+ unsigned long chksum;
ushort scsi_cfg1;
uchar byte;
uchar tid;
@@ -7668,9 +6120,24 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc)
/* We need to reset back to normal mode after LRAM test passes. */
AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE);
- asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf,
- _adv_asc38C1600_size, ADV_38C1600_MEMSIZE,
- _adv_asc38C1600_chksum);
+ err = request_firmware(&fw, fwname, asc_dvc->drv_ptr->dev);
+ if (err) {
+ printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ fwname, err);
+ return err;
+ }
+ if (fw->size < 4) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, fwname);
+ release_firmware(fw);
+ return -EINVAL;
+ }
+ chksum = (fw->data[3] << 24) | (fw->data[2] << 16) |
+ (fw->data[1] << 8) | fw->data[0];
+ asc_dvc->err_code = AdvLoadMicrocode(iop_base, &fw->data[4],
+ fw->size - 4, ADV_38C1600_MEMSIZE,
+ chksum);
+ release_firmware(fw);
if (asc_dvc->err_code)
return ADV_ERROR;
@@ -14353,3 +12820,7 @@ module_init(advansys_init);
module_exit(advansys_exit);
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("advansys/mcode.bin");
+MODULE_FIRMWARE("advansys/3550.bin");
+MODULE_FIRMWARE("advansys/38C0800.bin");
+MODULE_FIRMWARE("advansys/38C1600.bin");
diff --git a/drivers/scsi/aic7xxx/aic79xx_core.c b/drivers/scsi/aic7xxx/aic79xx_core.c
index bdad54ec088..63b521d615f 100644
--- a/drivers/scsi/aic7xxx/aic79xx_core.c
+++ b/drivers/scsi/aic7xxx/aic79xx_core.c
@@ -1034,7 +1034,7 @@ ahd_intr(struct ahd_softc *ahd)
}
/******************************** Private Inlines *****************************/
-static __inline void
+static inline void
ahd_assert_atn(struct ahd_softc *ahd)
{
ahd_outb(ahd, SCSISIGO, ATNO);
@@ -1069,7 +1069,7 @@ ahd_currently_packetized(struct ahd_softc *ahd)
return (packetized);
}
-static __inline int
+static inline int
ahd_set_active_fifo(struct ahd_softc *ahd)
{
u_int active_fifo;
@@ -1086,7 +1086,7 @@ ahd_set_active_fifo(struct ahd_softc *ahd)
}
}
-static __inline void
+static inline void
ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl)
{
ahd_busy_tcl(ahd, tcl, SCB_LIST_NULL);
@@ -1096,7 +1096,7 @@ ahd_unbusy_tcl(struct ahd_softc *ahd, u_int tcl)
* Determine whether the sequencer reported a residual
* for this SCB/transaction.
*/
-static __inline void
+static inline void
ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
{
uint32_t sgptr;
@@ -1106,7 +1106,7 @@ ahd_update_residual(struct ahd_softc *ahd, struct scb *scb)
ahd_calc_residual(ahd, scb);
}
-static __inline void
+static inline void
ahd_complete_scb(struct ahd_softc *ahd, struct scb *scb)
{
uint32_t sgptr;
@@ -7987,7 +7987,7 @@ ahd_resume(struct ahd_softc *ahd)
* scbid that should be restored once manipualtion
* of the TCL entry is complete.
*/
-static __inline u_int
+static inline u_int
ahd_index_busy_tcl(struct ahd_softc *ahd, u_int *saved_scbid, u_int tcl)
{
/*
diff --git a/drivers/scsi/aic7xxx/aic79xx_inline.h b/drivers/scsi/aic7xxx/aic79xx_inline.h
index 5f12cf9d99d..09335a3c869 100644
--- a/drivers/scsi/aic7xxx/aic79xx_inline.h
+++ b/drivers/scsi/aic7xxx/aic79xx_inline.h
@@ -46,21 +46,20 @@
#define _AIC79XX_INLINE_H_
/******************************** Debugging ***********************************/
-static __inline char *ahd_name(struct ahd_softc *ahd);
+static inline char *ahd_name(struct ahd_softc *ahd);
-static __inline char *
-ahd_name(struct ahd_softc *ahd)
+static inline char *ahd_name(struct ahd_softc *ahd)
{
return (ahd->name);
}
/************************ Sequencer Execution Control *************************/
-static __inline void ahd_known_modes(struct ahd_softc *ahd,
+static inline void ahd_known_modes(struct ahd_softc *ahd,
ahd_mode src, ahd_mode dst);
-static __inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
+static inline ahd_mode_state ahd_build_mode_state(struct ahd_softc *ahd,
ahd_mode src,
ahd_mode dst);
-static __inline void ahd_extract_mode_state(struct ahd_softc *ahd,
+static inline void ahd_extract_mode_state(struct ahd_softc *ahd,
ahd_mode_state state,
ahd_mode *src, ahd_mode *dst);
@@ -73,7 +72,7 @@ int ahd_is_paused(struct ahd_softc *ahd);
void ahd_pause(struct ahd_softc *ahd);
void ahd_unpause(struct ahd_softc *ahd);
-static __inline void
+static inline void
ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
{
ahd->src_mode = src;
@@ -82,13 +81,13 @@ ahd_known_modes(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
ahd->saved_dst_mode = dst;
}
-static __inline ahd_mode_state
+static inline ahd_mode_state
ahd_build_mode_state(struct ahd_softc *ahd, ahd_mode src, ahd_mode dst)
{
return ((src << SRC_MODE_SHIFT) | (dst << DST_MODE_SHIFT));
}
-static __inline void
+static inline void
ahd_extract_mode_state(struct ahd_softc *ahd, ahd_mode_state state,
ahd_mode *src, ahd_mode *dst)
{
@@ -102,13 +101,12 @@ void *ahd_sg_setup(struct ahd_softc *ahd, struct scb *scb,
bus_size_t len, int last);
/************************** Memory mapping routines ***************************/
-static __inline size_t ahd_sg_size(struct ahd_softc *ahd);
+static inline size_t ahd_sg_size(struct ahd_softc *ahd);
void ahd_sync_sglist(struct ahd_softc *ahd,
struct scb *scb, int op);
-static __inline size_t
-ahd_sg_size(struct ahd_softc *ahd)
+static inline size_t ahd_sg_size(struct ahd_softc *ahd)
{
if ((ahd->flags & AHD_64BIT_ADDRESSING) != 0)
return (sizeof(struct ahd_dma64_seg));
@@ -141,11 +139,9 @@ struct scb *
ahd_lookup_scb(struct ahd_softc *ahd, u_int tag);
void ahd_queue_scb(struct ahd_softc *ahd, struct scb *scb);
-static __inline uint8_t *
- ahd_get_sense_buf(struct ahd_softc *ahd,
+static inline uint8_t *ahd_get_sense_buf(struct ahd_softc *ahd,
struct scb *scb);
-static __inline uint32_t
- ahd_get_sense_bufaddr(struct ahd_softc *ahd,
+static inline uint32_t ahd_get_sense_bufaddr(struct ahd_softc *ahd,
struct scb *scb);
#if 0 /* unused */
@@ -158,13 +154,13 @@ do { \
#endif
-static __inline uint8_t *
+static inline uint8_t *
ahd_get_sense_buf(struct ahd_softc *ahd, struct scb *scb)
{
return (scb->sense_data);
}
-static __inline uint32_t
+static inline uint32_t
ahd_get_sense_bufaddr(struct ahd_softc *ahd, struct scb *scb)
{
return (scb->sense_busaddr);
diff --git a/drivers/scsi/aic7xxx/aic79xx_osm.h b/drivers/scsi/aic7xxx/aic79xx_osm.h
index 8d6612c1992..55c1fe07969 100644
--- a/drivers/scsi/aic7xxx/aic79xx_osm.h
+++ b/drivers/scsi/aic7xxx/aic79xx_osm.h
@@ -395,19 +395,19 @@ struct info_str {
};
/******************************** Locking *************************************/
-static __inline void
+static inline void
ahd_lockinit(struct ahd_softc *ahd)
{
spin_lock_init(&ahd->platform_data->spin_lock);
}
-static __inline void
+static inline void
ahd_lock(struct ahd_softc *ahd, unsigned long *flags)
{
spin_lock_irqsave(&ahd->platform_data->spin_lock, *flags);
}
-static __inline void
+static inline void
ahd_unlock(struct ahd_softc *ahd, unsigned long *flags)
{
spin_unlock_irqrestore(&ahd->platform_data->spin_lock, *flags);
@@ -490,29 +490,29 @@ void ahd_pci_write_config(ahd_dev_softc_t pci,
int reg, uint32_t value,
int width);
-static __inline int ahd_get_pci_function(ahd_dev_softc_t);
-static __inline int
+static inline int ahd_get_pci_function(ahd_dev_softc_t);
+static inline int
ahd_get_pci_function(ahd_dev_softc_t pci)
{
return (PCI_FUNC(pci->devfn));
}
-static __inline int ahd_get_pci_slot(ahd_dev_softc_t);
-static __inline int
+static inline int ahd_get_pci_slot(ahd_dev_softc_t);
+static inline int
ahd_get_pci_slot(ahd_dev_softc_t pci)
{
return (PCI_SLOT(pci->devfn));
}
-static __inline int ahd_get_pci_bus(ahd_dev_softc_t);
-static __inline int
+static inline int ahd_get_pci_bus(ahd_dev_softc_t);
+static inline int
ahd_get_pci_bus(ahd_dev_softc_t pci)
{
return (pci->bus->number);
}
-static __inline void ahd_flush_device_writes(struct ahd_softc *);
-static __inline void
+static inline void ahd_flush_device_writes(struct ahd_softc *);
+static inline void
ahd_flush_device_writes(struct ahd_softc *ahd)
{
/* XXX Is this sufficient for all architectures??? */
@@ -524,81 +524,81 @@ int ahd_linux_proc_info(struct Scsi_Host *, char *, char **,
off_t, int, int);
/*********************** Transaction Access Wrappers **************************/
-static __inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
-static __inline void ahd_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
-static __inline void ahd_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
-static __inline uint32_t ahd_get_transaction_status(struct scb *);
-static __inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
-static __inline uint32_t ahd_get_scsi_status(struct scb *);
-static __inline void ahd_set_transaction_tag(struct scb *, int, u_int);
-static __inline u_long ahd_get_transfer_length(struct scb *);
-static __inline int ahd_get_transfer_dir(struct scb *);
-static __inline void ahd_set_residual(struct scb *, u_long);
-static __inline void ahd_set_sense_residual(struct scb *scb, u_long resid);
-static __inline u_long ahd_get_residual(struct scb *);
-static __inline u_long ahd_get_sense_residual(struct scb *);
-static __inline int ahd_perform_autosense(struct scb *);
-static __inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *,
+static inline void ahd_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
+static inline void ahd_set_transaction_status(struct scb *, uint32_t);
+static inline void ahd_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
+static inline void ahd_set_scsi_status(struct scb *, uint32_t);
+static inline uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd);
+static inline uint32_t ahd_get_transaction_status(struct scb *);
+static inline uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd);
+static inline uint32_t ahd_get_scsi_status(struct scb *);
+static inline void ahd_set_transaction_tag(struct scb *, int, u_int);
+static inline u_long ahd_get_transfer_length(struct scb *);
+static inline int ahd_get_transfer_dir(struct scb *);
+static inline void ahd_set_residual(struct scb *, u_long);
+static inline void ahd_set_sense_residual(struct scb *scb, u_long resid);
+static inline u_long ahd_get_residual(struct scb *);
+static inline u_long ahd_get_sense_residual(struct scb *);
+static inline int ahd_perform_autosense(struct scb *);
+static inline uint32_t ahd_get_sense_bufsize(struct ahd_softc *,
struct scb *);
-static __inline void ahd_notify_xfer_settings_change(struct ahd_softc *,
+static inline void ahd_notify_xfer_settings_change(struct ahd_softc *,
struct ahd_devinfo *);
-static __inline void ahd_platform_scb_free(struct ahd_softc *ahd,
+static inline void ahd_platform_scb_free(struct ahd_softc *ahd,
struct scb *scb);
-static __inline void ahd_freeze_scb(struct scb *scb);
+static inline void ahd_freeze_scb(struct scb *scb);
-static __inline
+static inline
void ahd_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~(CAM_STATUS_MASK << 16);
cmd->result |= status << 16;
}
-static __inline
+static inline
void ahd_set_transaction_status(struct scb *scb, uint32_t status)
{
ahd_cmd_set_transaction_status(scb->io_ctx,status);
}
-static __inline
+static inline
void ahd_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~0xFFFF;
cmd->result |= status;
}
-static __inline
+static inline
void ahd_set_scsi_status(struct scb *scb, uint32_t status)
{
ahd_cmd_set_scsi_status(scb->io_ctx, status);
}
-static __inline
+static inline
uint32_t ahd_cmd_get_transaction_status(struct scsi_cmnd *cmd)
{
return ((cmd->result >> 16) & CAM_STATUS_MASK);
}
-static __inline
+static inline
uint32_t ahd_get_transaction_status(struct scb *scb)
{
return (ahd_cmd_get_transaction_status(scb->io_ctx));
}
-static __inline
+static inline
uint32_t ahd_cmd_get_scsi_status(struct scsi_cmnd *cmd)
{
return (cmd->result & 0xFFFF);
}
-static __inline
+static inline
uint32_t ahd_get_scsi_status(struct scb *scb)
{
return (ahd_cmd_get_scsi_status(scb->io_ctx));
}
-static __inline
+static inline
void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type)
{
/*
@@ -607,43 +607,43 @@ void ahd_set_transaction_tag(struct scb *scb, int enabled, u_int type)
*/
}
-static __inline
+static inline
u_long ahd_get_transfer_length(struct scb *scb)
{
return (scb->platform_data->xfer_len);
}
-static __inline
+static inline
int ahd_get_transfer_dir(struct scb *scb)
{
return (scb->io_ctx->sc_data_direction);
}
-static __inline
+static inline
void ahd_set_residual(struct scb *scb, u_long resid)
{
scsi_set_resid(scb->io_ctx, resid);
}
-static __inline
+static inline
void ahd_set_sense_residual(struct scb *scb, u_long resid)
{
scb->platform_data->sense_resid = resid;
}
-static __inline
+static inline
u_long ahd_get_residual(struct scb *scb)
{
return scsi_get_resid(scb->io_ctx);
}
-static __inline
+static inline
u_long ahd_get_sense_residual(struct scb *scb)
{
return (scb->platform_data->sense_resid);
}
-static __inline
+static inline
int ahd_perform_autosense(struct scb *scb)
{
/*
@@ -654,20 +654,20 @@ int ahd_perform_autosense(struct scb *scb)
return (1);
}
-static __inline uint32_t
+static inline uint32_t
ahd_get_sense_bufsize(struct ahd_softc *ahd, struct scb *scb)
{
return (sizeof(struct scsi_sense_data));
}
-static __inline void
+static inline void
ahd_notify_xfer_settings_change(struct ahd_softc *ahd,
struct ahd_devinfo *devinfo)
{
/* Nothing to do here for linux */
}
-static __inline void
+static inline void
ahd_platform_scb_free(struct ahd_softc *ahd, struct scb *scb)
{
ahd->flags &= ~AHD_RESOURCE_SHORTAGE;
@@ -678,7 +678,7 @@ void ahd_platform_free(struct ahd_softc *ahd);
void ahd_platform_init(struct ahd_softc *ahd);
void ahd_platform_freeze_devq(struct ahd_softc *ahd, struct scb *scb);
-static __inline void
+static inline void
ahd_freeze_scb(struct scb *scb)
{
if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {
diff --git a/drivers/scsi/aic7xxx/aic79xx_pci.c b/drivers/scsi/aic7xxx/aic79xx_pci.c
index a734d77e880..90a04a37b4f 100644
--- a/drivers/scsi/aic7xxx/aic79xx_pci.c
+++ b/drivers/scsi/aic7xxx/aic79xx_pci.c
@@ -51,7 +51,7 @@
#include "aic79xx_pci.h"
-static __inline uint64_t
+static inline uint64_t
ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
{
uint64_t id;
@@ -377,14 +377,12 @@ ahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
error = ahd_init(ahd);
if (error != 0)
return (error);
+ ahd->init_level++;
/*
* Allow interrupts now that we are completely setup.
*/
- error = ahd_pci_map_int(ahd);
- if (!error)
- ahd->init_level++;
- return error;
+ return ahd_pci_map_int(ahd);
}
#ifdef CONFIG_PM
diff --git a/drivers/scsi/aic7xxx/aic7xxx_inline.h b/drivers/scsi/aic7xxx/aic7xxx_inline.h
index 09bf2f4d78d..0b57b783ef4 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_inline.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_inline.h
@@ -55,10 +55,9 @@ void ahc_sync_sglist(struct ahc_softc *ahc,
struct scb *scb, int op);
/******************************** Debugging ***********************************/
-static __inline char *ahc_name(struct ahc_softc *ahc);
+static inline char *ahc_name(struct ahc_softc *ahc);
-static __inline char *
-ahc_name(struct ahc_softc *ahc)
+static inline char *ahc_name(struct ahc_softc *ahc)
{
return (ahc->name);
}
diff --git a/drivers/scsi/aic7xxx/aic7xxx_osm.h b/drivers/scsi/aic7xxx/aic7xxx_osm.h
index 3f7238db35e..56f07e527b4 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_osm.h
+++ b/drivers/scsi/aic7xxx/aic7xxx_osm.h
@@ -230,7 +230,7 @@ int ahc_dmamap_unload(struct ahc_softc *, bus_dma_tag_t, bus_dmamap_t);
#include "aic7xxx.h"
/***************************** Timer Facilities *******************************/
-static __inline void
+static inline void
ahc_scb_timer_reset(struct scb *scb, u_int usec)
{
}
@@ -401,19 +401,19 @@ struct info_str {
/******************************** Locking *************************************/
/* Lock protecting internal data structures */
-static __inline void
+static inline void
ahc_lockinit(struct ahc_softc *ahc)
{
spin_lock_init(&ahc->platform_data->spin_lock);
}
-static __inline void
+static inline void
ahc_lock(struct ahc_softc *ahc, unsigned long *flags)
{
spin_lock_irqsave(&ahc->platform_data->spin_lock, *flags);
}
-static __inline void
+static inline void
ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
{
spin_unlock_irqrestore(&ahc->platform_data->spin_lock, *flags);
@@ -493,22 +493,22 @@ void ahc_pci_write_config(ahc_dev_softc_t pci,
int reg, uint32_t value,
int width);
-static __inline int ahc_get_pci_function(ahc_dev_softc_t);
-static __inline int
+static inline int ahc_get_pci_function(ahc_dev_softc_t);
+static inline int
ahc_get_pci_function(ahc_dev_softc_t pci)
{
return (PCI_FUNC(pci->devfn));
}
-static __inline int ahc_get_pci_slot(ahc_dev_softc_t);
-static __inline int
+static inline int ahc_get_pci_slot(ahc_dev_softc_t);
+static inline int
ahc_get_pci_slot(ahc_dev_softc_t pci)
{
return (PCI_SLOT(pci->devfn));
}
-static __inline int ahc_get_pci_bus(ahc_dev_softc_t);
-static __inline int
+static inline int ahc_get_pci_bus(ahc_dev_softc_t);
+static inline int
ahc_get_pci_bus(ahc_dev_softc_t pci)
{
return (pci->bus->number);
@@ -521,8 +521,8 @@ static inline void ahc_linux_pci_exit(void) {
}
#endif
-static __inline void ahc_flush_device_writes(struct ahc_softc *);
-static __inline void
+static inline void ahc_flush_device_writes(struct ahc_softc *);
+static inline void
ahc_flush_device_writes(struct ahc_softc *ahc)
{
/* XXX Is this sufficient for all architectures??? */
@@ -535,81 +535,81 @@ int ahc_linux_proc_info(struct Scsi_Host *, char *, char **,
/*************************** Domain Validation ********************************/
/*********************** Transaction Access Wrappers *************************/
-static __inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
-static __inline void ahc_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
-static __inline void ahc_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd);
-static __inline uint32_t ahc_get_transaction_status(struct scb *);
-static __inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd);
-static __inline uint32_t ahc_get_scsi_status(struct scb *);
-static __inline void ahc_set_transaction_tag(struct scb *, int, u_int);
-static __inline u_long ahc_get_transfer_length(struct scb *);
-static __inline int ahc_get_transfer_dir(struct scb *);
-static __inline void ahc_set_residual(struct scb *, u_long);
-static __inline void ahc_set_sense_residual(struct scb *scb, u_long resid);
-static __inline u_long ahc_get_residual(struct scb *);
-static __inline u_long ahc_get_sense_residual(struct scb *);
-static __inline int ahc_perform_autosense(struct scb *);
-static __inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *,
+static inline void ahc_cmd_set_transaction_status(struct scsi_cmnd *, uint32_t);
+static inline void ahc_set_transaction_status(struct scb *, uint32_t);
+static inline void ahc_cmd_set_scsi_status(struct scsi_cmnd *, uint32_t);
+static inline void ahc_set_scsi_status(struct scb *, uint32_t);
+static inline uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd);
+static inline uint32_t ahc_get_transaction_status(struct scb *);
+static inline uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd);
+static inline uint32_t ahc_get_scsi_status(struct scb *);
+static inline void ahc_set_transaction_tag(struct scb *, int, u_int);
+static inline u_long ahc_get_transfer_length(struct scb *);
+static inline int ahc_get_transfer_dir(struct scb *);
+static inline void ahc_set_residual(struct scb *, u_long);
+static inline void ahc_set_sense_residual(struct scb *scb, u_long resid);
+static inline u_long ahc_get_residual(struct scb *);
+static inline u_long ahc_get_sense_residual(struct scb *);
+static inline int ahc_perform_autosense(struct scb *);
+static inline uint32_t ahc_get_sense_bufsize(struct ahc_softc *,
struct scb *);
-static __inline void ahc_notify_xfer_settings_change(struct ahc_softc *,
+static inline void ahc_notify_xfer_settings_change(struct ahc_softc *,
struct ahc_devinfo *);
-static __inline void ahc_platform_scb_free(struct ahc_softc *ahc,
+static inline void ahc_platform_scb_free(struct ahc_softc *ahc,
struct scb *scb);
-static __inline void ahc_freeze_scb(struct scb *scb);
+static inline void ahc_freeze_scb(struct scb *scb);
-static __inline
+static inline
void ahc_cmd_set_transaction_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~(CAM_STATUS_MASK << 16);
cmd->result |= status << 16;
}
-static __inline
+static inline
void ahc_set_transaction_status(struct scb *scb, uint32_t status)
{
ahc_cmd_set_transaction_status(scb->io_ctx,status);
}
-static __inline
+static inline
void ahc_cmd_set_scsi_status(struct scsi_cmnd *cmd, uint32_t status)
{
cmd->result &= ~0xFFFF;
cmd->result |= status;
}
-static __inline
+static inline
void ahc_set_scsi_status(struct scb *scb, uint32_t status)
{
ahc_cmd_set_scsi_status(scb->io_ctx, status);
}
-static __inline
+static inline
uint32_t ahc_cmd_get_transaction_status(struct scsi_cmnd *cmd)
{
return ((cmd->result >> 16) & CAM_STATUS_MASK);
}
-static __inline
+static inline
uint32_t ahc_get_transaction_status(struct scb *scb)
{
return (ahc_cmd_get_transaction_status(scb->io_ctx));
}
-static __inline
+static inline
uint32_t ahc_cmd_get_scsi_status(struct scsi_cmnd *cmd)
{
return (cmd->result & 0xFFFF);
}
-static __inline
+static inline
uint32_t ahc_get_scsi_status(struct scb *scb)
{
return (ahc_cmd_get_scsi_status(scb->io_ctx));
}
-static __inline
+static inline
void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type)
{
/*
@@ -618,43 +618,43 @@ void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type)
*/
}
-static __inline
+static inline
u_long ahc_get_transfer_length(struct scb *scb)
{
return (scb->platform_data->xfer_len);
}
-static __inline
+static inline
int ahc_get_transfer_dir(struct scb *scb)
{
return (scb->io_ctx->sc_data_direction);
}
-static __inline
+static inline
void ahc_set_residual(struct scb *scb, u_long resid)
{
scsi_set_resid(scb->io_ctx, resid);
}
-static __inline
+static inline
void ahc_set_sense_residual(struct scb *scb, u_long resid)
{
scb->platform_data->sense_resid = resid;
}
-static __inline
+static inline
u_long ahc_get_residual(struct scb *scb)
{
return scsi_get_resid(scb->io_ctx);
}
-static __inline
+static inline
u_long ahc_get_sense_residual(struct scb *scb)
{
return (scb->platform_data->sense_resid);
}
-static __inline
+static inline
int ahc_perform_autosense(struct scb *scb)
{
/*
@@ -665,20 +665,20 @@ int ahc_perform_autosense(struct scb *scb)
return (1);
}
-static __inline uint32_t
+static inline uint32_t
ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb)
{
return (sizeof(struct scsi_sense_data));
}
-static __inline void
+static inline void
ahc_notify_xfer_settings_change(struct ahc_softc *ahc,
struct ahc_devinfo *devinfo)
{
/* Nothing to do here for linux */
}
-static __inline void
+static inline void
ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
{
}
@@ -687,7 +687,7 @@ int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
void ahc_platform_free(struct ahc_softc *ahc);
void ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
-static __inline void
+static inline void
ahc_freeze_scb(struct scb *scb)
{
if ((scb->io_ctx->result & (CAM_DEV_QFRZN << 16)) == 0) {
diff --git a/drivers/scsi/aic7xxx/aic7xxx_pci.c b/drivers/scsi/aic7xxx/aic7xxx_pci.c
index c07cb6eebb0..27014b9de12 100644
--- a/drivers/scsi/aic7xxx/aic7xxx_pci.c
+++ b/drivers/scsi/aic7xxx/aic7xxx_pci.c
@@ -54,7 +54,7 @@
#include "aic7xxx_pci.h"
-static __inline uint64_t
+static inline uint64_t
ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
{
uint64_t id;
@@ -960,16 +960,12 @@ ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry)
error = ahc_init(ahc);
if (error != 0)
return (error);
+ ahc->init_level++;
/*
* Allow interrupts now that we are completely setup.
*/
- error = ahc_pci_map_int(ahc);
- if (error != 0)
- return (error);
-
- ahc->init_level++;
- return (0);
+ return ahc_pci_map_int(ahc);
}
/*
diff --git a/drivers/scsi/aic7xxx/aiclib.h b/drivers/scsi/aic7xxx/aiclib.h
index 3bfbf0fe1ec..f8fd198aafb 100644
--- a/drivers/scsi/aic7xxx/aiclib.h
+++ b/drivers/scsi/aic7xxx/aiclib.h
@@ -133,7 +133,7 @@ struct scsi_sense_data
#define SCSI_STATUS_TASK_ABORTED 0x40
/************************* Large Disk Handling ********************************/
-static __inline int
+static inline int
aic_sector_div(sector_t capacity, int heads, int sectors)
{
/* ugly, ugly sector_div calling convention.. */
@@ -141,7 +141,7 @@ aic_sector_div(sector_t capacity, int heads, int sectors)
return (int)capacity;
}
-static __inline uint32_t
+static inline uint32_t
scsi_4btoul(uint8_t *bytes)
{
uint32_t rv;
diff --git a/drivers/scsi/arm/cumana_2.c b/drivers/scsi/arm/cumana_2.c
index 68a64123af8..c9902b5c1f2 100644
--- a/drivers/scsi/arm/cumana_2.c
+++ b/drivers/scsi/arm/cumana_2.c
@@ -318,7 +318,7 @@ cumanascsi_2_set_proc_info(struct Scsi_Host *host, char *buffer, int length)
{
int ret = length;
- if (length >= 11 && strcmp(buffer, "CUMANASCSI2") == 0) {
+ if (length >= 11 && strncmp(buffer, "CUMANASCSI2", 11) == 0) {
buffer += 11;
length -= 11;
@@ -390,7 +390,8 @@ static struct scsi_host_template cumanascsi2_template = {
.eh_abort_handler = fas216_eh_abort,
.can_queue = 1,
.this_id = 7,
- .sg_tablesize = SG_ALL,
+ .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
+ .dma_boundary = IOMD_DMA_BOUNDARY,
.cmd_per_lun = 1,
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "cumanascsi2",
diff --git a/drivers/scsi/arm/eesox.c b/drivers/scsi/arm/eesox.c
index bb2477b3fb0..d8435132f46 100644
--- a/drivers/scsi/arm/eesox.c
+++ b/drivers/scsi/arm/eesox.c
@@ -508,7 +508,8 @@ static struct scsi_host_template eesox_template = {
.eh_abort_handler = fas216_eh_abort,
.can_queue = 1,
.this_id = 7,
- .sg_tablesize = SG_ALL,
+ .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
+ .dma_boundary = IOMD_DMA_BOUNDARY,
.cmd_per_lun = 1,
.use_clustering = DISABLE_CLUSTERING,
.proc_name = "eesox",
diff --git a/drivers/scsi/arm/powertec.c b/drivers/scsi/arm/powertec.c
index d9a546d1917..e2297b4c1b9 100644
--- a/drivers/scsi/arm/powertec.c
+++ b/drivers/scsi/arm/powertec.c
@@ -302,7 +302,8 @@ static struct scsi_host_template powertecscsi_template = {
.can_queue = 8,
.this_id = 7,
- .sg_tablesize = SG_ALL,
+ .sg_tablesize = SCSI_MAX_SG_CHAIN_SEGMENTS,
+ .dma_boundary = IOMD_DMA_BOUNDARY,
.cmd_per_lun = 2,
.use_clustering = ENABLE_CLUSTERING,
.proc_name = "powertec",
diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c
index 93b61f14865..0471f880048 100644
--- a/drivers/scsi/atari_NCR5380.c
+++ b/drivers/scsi/atari_NCR5380.c
@@ -844,7 +844,7 @@ static char *lprint_Scsi_Cmnd(Scsi_Cmnd *cmd, char *pos, char *buffer, int lengt
*
*/
-static int NCR5380_init(struct Scsi_Host *instance, int flags)
+static int __init NCR5380_init(struct Scsi_Host *instance, int flags)
{
int i;
SETUP_HOSTDATA(instance);
diff --git a/drivers/scsi/atari_scsi.c b/drivers/scsi/atari_scsi.c
index 21fe07f9df8..ad7a23aef0e 100644
--- a/drivers/scsi/atari_scsi.c
+++ b/drivers/scsi/atari_scsi.c
@@ -589,7 +589,7 @@ int atari_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *))
#endif
-int atari_scsi_detect(struct scsi_host_template *host)
+int __init atari_scsi_detect(struct scsi_host_template *host)
{
static int called = 0;
struct Scsi_Host *instance;
diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c
index d858f3d4127..5799cb5cba6 100644
--- a/drivers/scsi/bvme6000_scsi.c
+++ b/drivers/scsi/bvme6000_scsi.c
@@ -34,7 +34,7 @@ static struct scsi_host_template bvme6000_scsi_driver_template = {
static struct platform_device *bvme6000_scsi_device;
static __devinit int
-bvme6000_probe(struct device *dev)
+bvme6000_probe(struct platform_device *dev)
{
struct Scsi_Host *host;
struct NCR_700_Host_Parameters *hostdata;
@@ -58,7 +58,8 @@ bvme6000_probe(struct device *dev)
hostdata->ctest7_extra = CTEST7_TT1;
/* and register the chip */
- host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, dev);
+ host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata,
+ &dev->dev);
if (!host) {
printk(KERN_ERR "bvme6000-scsi: No host detected; "
"board configuration problem?\n");
@@ -73,7 +74,7 @@ bvme6000_probe(struct device *dev)
goto out_put_host;
}
- dev_set_drvdata(dev, host);
+ platform_set_drvdata(dev, host);
scsi_scan_host(host);
return 0;
@@ -87,9 +88,9 @@ bvme6000_probe(struct device *dev)
}
static __devexit int
-bvme6000_device_remove(struct device *dev)
+bvme6000_device_remove(struct platform_device *dev)
{
- struct Scsi_Host *host = dev_get_drvdata(dev);
+ struct Scsi_Host *host = platform_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
scsi_remove_host(host);
@@ -100,25 +101,27 @@ bvme6000_device_remove(struct device *dev)
return 0;
}
-static struct device_driver bvme6000_scsi_driver = {
- .name = "bvme6000-scsi",
- .bus = &platform_bus_type,
- .probe = bvme6000_probe,
- .remove = __devexit_p(bvme6000_device_remove),
+static struct platform_driver bvme6000_scsi_driver = {
+ .driver = {
+ .name = "bvme6000-scsi",
+ .owner = THIS_MODULE,
+ },
+ .probe = bvme6000_probe,
+ .remove = __devexit_p(bvme6000_device_remove),
};
static int __init bvme6000_scsi_init(void)
{
int err;
- err = driver_register(&bvme6000_scsi_driver);
+ err = platform_driver_register(&bvme6000_scsi_driver);
if (err)
return err;
bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi",
-1, NULL, 0);
if (IS_ERR(bvme6000_scsi_device)) {
- driver_unregister(&bvme6000_scsi_driver);
+ platform_driver_unregister(&bvme6000_scsi_driver);
return PTR_ERR(bvme6000_scsi_device);
}
@@ -128,7 +131,7 @@ static int __init bvme6000_scsi_init(void)
static void __exit bvme6000_scsi_exit(void)
{
platform_device_unregister(bvme6000_scsi_device);
- driver_unregister(&bvme6000_scsi_driver);
+ platform_driver_unregister(&bvme6000_scsi_driver);
}
module_init(bvme6000_scsi_init);
diff --git a/drivers/scsi/ch.c b/drivers/scsi/ch.c
index af9725409f4..7b1633a8c15 100644
--- a/drivers/scsi/ch.c
+++ b/drivers/scsi/ch.c
@@ -41,6 +41,7 @@ MODULE_DESCRIPTION("device driver for scsi media changer devices");
MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org>");
MODULE_LICENSE("GPL");
MODULE_ALIAS_CHARDEV_MAJOR(SCSI_CHANGER_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_MEDIUM_CHANGER);
static int init = 1;
module_param(init, int, 0444);
diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c
index 4003deefb7d..e79e18101f8 100644
--- a/drivers/scsi/constants.c
+++ b/drivers/scsi/constants.c
@@ -1373,21 +1373,14 @@ static const char * const driverbyte_table[]={
"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", "DRIVER_SENSE"};
#define NUM_DRIVERBYTE_STRS ARRAY_SIZE(driverbyte_table)
-static const char * const driversuggest_table[]={"SUGGEST_OK",
-"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
-"SUGGEST_5", "SUGGEST_6", "SUGGEST_7", "SUGGEST_SENSE"};
-#define NUM_SUGGEST_STRS ARRAY_SIZE(driversuggest_table)
-
void scsi_show_result(int result)
{
int hb = host_byte(result);
- int db = (driver_byte(result) & DRIVER_MASK);
- int su = ((driver_byte(result) & SUGGEST_MASK) >> 4);
+ int db = driver_byte(result);
- printk("Result: hostbyte=%s driverbyte=%s,%s\n",
+ printk("Result: hostbyte=%s driverbyte=%s\n",
(hb < NUM_HOSTBYTE_STRS ? hostbyte_table[hb] : "invalid"),
- (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"),
- (su < NUM_SUGGEST_STRS ? driversuggest_table[su] : "invalid"));
+ (db < NUM_DRIVERBYTE_STRS ? driverbyte_table[db] : "invalid"));
}
#else
diff --git a/drivers/scsi/cxgb3i/Kbuild b/drivers/scsi/cxgb3i/Kbuild
index ee7d6d2f9c3..25a2032bfa2 100644
--- a/drivers/scsi/cxgb3i/Kbuild
+++ b/drivers/scsi/cxgb3i/Kbuild
@@ -1,4 +1,4 @@
EXTRA_CFLAGS += -I$(TOPDIR)/drivers/net/cxgb3
-cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o
-obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i_ddp.o cxgb3i.o
+cxgb3i-y := cxgb3i_init.o cxgb3i_iscsi.o cxgb3i_pdu.o cxgb3i_offload.o cxgb3i_ddp.o
+obj-$(CONFIG_SCSI_CXGB3_ISCSI) += cxgb3i.o
diff --git a/drivers/scsi/cxgb3i/cxgb3i.h b/drivers/scsi/cxgb3i/cxgb3i.h
index fde6e4c634e..d362860e750 100644
--- a/drivers/scsi/cxgb3i/cxgb3i.h
+++ b/drivers/scsi/cxgb3i/cxgb3i.h
@@ -20,6 +20,7 @@
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/scatterlist.h>
+#include <linux/skbuff.h>
#include <scsi/libiscsi_tcp.h>
/* from cxgb3 LLD */
@@ -65,10 +66,12 @@ struct cxgb3i_hba {
* @pdev: pointer to pci dev
* @hba_cnt: # of hbas (the same as # of ports)
* @hba: all the hbas on this adapter
+ * @flags: bit flag for adapter event/status
* @tx_max_size: max. tx packet size supported
* @rx_max_size: max. rx packet size supported
* @tag_format: ddp tag format settings
*/
+#define CXGB3I_ADAPTER_FLAG_RESET 0x1
struct cxgb3i_adapter {
struct list_head list_head;
spinlock_t lock;
@@ -77,6 +80,7 @@ struct cxgb3i_adapter {
unsigned char hba_cnt;
struct cxgb3i_hba *hba[MAX_NPORTS];
+ unsigned int flags;
unsigned int tx_max_size;
unsigned int rx_max_size;
@@ -113,13 +117,32 @@ struct cxgb3i_endpoint {
struct cxgb3i_conn *cconn;
};
+/**
+ * struct cxgb3i_task_data - private iscsi task data
+ *
+ * @nr_frags: # of coalesced page frags (from scsi sgl)
+ * @frags: coalesced page frags (from scsi sgl)
+ * @skb: tx pdu skb
+ * @offset: data offset for the next pdu
+ * @count: max. possible pdu payload
+ * @sgoffset: offset to the first sg entry for a given offset
+ */
+#define MAX_PDU_FRAGS ((ULP2_MAX_PDU_PAYLOAD + 512 - 1) / 512)
+struct cxgb3i_task_data {
+ unsigned short nr_frags;
+ skb_frag_t frags[MAX_PDU_FRAGS];
+ struct sk_buff *skb;
+ unsigned int offset;
+ unsigned int count;
+ unsigned int sgoffset;
+};
+
int cxgb3i_iscsi_init(void);
void cxgb3i_iscsi_cleanup(void);
-struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *);
-void cxgb3i_adapter_remove(struct t3cdev *);
-int cxgb3i_adapter_ulp_init(struct cxgb3i_adapter *);
-void cxgb3i_adapter_ulp_cleanup(struct cxgb3i_adapter *);
+struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *);
+void cxgb3i_adapter_open(struct t3cdev *);
+void cxgb3i_adapter_close(struct t3cdev *);
struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *);
struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *,
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.c b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
index 08f3a09d923..d06a661c209 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.c
@@ -23,19 +23,6 @@
#include "cxgb3i_ddp.h"
-#define DRV_MODULE_NAME "cxgb3i_ddp"
-#define DRV_MODULE_VERSION "1.0.0"
-#define DRV_MODULE_RELDATE "Dec. 1, 2008"
-
-static char version[] =
- "Chelsio S3xx iSCSI DDP " DRV_MODULE_NAME
- " v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
-
-MODULE_AUTHOR("Karen Xie <kxie@chelsio.com>");
-MODULE_DESCRIPTION("cxgb3i ddp pagepod manager");
-MODULE_LICENSE("GPL");
-MODULE_VERSION(DRV_MODULE_VERSION);
-
#define ddp_log_error(fmt...) printk(KERN_ERR "cxgb3i_ddp: ERR! " fmt)
#define ddp_log_warn(fmt...) printk(KERN_WARNING "cxgb3i_ddp: WARN! " fmt)
#define ddp_log_info(fmt...) printk(KERN_INFO "cxgb3i_ddp: " fmt)
@@ -66,9 +53,6 @@ static unsigned char ddp_page_order[DDP_PGIDX_MAX] = {0, 1, 2, 4};
static unsigned char ddp_page_shift[DDP_PGIDX_MAX] = {12, 13, 14, 16};
static unsigned char page_idx = DDP_PGIDX_MAX;
-static LIST_HEAD(cxgb3i_ddp_list);
-static DEFINE_RWLOCK(cxgb3i_ddp_rwlock);
-
/*
* functions to program the pagepod in h/w
*/
@@ -113,8 +97,8 @@ static int set_ddp_map(struct cxgb3i_ddp_info *ddp, struct pagepod_hdr *hdr,
return 0;
}
-static int clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int idx,
- unsigned int npods)
+static void clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int tag,
+ unsigned int idx, unsigned int npods)
{
unsigned int pm_addr = (idx << PPOD_SIZE_SHIFT) + ddp->llimit;
int i;
@@ -122,13 +106,17 @@ static int clear_ddp_map(struct cxgb3i_ddp_info *ddp, unsigned int idx,
for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
struct sk_buff *skb = ddp->gl_skb[idx];
+ if (!skb) {
+ ddp_log_error("ddp tag 0x%x, 0x%x, %d/%u, skb NULL.\n",
+ tag, idx, i, npods);
+ continue;
+ }
ddp->gl_skb[idx] = NULL;
memset((skb->head + sizeof(struct ulp_mem_io)), 0, PPOD_SIZE);
ulp_mem_io_set_hdr(skb, pm_addr);
skb->priority = CPL_PRIORITY_CONTROL;
cxgb3_ofld_send(ddp->tdev, skb);
}
- return 0;
}
static inline int ddp_find_unused_entries(struct cxgb3i_ddp_info *ddp,
@@ -196,7 +184,7 @@ static inline int ddp_alloc_gl_skb(struct cxgb3i_ddp_info *ddp, int idx,
}
/**
- * cxgb3i_ddp_find_page_index - return ddp page index for a given page size.
+ * cxgb3i_ddp_find_page_index - return ddp page index for a given page size
* @pgsz: page size
* return the ddp page index, if no match is found return DDP_PGIDX_MAX.
*/
@@ -211,7 +199,6 @@ int cxgb3i_ddp_find_page_index(unsigned long pgsz)
ddp_log_debug("ddp page size 0x%lx not supported.\n", pgsz);
return DDP_PGIDX_MAX;
}
-EXPORT_SYMBOL_GPL(cxgb3i_ddp_find_page_index);
static inline void ddp_gl_unmap(struct pci_dev *pdev,
struct cxgb3i_gather_list *gl)
@@ -334,7 +321,6 @@ error_out:
kfree(gl);
return NULL;
}
-EXPORT_SYMBOL_GPL(cxgb3i_ddp_make_gl);
/**
* cxgb3i_ddp_release_gl - release a page buffer list
@@ -348,15 +334,13 @@ void cxgb3i_ddp_release_gl(struct cxgb3i_gather_list *gl,
ddp_gl_unmap(pdev, gl);
kfree(gl);
}
-EXPORT_SYMBOL_GPL(cxgb3i_ddp_release_gl);
/**
* cxgb3i_ddp_tag_reserve - set up ddp for a data transfer
* @tdev: t3cdev adapter
* @tid: connection id
* @tformat: tag format
- * @tagp: the s/w tag, if ddp setup is successful, it will be updated with
- * ddp/hw tag
+ * @tagp: contains s/w tag initially, will be updated with ddp/hw tag
* @gl: the page momory list
* @gfp: allocation mode
*
@@ -431,7 +415,6 @@ unmark_entries:
ddp_unmark_entries(ddp, idx, npods);
return err;
}
-EXPORT_SYMBOL_GPL(cxgb3i_ddp_tag_reserve);
/**
* cxgb3i_ddp_tag_release - release a ddp tag
@@ -454,22 +437,21 @@ void cxgb3i_ddp_tag_release(struct t3cdev *tdev, u32 tag)
struct cxgb3i_gather_list *gl = ddp->gl_map[idx];
unsigned int npods;
- if (!gl) {
- ddp_log_error("release ddp 0x%x, idx 0x%x, gl NULL.\n",
- tag, idx);
+ if (!gl || !gl->nelem) {
+ ddp_log_error("release 0x%x, idx 0x%x, gl 0x%p, %u.\n",
+ tag, idx, gl, gl ? gl->nelem : 0);
return;
}
npods = (gl->nelem + PPOD_PAGES_MAX - 1) >> PPOD_PAGES_SHIFT;
ddp_log_debug("ddp tag 0x%x, release idx 0x%x, npods %u.\n",
tag, idx, npods);
- clear_ddp_map(ddp, idx, npods);
+ clear_ddp_map(ddp, tag, idx, npods);
ddp_unmark_entries(ddp, idx, npods);
cxgb3i_ddp_release_gl(gl, ddp->pdev);
} else
ddp_log_error("ddp tag 0x%x, idx 0x%x > max 0x%x.\n",
tag, idx, ddp->nppods);
}
-EXPORT_SYMBOL_GPL(cxgb3i_ddp_tag_release);
static int setup_conn_pgidx(struct t3cdev *tdev, unsigned int tid, int pg_idx,
int reply)
@@ -510,7 +492,6 @@ int cxgb3i_setup_conn_host_pagesize(struct t3cdev *tdev, unsigned int tid,
{
return setup_conn_pgidx(tdev, tid, page_idx, reply);
}
-EXPORT_SYMBOL_GPL(cxgb3i_setup_conn_host_pagesize);
/**
* cxgb3i_setup_conn_pagesize - setup the conn.'s ddp page size
@@ -527,7 +508,6 @@ int cxgb3i_setup_conn_pagesize(struct t3cdev *tdev, unsigned int tid,
return setup_conn_pgidx(tdev, tid, pgidx, reply);
}
-EXPORT_SYMBOL_GPL(cxgb3i_setup_conn_pagesize);
/**
* cxgb3i_setup_conn_digest - setup conn. digest setting
@@ -563,26 +543,104 @@ int cxgb3i_setup_conn_digest(struct t3cdev *tdev, unsigned int tid,
cxgb3_ofld_send(tdev, skb);
return 0;
}
-EXPORT_SYMBOL_GPL(cxgb3i_setup_conn_digest);
-static int ddp_init(struct t3cdev *tdev)
+
+/**
+ * cxgb3i_adapter_ddp_info - read the adapter's ddp information
+ * @tdev: t3cdev adapter
+ * @tformat: tag format
+ * @txsz: max tx pdu payload size, filled in by this func.
+ * @rxsz: max rx pdu payload size, filled in by this func.
+ * setup the tag format for a given iscsi entity
+ */
+int cxgb3i_adapter_ddp_info(struct t3cdev *tdev,
+ struct cxgb3i_tag_format *tformat,
+ unsigned int *txsz, unsigned int *rxsz)
+{
+ struct cxgb3i_ddp_info *ddp;
+ unsigned char idx_bits;
+
+ if (!tformat)
+ return -EINVAL;
+
+ if (!tdev->ulp_iscsi)
+ return -EINVAL;
+
+ ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
+
+ idx_bits = 32 - tformat->sw_bits;
+ tformat->rsvd_bits = ddp->idx_bits;
+ tformat->rsvd_shift = PPOD_IDX_SHIFT;
+ tformat->rsvd_mask = (1 << tformat->rsvd_bits) - 1;
+
+ ddp_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
+ tformat->sw_bits, tformat->rsvd_bits,
+ tformat->rsvd_shift, tformat->rsvd_mask);
+
+ *txsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+ ddp->max_txsz - ISCSI_PDU_NONPAYLOAD_LEN);
+ *rxsz = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
+ ddp->max_rxsz - ISCSI_PDU_NONPAYLOAD_LEN);
+ ddp_log_info("max payload size: %u/%u, %u/%u.\n",
+ *txsz, ddp->max_txsz, *rxsz, ddp->max_rxsz);
+ return 0;
+}
+
+/**
+ * cxgb3i_ddp_cleanup - release the cxgb3 adapter's ddp resource
+ * @tdev: t3cdev adapter
+ * release all the resource held by the ddp pagepod manager for a given
+ * adapter if needed
+ */
+void cxgb3i_ddp_cleanup(struct t3cdev *tdev)
+{
+ int i = 0;
+ struct cxgb3i_ddp_info *ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
+
+ ddp_log_info("t3dev 0x%p, release ddp 0x%p.\n", tdev, ddp);
+
+ if (ddp) {
+ tdev->ulp_iscsi = NULL;
+ while (i < ddp->nppods) {
+ struct cxgb3i_gather_list *gl = ddp->gl_map[i];
+ if (gl) {
+ int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
+ >> PPOD_PAGES_SHIFT;
+ ddp_log_info("t3dev 0x%p, ddp %d + %d.\n",
+ tdev, i, npods);
+ kfree(gl);
+ ddp_free_gl_skb(ddp, i, npods);
+ i += npods;
+ } else
+ i++;
+ }
+ cxgb3i_free_big_mem(ddp);
+ }
+}
+
+/**
+ * ddp_init - initialize the cxgb3 adapter's ddp resource
+ * @tdev: t3cdev adapter
+ * initialize the ddp pagepod manager for a given adapter
+ */
+static void ddp_init(struct t3cdev *tdev)
{
struct cxgb3i_ddp_info *ddp;
struct ulp_iscsi_info uinfo;
unsigned int ppmax, bits;
int i, err;
- static int vers_printed;
- if (!vers_printed) {
- printk(KERN_INFO "%s", version);
- vers_printed = 1;
+ if (tdev->ulp_iscsi) {
+ ddp_log_warn("t3dev 0x%p, ddp 0x%p already set up.\n",
+ tdev, tdev->ulp_iscsi);
+ return;
}
err = tdev->ctl(tdev, ULP_ISCSI_GET_PARAMS, &uinfo);
if (err < 0) {
ddp_log_error("%s, failed to get iscsi param err=%d.\n",
tdev->name, err);
- return err;
+ return;
}
ppmax = (uinfo.ulimit - uinfo.llimit + 1) >> PPOD_SIZE_SHIFT;
@@ -599,7 +657,7 @@ static int ddp_init(struct t3cdev *tdev)
if (!ddp) {
ddp_log_warn("%s unable to alloc ddp 0x%d, ddp disabled.\n",
tdev->name, ppmax);
- return 0;
+ return;
}
ddp->gl_map = (struct cxgb3i_gather_list **)(ddp + 1);
ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
@@ -633,139 +691,26 @@ static int ddp_init(struct t3cdev *tdev)
tdev->ulp_iscsi = ddp;
- /* add to the list */
- write_lock(&cxgb3i_ddp_rwlock);
- list_add_tail(&ddp->list, &cxgb3i_ddp_list);
- write_unlock(&cxgb3i_ddp_rwlock);
-
- ddp_log_info("nppods %u (0x%x ~ 0x%x), bits %u, mask 0x%x,0x%x "
- "pkt %u,%u.\n",
- ppmax, ddp->llimit, ddp->ulimit, ddp->idx_bits,
- ddp->idx_mask, ddp->rsvd_tag_mask,
- ddp->max_txsz, ddp->max_rxsz);
- return 0;
+ ddp_log_info("tdev 0x%p, nppods %u, bits %u, mask 0x%x,0x%x pkt %u/%u,"
+ " %u/%u.\n",
+ tdev, ppmax, ddp->idx_bits, ddp->idx_mask,
+ ddp->rsvd_tag_mask, ddp->max_txsz, uinfo.max_txsz,
+ ddp->max_rxsz, uinfo.max_rxsz);
+ return;
free_ddp_map:
cxgb3i_free_big_mem(ddp);
- return err;
-}
-
-/**
- * cxgb3i_adapter_ddp_init - initialize the adapter's ddp resource
- * @tdev: t3cdev adapter
- * @tformat: tag format
- * @txsz: max tx pkt size, filled in by this func.
- * @rxsz: max rx pkt size, filled in by this func.
- * initialize the ddp pagepod manager for a given adapter if needed and
- * setup the tag format for a given iscsi entity
- */
-int cxgb3i_adapter_ddp_init(struct t3cdev *tdev,
- struct cxgb3i_tag_format *tformat,
- unsigned int *txsz, unsigned int *rxsz)
-{
- struct cxgb3i_ddp_info *ddp;
- unsigned char idx_bits;
-
- if (!tformat)
- return -EINVAL;
-
- if (!tdev->ulp_iscsi) {
- int err = ddp_init(tdev);
- if (err < 0)
- return err;
- }
- ddp = (struct cxgb3i_ddp_info *)tdev->ulp_iscsi;
-
- idx_bits = 32 - tformat->sw_bits;
- tformat->rsvd_bits = ddp->idx_bits;
- tformat->rsvd_shift = PPOD_IDX_SHIFT;
- tformat->rsvd_mask = (1 << tformat->rsvd_bits) - 1;
-
- ddp_log_info("tag format: sw %u, rsvd %u,%u, mask 0x%x.\n",
- tformat->sw_bits, tformat->rsvd_bits,
- tformat->rsvd_shift, tformat->rsvd_mask);
-
- *txsz = ddp->max_txsz;
- *rxsz = ddp->max_rxsz;
- ddp_log_info("ddp max pkt size: %u, %u.\n",
- ddp->max_txsz, ddp->max_rxsz);
- return 0;
-}
-EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_init);
-
-static void ddp_release(struct cxgb3i_ddp_info *ddp)
-{
- int i = 0;
- struct t3cdev *tdev = ddp->tdev;
-
- tdev->ulp_iscsi = NULL;
- while (i < ddp->nppods) {
- struct cxgb3i_gather_list *gl = ddp->gl_map[i];
- if (gl) {
- int npods = (gl->nelem + PPOD_PAGES_MAX - 1)
- >> PPOD_PAGES_SHIFT;
-
- kfree(gl);
- ddp_free_gl_skb(ddp, i, npods);
- } else
- i++;
- }
- cxgb3i_free_big_mem(ddp);
-}
-
-/**
- * cxgb3i_adapter_ddp_cleanup - release the adapter's ddp resource
- * @tdev: t3cdev adapter
- * release all the resource held by the ddp pagepod manager for a given
- * adapter if needed
- */
-void cxgb3i_adapter_ddp_cleanup(struct t3cdev *tdev)
-{
- struct cxgb3i_ddp_info *ddp;
-
- /* remove from the list */
- write_lock(&cxgb3i_ddp_rwlock);
- list_for_each_entry(ddp, &cxgb3i_ddp_list, list) {
- if (ddp->tdev == tdev) {
- list_del(&ddp->list);
- break;
- }
- }
- write_unlock(&cxgb3i_ddp_rwlock);
-
- if (ddp)
- ddp_release(ddp);
-}
-EXPORT_SYMBOL_GPL(cxgb3i_adapter_ddp_cleanup);
-
-/**
- * cxgb3i_ddp_init_module - module init entry point
- * initialize any driver wide global data structures
- */
-static int __init cxgb3i_ddp_init_module(void)
-{
- page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
- ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n",
- PAGE_SIZE, page_idx);
- return 0;
}
/**
- * cxgb3i_ddp_exit_module - module cleanup/exit entry point
- * go through the ddp list and release any resource held.
+ * cxgb3i_ddp_init - initialize ddp functions
*/
-static void __exit cxgb3i_ddp_exit_module(void)
+void cxgb3i_ddp_init(struct t3cdev *tdev)
{
- struct cxgb3i_ddp_info *ddp;
-
- /* release all ddp manager if there is any */
- write_lock(&cxgb3i_ddp_rwlock);
- list_for_each_entry(ddp, &cxgb3i_ddp_list, list) {
- list_del(&ddp->list);
- ddp_release(ddp);
+ if (page_idx == DDP_PGIDX_MAX) {
+ page_idx = cxgb3i_ddp_find_page_index(PAGE_SIZE);
+ ddp_log_info("system PAGE_SIZE %lu, ddp idx %u.\n",
+ PAGE_SIZE, page_idx);
}
- write_unlock(&cxgb3i_ddp_rwlock);
+ ddp_init(tdev);
}
-
-module_init(cxgb3i_ddp_init_module);
-module_exit(cxgb3i_ddp_exit_module);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_ddp.h b/drivers/scsi/cxgb3i/cxgb3i_ddp.h
index 5c7c4d95c49..0d296de7cf3 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_ddp.h
+++ b/drivers/scsi/cxgb3i/cxgb3i_ddp.h
@@ -13,6 +13,8 @@
#ifndef __CXGB3I_ULP2_DDP_H__
#define __CXGB3I_ULP2_DDP_H__
+#include <linux/vmalloc.h>
+
/**
* struct cxgb3i_tag_format - cxgb3i ulp tag format for an iscsi entity
*
@@ -85,8 +87,9 @@ struct cxgb3i_ddp_info {
struct sk_buff **gl_skb;
};
+#define ISCSI_PDU_NONPAYLOAD_LEN 312 /* bhs(48) + ahs(256) + digest(8) */
#define ULP2_MAX_PKT_SIZE 16224
-#define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_MAX)
+#define ULP2_MAX_PDU_PAYLOAD (ULP2_MAX_PKT_SIZE - ISCSI_PDU_NONPAYLOAD_LEN)
#define PPOD_PAGES_MAX 4
#define PPOD_PAGES_SHIFT 2 /* 4 pages per pod */
@@ -182,12 +185,11 @@ static inline int cxgb3i_is_ddp_tag(struct cxgb3i_tag_format *tformat, u32 tag)
}
/**
- * cxgb3i_sw_tag_usable - check if a given s/w tag has enough bits left for
- * the reserved/hw bits
+ * cxgb3i_sw_tag_usable - check if s/w tag has enough bits left for hw bits
* @tformat: tag format information
* @sw_tag: s/w tag to be checked
*
- * return true if the tag is a ddp tag, false otherwise.
+ * return true if the tag can be used for hw ddp tag, false otherwise.
*/
static inline int cxgb3i_sw_tag_usable(struct cxgb3i_tag_format *tformat,
u32 sw_tag)
@@ -219,8 +221,7 @@ static inline u32 cxgb3i_set_non_ddp_tag(struct cxgb3i_tag_format *tformat,
}
/**
- * cxgb3i_ddp_tag_base - shift the s/w tag bits so that reserved bits are not
- * used.
+ * cxgb3i_ddp_tag_base - shift s/w tag bits so that reserved bits are not used
* @tformat: tag format information
* @sw_tag: s/w tag to be checked
*/
@@ -300,7 +301,9 @@ int cxgb3i_setup_conn_pagesize(struct t3cdev *, unsigned int tid, int reply,
int cxgb3i_setup_conn_digest(struct t3cdev *, unsigned int tid,
int hcrc, int dcrc, int reply);
int cxgb3i_ddp_find_page_index(unsigned long pgsz);
-int cxgb3i_adapter_ddp_init(struct t3cdev *, struct cxgb3i_tag_format *,
+int cxgb3i_adapter_ddp_info(struct t3cdev *, struct cxgb3i_tag_format *,
unsigned int *txsz, unsigned int *rxsz);
-void cxgb3i_adapter_ddp_cleanup(struct t3cdev *);
+
+void cxgb3i_ddp_init(struct t3cdev *);
+void cxgb3i_ddp_cleanup(struct t3cdev *);
#endif
diff --git a/drivers/scsi/cxgb3i/cxgb3i_init.c b/drivers/scsi/cxgb3i/cxgb3i_init.c
index 091ecb4d9f3..042d9bce991 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_init.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_init.c
@@ -12,8 +12,8 @@
#include "cxgb3i.h"
#define DRV_MODULE_NAME "cxgb3i"
-#define DRV_MODULE_VERSION "1.0.0"
-#define DRV_MODULE_RELDATE "Jun. 1, 2008"
+#define DRV_MODULE_VERSION "1.0.2"
+#define DRV_MODULE_RELDATE "Mar. 2009"
static char version[] =
"Chelsio S3xx iSCSI Driver " DRV_MODULE_NAME
@@ -26,6 +26,7 @@ MODULE_VERSION(DRV_MODULE_VERSION);
static void open_s3_dev(struct t3cdev *);
static void close_s3_dev(struct t3cdev *);
+static void s3_err_handler(struct t3cdev *tdev, u32 status, u32 error);
static cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
static struct cxgb3_client t3c_client = {
@@ -33,6 +34,7 @@ static struct cxgb3_client t3c_client = {
.handlers = cxgb3i_cpl_handlers,
.add = open_s3_dev,
.remove = close_s3_dev,
+ .err_handler = s3_err_handler,
};
/**
@@ -48,8 +50,9 @@ static void open_s3_dev(struct t3cdev *t3dev)
vers_printed = 1;
}
+ cxgb3i_ddp_init(t3dev);
cxgb3i_sdev_add(t3dev, &t3c_client);
- cxgb3i_adapter_add(t3dev);
+ cxgb3i_adapter_open(t3dev);
}
/**
@@ -58,8 +61,28 @@ static void open_s3_dev(struct t3cdev *t3dev)
*/
static void close_s3_dev(struct t3cdev *t3dev)
{
- cxgb3i_adapter_remove(t3dev);
+ cxgb3i_adapter_close(t3dev);
cxgb3i_sdev_remove(t3dev);
+ cxgb3i_ddp_cleanup(t3dev);
+}
+
+static void s3_err_handler(struct t3cdev *tdev, u32 status, u32 error)
+{
+ struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(tdev);
+
+ cxgb3i_log_info("snic 0x%p, tdev 0x%p, status 0x%x, err 0x%x.\n",
+ snic, tdev, status, error);
+ if (!snic)
+ return;
+
+ switch (status) {
+ case OFFLOAD_STATUS_DOWN:
+ snic->flags |= CXGB3I_ADAPTER_FLAG_RESET;
+ break;
+ case OFFLOAD_STATUS_UP:
+ snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
+ break;
+ }
}
/**
diff --git a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
index d83464b9b3f..fff8e432764 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_iscsi.c
@@ -53,36 +53,52 @@ static LIST_HEAD(cxgb3i_snic_list);
static DEFINE_RWLOCK(cxgb3i_snic_rwlock);
/**
- * cxgb3i_adapter_add - init a s3 adapter structure and any h/w settings
- * @t3dev: t3cdev adapter
- * return the resulting cxgb3i_adapter struct
+ * cxgb3i_adpater_find_by_tdev - find the cxgb3i_adapter structure via t3cdev
+ * @tdev: t3cdev pointer
*/
-struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev)
+struct cxgb3i_adapter *cxgb3i_adapter_find_by_tdev(struct t3cdev *tdev)
{
struct cxgb3i_adapter *snic;
- struct adapter *adapter = tdev2adap(t3dev);
- int i;
- snic = kzalloc(sizeof(*snic), GFP_KERNEL);
- if (!snic) {
- cxgb3i_api_debug("cxgb3 %s, OOM.\n", t3dev->name);
- return NULL;
+ read_lock(&cxgb3i_snic_rwlock);
+ list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
+ if (snic->tdev == tdev) {
+ read_unlock(&cxgb3i_snic_rwlock);
+ return snic;
+ }
}
- spin_lock_init(&snic->lock);
+ read_unlock(&cxgb3i_snic_rwlock);
+ return NULL;
+}
+
+static inline int adapter_update(struct cxgb3i_adapter *snic)
+{
+ cxgb3i_log_info("snic 0x%p, t3dev 0x%p, updating.\n",
+ snic, snic->tdev);
+ return cxgb3i_adapter_ddp_info(snic->tdev, &snic->tag_format,
+ &snic->tx_max_size,
+ &snic->rx_max_size);
+}
+
+static int adapter_add(struct cxgb3i_adapter *snic)
+{
+ struct t3cdev *t3dev = snic->tdev;
+ struct adapter *adapter = tdev2adap(t3dev);
+ int i, err;
- snic->tdev = t3dev;
snic->pdev = adapter->pdev;
snic->tag_format.sw_bits = sw_tag_idx_bits + sw_tag_age_bits;
- if (cxgb3i_adapter_ddp_init(t3dev, &snic->tag_format,
+ err = cxgb3i_adapter_ddp_info(t3dev, &snic->tag_format,
&snic->tx_max_size,
- &snic->rx_max_size) < 0)
- goto free_snic;
+ &snic->rx_max_size);
+ if (err < 0)
+ return err;
for_each_port(adapter, i) {
snic->hba[i] = cxgb3i_hba_host_add(snic, adapter->port[i]);
if (!snic->hba[i])
- goto ulp_cleanup;
+ return -EINVAL;
}
snic->hba_cnt = adapter->params.nports;
@@ -91,52 +107,75 @@ struct cxgb3i_adapter *cxgb3i_adapter_add(struct t3cdev *t3dev)
list_add_tail(&snic->list_head, &cxgb3i_snic_list);
write_unlock(&cxgb3i_snic_rwlock);
- return snic;
+ cxgb3i_log_info("t3dev 0x%p open, snic 0x%p, %u scsi hosts added.\n",
+ t3dev, snic, snic->hba_cnt);
+ return 0;
+}
-ulp_cleanup:
- cxgb3i_adapter_ddp_cleanup(t3dev);
-free_snic:
- kfree(snic);
- return NULL;
+/**
+ * cxgb3i_adapter_open - init a s3 adapter structure and any h/w settings
+ * @t3dev: t3cdev adapter
+ */
+void cxgb3i_adapter_open(struct t3cdev *t3dev)
+{
+ struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
+ int err;
+
+ if (snic)
+ err = adapter_update(snic);
+ else {
+ snic = kzalloc(sizeof(*snic), GFP_KERNEL);
+ if (snic) {
+ spin_lock_init(&snic->lock);
+ snic->tdev = t3dev;
+ err = adapter_add(snic);
+ } else
+ err = -ENOMEM;
+ }
+
+ if (err < 0) {
+ cxgb3i_log_info("snic 0x%p, f 0x%x, t3dev 0x%p open, err %d.\n",
+ snic, snic ? snic->flags : 0, t3dev, err);
+ if (snic) {
+ snic->flags &= ~CXGB3I_ADAPTER_FLAG_RESET;
+ cxgb3i_adapter_close(t3dev);
+ }
+ }
}
/**
- * cxgb3i_adapter_remove - release all the resources held and cleanup any
- * h/w settings
+ * cxgb3i_adapter_close - release the resources held and cleanup h/w settings
* @t3dev: t3cdev adapter
*/
-void cxgb3i_adapter_remove(struct t3cdev *t3dev)
+void cxgb3i_adapter_close(struct t3cdev *t3dev)
{
+ struct cxgb3i_adapter *snic = cxgb3i_adapter_find_by_tdev(t3dev);
int i;
- struct cxgb3i_adapter *snic;
+
+ if (!snic || snic->flags & CXGB3I_ADAPTER_FLAG_RESET) {
+ cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, f 0x%x.\n",
+ t3dev, snic, snic ? snic->flags : 0);
+ return;
+ }
/* remove from the list */
write_lock(&cxgb3i_snic_rwlock);
- list_for_each_entry(snic, &cxgb3i_snic_list, list_head) {
- if (snic->tdev == t3dev) {
- list_del(&snic->list_head);
- break;
- }
- }
+ list_del(&snic->list_head);
write_unlock(&cxgb3i_snic_rwlock);
- if (snic) {
- for (i = 0; i < snic->hba_cnt; i++) {
- if (snic->hba[i]) {
- cxgb3i_hba_host_remove(snic->hba[i]);
- snic->hba[i] = NULL;
- }
+ for (i = 0; i < snic->hba_cnt; i++) {
+ if (snic->hba[i]) {
+ cxgb3i_hba_host_remove(snic->hba[i]);
+ snic->hba[i] = NULL;
}
-
- /* release ddp resources */
- cxgb3i_adapter_ddp_cleanup(snic->tdev);
- kfree(snic);
}
+ cxgb3i_log_info("t3dev 0x%p close, snic 0x%p, %u scsi hosts removed.\n",
+ t3dev, snic, snic->hba_cnt);
+ kfree(snic);
}
/**
- * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure with a given
- * net_device
+ * cxgb3i_hba_find_by_netdev - find the cxgb3i_hba structure via net_device
* @t3dev: t3cdev adapter
*/
struct cxgb3i_hba *cxgb3i_hba_find_by_netdev(struct net_device *ndev)
@@ -170,10 +209,10 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
int err;
shost = iscsi_host_alloc(&cxgb3i_host_template,
- sizeof(struct cxgb3i_hba),
- CXGB3I_SCSI_QDEPTH_DFLT);
+ sizeof(struct cxgb3i_hba), 1);
if (!shost) {
- cxgb3i_log_info("iscsi_host_alloc failed.\n");
+ cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_alloc failed.\n",
+ snic, ndev);
return NULL;
}
@@ -191,7 +230,8 @@ struct cxgb3i_hba *cxgb3i_hba_host_add(struct cxgb3i_adapter *snic,
pci_dev_get(snic->pdev);
err = iscsi_host_add(shost, &snic->pdev->dev);
if (err) {
- cxgb3i_log_info("iscsi_host_add failed.\n");
+ cxgb3i_log_info("snic 0x%p, ndev 0x%p, host_add failed.\n",
+ snic, ndev);
goto pci_dev_put;
}
@@ -335,13 +375,12 @@ static void cxgb3i_ep_disconnect(struct iscsi_endpoint *ep)
* @cmds_max: max # of commands
* @qdepth: scsi queue depth
* @initial_cmdsn: initial iscsi CMDSN for this session
- * @host_no: pointer to return host no
*
* Creates a new iSCSI session
*/
static struct iscsi_cls_session *
cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
- u32 initial_cmdsn, u32 *host_no)
+ u32 initial_cmdsn)
{
struct cxgb3i_endpoint *cep;
struct cxgb3i_hba *hba;
@@ -360,11 +399,10 @@ cxgb3i_session_create(struct iscsi_endpoint *ep, u16 cmds_max, u16 qdepth,
cxgb3i_api_debug("ep 0x%p, cep 0x%p, hba 0x%p.\n", ep, cep, hba);
BUG_ON(hba != iscsi_host_priv(shost));
- *host_no = shost->host_no;
-
cls_session = iscsi_session_setup(&cxgb3i_iscsi_transport, shost,
cmds_max,
- sizeof(struct iscsi_tcp_task),
+ sizeof(struct iscsi_tcp_task) +
+ sizeof(struct cxgb3i_task_data),
initial_cmdsn, ISCSI_MAX_TARGET);
if (!cls_session)
return NULL;
@@ -393,33 +431,30 @@ static void cxgb3i_session_destroy(struct iscsi_cls_session *cls_session)
}
/**
- * cxgb3i_conn_max_xmit_dlength -- check the max. xmit pdu segment size,
- * reduce it to be within the hardware limit if needed
+ * cxgb3i_conn_max_xmit_dlength -- calc the max. xmit pdu segment size
* @conn: iscsi connection
+ * check the max. xmit pdu payload, reduce it if needed
*/
static inline int cxgb3i_conn_max_xmit_dlength(struct iscsi_conn *conn)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
- cconn->hba->snic->tx_max_size -
- ISCSI_PDU_NONPAYLOAD_MAX);
+ unsigned int max = max(512 * MAX_SKB_FRAGS, SKB_TX_HEADROOM);
+ max = min(cconn->hba->snic->tx_max_size, max);
if (conn->max_xmit_dlength)
- conn->max_xmit_dlength = min_t(unsigned int,
- conn->max_xmit_dlength, max);
+ conn->max_xmit_dlength = min(conn->max_xmit_dlength, max);
else
conn->max_xmit_dlength = max;
align_pdu_size(conn->max_xmit_dlength);
- cxgb3i_log_info("conn 0x%p, max xmit %u.\n",
+ cxgb3i_api_debug("conn 0x%p, max xmit %u.\n",
conn, conn->max_xmit_dlength);
return 0;
}
/**
- * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size against
- * the hardware limit
+ * cxgb3i_conn_max_recv_dlength -- check the max. recv pdu segment size
* @conn: iscsi connection
* return 0 if the value is valid, < 0 otherwise.
*/
@@ -427,9 +462,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn)
{
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct cxgb3i_conn *cconn = tcp_conn->dd_data;
- unsigned int max = min_t(unsigned int, ULP2_MAX_PDU_PAYLOAD,
- cconn->hba->snic->rx_max_size -
- ISCSI_PDU_NONPAYLOAD_MAX);
+ unsigned int max = cconn->hba->snic->rx_max_size;
align_pdu_size(max);
if (conn->max_recv_dlength) {
@@ -439,8 +472,7 @@ static inline int cxgb3i_conn_max_recv_dlength(struct iscsi_conn *conn)
conn->max_recv_dlength, max);
return -EINVAL;
}
- conn->max_recv_dlength = min_t(unsigned int,
- conn->max_recv_dlength, max);
+ conn->max_recv_dlength = min(conn->max_recv_dlength, max);
align_pdu_size(conn->max_recv_dlength);
} else
conn->max_recv_dlength = max;
@@ -763,9 +795,9 @@ static void cxgb3i_parse_itt(struct iscsi_conn *conn, itt_t itt,
/**
* cxgb3i_reserve_itt - generate tag for a give task
- * Try to set up ddp for a scsi read task.
* @task: iscsi task
* @hdr_itt: tag, filled in by this function
+ * Set up ddp for scsi read tasks if possible.
*/
int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
{
@@ -813,9 +845,9 @@ int cxgb3i_reserve_itt(struct iscsi_task *task, itt_t *hdr_itt)
/**
* cxgb3i_release_itt - release the tag for a given task
- * if the tag is a ddp tag, release the ddp setup
* @task: iscsi task
* @hdr_itt: tag
+ * If the tag is a ddp tag, release the ddp setup
*/
void cxgb3i_release_itt(struct iscsi_task *task, itt_t hdr_itt)
{
@@ -844,10 +876,10 @@ static struct scsi_host_template cxgb3i_host_template = {
.proc_name = "cxgb3i",
.queuecommand = iscsi_queuecommand,
.change_queue_depth = iscsi_change_queue_depth,
- .can_queue = 128 * (ISCSI_DEF_XMIT_CMDS_MAX - 1),
+ .can_queue = CXGB3I_SCSI_QDEPTH_DFLT - 1,
.sg_tablesize = SG_ALL,
.max_sectors = 0xFFFF,
- .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
+ .cmd_per_lun = CXGB3I_SCSI_QDEPTH_DFLT,
.eh_abort_handler = iscsi_eh_abort,
.eh_device_reset_handler = iscsi_eh_device_reset,
.eh_target_reset_handler = iscsi_eh_target_reset,
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.c b/drivers/scsi/cxgb3i/cxgb3i_offload.c
index a865f1fefe8..4d8654cdbda 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_offload.c
@@ -23,19 +23,19 @@
#include "cxgb3i_ddp.h"
#ifdef __DEBUG_C3CN_CONN__
-#define c3cn_conn_debug cxgb3i_log_info
+#define c3cn_conn_debug cxgb3i_log_debug
#else
#define c3cn_conn_debug(fmt...)
#endif
#ifdef __DEBUG_C3CN_TX__
-#define c3cn_tx_debug cxgb3i_log_debug
+#define c3cn_tx_debug cxgb3i_log_debug
#else
#define c3cn_tx_debug(fmt...)
#endif
#ifdef __DEBUG_C3CN_RX__
-#define c3cn_rx_debug cxgb3i_log_debug
+#define c3cn_rx_debug cxgb3i_log_debug
#else
#define c3cn_rx_debug(fmt...)
#endif
@@ -47,9 +47,9 @@ static int cxgb3_rcv_win = 256 * 1024;
module_param(cxgb3_rcv_win, int, 0644);
MODULE_PARM_DESC(cxgb3_rcv_win, "TCP receive window in bytes (default=256KB)");
-static int cxgb3_snd_win = 64 * 1024;
+static int cxgb3_snd_win = 128 * 1024;
module_param(cxgb3_snd_win, int, 0644);
-MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=64KB)");
+MODULE_PARM_DESC(cxgb3_snd_win, "TCP send window in bytes (default=128KB)");
static int cxgb3_rx_credit_thres = 10 * 1024;
module_param(cxgb3_rx_credit_thres, int, 0644);
@@ -94,29 +94,30 @@ static int c3cn_get_port(struct s3_conn *c3cn, struct cxgb3i_sdev_data *cdata)
if (!cdata)
goto error_out;
- if (c3cn->saddr.sin_port != 0) {
- idx = ntohs(c3cn->saddr.sin_port) - cxgb3_sport_base;
- if (idx < 0 || idx >= cxgb3_max_connect)
- return 0;
- if (!test_and_set_bit(idx, cdata->sport_map))
- return -EADDRINUSE;
+ if (c3cn->saddr.sin_port) {
+ cxgb3i_log_error("connect, sin_port NON-ZERO %u.\n",
+ c3cn->saddr.sin_port);
+ return -EADDRINUSE;
}
- /* the sport_map_next may not be accurate but that is okay, sport_map
- should be */
- start = idx = cdata->sport_map_next;
+ spin_lock_bh(&cdata->lock);
+ start = idx = cdata->sport_next;
do {
if (++idx >= cxgb3_max_connect)
idx = 0;
- if (!(test_and_set_bit(idx, cdata->sport_map))) {
+ if (!cdata->sport_conn[idx]) {
c3cn->saddr.sin_port = htons(cxgb3_sport_base + idx);
- cdata->sport_map_next = idx;
+ cdata->sport_next = idx;
+ cdata->sport_conn[idx] = c3cn;
+ spin_unlock_bh(&cdata->lock);
+
c3cn_conn_debug("%s reserve port %u.\n",
cdata->cdev->name,
cxgb3_sport_base + idx);
return 0;
}
} while (idx != start);
+ spin_unlock_bh(&cdata->lock);
error_out:
return -EADDRNOTAVAIL;
@@ -124,15 +125,19 @@ error_out:
static void c3cn_put_port(struct s3_conn *c3cn)
{
- struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(c3cn->cdev);
+ if (!c3cn->cdev)
+ return;
if (c3cn->saddr.sin_port) {
+ struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(c3cn->cdev);
int idx = ntohs(c3cn->saddr.sin_port) - cxgb3_sport_base;
c3cn->saddr.sin_port = 0;
if (idx < 0 || idx >= cxgb3_max_connect)
return;
- clear_bit(idx, cdata->sport_map);
+ spin_lock_bh(&cdata->lock);
+ cdata->sport_conn[idx] = NULL;
+ spin_unlock_bh(&cdata->lock);
c3cn_conn_debug("%s, release port %u.\n",
cdata->cdev->name, cxgb3_sport_base + idx);
}
@@ -301,8 +306,8 @@ static void act_open_req_arp_failure(struct t3cdev *dev, struct sk_buff *skb)
static void skb_entail(struct s3_conn *c3cn, struct sk_buff *skb,
int flags)
{
- CXGB3_SKB_CB(skb)->seq = c3cn->write_seq;
- CXGB3_SKB_CB(skb)->flags = flags;
+ skb_tcp_seq(skb) = c3cn->write_seq;
+ skb_flags(skb) = flags;
__skb_queue_tail(&c3cn->write_queue, skb);
}
@@ -457,12 +462,9 @@ static unsigned int wrlen __read_mostly;
* The number of WRs needed for an skb depends on the number of fragments
* in the skb and whether it has any payload in its main body. This maps the
* length of the gather list represented by an skb into the # of necessary WRs.
- *
- * The max. length of an skb is controlled by the max pdu size which is ~16K.
- * Also, assume the min. fragment length is the sector size (512), then add
- * extra fragment counts for iscsi bhs and payload padding.
+ * The extra two fragments are for iscsi bhs and payload padding.
*/
-#define SKB_WR_LIST_SIZE (16384/512 + 3)
+#define SKB_WR_LIST_SIZE (MAX_SKB_FRAGS + 2)
static unsigned int skb_wrs[SKB_WR_LIST_SIZE] __read_mostly;
static void s3_init_wr_tab(unsigned int wr_len)
@@ -485,7 +487,7 @@ static void s3_init_wr_tab(unsigned int wr_len)
static inline void reset_wr_list(struct s3_conn *c3cn)
{
- c3cn->wr_pending_head = NULL;
+ c3cn->wr_pending_head = c3cn->wr_pending_tail = NULL;
}
/*
@@ -496,7 +498,7 @@ static inline void reset_wr_list(struct s3_conn *c3cn)
static inline void enqueue_wr(struct s3_conn *c3cn,
struct sk_buff *skb)
{
- skb_wr_data(skb) = NULL;
+ skb_tx_wr_next(skb) = NULL;
/*
* We want to take an extra reference since both us and the driver
@@ -509,10 +511,22 @@ static inline void enqueue_wr(struct s3_conn *c3cn,
if (!c3cn->wr_pending_head)
c3cn->wr_pending_head = skb;
else
- skb_wr_data(skb) = skb;
+ skb_tx_wr_next(c3cn->wr_pending_tail) = skb;
c3cn->wr_pending_tail = skb;
}
+static int count_pending_wrs(struct s3_conn *c3cn)
+{
+ int n = 0;
+ const struct sk_buff *skb = c3cn->wr_pending_head;
+
+ while (skb) {
+ n += skb->csum;
+ skb = skb_tx_wr_next(skb);
+ }
+ return n;
+}
+
static inline struct sk_buff *peek_wr(const struct s3_conn *c3cn)
{
return c3cn->wr_pending_head;
@@ -529,8 +543,8 @@ static inline struct sk_buff *dequeue_wr(struct s3_conn *c3cn)
if (likely(skb)) {
/* Don't bother clearing the tail */
- c3cn->wr_pending_head = skb_wr_data(skb);
- skb_wr_data(skb) = NULL;
+ c3cn->wr_pending_head = skb_tx_wr_next(skb);
+ skb_tx_wr_next(skb) = NULL;
}
return skb;
}
@@ -543,13 +557,14 @@ static void purge_wr_queue(struct s3_conn *c3cn)
}
static inline void make_tx_data_wr(struct s3_conn *c3cn, struct sk_buff *skb,
- int len)
+ int len, int req_completion)
{
struct tx_data_wr *req;
skb_reset_transport_header(skb);
req = (struct tx_data_wr *)__skb_push(skb, sizeof(*req));
- req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA));
+ req->wr_hi = htonl(V_WR_OP(FW_WROPCODE_OFLD_TX_DATA) |
+ (req_completion ? F_WR_COMPL : 0));
req->wr_lo = htonl(V_WR_TID(c3cn->tid));
req->sndseq = htonl(c3cn->snd_nxt);
/* len includes the length of any HW ULP additions */
@@ -592,7 +607,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
if (unlikely(c3cn->state == C3CN_STATE_CONNECTING ||
c3cn->state == C3CN_STATE_CLOSE_WAIT_1 ||
- c3cn->state == C3CN_STATE_ABORTING)) {
+ c3cn->state >= C3CN_STATE_ABORTING)) {
c3cn_tx_debug("c3cn 0x%p, in closing state %u.\n",
c3cn, c3cn->state);
return 0;
@@ -615,7 +630,7 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
if (c3cn->wr_avail < wrs_needed) {
c3cn_tx_debug("c3cn 0x%p, skb len %u/%u, frag %u, "
"wr %d < %u.\n",
- c3cn, skb->len, skb->datalen, frags,
+ c3cn, skb->len, skb->data_len, frags,
wrs_needed, c3cn->wr_avail);
break;
}
@@ -627,20 +642,24 @@ static int c3cn_push_tx_frames(struct s3_conn *c3cn, int req_completion)
c3cn->wr_unacked += wrs_needed;
enqueue_wr(c3cn, skb);
- if (likely(CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_NEED_HDR)) {
- len += ulp_extra_len(skb);
- make_tx_data_wr(c3cn, skb, len);
- c3cn->snd_nxt += len;
- if ((req_completion
- && c3cn->wr_unacked == wrs_needed)
- || (CXGB3_SKB_CB(skb)->flags & C3CB_FLAG_COMPL)
- || c3cn->wr_unacked >= c3cn->wr_max / 2) {
- struct work_request_hdr *wr = cplhdr(skb);
+ c3cn_tx_debug("c3cn 0x%p, enqueue, skb len %u/%u, frag %u, "
+ "wr %d, left %u, unack %u.\n",
+ c3cn, skb->len, skb->data_len, frags,
+ wrs_needed, c3cn->wr_avail, c3cn->wr_unacked);
- wr->wr_hi |= htonl(F_WR_COMPL);
+
+ if (likely(skb_flags(skb) & C3CB_FLAG_NEED_HDR)) {
+ if ((req_completion &&
+ c3cn->wr_unacked == wrs_needed) ||
+ (skb_flags(skb) & C3CB_FLAG_COMPL) ||
+ c3cn->wr_unacked >= c3cn->wr_max / 2) {
+ req_completion = 1;
c3cn->wr_unacked = 0;
}
- CXGB3_SKB_CB(skb)->flags &= ~C3CB_FLAG_NEED_HDR;
+ len += ulp_extra_len(skb);
+ make_tx_data_wr(c3cn, skb, len, req_completion);
+ c3cn->snd_nxt += len;
+ skb_flags(skb) &= ~C3CB_FLAG_NEED_HDR;
}
total_size += skb->truesize;
@@ -735,8 +754,11 @@ static void process_act_establish(struct s3_conn *c3cn, struct sk_buff *skb)
if (unlikely(c3cn_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED)))
/* upper layer has requested closing */
send_abort_req(c3cn);
- else if (c3cn_push_tx_frames(c3cn, 1))
+ else {
+ if (skb_queue_len(&c3cn->write_queue))
+ c3cn_push_tx_frames(c3cn, 1);
cxgb3i_conn_tx_open(c3cn);
+ }
}
static int do_act_establish(struct t3cdev *cdev, struct sk_buff *skb,
@@ -1082,8 +1104,8 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
return;
}
- CXGB3_SKB_CB(skb)->seq = ntohl(hdr_cpl->seq);
- CXGB3_SKB_CB(skb)->flags = 0;
+ skb_tcp_seq(skb) = ntohl(hdr_cpl->seq);
+ skb_flags(skb) = 0;
skb_reset_transport_header(skb);
__skb_pull(skb, sizeof(struct cpl_iscsi_hdr));
@@ -1103,12 +1125,12 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
goto abort_conn;
skb_ulp_mode(skb) = ULP2_FLAG_DATA_READY;
- skb_ulp_pdulen(skb) = ntohs(ddp_cpl.len);
- skb_ulp_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
+ skb_rx_pdulen(skb) = ntohs(ddp_cpl.len);
+ skb_rx_ddigest(skb) = ntohl(ddp_cpl.ulp_crc);
status = ntohl(ddp_cpl.ddp_status);
c3cn_rx_debug("rx skb 0x%p, len %u, pdulen %u, ddp status 0x%x.\n",
- skb, skb->len, skb_ulp_pdulen(skb), status);
+ skb, skb->len, skb_rx_pdulen(skb), status);
if (status & (1 << RX_DDP_STATUS_HCRC_SHIFT))
skb_ulp_mode(skb) |= ULP2_FLAG_HCRC_ERROR;
@@ -1126,7 +1148,7 @@ static void process_rx_iscsi_hdr(struct s3_conn *c3cn, struct sk_buff *skb)
} else if (status & (1 << RX_DDP_STATUS_DDP_SHIFT))
skb_ulp_mode(skb) |= ULP2_FLAG_DATA_DDPED;
- c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_ulp_pdulen(skb);
+ c3cn->rcv_nxt = ntohl(ddp_cpl.seq) + skb_rx_pdulen(skb);
__pskb_trim(skb, len);
__skb_queue_tail(&c3cn->receive_queue, skb);
cxgb3i_conn_pdu_ready(c3cn);
@@ -1151,12 +1173,27 @@ static int do_iscsi_hdr(struct t3cdev *t3dev, struct sk_buff *skb, void *ctx)
* Process an acknowledgment of WR completion. Advance snd_una and send the
* next batch of work requests from the write queue.
*/
+static void check_wr_invariants(struct s3_conn *c3cn)
+{
+ int pending = count_pending_wrs(c3cn);
+
+ if (unlikely(c3cn->wr_avail + pending != c3cn->wr_max))
+ cxgb3i_log_error("TID %u: credit imbalance: avail %u, "
+ "pending %u, total should be %u\n",
+ c3cn->tid, c3cn->wr_avail, pending,
+ c3cn->wr_max);
+}
+
static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
{
struct cpl_wr_ack *hdr = cplhdr(skb);
unsigned int credits = ntohs(hdr->credits);
u32 snd_una = ntohl(hdr->snd_una);
+ c3cn_tx_debug("%u WR credits, avail %u, unack %u, TID %u, state %u.\n",
+ credits, c3cn->wr_avail, c3cn->wr_unacked,
+ c3cn->tid, c3cn->state);
+
c3cn->wr_avail += credits;
if (c3cn->wr_unacked > c3cn->wr_max - c3cn->wr_avail)
c3cn->wr_unacked = c3cn->wr_max - c3cn->wr_avail;
@@ -1171,6 +1208,17 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
break;
}
if (unlikely(credits < p->csum)) {
+ struct tx_data_wr *w = cplhdr(p);
+ cxgb3i_log_error("TID %u got %u WR credits need %u, "
+ "len %u, main body %u, frags %u, "
+ "seq # %u, ACK una %u, ACK nxt %u, "
+ "WR_AVAIL %u, WRs pending %u\n",
+ c3cn->tid, credits, p->csum, p->len,
+ p->len - p->data_len,
+ skb_shinfo(p)->nr_frags,
+ ntohl(w->sndseq), snd_una,
+ ntohl(hdr->snd_nxt), c3cn->wr_avail,
+ count_pending_wrs(c3cn) - credits);
p->csum -= credits;
break;
} else {
@@ -1180,15 +1228,24 @@ static void process_wr_ack(struct s3_conn *c3cn, struct sk_buff *skb)
}
}
- if (unlikely(before(snd_una, c3cn->snd_una)))
+ check_wr_invariants(c3cn);
+
+ if (unlikely(before(snd_una, c3cn->snd_una))) {
+ cxgb3i_log_error("TID %u, unexpected sequence # %u in WR_ACK "
+ "snd_una %u\n",
+ c3cn->tid, snd_una, c3cn->snd_una);
goto out_free;
+ }
if (c3cn->snd_una != snd_una) {
c3cn->snd_una = snd_una;
dst_confirm(c3cn->dst_cache);
}
- if (skb_queue_len(&c3cn->write_queue) && c3cn_push_tx_frames(c3cn, 0))
+ if (skb_queue_len(&c3cn->write_queue)) {
+ if (c3cn_push_tx_frames(c3cn, 0))
+ cxgb3i_conn_tx_open(c3cn);
+ } else
cxgb3i_conn_tx_open(c3cn);
out_free:
__kfree_skb(skb);
@@ -1253,11 +1310,7 @@ static void c3cn_release_offload_resources(struct s3_conn *c3cn)
struct t3cdev *cdev = c3cn->cdev;
unsigned int tid = c3cn->tid;
- if (!cdev)
- return;
-
c3cn->qset = 0;
-
c3cn_free_cpl_skbs(c3cn);
if (c3cn->wr_avail != c3cn->wr_max) {
@@ -1265,18 +1318,22 @@ static void c3cn_release_offload_resources(struct s3_conn *c3cn)
reset_wr_list(c3cn);
}
- if (c3cn->l2t) {
- l2t_release(L2DATA(cdev), c3cn->l2t);
- c3cn->l2t = NULL;
- }
-
- if (c3cn->state == C3CN_STATE_CONNECTING) /* we have ATID */
- s3_free_atid(cdev, tid);
- else { /* we have TID */
- cxgb3_remove_tid(cdev, (void *)c3cn, tid);
- c3cn_put(c3cn);
+ if (cdev) {
+ if (c3cn->l2t) {
+ l2t_release(L2DATA(cdev), c3cn->l2t);
+ c3cn->l2t = NULL;
+ }
+ if (c3cn->state == C3CN_STATE_CONNECTING)
+ /* we have ATID */
+ s3_free_atid(cdev, tid);
+ else {
+ /* we have TID */
+ cxgb3_remove_tid(cdev, (void *)c3cn, tid);
+ c3cn_put(c3cn);
+ }
}
+ c3cn->dst_cache = NULL;
c3cn->cdev = NULL;
}
@@ -1373,10 +1430,10 @@ void cxgb3i_c3cn_release(struct s3_conn *c3cn)
{
c3cn_conn_debug("c3cn 0x%p, s %u, f 0x%lx.\n",
c3cn, c3cn->state, c3cn->flags);
- if (likely(c3cn->state != C3CN_STATE_CONNECTING))
- c3cn_active_close(c3cn);
- else
+ if (unlikely(c3cn->state == C3CN_STATE_CONNECTING))
c3cn_set_flag(c3cn, C3CN_ACTIVE_CLOSE_NEEDED);
+ else if (likely(c3cn->state != C3CN_STATE_CLOSED))
+ c3cn_active_close(c3cn);
c3cn_put(c3cn);
}
@@ -1452,7 +1509,7 @@ static void init_offload_conn(struct s3_conn *c3cn,
struct dst_entry *dst)
{
BUG_ON(c3cn->cdev != cdev);
- c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs;
+ c3cn->wr_max = c3cn->wr_avail = T3C_DATA(cdev)->max_wrs - 1;
c3cn->wr_unacked = 0;
c3cn->mss_idx = select_mss(c3cn, dst_mtu(dst));
@@ -1605,7 +1662,6 @@ int cxgb3i_c3cn_connect(struct s3_conn *c3cn, struct sockaddr_in *usin)
c3cn_set_state(c3cn, C3CN_STATE_CLOSED);
ip_rt_put(rt);
c3cn_put_port(c3cn);
- c3cn->daddr.sin_port = 0;
return err;
}
@@ -1671,9 +1727,17 @@ int cxgb3i_c3cn_send_pdus(struct s3_conn *c3cn, struct sk_buff *skb)
goto out_err;
}
- err = -EPIPE;
if (c3cn->err) {
c3cn_tx_debug("c3cn 0x%p, err %d.\n", c3cn, c3cn->err);
+ err = -EPIPE;
+ goto out_err;
+ }
+
+ if (c3cn->write_seq - c3cn->snd_una >= cxgb3_snd_win) {
+ c3cn_tx_debug("c3cn 0x%p, snd %u - %u > %u.\n",
+ c3cn, c3cn->write_seq, c3cn->snd_una,
+ cxgb3_snd_win);
+ err = -EAGAIN;
goto out_err;
}
@@ -1717,10 +1781,25 @@ out_err:
static void sdev_data_cleanup(struct cxgb3i_sdev_data *cdata)
{
struct adap_ports *ports = &cdata->ports;
+ struct s3_conn *c3cn;
int i;
+ for (i = 0; i < cxgb3_max_connect; i++) {
+ if (cdata->sport_conn[i]) {
+ c3cn = cdata->sport_conn[i];
+ cdata->sport_conn[i] = NULL;
+
+ spin_lock_bh(&c3cn->lock);
+ c3cn->cdev = NULL;
+ c3cn_set_flag(c3cn, C3CN_OFFLOAD_DOWN);
+ c3cn_closed(c3cn);
+ spin_unlock_bh(&c3cn->lock);
+ }
+ }
+
for (i = 0; i < ports->nports; i++)
NDEV2CDATA(ports->lldevs[i]) = NULL;
+
cxgb3i_free_big_mem(cdata);
}
@@ -1762,21 +1841,27 @@ void cxgb3i_sdev_add(struct t3cdev *cdev, struct cxgb3_client *client)
struct cxgb3i_sdev_data *cdata;
struct ofld_page_info rx_page_info;
unsigned int wr_len;
- int mapsize = DIV_ROUND_UP(cxgb3_max_connect,
- 8 * sizeof(unsigned long));
+ int mapsize = cxgb3_max_connect * sizeof(struct s3_conn *);
int i;
cdata = cxgb3i_alloc_big_mem(sizeof(*cdata) + mapsize, GFP_KERNEL);
- if (!cdata)
+ if (!cdata) {
+ cxgb3i_log_warn("t3dev 0x%p, offload up, OOM %d.\n",
+ cdev, mapsize);
return;
+ }
if (cdev->ctl(cdev, GET_WR_LEN, &wr_len) < 0 ||
cdev->ctl(cdev, GET_PORTS, &cdata->ports) < 0 ||
- cdev->ctl(cdev, GET_RX_PAGE_INFO, &rx_page_info) < 0)
+ cdev->ctl(cdev, GET_RX_PAGE_INFO, &rx_page_info) < 0) {
+ cxgb3i_log_warn("t3dev 0x%p, offload up, ioctl failed.\n",
+ cdev);
goto free_cdata;
+ }
s3_init_wr_tab(wr_len);
+ spin_lock_init(&cdata->lock);
INIT_LIST_HEAD(&cdata->list);
cdata->cdev = cdev;
cdata->client = client;
@@ -1788,6 +1873,7 @@ void cxgb3i_sdev_add(struct t3cdev *cdev, struct cxgb3_client *client)
list_add_tail(&cdata->list, &cdata_list);
write_unlock(&cdata_rwlock);
+ cxgb3i_log_info("t3dev 0x%p, offload up, added.\n", cdev);
return;
free_cdata:
@@ -1802,6 +1888,8 @@ void cxgb3i_sdev_remove(struct t3cdev *cdev)
{
struct cxgb3i_sdev_data *cdata = CXGB3_SDEV_DATA(cdev);
+ cxgb3i_log_info("t3dev 0x%p, offload down, remove.\n", cdev);
+
write_lock(&cdata_rwlock);
list_del(&cdata->list);
write_unlock(&cdata_rwlock);
diff --git a/drivers/scsi/cxgb3i/cxgb3i_offload.h b/drivers/scsi/cxgb3i/cxgb3i_offload.h
index d23156907ff..ebfca960c0a 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_offload.h
+++ b/drivers/scsi/cxgb3i/cxgb3i_offload.h
@@ -16,7 +16,7 @@
#define _CXGB3I_OFFLOAD_H
#include <linux/skbuff.h>
-#include <net/tcp.h>
+#include <linux/in.h>
#include "common.h"
#include "adapter.h"
@@ -135,6 +135,7 @@ enum c3cn_flags {
C3CN_ABORT_RPL_PENDING, /* expecting an abort reply */
C3CN_TX_DATA_SENT, /* already sent a TX_DATA WR */
C3CN_ACTIVE_CLOSE_NEEDED, /* need to be closed */
+ C3CN_OFFLOAD_DOWN /* offload function off */
};
/**
@@ -147,16 +148,17 @@ enum c3cn_flags {
* @cdev: t3cdev adapter
* @client: CPL client pointer
* @ports: array of adapter ports
- * @sport_map_next: next index into the port map
- * @sport_map: source port map
+ * @sport_next: next port
+ * @sport_conn: source port connection
*/
struct cxgb3i_sdev_data {
struct list_head list;
struct t3cdev *cdev;
struct cxgb3_client *client;
struct adap_ports ports;
- unsigned int sport_map_next;
- unsigned long sport_map[0];
+ spinlock_t lock;
+ unsigned int sport_next;
+ struct s3_conn *sport_conn[0];
};
#define NDEV2CDATA(ndev) (*(struct cxgb3i_sdev_data **)&(ndev)->ec_ptr)
#define CXGB3_SDEV_DATA(cdev) NDEV2CDATA((cdev)->lldev)
@@ -178,25 +180,33 @@ void cxgb3i_c3cn_release(struct s3_conn *);
* @flag: see C3CB_FLAG_* below
* @ulp_mode: ULP mode/submode of sk_buff
* @seq: tcp sequence number
- * @ddigest: pdu data digest
- * @pdulen: recovered pdu length
- * @wr_data: scratch area for tx wr
*/
+struct cxgb3_skb_rx_cb {
+ __u32 ddigest; /* data digest */
+ __u32 pdulen; /* recovered pdu length */
+};
+
+struct cxgb3_skb_tx_cb {
+ struct sk_buff *wr_next; /* next wr */
+};
+
struct cxgb3_skb_cb {
__u8 flags;
__u8 ulp_mode;
__u32 seq;
- __u32 ddigest;
- __u32 pdulen;
- struct sk_buff *wr_data;
+ union {
+ struct cxgb3_skb_rx_cb rx;
+ struct cxgb3_skb_tx_cb tx;
+ };
};
#define CXGB3_SKB_CB(skb) ((struct cxgb3_skb_cb *)&((skb)->cb[0]))
-
+#define skb_flags(skb) (CXGB3_SKB_CB(skb)->flags)
#define skb_ulp_mode(skb) (CXGB3_SKB_CB(skb)->ulp_mode)
-#define skb_ulp_ddigest(skb) (CXGB3_SKB_CB(skb)->ddigest)
-#define skb_ulp_pdulen(skb) (CXGB3_SKB_CB(skb)->pdulen)
-#define skb_wr_data(skb) (CXGB3_SKB_CB(skb)->wr_data)
+#define skb_tcp_seq(skb) (CXGB3_SKB_CB(skb)->seq)
+#define skb_rx_ddigest(skb) (CXGB3_SKB_CB(skb)->rx.ddigest)
+#define skb_rx_pdulen(skb) (CXGB3_SKB_CB(skb)->rx.pdulen)
+#define skb_tx_wr_next(skb) (CXGB3_SKB_CB(skb)->tx.wr_next)
enum c3cb_flags {
C3CB_FLAG_NEED_HDR = 1 << 0, /* packet needs a TX_DATA_WR header */
@@ -217,6 +227,7 @@ struct sge_opaque_hdr {
/* for TX: a skb must have a headroom of at least TX_HEADER_LEN bytes */
#define TX_HEADER_LEN \
(sizeof(struct tx_data_wr) + sizeof(struct sge_opaque_hdr))
+#define SKB_TX_HEADROOM SKB_MAX_HEAD(TX_HEADER_LEN)
/*
* get and set private ip for iscsi traffic
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.c b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
index ce7ce8c6094..7eebc9a7cb3 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.c
+++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.c
@@ -32,6 +32,10 @@
#define cxgb3i_tx_debug(fmt...)
#endif
+/* always allocate rooms for AHS */
+#define SKB_TX_PDU_HEADER_LEN \
+ (sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE)
+static unsigned int skb_extra_headroom;
static struct page *pad_page;
/*
@@ -146,12 +150,13 @@ static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
void cxgb3i_conn_cleanup_task(struct iscsi_task *task)
{
- struct iscsi_tcp_task *tcp_task = task->dd_data;
+ struct cxgb3i_task_data *tdata = task->dd_data +
+ sizeof(struct iscsi_tcp_task);
/* never reached the xmit task callout */
- if (tcp_task->dd_data)
- kfree_skb(tcp_task->dd_data);
- tcp_task->dd_data = NULL;
+ if (tdata->skb)
+ __kfree_skb(tdata->skb);
+ memset(tdata, 0, sizeof(struct cxgb3i_task_data));
/* MNC - Do we need a check in case this is called but
* cxgb3i_conn_alloc_pdu has never been called on the task */
@@ -159,28 +164,102 @@ void cxgb3i_conn_cleanup_task(struct iscsi_task *task)
iscsi_tcp_cleanup_task(task);
}
-/*
- * We do not support ahs yet
- */
+static int sgl_seek_offset(struct scatterlist *sgl, unsigned int sgcnt,
+ unsigned int offset, unsigned int *off,
+ struct scatterlist **sgp)
+{
+ int i;
+ struct scatterlist *sg;
+
+ for_each_sg(sgl, sg, sgcnt, i) {
+ if (offset < sg->length) {
+ *off = offset;
+ *sgp = sg;
+ return 0;
+ }
+ offset -= sg->length;
+ }
+ return -EFAULT;
+}
+
+static int sgl_read_to_frags(struct scatterlist *sg, unsigned int sgoffset,
+ unsigned int dlen, skb_frag_t *frags,
+ int frag_max)
+{
+ unsigned int datalen = dlen;
+ unsigned int sglen = sg->length - sgoffset;
+ struct page *page = sg_page(sg);
+ int i;
+
+ i = 0;
+ do {
+ unsigned int copy;
+
+ if (!sglen) {
+ sg = sg_next(sg);
+ if (!sg) {
+ cxgb3i_log_error("%s, sg NULL, len %u/%u.\n",
+ __func__, datalen, dlen);
+ return -EINVAL;
+ }
+ sgoffset = 0;
+ sglen = sg->length;
+ page = sg_page(sg);
+
+ }
+ copy = min(datalen, sglen);
+ if (i && page == frags[i - 1].page &&
+ sgoffset + sg->offset ==
+ frags[i - 1].page_offset + frags[i - 1].size) {
+ frags[i - 1].size += copy;
+ } else {
+ if (i >= frag_max) {
+ cxgb3i_log_error("%s, too many pages %u, "
+ "dlen %u.\n", __func__,
+ frag_max, dlen);
+ return -EINVAL;
+ }
+
+ frags[i].page = page;
+ frags[i].page_offset = sg->offset + sgoffset;
+ frags[i].size = copy;
+ i++;
+ }
+ datalen -= copy;
+ sgoffset += copy;
+ sglen -= copy;
+ } while (datalen);
+
+ return i;
+}
+
int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
{
+ struct iscsi_conn *conn = task->conn;
struct iscsi_tcp_task *tcp_task = task->dd_data;
- struct sk_buff *skb;
+ struct cxgb3i_task_data *tdata = task->dd_data + sizeof(*tcp_task);
+ struct scsi_cmnd *sc = task->sc;
+ int headroom = SKB_TX_PDU_HEADER_LEN;
+ tcp_task->dd_data = tdata;
task->hdr = NULL;
- /* always allocate rooms for AHS */
- skb = alloc_skb(sizeof(struct iscsi_hdr) + ISCSI_MAX_AHS_SIZE +
- TX_HEADER_LEN, GFP_ATOMIC);
- if (!skb)
+
+ /* write command, need to send data pdus */
+ if (skb_extra_headroom && (opcode == ISCSI_OP_SCSI_DATA_OUT ||
+ (opcode == ISCSI_OP_SCSI_CMD &&
+ (scsi_bidi_cmnd(sc) || sc->sc_data_direction == DMA_TO_DEVICE))))
+ headroom += min(skb_extra_headroom, conn->max_xmit_dlength);
+
+ tdata->skb = alloc_skb(TX_HEADER_LEN + headroom, GFP_ATOMIC);
+ if (!tdata->skb)
return -ENOMEM;
+ skb_reserve(tdata->skb, TX_HEADER_LEN);
cxgb3i_tx_debug("task 0x%p, opcode 0x%x, skb 0x%p.\n",
- task, opcode, skb);
+ task, opcode, tdata->skb);
- tcp_task->dd_data = skb;
- skb_reserve(skb, TX_HEADER_LEN);
- task->hdr = (struct iscsi_hdr *)skb->data;
- task->hdr_max = sizeof(struct iscsi_hdr);
+ task->hdr = (struct iscsi_hdr *)tdata->skb->data;
+ task->hdr_max = SKB_TX_PDU_HEADER_LEN;
/* data_out uses scsi_cmd's itt */
if (opcode != ISCSI_OP_SCSI_DATA_OUT)
@@ -192,13 +271,13 @@ int cxgb3i_conn_alloc_pdu(struct iscsi_task *task, u8 opcode)
int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
unsigned int count)
{
- struct iscsi_tcp_task *tcp_task = task->dd_data;
- struct sk_buff *skb = tcp_task->dd_data;
struct iscsi_conn *conn = task->conn;
- struct page *pg;
+ struct iscsi_tcp_task *tcp_task = task->dd_data;
+ struct cxgb3i_task_data *tdata = tcp_task->dd_data;
+ struct sk_buff *skb = tdata->skb;
unsigned int datalen = count;
int i, padlen = iscsi_padding(count);
- skb_frag_t *frag;
+ struct page *pg;
cxgb3i_tx_debug("task 0x%p,0x%p, offset %u, count %u, skb 0x%p.\n",
task, task->sc, offset, count, skb);
@@ -209,90 +288,94 @@ int cxgb3i_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
return 0;
if (task->sc) {
- struct scatterlist *sg;
- struct scsi_data_buffer *sdb;
- unsigned int sgoffset = offset;
- struct page *sgpg;
- unsigned int sglen;
-
- sdb = scsi_out(task->sc);
- sg = sdb->table.sgl;
-
- for_each_sg(sdb->table.sgl, sg, sdb->table.nents, i) {
- cxgb3i_tx_debug("sg %d, page 0x%p, len %u offset %u\n",
- i, sg_page(sg), sg->length, sg->offset);
-
- if (sgoffset < sg->length)
- break;
- sgoffset -= sg->length;
+ struct scsi_data_buffer *sdb = scsi_out(task->sc);
+ struct scatterlist *sg = NULL;
+ int err;
+
+ tdata->offset = offset;
+ tdata->count = count;
+ err = sgl_seek_offset(sdb->table.sgl, sdb->table.nents,
+ tdata->offset, &tdata->sgoffset, &sg);
+ if (err < 0) {
+ cxgb3i_log_warn("tpdu, sgl %u, bad offset %u/%u.\n",
+ sdb->table.nents, tdata->offset,
+ sdb->length);
+ return err;
}
- sgpg = sg_page(sg);
- sglen = sg->length - sgoffset;
-
- do {
- int j = skb_shinfo(skb)->nr_frags;
- unsigned int copy;
-
- if (!sglen) {
- sg = sg_next(sg);
- sgpg = sg_page(sg);
- sgoffset = 0;
- sglen = sg->length;
- ++i;
+ err = sgl_read_to_frags(sg, tdata->sgoffset, tdata->count,
+ tdata->frags, MAX_PDU_FRAGS);
+ if (err < 0) {
+ cxgb3i_log_warn("tpdu, sgl %u, bad offset %u + %u.\n",
+ sdb->table.nents, tdata->offset,
+ tdata->count);
+ return err;
+ }
+ tdata->nr_frags = err;
+
+ if (tdata->nr_frags > MAX_SKB_FRAGS ||
+ (padlen && tdata->nr_frags == MAX_SKB_FRAGS)) {
+ char *dst = skb->data + task->hdr_len;
+ skb_frag_t *frag = tdata->frags;
+
+ /* data fits in the skb's headroom */
+ for (i = 0; i < tdata->nr_frags; i++, frag++) {
+ char *src = kmap_atomic(frag->page,
+ KM_SOFTIRQ0);
+
+ memcpy(dst, src+frag->page_offset, frag->size);
+ dst += frag->size;
+ kunmap_atomic(src, KM_SOFTIRQ0);
}
- copy = min(sglen, datalen);
- if (j && skb_can_coalesce(skb, j, sgpg,
- sg->offset + sgoffset)) {
- skb_shinfo(skb)->frags[j - 1].size += copy;
- } else {
- get_page(sgpg);
- skb_fill_page_desc(skb, j, sgpg,
- sg->offset + sgoffset, copy);
+ if (padlen) {
+ memset(dst, 0, padlen);
+ padlen = 0;
}
- sgoffset += copy;
- sglen -= copy;
- datalen -= copy;
- } while (datalen);
+ skb_put(skb, count + padlen);
+ } else {
+ /* data fit into frag_list */
+ for (i = 0; i < tdata->nr_frags; i++)
+ get_page(tdata->frags[i].page);
+
+ memcpy(skb_shinfo(skb)->frags, tdata->frags,
+ sizeof(skb_frag_t) * tdata->nr_frags);
+ skb_shinfo(skb)->nr_frags = tdata->nr_frags;
+ skb->len += count;
+ skb->data_len += count;
+ skb->truesize += count;
+ }
+
} else {
pg = virt_to_page(task->data);
- while (datalen) {
- i = skb_shinfo(skb)->nr_frags;
- frag = &skb_shinfo(skb)->frags[i];
-
- get_page(pg);
- frag->page = pg;
- frag->page_offset = 0;
- frag->size = min((unsigned int)PAGE_SIZE, datalen);
-
- skb_shinfo(skb)->nr_frags++;
- datalen -= frag->size;
- pg++;
- }
+ get_page(pg);
+ skb_fill_page_desc(skb, 0, pg, offset_in_page(task->data),
+ count);
+ skb->len += count;
+ skb->data_len += count;
+ skb->truesize += count;
}
if (padlen) {
i = skb_shinfo(skb)->nr_frags;
- frag = &skb_shinfo(skb)->frags[i];
- frag->page = pad_page;
- frag->page_offset = 0;
- frag->size = padlen;
- skb_shinfo(skb)->nr_frags++;
+ get_page(pad_page);
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, pad_page, 0,
+ padlen);
+
+ skb->data_len += padlen;
+ skb->truesize += padlen;
+ skb->len += padlen;
}
- datalen = count + padlen;
- skb->data_len += datalen;
- skb->truesize += datalen;
- skb->len += datalen;
return 0;
}
int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
{
- struct iscsi_tcp_task *tcp_task = task->dd_data;
- struct sk_buff *skb = tcp_task->dd_data;
struct iscsi_tcp_conn *tcp_conn = task->conn->dd_data;
struct cxgb3i_conn *cconn = tcp_conn->dd_data;
+ struct iscsi_tcp_task *tcp_task = task->dd_data;
+ struct cxgb3i_task_data *tdata = tcp_task->dd_data;
+ struct sk_buff *skb = tdata->skb;
unsigned int datalen;
int err;
@@ -300,13 +383,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
return 0;
datalen = skb->data_len;
- tcp_task->dd_data = NULL;
+ tdata->skb = NULL;
err = cxgb3i_c3cn_send_pdus(cconn->cep->c3cn, skb);
- cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
- task, skb, skb->len, skb->data_len, err);
if (err > 0) {
int pdulen = err;
+ cxgb3i_tx_debug("task 0x%p, skb 0x%p, len %u/%u, rv %d.\n",
+ task, skb, skb->len, skb->data_len, err);
+
if (task->conn->hdrdgst_en)
pdulen += ISCSI_DIGEST_SIZE;
if (datalen && task->conn->datadgst_en)
@@ -325,12 +409,14 @@ int cxgb3i_conn_xmit_pdu(struct iscsi_task *task)
return err;
}
/* reset skb to send when we are called again */
- tcp_task->dd_data = skb;
+ tdata->skb = skb;
return -EAGAIN;
}
int cxgb3i_pdu_init(void)
{
+ if (SKB_TX_HEADROOM > (512 * MAX_SKB_FRAGS))
+ skb_extra_headroom = SKB_TX_HEADROOM;
pad_page = alloc_page(GFP_KERNEL);
if (!pad_page)
return -ENOMEM;
@@ -366,7 +452,9 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
skb = skb_peek(&c3cn->receive_queue);
while (!err && skb) {
__skb_unlink(skb, &c3cn->receive_queue);
- read += skb_ulp_pdulen(skb);
+ read += skb_rx_pdulen(skb);
+ cxgb3i_rx_debug("conn 0x%p, cn 0x%p, rx skb 0x%p, pdulen %u.\n",
+ conn, c3cn, skb, skb_rx_pdulen(skb));
err = cxgb3i_conn_read_pdu_skb(conn, skb);
__kfree_skb(skb);
skb = skb_peek(&c3cn->receive_queue);
@@ -377,6 +465,11 @@ void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn)
cxgb3i_c3cn_rx_credits(c3cn, read);
}
conn->rxdata_octets += read;
+
+ if (err) {
+ cxgb3i_log_info("conn 0x%p rx failed err %d.\n", conn, err);
+ iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
+ }
}
void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
@@ -386,7 +479,7 @@ void cxgb3i_conn_tx_open(struct s3_conn *c3cn)
cxgb3i_tx_debug("cn 0x%p.\n", c3cn);
if (conn) {
cxgb3i_tx_debug("cn 0x%p, cid %d.\n", c3cn, conn->id);
- scsi_queue_work(conn->session->host, &conn->xmitwork);
+ iscsi_conn_queue_work(conn);
}
}
diff --git a/drivers/scsi/cxgb3i/cxgb3i_pdu.h b/drivers/scsi/cxgb3i/cxgb3i_pdu.h
index a3f685cc236..0770b23d90d 100644
--- a/drivers/scsi/cxgb3i/cxgb3i_pdu.h
+++ b/drivers/scsi/cxgb3i/cxgb3i_pdu.h
@@ -53,7 +53,7 @@ struct cpl_rx_data_ddp_norss {
#define ULP2_FLAG_DCRC_ERROR 0x20
#define ULP2_FLAG_PAD_ERROR 0x40
-void cxgb3i_conn_closing(struct s3_conn *);
+void cxgb3i_conn_closing(struct s3_conn *c3cn);
void cxgb3i_conn_pdu_ready(struct s3_conn *c3cn);
void cxgb3i_conn_tx_open(struct s3_conn *c3cn);
#endif
diff --git a/drivers/scsi/device_handler/scsi_dh_alua.c b/drivers/scsi/device_handler/scsi_dh_alua.c
index e356b43753f..dba154c8ff6 100644
--- a/drivers/scsi/device_handler/scsi_dh_alua.c
+++ b/drivers/scsi/device_handler/scsi_dh_alua.c
@@ -247,8 +247,8 @@ static unsigned submit_stpg(struct scsi_device *sdev, struct alua_dh_data *h)
/* Prepare the data buffer */
memset(h->buff, 0, stpg_len);
h->buff[4] = TPGS_STATE_OPTIMIZED & 0x0f;
- h->buff[6] = (h->group_id >> 8) & 0x0f;
- h->buff[7] = h->group_id & 0x0f;
+ h->buff[6] = (h->group_id >> 8) & 0xff;
+ h->buff[7] = h->group_id & 0xff;
rq = get_alua_req(sdev, h->buff, stpg_len, WRITE);
if (!rq)
@@ -461,6 +461,15 @@ static int alua_check_sense(struct scsi_device *sdev,
*/
return ADD_TO_MLQUEUE;
}
+ if (sense_hdr->asc == 0x3f && sense_hdr->ascq == 0x0e) {
+ /*
+ * REPORTED_LUNS_DATA_HAS_CHANGED is reported
+ * when switching controllers on targets like
+ * Intel Multi-Flex. We can just retry.
+ */
+ return ADD_TO_MLQUEUE;
+ }
+
break;
}
@@ -691,6 +700,7 @@ static const struct scsi_dh_devlist alua_dev_list[] = {
{"IBM", "2107900" },
{"IBM", "2145" },
{"Pillar", "Axiom" },
+ {"Intel", "Multi-Flex"},
{NULL, NULL}
};
diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c
index 53664765570..43b8c51e98d 100644
--- a/drivers/scsi/device_handler/scsi_dh_rdac.c
+++ b/drivers/scsi/device_handler/scsi_dh_rdac.c
@@ -449,28 +449,40 @@ static int mode_select_handle_sense(struct scsi_device *sdev,
unsigned char *sensebuf)
{
struct scsi_sense_hdr sense_hdr;
- int sense, err = SCSI_DH_IO, ret;
+ int err = SCSI_DH_IO, ret;
ret = scsi_normalize_sense(sensebuf, SCSI_SENSE_BUFFERSIZE, &sense_hdr);
if (!ret)
goto done;
err = SCSI_DH_OK;
- sense = (sense_hdr.sense_key << 16) | (sense_hdr.asc << 8) |
- sense_hdr.ascq;
- /* If it is retryable failure, submit the c9 inquiry again */
- if (sense == 0x59136 || sense == 0x68b02 || sense == 0xb8b02 ||
- sense == 0x62900) {
- /* 0x59136 - Command lock contention
- * 0x[6b]8b02 - Quiesense in progress or achieved
- * 0x62900 - Power On, Reset, or Bus Device Reset
- */
+
+ switch (sense_hdr.sense_key) {
+ case NO_SENSE:
+ case ABORTED_COMMAND:
+ case UNIT_ATTENTION:
err = SCSI_DH_RETRY;
+ break;
+ case NOT_READY:
+ if (sense_hdr.asc == 0x04 && sense_hdr.ascq == 0x01)
+ /* LUN Not Ready and is in the Process of Becoming
+ * Ready
+ */
+ err = SCSI_DH_RETRY;
+ break;
+ case ILLEGAL_REQUEST:
+ if (sense_hdr.asc == 0x91 && sense_hdr.ascq == 0x36)
+ /*
+ * Command Lock contention
+ */
+ err = SCSI_DH_RETRY;
+ break;
+ default:
+ sdev_printk(KERN_INFO, sdev,
+ "MODE_SELECT failed with sense %02x/%02x/%02x.\n",
+ sense_hdr.sense_key, sense_hdr.asc, sense_hdr.ascq);
}
- if (sense)
- sdev_printk(KERN_INFO, sdev,
- "MODE_SELECT failed with sense 0x%x.\n", sense);
done:
return err;
}
@@ -562,6 +574,12 @@ static int rdac_check_sense(struct scsi_device *sdev,
* Just retry and wait.
*/
return ADD_TO_MLQUEUE;
+ if (sense_hdr->asc == 0xA1 && sense_hdr->ascq == 0x02)
+ /* LUN Not Ready - Quiescense in progress
+ * or has been achieved
+ * Just retry.
+ */
+ return ADD_TO_MLQUEUE;
break;
case ILLEGAL_REQUEST:
if (sense_hdr->asc == 0x94 && sense_hdr->ascq == 0x01) {
@@ -579,6 +597,11 @@ static int rdac_check_sense(struct scsi_device *sdev,
* Power On, Reset, or Bus Device Reset, just retry.
*/
return ADD_TO_MLQUEUE;
+ if (sense_hdr->asc == 0x8b && sense_hdr->ascq == 0x02)
+ /*
+ * Quiescence in progress , just retry.
+ */
+ return ADD_TO_MLQUEUE;
break;
}
/* success just means we do not care what scsi-ml does */
diff --git a/drivers/scsi/fcoe/Makefile b/drivers/scsi/fcoe/Makefile
index b78da06d7c0..950f27615c7 100644
--- a/drivers/scsi/fcoe/Makefile
+++ b/drivers/scsi/fcoe/Makefile
@@ -1,8 +1,2 @@
-# $Id: Makefile
-
obj-$(CONFIG_FCOE) += fcoe.o
-
-fcoe-y := \
- libfcoe.o \
- fcoe_sw.o \
- fc_transport_fcoe.o
+obj-$(CONFIG_LIBFCOE) += libfcoe.o
diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c
deleted file mode 100644
index bf7fe6fc082..00000000000
--- a/drivers/scsi/fcoe/fc_transport_fcoe.c
+++ /dev/null
@@ -1,446 +0,0 @@
-/*
- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Maintained at www.Open-FCoE.org
- */
-
-#include <linux/pci.h>
-#include <scsi/libfcoe.h>
-#include <scsi/fc_transport_fcoe.h>
-
-/* internal fcoe transport */
-struct fcoe_transport_internal {
- struct fcoe_transport *t;
- struct net_device *netdev;
- struct list_head list;
-};
-
-/* fcoe transports list and its lock */
-static LIST_HEAD(fcoe_transports);
-static DEFINE_MUTEX(fcoe_transports_lock);
-
-/**
- * fcoe_transport_default - returns ptr to the default transport fcoe_sw
- **/
-struct fcoe_transport *fcoe_transport_default(void)
-{
- return &fcoe_sw_transport;
-}
-
-/**
- * fcoe_transport_to_pcidev - get the pci dev from a netdev
- * @netdev: the netdev that pci dev will be retrived from
- *
- * Returns: NULL or the corrsponding pci_dev
- **/
-struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev)
-{
- if (!netdev->dev.parent)
- return NULL;
- return to_pci_dev(netdev->dev.parent);
-}
-
-/**
- * fcoe_transport_device_lookup - find out netdev is managed by the
- * transport
- * assign a transport to a device
- * @netdev: the netdev the transport to be attached to
- *
- * This will look for existing offload driver, if not found, it falls back to
- * the default sw hba (fcoe_sw) as its fcoe transport.
- *
- * Returns: 0 for success
- **/
-static struct fcoe_transport_internal *fcoe_transport_device_lookup(
- struct fcoe_transport *t, struct net_device *netdev)
-{
- struct fcoe_transport_internal *ti;
-
- /* assign the transpor to this device */
- mutex_lock(&t->devlock);
- list_for_each_entry(ti, &t->devlist, list) {
- if (ti->netdev == netdev) {
- mutex_unlock(&t->devlock);
- return ti;
- }
- }
- mutex_unlock(&t->devlock);
- return NULL;
-}
-/**
- * fcoe_transport_device_add - assign a transport to a device
- * @netdev: the netdev the transport to be attached to
- *
- * This will look for existing offload driver, if not found, it falls back to
- * the default sw hba (fcoe_sw) as its fcoe transport.
- *
- * Returns: 0 for success
- **/
-static int fcoe_transport_device_add(struct fcoe_transport *t,
- struct net_device *netdev)
-{
- struct fcoe_transport_internal *ti;
-
- ti = fcoe_transport_device_lookup(t, netdev);
- if (ti) {
- printk(KERN_DEBUG "fcoe_transport_device_add:"
- "device %s is already added to transport %s\n",
- netdev->name, t->name);
- return -EEXIST;
- }
- /* allocate an internal struct to host the netdev and the list */
- ti = kzalloc(sizeof(*ti), GFP_KERNEL);
- if (!ti)
- return -ENOMEM;
-
- ti->t = t;
- ti->netdev = netdev;
- INIT_LIST_HEAD(&ti->list);
- dev_hold(ti->netdev);
-
- mutex_lock(&t->devlock);
- list_add(&ti->list, &t->devlist);
- mutex_unlock(&t->devlock);
-
- printk(KERN_DEBUG "fcoe_transport_device_add:"
- "device %s added to transport %s\n",
- netdev->name, t->name);
-
- return 0;
-}
-
-/**
- * fcoe_transport_device_remove - remove a device from its transport
- * @netdev: the netdev the transport to be attached to
- *
- * this removes the device from the transport so the given transport will
- * not manage this device any more
- *
- * Returns: 0 for success
- **/
-static int fcoe_transport_device_remove(struct fcoe_transport *t,
- struct net_device *netdev)
-{
- struct fcoe_transport_internal *ti;
-
- ti = fcoe_transport_device_lookup(t, netdev);
- if (!ti) {
- printk(KERN_DEBUG "fcoe_transport_device_remove:"
- "device %s is not managed by transport %s\n",
- netdev->name, t->name);
- return -ENODEV;
- }
- mutex_lock(&t->devlock);
- list_del(&ti->list);
- mutex_unlock(&t->devlock);
- printk(KERN_DEBUG "fcoe_transport_device_remove:"
- "device %s removed from transport %s\n",
- netdev->name, t->name);
- dev_put(ti->netdev);
- kfree(ti);
- return 0;
-}
-
-/**
- * fcoe_transport_device_remove_all - remove all from transport devlist
- *
- * this removes the device from the transport so the given transport will
- * not manage this device any more
- *
- * Returns: 0 for success
- **/
-static void fcoe_transport_device_remove_all(struct fcoe_transport *t)
-{
- struct fcoe_transport_internal *ti, *tmp;
-
- mutex_lock(&t->devlock);
- list_for_each_entry_safe(ti, tmp, &t->devlist, list) {
- list_del(&ti->list);
- kfree(ti);
- }
- mutex_unlock(&t->devlock);
-}
-
-/**
- * fcoe_transport_match - use the bus device match function to match the hw
- * @t: the fcoe transport
- * @netdev:
- *
- * This function is used to check if the givne transport wants to manage the
- * input netdev. if the transports implements the match function, it will be
- * called, o.w. we just compare the pci vendor and device id.
- *
- * Returns: true for match up
- **/
-static bool fcoe_transport_match(struct fcoe_transport *t,
- struct net_device *netdev)
-{
- /* match transport by vendor and device id */
- struct pci_dev *pci;
-
- pci = fcoe_transport_pcidev(netdev);
-
- if (pci) {
- printk(KERN_DEBUG "fcoe_transport_match:"
- "%s:%x:%x -- %s:%x:%x\n",
- t->name, t->vendor, t->device,
- netdev->name, pci->vendor, pci->device);
-
- /* if transport supports match */
- if (t->match)
- return t->match(netdev);
-
- /* else just compare the vendor and device id: pci only */
- return (t->vendor == pci->vendor) && (t->device == pci->device);
- }
- return false;
-}
-
-/**
- * fcoe_transport_lookup - check if the transport is already registered
- * @t: the transport to be looked up
- *
- * This compares the parent device (pci) vendor and device id
- *
- * Returns: NULL if not found
- *
- * TODO - return default sw transport if no other transport is found
- **/
-static struct fcoe_transport *fcoe_transport_lookup(
- struct net_device *netdev)
-{
- struct fcoe_transport *t;
-
- mutex_lock(&fcoe_transports_lock);
- list_for_each_entry(t, &fcoe_transports, list) {
- if (fcoe_transport_match(t, netdev)) {
- mutex_unlock(&fcoe_transports_lock);
- return t;
- }
- }
- mutex_unlock(&fcoe_transports_lock);
-
- printk(KERN_DEBUG "fcoe_transport_lookup:"
- "use default transport for %s\n", netdev->name);
- return fcoe_transport_default();
-}
-
-/**
- * fcoe_transport_register - adds a fcoe transport to the fcoe transports list
- * @t: ptr to the fcoe transport to be added
- *
- * Returns: 0 for success
- **/
-int fcoe_transport_register(struct fcoe_transport *t)
-{
- struct fcoe_transport *tt;
-
- /* TODO - add fcoe_transport specific initialization here */
- mutex_lock(&fcoe_transports_lock);
- list_for_each_entry(tt, &fcoe_transports, list) {
- if (tt == t) {
- mutex_unlock(&fcoe_transports_lock);
- return -EEXIST;
- }
- }
- list_add_tail(&t->list, &fcoe_transports);
- mutex_unlock(&fcoe_transports_lock);
-
- mutex_init(&t->devlock);
- INIT_LIST_HEAD(&t->devlist);
-
- printk(KERN_DEBUG "fcoe_transport_register:%s\n", t->name);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_transport_register);
-
-/**
- * fcoe_transport_unregister - remove the tranport fro the fcoe transports list
- * @t: ptr to the fcoe transport to be removed
- *
- * Returns: 0 for success
- **/
-int fcoe_transport_unregister(struct fcoe_transport *t)
-{
- struct fcoe_transport *tt, *tmp;
-
- mutex_lock(&fcoe_transports_lock);
- list_for_each_entry_safe(tt, tmp, &fcoe_transports, list) {
- if (tt == t) {
- list_del(&t->list);
- mutex_unlock(&fcoe_transports_lock);
- fcoe_transport_device_remove_all(t);
- printk(KERN_DEBUG "fcoe_transport_unregister:%s\n",
- t->name);
- return 0;
- }
- }
- mutex_unlock(&fcoe_transports_lock);
- return -ENODEV;
-}
-EXPORT_SYMBOL_GPL(fcoe_transport_unregister);
-
-/*
- * fcoe_load_transport_driver - load an offload driver by alias name
- * @netdev: the target net device
- *
- * Requests for an offload driver module as the fcoe transport, if fails, it
- * falls back to use the SW HBA (fcoe_sw) as its transport
- *
- * TODO -
- * 1. supports only PCI device
- * 2. needs fix for VLAn and bonding
- * 3. pure hw fcoe hba may not have netdev
- *
- * Returns: 0 for success
- **/
-int fcoe_load_transport_driver(struct net_device *netdev)
-{
- struct pci_dev *pci;
- struct device *dev = netdev->dev.parent;
-
- if (fcoe_transport_lookup(netdev)) {
- /* load default transport */
- printk(KERN_DEBUG "fcoe: already loaded transport for %s\n",
- netdev->name);
- return -EEXIST;
- }
-
- pci = to_pci_dev(dev);
- if (dev->bus != &pci_bus_type) {
- printk(KERN_DEBUG "fcoe: support noly PCI device\n");
- return -ENODEV;
- }
- printk(KERN_DEBUG "fcoe: loading driver fcoe-pci-0x%04x-0x%04x\n",
- pci->vendor, pci->device);
-
- return request_module("fcoe-pci-0x%04x-0x%04x",
- pci->vendor, pci->device);
-
-}
-EXPORT_SYMBOL_GPL(fcoe_load_transport_driver);
-
-/**
- * fcoe_transport_attach - load transport to fcoe
- * @netdev: the netdev the transport to be attached to
- *
- * This will look for existing offload driver, if not found, it falls back to
- * the default sw hba (fcoe_sw) as its fcoe transport.
- *
- * Returns: 0 for success
- **/
-int fcoe_transport_attach(struct net_device *netdev)
-{
- struct fcoe_transport *t;
-
- /* find the corresponding transport */
- t = fcoe_transport_lookup(netdev);
- if (!t) {
- printk(KERN_DEBUG "fcoe_transport_attach"
- ":no transport for %s:use %s\n",
- netdev->name, t->name);
- return -ENODEV;
- }
- /* add to the transport */
- if (fcoe_transport_device_add(t, netdev)) {
- printk(KERN_DEBUG "fcoe_transport_attach"
- ":failed to add %s to tramsport %s\n",
- netdev->name, t->name);
- return -EIO;
- }
- /* transport create function */
- if (t->create)
- t->create(netdev);
-
- printk(KERN_DEBUG "fcoe_transport_attach:transport %s for %s\n",
- t->name, netdev->name);
- return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_transport_attach);
-
-/**
- * fcoe_transport_release - unload transport from fcoe
- * @netdev: the net device on which fcoe is to be released
- *
- * Returns: 0 for success
- **/
-int fcoe_transport_release(struct net_device *netdev)
-{
- struct fcoe_transport *t;
-
- /* find the corresponding transport */
- t = fcoe_transport_lookup(netdev);
- if (!t) {
- printk(KERN_DEBUG "fcoe_transport_release:"
- "no transport for %s:use %s\n",
- netdev->name, t->name);
- return -ENODEV;
- }
- /* remove the device from the transport */
- if (fcoe_transport_device_remove(t, netdev)) {
- printk(KERN_DEBUG "fcoe_transport_release:"
- "failed to add %s to tramsport %s\n",
- netdev->name, t->name);
- return -EIO;
- }
- /* transport destroy function */
- if (t->destroy)
- t->destroy(netdev);
-
- printk(KERN_DEBUG "fcoe_transport_release:"
- "device %s dettached from transport %s\n",
- netdev->name, t->name);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_transport_release);
-
-/**
- * fcoe_transport_init - initializes fcoe transport layer
- *
- * This prepares for the fcoe transport layer
- *
- * Returns: none
- **/
-int __init fcoe_transport_init(void)
-{
- INIT_LIST_HEAD(&fcoe_transports);
- mutex_init(&fcoe_transports_lock);
- return 0;
-}
-
-/**
- * fcoe_transport_exit - cleans up the fcoe transport layer
- * This cleans up the fcoe transport layer. removing any transport on the list,
- * note that the transport destroy func is not called here.
- *
- * Returns: none
- **/
-int __exit fcoe_transport_exit(void)
-{
- struct fcoe_transport *t, *tmp;
-
- mutex_lock(&fcoe_transports_lock);
- list_for_each_entry_safe(t, tmp, &fcoe_transports, list) {
- list_del(&t->list);
- mutex_unlock(&fcoe_transports_lock);
- fcoe_transport_device_remove_all(t);
- mutex_lock(&fcoe_transports_lock);
- }
- mutex_unlock(&fcoe_transports_lock);
- return 0;
-}
diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
new file mode 100644
index 00000000000..94e1e318977
--- /dev/null
+++ b/drivers/scsi/fcoe/fcoe.c
@@ -0,0 +1,1878 @@
+/*
+ * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Maintained at www.Open-FCoE.org
+ */
+
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/spinlock.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/crc32.h>
+#include <linux/cpu.h>
+#include <linux/fs.h>
+#include <linux/sysfs.h>
+#include <linux/ctype.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsicam.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_fc.h>
+#include <net/rtnetlink.h>
+
+#include <scsi/fc/fc_encaps.h>
+#include <scsi/fc/fc_fip.h>
+
+#include <scsi/libfc.h>
+#include <scsi/fc_frame.h>
+#include <scsi/libfcoe.h>
+
+#include "fcoe.h"
+
+static int debug_fcoe;
+
+MODULE_AUTHOR("Open-FCoE.org");
+MODULE_DESCRIPTION("FCoE");
+MODULE_LICENSE("GPL v2");
+
+/* fcoe host list */
+LIST_HEAD(fcoe_hostlist);
+DEFINE_RWLOCK(fcoe_hostlist_lock);
+DEFINE_TIMER(fcoe_timer, NULL, 0, 0);
+DEFINE_PER_CPU(struct fcoe_percpu_s, fcoe_percpu);
+
+/* Function Prototyes */
+static int fcoe_reset(struct Scsi_Host *shost);
+static int fcoe_xmit(struct fc_lport *, struct fc_frame *);
+static int fcoe_rcv(struct sk_buff *, struct net_device *,
+ struct packet_type *, struct net_device *);
+static int fcoe_percpu_receive_thread(void *arg);
+static void fcoe_clean_pending_queue(struct fc_lport *lp);
+static void fcoe_percpu_clean(struct fc_lport *lp);
+static int fcoe_link_ok(struct fc_lport *lp);
+
+static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
+static int fcoe_hostlist_add(const struct fc_lport *);
+static int fcoe_hostlist_remove(const struct fc_lport *);
+
+static int fcoe_check_wait_queue(struct fc_lport *);
+static int fcoe_device_notification(struct notifier_block *, ulong, void *);
+static void fcoe_dev_setup(void);
+static void fcoe_dev_cleanup(void);
+
+/* notification function from net device */
+static struct notifier_block fcoe_notifier = {
+ .notifier_call = fcoe_device_notification,
+};
+
+static struct scsi_transport_template *scsi_transport_fcoe_sw;
+
+struct fc_function_template fcoe_transport_function = {
+ .show_host_node_name = 1,
+ .show_host_port_name = 1,
+ .show_host_supported_classes = 1,
+ .show_host_supported_fc4s = 1,
+ .show_host_active_fc4s = 1,
+ .show_host_maxframe_size = 1,
+
+ .show_host_port_id = 1,
+ .show_host_supported_speeds = 1,
+ .get_host_speed = fc_get_host_speed,
+ .show_host_speed = 1,
+ .show_host_port_type = 1,
+ .get_host_port_state = fc_get_host_port_state,
+ .show_host_port_state = 1,
+ .show_host_symbolic_name = 1,
+
+ .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
+ .show_rport_maxframe_size = 1,
+ .show_rport_supported_classes = 1,
+
+ .show_host_fabric_name = 1,
+ .show_starget_node_name = 1,
+ .show_starget_port_name = 1,
+ .show_starget_port_id = 1,
+ .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
+ .show_rport_dev_loss_tmo = 1,
+ .get_fc_host_stats = fc_get_host_stats,
+ .issue_fc_host_lip = fcoe_reset,
+
+ .terminate_rport_io = fc_rport_terminate_io,
+};
+
+static struct scsi_host_template fcoe_shost_template = {
+ .module = THIS_MODULE,
+ .name = "FCoE Driver",
+ .proc_name = FCOE_NAME,
+ .queuecommand = fc_queuecommand,
+ .eh_abort_handler = fc_eh_abort,
+ .eh_device_reset_handler = fc_eh_device_reset,
+ .eh_host_reset_handler = fc_eh_host_reset,
+ .slave_alloc = fc_slave_alloc,
+ .change_queue_depth = fc_change_queue_depth,
+ .change_queue_type = fc_change_queue_type,
+ .this_id = -1,
+ .cmd_per_lun = 32,
+ .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
+ .use_clustering = ENABLE_CLUSTERING,
+ .sg_tablesize = SG_ALL,
+ .max_sectors = 0xffff,
+};
+
+/**
+ * fcoe_lport_config() - sets up the fc_lport
+ * @lp: ptr to the fc_lport
+ * @shost: ptr to the parent scsi host
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_lport_config(struct fc_lport *lp)
+{
+ lp->link_up = 0;
+ lp->qfull = 0;
+ lp->max_retry_count = 3;
+ lp->e_d_tov = 2 * 1000; /* FC-FS default */
+ lp->r_a_tov = 2 * 2 * 1000;
+ lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
+ FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
+
+ fc_lport_init_stats(lp);
+
+ /* lport fc_lport related configuration */
+ fc_lport_config(lp);
+
+ /* offload related configuration */
+ lp->crc_offload = 0;
+ lp->seq_offload = 0;
+ lp->lro_enabled = 0;
+ lp->lro_xid = 0;
+ lp->lso_max = 0;
+
+ return 0;
+}
+
+/**
+ * fcoe_netdev_config() - Set up netdev for SW FCoE
+ * @lp : ptr to the fc_lport
+ * @netdev : ptr to the associated netdevice struct
+ *
+ * Must be called after fcoe_lport_config() as it will use lport mutex
+ *
+ * Returns : 0 for success
+ */
+static int fcoe_netdev_config(struct fc_lport *lp, struct net_device *netdev)
+{
+ u32 mfs;
+ u64 wwnn, wwpn;
+ struct fcoe_softc *fc;
+ u8 flogi_maddr[ETH_ALEN];
+
+ /* Setup lport private data to point to fcoe softc */
+ fc = lport_priv(lp);
+ fc->ctlr.lp = lp;
+ fc->real_dev = netdev;
+ fc->phys_dev = netdev;
+
+ /* Require support for get_pauseparam ethtool op. */
+ if (netdev->priv_flags & IFF_802_1Q_VLAN)
+ fc->phys_dev = vlan_dev_real_dev(netdev);
+
+ /* Do not support for bonding device */
+ if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
+ (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
+ (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
+ return -EOPNOTSUPP;
+ }
+
+ /*
+ * Determine max frame size based on underlying device and optional
+ * user-configured limit. If the MFS is too low, fcoe_link_ok()
+ * will return 0, so do this first.
+ */
+ mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
+ sizeof(struct fcoe_crc_eof));
+ if (fc_set_mfs(lp, mfs))
+ return -EINVAL;
+
+ /* offload features support */
+ if (fc->real_dev->features & NETIF_F_SG)
+ lp->sg_supp = 1;
+
+#ifdef NETIF_F_FCOE_CRC
+ if (netdev->features & NETIF_F_FCOE_CRC) {
+ lp->crc_offload = 1;
+ printk(KERN_DEBUG "fcoe:%s supports FCCRC offload\n",
+ netdev->name);
+ }
+#endif
+#ifdef NETIF_F_FSO
+ if (netdev->features & NETIF_F_FSO) {
+ lp->seq_offload = 1;
+ lp->lso_max = netdev->gso_max_size;
+ printk(KERN_DEBUG "fcoe:%s supports LSO for max len 0x%x\n",
+ netdev->name, lp->lso_max);
+ }
+#endif
+ if (netdev->fcoe_ddp_xid) {
+ lp->lro_enabled = 1;
+ lp->lro_xid = netdev->fcoe_ddp_xid;
+ printk(KERN_DEBUG "fcoe:%s supports LRO for max xid 0x%x\n",
+ netdev->name, lp->lro_xid);
+ }
+ skb_queue_head_init(&fc->fcoe_pending_queue);
+ fc->fcoe_pending_queue_active = 0;
+
+ /* setup Source Mac Address */
+ memcpy(fc->ctlr.ctl_src_addr, fc->real_dev->dev_addr,
+ fc->real_dev->addr_len);
+
+ wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
+ fc_set_wwnn(lp, wwnn);
+ /* XXX - 3rd arg needs to be vlan id */
+ wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
+ fc_set_wwpn(lp, wwpn);
+
+ /*
+ * Add FCoE MAC address as second unicast MAC address
+ * or enter promiscuous mode if not capable of listening
+ * for multiple unicast MACs.
+ */
+ rtnl_lock();
+ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
+ dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
+ rtnl_unlock();
+
+ /*
+ * setup the receive function from ethernet driver
+ * on the ethertype for the given device
+ */
+ fc->fcoe_packet_type.func = fcoe_rcv;
+ fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
+ fc->fcoe_packet_type.dev = fc->real_dev;
+ dev_add_pack(&fc->fcoe_packet_type);
+
+ return 0;
+}
+
+/**
+ * fcoe_shost_config() - Sets up fc_lport->host
+ * @lp : ptr to the fc_lport
+ * @shost : ptr to the associated scsi host
+ * @dev : device associated to scsi host
+ *
+ * Must be called after fcoe_lport_config() and fcoe_netdev_config()
+ *
+ * Returns : 0 for success
+ */
+static int fcoe_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
+ struct device *dev)
+{
+ int rc = 0;
+
+ /* lport scsi host config */
+ lp->host = shost;
+
+ lp->host->max_lun = FCOE_MAX_LUN;
+ lp->host->max_id = FCOE_MAX_FCP_TARGET;
+ lp->host->max_channel = 0;
+ lp->host->transportt = scsi_transport_fcoe_sw;
+
+ /* add the new host to the SCSI-ml */
+ rc = scsi_add_host(lp->host, dev);
+ if (rc) {
+ FC_DBG("fcoe_shost_config:error on scsi_add_host\n");
+ return rc;
+ }
+ sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
+ FCOE_NAME, FCOE_VERSION,
+ fcoe_netdev(lp)->name);
+
+ return 0;
+}
+
+/**
+ * fcoe_em_config() - allocates em for this lport
+ * @lp: the port that em is to allocated for
+ *
+ * Returns : 0 on success
+ */
+static inline int fcoe_em_config(struct fc_lport *lp)
+{
+ BUG_ON(lp->emp);
+
+ lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
+ FCOE_MIN_XID, FCOE_MAX_XID);
+ if (!lp->emp)
+ return -ENOMEM;
+
+ return 0;
+}
+
+/**
+ * fcoe_if_destroy() - FCoE software HBA tear-down function
+ * @netdev: ptr to the associated net_device
+ *
+ * Returns: 0 if link is OK for use by FCoE.
+ */
+static int fcoe_if_destroy(struct net_device *netdev)
+{
+ struct fc_lport *lp = NULL;
+ struct fcoe_softc *fc;
+ u8 flogi_maddr[ETH_ALEN];
+
+ BUG_ON(!netdev);
+
+ printk(KERN_DEBUG "fcoe_if_destroy:interface on %s\n",
+ netdev->name);
+
+ lp = fcoe_hostlist_lookup(netdev);
+ if (!lp)
+ return -ENODEV;
+
+ fc = lport_priv(lp);
+
+ /* Logout of the fabric */
+ fc_fabric_logoff(lp);
+
+ /* Remove the instance from fcoe's list */
+ fcoe_hostlist_remove(lp);
+
+ /* Don't listen for Ethernet packets anymore */
+ dev_remove_pack(&fc->fcoe_packet_type);
+ dev_remove_pack(&fc->fip_packet_type);
+ fcoe_ctlr_destroy(&fc->ctlr);
+
+ /* Cleanup the fc_lport */
+ fc_lport_destroy(lp);
+ fc_fcp_destroy(lp);
+
+ /* Detach from the scsi-ml */
+ fc_remove_host(lp->host);
+ scsi_remove_host(lp->host);
+
+ /* There are no more rports or I/O, free the EM */
+ if (lp->emp)
+ fc_exch_mgr_free(lp->emp);
+
+ /* Delete secondary MAC addresses */
+ rtnl_lock();
+ memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
+ dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
+ if (!is_zero_ether_addr(fc->ctlr.data_src_addr))
+ dev_unicast_delete(fc->real_dev,
+ fc->ctlr.data_src_addr, ETH_ALEN);
+ dev_mc_delete(fc->real_dev, FIP_ALL_ENODE_MACS, ETH_ALEN, 0);
+ rtnl_unlock();
+
+ /* Free the per-CPU revieve threads */
+ fcoe_percpu_clean(lp);
+
+ /* Free existing skbs */
+ fcoe_clean_pending_queue(lp);
+
+ /* Free memory used by statistical counters */
+ fc_lport_free_stats(lp);
+
+ /* Release the net_device and Scsi_Host */
+ dev_put(fc->real_dev);
+ scsi_host_put(lp->host);
+
+ return 0;
+}
+
+/*
+ * fcoe_ddp_setup - calls LLD's ddp_setup through net_device
+ * @lp: the corresponding fc_lport
+ * @xid: the exchange id for this ddp transfer
+ * @sgl: the scatterlist describing this transfer
+ * @sgc: number of sg items
+ *
+ * Returns : 0 no ddp
+ */
+static int fcoe_ddp_setup(struct fc_lport *lp, u16 xid,
+ struct scatterlist *sgl, unsigned int sgc)
+{
+ struct net_device *n = fcoe_netdev(lp);
+
+ if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_setup)
+ return n->netdev_ops->ndo_fcoe_ddp_setup(n, xid, sgl, sgc);
+
+ return 0;
+}
+
+/*
+ * fcoe_ddp_done - calls LLD's ddp_done through net_device
+ * @lp: the corresponding fc_lport
+ * @xid: the exchange id for this ddp transfer
+ *
+ * Returns : the length of data that have been completed by ddp
+ */
+static int fcoe_ddp_done(struct fc_lport *lp, u16 xid)
+{
+ struct net_device *n = fcoe_netdev(lp);
+
+ if (n->netdev_ops && n->netdev_ops->ndo_fcoe_ddp_done)
+ return n->netdev_ops->ndo_fcoe_ddp_done(n, xid);
+ return 0;
+}
+
+static struct libfc_function_template fcoe_libfc_fcn_templ = {
+ .frame_send = fcoe_xmit,
+ .ddp_setup = fcoe_ddp_setup,
+ .ddp_done = fcoe_ddp_done,
+};
+
+/**
+ * fcoe_fip_recv - handle a received FIP frame.
+ * @skb: the receive skb
+ * @dev: associated &net_device
+ * @ptype: the &packet_type structure which was used to register this handler.
+ * @orig_dev: original receive &net_device, in case @dev is a bond.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_fip_recv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *ptype,
+ struct net_device *orig_dev)
+{
+ struct fcoe_softc *fc;
+
+ fc = container_of(ptype, struct fcoe_softc, fip_packet_type);
+ fcoe_ctlr_recv(&fc->ctlr, skb);
+ return 0;
+}
+
+/**
+ * fcoe_fip_send() - send an Ethernet-encapsulated FIP frame.
+ * @fip: FCoE controller.
+ * @skb: FIP Packet.
+ */
+static void fcoe_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+ skb->dev = fcoe_from_ctlr(fip)->real_dev;
+ dev_queue_xmit(skb);
+}
+
+/**
+ * fcoe_update_src_mac() - Update Ethernet MAC filters.
+ * @fip: FCoE controller.
+ * @old: Unicast MAC address to delete if the MAC is non-zero.
+ * @new: Unicast MAC address to add.
+ *
+ * Remove any previously-set unicast MAC filter.
+ * Add secondary FCoE MAC address filter for our OUI.
+ */
+static void fcoe_update_src_mac(struct fcoe_ctlr *fip, u8 *old, u8 *new)
+{
+ struct fcoe_softc *fc;
+
+ fc = fcoe_from_ctlr(fip);
+ rtnl_lock();
+ if (!is_zero_ether_addr(old))
+ dev_unicast_delete(fc->real_dev, old, ETH_ALEN);
+ dev_unicast_add(fc->real_dev, new, ETH_ALEN);
+ rtnl_unlock();
+}
+
+/**
+ * fcoe_if_create() - this function creates the fcoe interface
+ * @netdev: pointer the associated netdevice
+ *
+ * Creates fc_lport struct and scsi_host for lport, configures lport
+ * and starts fabric login.
+ *
+ * Returns : 0 on success
+ */
+static int fcoe_if_create(struct net_device *netdev)
+{
+ int rc;
+ struct fc_lport *lp = NULL;
+ struct fcoe_softc *fc;
+ struct Scsi_Host *shost;
+
+ BUG_ON(!netdev);
+
+ printk(KERN_DEBUG "fcoe_if_create:interface on %s\n",
+ netdev->name);
+
+ lp = fcoe_hostlist_lookup(netdev);
+ if (lp)
+ return -EEXIST;
+
+ shost = libfc_host_alloc(&fcoe_shost_template,
+ sizeof(struct fcoe_softc));
+ if (!shost) {
+ FC_DBG("Could not allocate host structure\n");
+ return -ENOMEM;
+ }
+ lp = shost_priv(shost);
+ fc = lport_priv(lp);
+
+ /* configure fc_lport, e.g., em */
+ rc = fcoe_lport_config(lp);
+ if (rc) {
+ FC_DBG("Could not configure lport\n");
+ goto out_host_put;
+ }
+
+ /* configure lport network properties */
+ rc = fcoe_netdev_config(lp, netdev);
+ if (rc) {
+ FC_DBG("Could not configure netdev for lport\n");
+ goto out_host_put;
+ }
+
+ /*
+ * Initialize FIP.
+ */
+ fcoe_ctlr_init(&fc->ctlr);
+ fc->ctlr.send = fcoe_fip_send;
+ fc->ctlr.update_mac = fcoe_update_src_mac;
+
+ fc->fip_packet_type.func = fcoe_fip_recv;
+ fc->fip_packet_type.type = htons(ETH_P_FIP);
+ fc->fip_packet_type.dev = fc->real_dev;
+ dev_add_pack(&fc->fip_packet_type);
+
+ /* configure lport scsi host properties */
+ rc = fcoe_shost_config(lp, shost, &netdev->dev);
+ if (rc) {
+ FC_DBG("Could not configure shost for lport\n");
+ goto out_host_put;
+ }
+
+ /* lport exch manager allocation */
+ rc = fcoe_em_config(lp);
+ if (rc) {
+ FC_DBG("Could not configure em for lport\n");
+ goto out_host_put;
+ }
+
+ /* Initialize the library */
+ rc = fcoe_libfc_config(lp, &fcoe_libfc_fcn_templ);
+ if (rc) {
+ FC_DBG("Could not configure libfc for lport!\n");
+ goto out_lp_destroy;
+ }
+
+ /* add to lports list */
+ fcoe_hostlist_add(lp);
+
+ lp->boot_time = jiffies;
+
+ fc_fabric_login(lp);
+
+ if (!fcoe_link_ok(lp))
+ fcoe_ctlr_link_up(&fc->ctlr);
+
+ dev_hold(netdev);
+
+ return rc;
+
+out_lp_destroy:
+ fc_exch_mgr_free(lp->emp); /* Free the EM */
+out_host_put:
+ scsi_host_put(lp->host);
+ return rc;
+}
+
+/**
+ * fcoe_if_init() - attach to scsi transport
+ *
+ * Returns : 0 on success
+ */
+static int __init fcoe_if_init(void)
+{
+ /* attach to scsi transport */
+ scsi_transport_fcoe_sw =
+ fc_attach_transport(&fcoe_transport_function);
+
+ if (!scsi_transport_fcoe_sw) {
+ printk(KERN_ERR "fcoe_init:fc_attach_transport() failed\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+/**
+ * fcoe_if_exit() - detach from scsi transport
+ *
+ * Returns : 0 on success
+ */
+int __exit fcoe_if_exit(void)
+{
+ fc_release_transport(scsi_transport_fcoe_sw);
+ return 0;
+}
+
+/**
+ * fcoe_percpu_thread_create() - Create a receive thread for an online cpu
+ * @cpu: cpu index for the online cpu
+ */
+static void fcoe_percpu_thread_create(unsigned int cpu)
+{
+ struct fcoe_percpu_s *p;
+ struct task_struct *thread;
+
+ p = &per_cpu(fcoe_percpu, cpu);
+
+ thread = kthread_create(fcoe_percpu_receive_thread,
+ (void *)p, "fcoethread/%d", cpu);
+
+ if (likely(!IS_ERR(p->thread))) {
+ kthread_bind(thread, cpu);
+ wake_up_process(thread);
+
+ spin_lock_bh(&p->fcoe_rx_list.lock);
+ p->thread = thread;
+ spin_unlock_bh(&p->fcoe_rx_list.lock);
+ }
+}
+
+/**
+ * fcoe_percpu_thread_destroy() - removes the rx thread for the given cpu
+ * @cpu: cpu index the rx thread is to be removed
+ *
+ * Destroys a per-CPU Rx thread. Any pending skbs are moved to the
+ * current CPU's Rx thread. If the thread being destroyed is bound to
+ * the CPU processing this context the skbs will be freed.
+ */
+static void fcoe_percpu_thread_destroy(unsigned int cpu)
+{
+ struct fcoe_percpu_s *p;
+ struct task_struct *thread;
+ struct page *crc_eof;
+ struct sk_buff *skb;
+#ifdef CONFIG_SMP
+ struct fcoe_percpu_s *p0;
+ unsigned targ_cpu = smp_processor_id();
+#endif /* CONFIG_SMP */
+
+ printk(KERN_DEBUG "fcoe: Destroying receive thread for CPU %d\n", cpu);
+
+ /* Prevent any new skbs from being queued for this CPU. */
+ p = &per_cpu(fcoe_percpu, cpu);
+ spin_lock_bh(&p->fcoe_rx_list.lock);
+ thread = p->thread;
+ p->thread = NULL;
+ crc_eof = p->crc_eof_page;
+ p->crc_eof_page = NULL;
+ p->crc_eof_offset = 0;
+ spin_unlock_bh(&p->fcoe_rx_list.lock);
+
+#ifdef CONFIG_SMP
+ /*
+ * Don't bother moving the skb's if this context is running
+ * on the same CPU that is having its thread destroyed. This
+ * can easily happen when the module is removed.
+ */
+ if (cpu != targ_cpu) {
+ p0 = &per_cpu(fcoe_percpu, targ_cpu);
+ spin_lock_bh(&p0->fcoe_rx_list.lock);
+ if (p0->thread) {
+ FC_DBG("Moving frames from CPU %d to CPU %d\n",
+ cpu, targ_cpu);
+
+ while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
+ __skb_queue_tail(&p0->fcoe_rx_list, skb);
+ spin_unlock_bh(&p0->fcoe_rx_list.lock);
+ } else {
+ /*
+ * The targeted CPU is not initialized and cannot accept
+ * new skbs. Unlock the targeted CPU and drop the skbs
+ * on the CPU that is going offline.
+ */
+ while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
+ kfree_skb(skb);
+ spin_unlock_bh(&p0->fcoe_rx_list.lock);
+ }
+ } else {
+ /*
+ * This scenario occurs when the module is being removed
+ * and all threads are being destroyed. skbs will continue
+ * to be shifted from the CPU thread that is being removed
+ * to the CPU thread associated with the CPU that is processing
+ * the module removal. Once there is only one CPU Rx thread it
+ * will reach this case and we will drop all skbs and later
+ * stop the thread.
+ */
+ spin_lock_bh(&p->fcoe_rx_list.lock);
+ while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
+ kfree_skb(skb);
+ spin_unlock_bh(&p->fcoe_rx_list.lock);
+ }
+#else
+ /*
+ * This a non-SMP scenario where the singluar Rx thread is
+ * being removed. Free all skbs and stop the thread.
+ */
+ spin_lock_bh(&p->fcoe_rx_list.lock);
+ while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
+ kfree_skb(skb);
+ spin_unlock_bh(&p->fcoe_rx_list.lock);
+#endif
+
+ if (thread)
+ kthread_stop(thread);
+
+ if (crc_eof)
+ put_page(crc_eof);
+}
+
+/**
+ * fcoe_cpu_callback() - fcoe cpu hotplug event callback
+ * @nfb: callback data block
+ * @action: event triggering the callback
+ * @hcpu: index for the cpu of this event
+ *
+ * This creates or destroys per cpu data for fcoe
+ *
+ * Returns NOTIFY_OK always.
+ */
+static int fcoe_cpu_callback(struct notifier_block *nfb,
+ unsigned long action, void *hcpu)
+{
+ unsigned cpu = (unsigned long)hcpu;
+
+ switch (action) {
+ case CPU_ONLINE:
+ case CPU_ONLINE_FROZEN:
+ FC_DBG("CPU %x online: Create Rx thread\n", cpu);
+ fcoe_percpu_thread_create(cpu);
+ break;
+ case CPU_DEAD:
+ case CPU_DEAD_FROZEN:
+ FC_DBG("CPU %x offline: Remove Rx thread\n", cpu);
+ fcoe_percpu_thread_destroy(cpu);
+ break;
+ default:
+ break;
+ }
+ return NOTIFY_OK;
+}
+
+static struct notifier_block fcoe_cpu_notifier = {
+ .notifier_call = fcoe_cpu_callback,
+};
+
+/**
+ * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ
+ * @skb: the receive skb
+ * @dev: associated net device
+ * @ptype: context
+ * @odldev: last device
+ *
+ * this function will receive the packet and build fc frame and pass it up
+ *
+ * Returns: 0 for success
+ */
+int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
+ struct packet_type *ptype, struct net_device *olddev)
+{
+ struct fc_lport *lp;
+ struct fcoe_rcv_info *fr;
+ struct fcoe_softc *fc;
+ struct fc_frame_header *fh;
+ struct fcoe_percpu_s *fps;
+ unsigned short oxid;
+ unsigned int cpu = 0;
+
+ fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
+ lp = fc->ctlr.lp;
+ if (unlikely(lp == NULL)) {
+ FC_DBG("cannot find hba structure");
+ goto err2;
+ }
+ if (!lp->link_up)
+ goto err2;
+
+ if (unlikely(debug_fcoe)) {
+ FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p "
+ "end:%p sum:%d dev:%s", skb->len, skb->data_len,
+ skb->head, skb->data, skb_tail_pointer(skb),
+ skb_end_pointer(skb), skb->csum,
+ skb->dev ? skb->dev->name : "<NULL>");
+
+ }
+
+ /* check for FCOE packet type */
+ if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
+ FC_DBG("wrong FC type frame");
+ goto err;
+ }
+
+ /*
+ * Check for minimum frame length, and make sure required FCoE
+ * and FC headers are pulled into the linear data area.
+ */
+ if (unlikely((skb->len < FCOE_MIN_FRAME) ||
+ !pskb_may_pull(skb, FCOE_HEADER_LEN)))
+ goto err;
+
+ skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
+ fh = (struct fc_frame_header *) skb_transport_header(skb);
+
+ oxid = ntohs(fh->fh_ox_id);
+
+ fr = fcoe_dev_from_skb(skb);
+ fr->fr_dev = lp;
+ fr->ptype = ptype;
+
+#ifdef CONFIG_SMP
+ /*
+ * The incoming frame exchange id(oxid) is ANDed with num of online
+ * cpu bits to get cpu and then this cpu is used for selecting
+ * a per cpu kernel thread from fcoe_percpu.
+ */
+ cpu = oxid & (num_online_cpus() - 1);
+#endif
+
+ fps = &per_cpu(fcoe_percpu, cpu);
+ spin_lock_bh(&fps->fcoe_rx_list.lock);
+ if (unlikely(!fps->thread)) {
+ /*
+ * The targeted CPU is not ready, let's target
+ * the first CPU now. For non-SMP systems this
+ * will check the same CPU twice.
+ */
+ FC_DBG("CPU is online, but no receive thread ready "
+ "for incoming skb- using first online CPU.\n");
+
+ spin_unlock_bh(&fps->fcoe_rx_list.lock);
+ cpu = first_cpu(cpu_online_map);
+ fps = &per_cpu(fcoe_percpu, cpu);
+ spin_lock_bh(&fps->fcoe_rx_list.lock);
+ if (!fps->thread) {
+ spin_unlock_bh(&fps->fcoe_rx_list.lock);
+ goto err;
+ }
+ }
+
+ /*
+ * We now have a valid CPU that we're targeting for
+ * this skb. We also have this receive thread locked,
+ * so we're free to queue skbs into it's queue.
+ */
+ __skb_queue_tail(&fps->fcoe_rx_list, skb);
+ if (fps->fcoe_rx_list.qlen == 1)
+ wake_up_process(fps->thread);
+
+ spin_unlock_bh(&fps->fcoe_rx_list.lock);
+
+ return 0;
+err:
+ fc_lport_get_stats(lp)->ErrorFrames++;
+
+err2:
+ kfree_skb(skb);
+ return -1;
+}
+EXPORT_SYMBOL_GPL(fcoe_rcv);
+
+/**
+ * fcoe_start_io() - pass to netdev to start xmit for fcoe
+ * @skb: the skb to be xmitted
+ *
+ * Returns: 0 for success
+ */
+static inline int fcoe_start_io(struct sk_buff *skb)
+{
+ int rc;
+
+ skb_get(skb);
+ rc = dev_queue_xmit(skb);
+ if (rc != 0)
+ return rc;
+ kfree_skb(skb);
+ return 0;
+}
+
+/**
+ * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof
+ * @skb: the skb to be xmitted
+ * @tlen: total len
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
+{
+ struct fcoe_percpu_s *fps;
+ struct page *page;
+
+ fps = &get_cpu_var(fcoe_percpu);
+ page = fps->crc_eof_page;
+ if (!page) {
+ page = alloc_page(GFP_ATOMIC);
+ if (!page) {
+ put_cpu_var(fcoe_percpu);
+ return -ENOMEM;
+ }
+ fps->crc_eof_page = page;
+ fps->crc_eof_offset = 0;
+ }
+
+ get_page(page);
+ skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
+ fps->crc_eof_offset, tlen);
+ skb->len += tlen;
+ skb->data_len += tlen;
+ skb->truesize += tlen;
+ fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
+
+ if (fps->crc_eof_offset >= PAGE_SIZE) {
+ fps->crc_eof_page = NULL;
+ fps->crc_eof_offset = 0;
+ put_page(page);
+ }
+ put_cpu_var(fcoe_percpu);
+ return 0;
+}
+
+/**
+ * fcoe_fc_crc() - calculates FC CRC in this fcoe skb
+ * @fp: the fc_frame containg data to be checksummed
+ *
+ * This uses crc32() to calculate the crc for fc frame
+ * Return : 32 bit crc
+ */
+u32 fcoe_fc_crc(struct fc_frame *fp)
+{
+ struct sk_buff *skb = fp_skb(fp);
+ struct skb_frag_struct *frag;
+ unsigned char *data;
+ unsigned long off, len, clen;
+ u32 crc;
+ unsigned i;
+
+ crc = crc32(~0, skb->data, skb_headlen(skb));
+
+ for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+ frag = &skb_shinfo(skb)->frags[i];
+ off = frag->page_offset;
+ len = frag->size;
+ while (len > 0) {
+ clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
+ data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
+ KM_SKB_DATA_SOFTIRQ);
+ crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
+ kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
+ off += clen;
+ len -= clen;
+ }
+ }
+ return crc;
+}
+
+/**
+ * fcoe_xmit() - FCoE frame transmit function
+ * @lp: the associated local port
+ * @fp: the fc_frame to be transmitted
+ *
+ * Return : 0 for success
+ */
+int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
+{
+ int wlen, rc = 0;
+ u32 crc;
+ struct ethhdr *eh;
+ struct fcoe_crc_eof *cp;
+ struct sk_buff *skb;
+ struct fcoe_dev_stats *stats;
+ struct fc_frame_header *fh;
+ unsigned int hlen; /* header length implies the version */
+ unsigned int tlen; /* trailer length */
+ unsigned int elen; /* eth header, may include vlan */
+ struct fcoe_softc *fc;
+ u8 sof, eof;
+ struct fcoe_hdr *hp;
+
+ WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
+
+ fc = lport_priv(lp);
+ fh = fc_frame_header_get(fp);
+ skb = fp_skb(fp);
+ wlen = skb->len / FCOE_WORD_TO_BYTE;
+
+ if (!lp->link_up) {
+ kfree(skb);
+ return 0;
+ }
+
+ if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ) &&
+ fcoe_ctlr_els_send(&fc->ctlr, skb))
+ return 0;
+
+ sof = fr_sof(fp);
+ eof = fr_eof(fp);
+
+ elen = (fc->real_dev->priv_flags & IFF_802_1Q_VLAN) ?
+ sizeof(struct vlan_ethhdr) : sizeof(struct ethhdr);
+ hlen = sizeof(struct fcoe_hdr);
+ tlen = sizeof(struct fcoe_crc_eof);
+ wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE;
+
+ /* crc offload */
+ if (likely(lp->crc_offload)) {
+ skb->ip_summed = CHECKSUM_PARTIAL;
+ skb->csum_start = skb_headroom(skb);
+ skb->csum_offset = skb->len;
+ crc = 0;
+ } else {
+ skb->ip_summed = CHECKSUM_NONE;
+ crc = fcoe_fc_crc(fp);
+ }
+
+ /* copy fc crc and eof to the skb buff */
+ if (skb_is_nonlinear(skb)) {
+ skb_frag_t *frag;
+ if (fcoe_get_paged_crc_eof(skb, tlen)) {
+ kfree_skb(skb);
+ return -ENOMEM;
+ }
+ frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
+ cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+ + frag->page_offset;
+ } else {
+ cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
+ }
+
+ memset(cp, 0, sizeof(*cp));
+ cp->fcoe_eof = eof;
+ cp->fcoe_crc32 = cpu_to_le32(~crc);
+
+ if (skb_is_nonlinear(skb)) {
+ kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
+ cp = NULL;
+ }
+
+ /* adjust skb netowrk/transport offsets to match mac/fcoe/fc */
+ skb_push(skb, elen + hlen);
+ skb_reset_mac_header(skb);
+ skb_reset_network_header(skb);
+ skb->mac_len = elen;
+ skb->protocol = htons(ETH_P_FCOE);
+ skb->dev = fc->real_dev;
+
+ /* fill up mac and fcoe headers */
+ eh = eth_hdr(skb);
+ eh->h_proto = htons(ETH_P_FCOE);
+ if (fc->ctlr.map_dest)
+ fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
+ else
+ /* insert GW address */
+ memcpy(eh->h_dest, fc->ctlr.dest_addr, ETH_ALEN);
+
+ if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN))
+ memcpy(eh->h_source, fc->ctlr.ctl_src_addr, ETH_ALEN);
+ else
+ memcpy(eh->h_source, fc->ctlr.data_src_addr, ETH_ALEN);
+
+ hp = (struct fcoe_hdr *)(eh + 1);
+ memset(hp, 0, sizeof(*hp));
+ if (FC_FCOE_VER)
+ FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
+ hp->fcoe_sof = sof;
+
+#ifdef NETIF_F_FSO
+ /* fcoe lso, mss is in max_payload which is non-zero for FCP data */
+ if (lp->seq_offload && fr_max_payload(fp)) {
+ skb_shinfo(skb)->gso_type = SKB_GSO_FCOE;
+ skb_shinfo(skb)->gso_size = fr_max_payload(fp);
+ } else {
+ skb_shinfo(skb)->gso_type = 0;
+ skb_shinfo(skb)->gso_size = 0;
+ }
+#endif
+ /* update tx stats: regardless if LLD fails */
+ stats = fc_lport_get_stats(lp);
+ stats->TxFrames++;
+ stats->TxWords += wlen;
+
+ /* send down to lld */
+ fr_dev(fp) = lp;
+ if (fc->fcoe_pending_queue.qlen)
+ rc = fcoe_check_wait_queue(lp);
+
+ if (rc == 0)
+ rc = fcoe_start_io(skb);
+
+ if (rc) {
+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
+ __skb_queue_tail(&fc->fcoe_pending_queue, skb);
+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+ if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
+ lp->qfull = 1;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_xmit);
+
+/**
+ * fcoe_percpu_receive_thread() - recv thread per cpu
+ * @arg: ptr to the fcoe per cpu struct
+ *
+ * Return: 0 for success
+ */
+int fcoe_percpu_receive_thread(void *arg)
+{
+ struct fcoe_percpu_s *p = arg;
+ u32 fr_len;
+ struct fc_lport *lp;
+ struct fcoe_rcv_info *fr;
+ struct fcoe_dev_stats *stats;
+ struct fc_frame_header *fh;
+ struct sk_buff *skb;
+ struct fcoe_crc_eof crc_eof;
+ struct fc_frame *fp;
+ u8 *mac = NULL;
+ struct fcoe_softc *fc;
+ struct fcoe_hdr *hp;
+
+ set_user_nice(current, -20);
+
+ while (!kthread_should_stop()) {
+
+ spin_lock_bh(&p->fcoe_rx_list.lock);
+ while ((skb = __skb_dequeue(&p->fcoe_rx_list)) == NULL) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ spin_unlock_bh(&p->fcoe_rx_list.lock);
+ schedule();
+ set_current_state(TASK_RUNNING);
+ if (kthread_should_stop())
+ return 0;
+ spin_lock_bh(&p->fcoe_rx_list.lock);
+ }
+ spin_unlock_bh(&p->fcoe_rx_list.lock);
+ fr = fcoe_dev_from_skb(skb);
+ lp = fr->fr_dev;
+ if (unlikely(lp == NULL)) {
+ FC_DBG("invalid HBA Structure");
+ kfree_skb(skb);
+ continue;
+ }
+
+ if (unlikely(debug_fcoe)) {
+ FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p "
+ "tail:%p end:%p sum:%d dev:%s",
+ skb->len, skb->data_len,
+ skb->head, skb->data, skb_tail_pointer(skb),
+ skb_end_pointer(skb), skb->csum,
+ skb->dev ? skb->dev->name : "<NULL>");
+ }
+
+ /*
+ * Save source MAC address before discarding header.
+ */
+ fc = lport_priv(lp);
+ if (skb_is_nonlinear(skb))
+ skb_linearize(skb); /* not ideal */
+ mac = eth_hdr(skb)->h_source;
+
+ /*
+ * Frame length checks and setting up the header pointers
+ * was done in fcoe_rcv already.
+ */
+ hp = (struct fcoe_hdr *) skb_network_header(skb);
+ fh = (struct fc_frame_header *) skb_transport_header(skb);
+
+ stats = fc_lport_get_stats(lp);
+ if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
+ if (stats->ErrorFrames < 5)
+ printk(KERN_WARNING "FCoE version "
+ "mismatch: The frame has "
+ "version %x, but the "
+ "initiator supports version "
+ "%x\n", FC_FCOE_DECAPS_VER(hp),
+ FC_FCOE_VER);
+ stats->ErrorFrames++;
+ kfree_skb(skb);
+ continue;
+ }
+
+ skb_pull(skb, sizeof(struct fcoe_hdr));
+ fr_len = skb->len - sizeof(struct fcoe_crc_eof);
+
+ stats->RxFrames++;
+ stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
+
+ fp = (struct fc_frame *)skb;
+ fc_frame_init(fp);
+ fr_dev(fp) = lp;
+ fr_sof(fp) = hp->fcoe_sof;
+
+ /* Copy out the CRC and EOF trailer for access */
+ if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
+ kfree_skb(skb);
+ continue;
+ }
+ fr_eof(fp) = crc_eof.fcoe_eof;
+ fr_crc(fp) = crc_eof.fcoe_crc32;
+ if (pskb_trim(skb, fr_len)) {
+ kfree_skb(skb);
+ continue;
+ }
+
+ /*
+ * We only check CRC if no offload is available and if it is
+ * it's solicited data, in which case, the FCP layer would
+ * check it during the copy.
+ */
+ if (lp->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY)
+ fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
+ else
+ fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
+
+ fh = fc_frame_header_get(fp);
+ if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
+ fh->fh_type == FC_TYPE_FCP) {
+ fc_exch_recv(lp, lp->emp, fp);
+ continue;
+ }
+ if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
+ if (le32_to_cpu(fr_crc(fp)) !=
+ ~crc32(~0, skb->data, fr_len)) {
+ if (debug_fcoe || stats->InvalidCRCCount < 5)
+ printk(KERN_WARNING "fcoe: dropping "
+ "frame with CRC error\n");
+ stats->InvalidCRCCount++;
+ stats->ErrorFrames++;
+ fc_frame_free(fp);
+ continue;
+ }
+ fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
+ }
+ if (unlikely(fc->ctlr.flogi_oxid != FC_XID_UNKNOWN) &&
+ fcoe_ctlr_recv_flogi(&fc->ctlr, fp, mac)) {
+ fc_frame_free(fp);
+ continue;
+ }
+ fc_exch_recv(lp, lp->emp, fp);
+ }
+ return 0;
+}
+
+/**
+ * fcoe_watchdog() - fcoe timer callback
+ * @vp:
+ *
+ * This checks the pending queue length for fcoe and set lport qfull
+ * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the
+ * fcoe_hostlist.
+ *
+ * Returns: 0 for success
+ */
+void fcoe_watchdog(ulong vp)
+{
+ struct fcoe_softc *fc;
+
+ read_lock(&fcoe_hostlist_lock);
+ list_for_each_entry(fc, &fcoe_hostlist, list) {
+ if (fc->ctlr.lp)
+ fcoe_check_wait_queue(fc->ctlr.lp);
+ }
+ read_unlock(&fcoe_hostlist_lock);
+
+ fcoe_timer.expires = jiffies + (1 * HZ);
+ add_timer(&fcoe_timer);
+}
+
+
+/**
+ * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue
+ * @lp: the fc_port for this skb
+ * @skb: the associated skb to be xmitted
+ *
+ * This empties the wait_queue, dequeue the head of the wait_queue queue
+ * and calls fcoe_start_io() for each packet, if all skb have been
+ * transmitted, return qlen or -1 if a error occurs, then restore
+ * wait_queue and try again later.
+ *
+ * The wait_queue is used when the skb transmit fails. skb will go
+ * in the wait_queue which will be emptied by the time function OR
+ * by the next skb transmit.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_check_wait_queue(struct fc_lport *lp)
+{
+ struct fcoe_softc *fc = lport_priv(lp);
+ struct sk_buff *skb;
+ int rc = -1;
+
+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
+ if (fc->fcoe_pending_queue_active)
+ goto out;
+ fc->fcoe_pending_queue_active = 1;
+
+ while (fc->fcoe_pending_queue.qlen) {
+ /* keep qlen > 0 until fcoe_start_io succeeds */
+ fc->fcoe_pending_queue.qlen++;
+ skb = __skb_dequeue(&fc->fcoe_pending_queue);
+
+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+ rc = fcoe_start_io(skb);
+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
+
+ if (rc) {
+ __skb_queue_head(&fc->fcoe_pending_queue, skb);
+ /* undo temporary increment above */
+ fc->fcoe_pending_queue.qlen--;
+ break;
+ }
+ /* undo temporary increment above */
+ fc->fcoe_pending_queue.qlen--;
+ }
+
+ if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
+ lp->qfull = 0;
+ fc->fcoe_pending_queue_active = 0;
+ rc = fc->fcoe_pending_queue.qlen;
+out:
+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+ return rc;
+}
+
+/**
+ * fcoe_dev_setup() - setup link change notification interface
+ */
+static void fcoe_dev_setup()
+{
+ /*
+ * here setup a interface specific wd time to
+ * monitor the link state
+ */
+ register_netdevice_notifier(&fcoe_notifier);
+}
+
+/**
+ * fcoe_dev_setup() - cleanup link change notification interface
+ */
+static void fcoe_dev_cleanup(void)
+{
+ unregister_netdevice_notifier(&fcoe_notifier);
+}
+
+/**
+ * fcoe_device_notification() - netdev event notification callback
+ * @notifier: context of the notification
+ * @event: type of event
+ * @ptr: fixed array for output parsed ifname
+ *
+ * This function is called by the ethernet driver in case of link change event
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_device_notification(struct notifier_block *notifier,
+ ulong event, void *ptr)
+{
+ struct fc_lport *lp = NULL;
+ struct net_device *real_dev = ptr;
+ struct fcoe_softc *fc;
+ struct fcoe_dev_stats *stats;
+ u32 link_possible = 1;
+ u32 mfs;
+ int rc = NOTIFY_OK;
+
+ read_lock(&fcoe_hostlist_lock);
+ list_for_each_entry(fc, &fcoe_hostlist, list) {
+ if (fc->real_dev == real_dev) {
+ lp = fc->ctlr.lp;
+ break;
+ }
+ }
+ read_unlock(&fcoe_hostlist_lock);
+ if (lp == NULL) {
+ rc = NOTIFY_DONE;
+ goto out;
+ }
+
+ switch (event) {
+ case NETDEV_DOWN:
+ case NETDEV_GOING_DOWN:
+ link_possible = 0;
+ break;
+ case NETDEV_UP:
+ case NETDEV_CHANGE:
+ break;
+ case NETDEV_CHANGEMTU:
+ mfs = fc->real_dev->mtu -
+ (sizeof(struct fcoe_hdr) +
+ sizeof(struct fcoe_crc_eof));
+ if (mfs >= FC_MIN_MAX_FRAME)
+ fc_set_mfs(lp, mfs);
+ break;
+ case NETDEV_REGISTER:
+ break;
+ default:
+ FC_DBG("Unknown event %ld from netdev netlink\n", event);
+ }
+ if (link_possible && !fcoe_link_ok(lp))
+ fcoe_ctlr_link_up(&fc->ctlr);
+ else if (fcoe_ctlr_link_down(&fc->ctlr)) {
+ stats = fc_lport_get_stats(lp);
+ stats->LinkFailureCount++;
+ fcoe_clean_pending_queue(lp);
+ }
+out:
+ return rc;
+}
+
+/**
+ * fcoe_if_to_netdev() - parse a name buffer to get netdev
+ * @ifname: fixed array for output parsed ifname
+ * @buffer: incoming buffer to be copied
+ *
+ * Returns: NULL or ptr to netdeive
+ */
+static struct net_device *fcoe_if_to_netdev(const char *buffer)
+{
+ char *cp;
+ char ifname[IFNAMSIZ + 2];
+
+ if (buffer) {
+ strlcpy(ifname, buffer, IFNAMSIZ);
+ cp = ifname + strlen(ifname);
+ while (--cp >= ifname && *cp == '\n')
+ *cp = '\0';
+ return dev_get_by_name(&init_net, ifname);
+ }
+ return NULL;
+}
+
+/**
+ * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev
+ * @netdev: the target netdev
+ *
+ * Returns: ptr to the struct module, NULL for failure
+ */
+static struct module *
+fcoe_netdev_to_module_owner(const struct net_device *netdev)
+{
+ struct device *dev;
+
+ if (!netdev)
+ return NULL;
+
+ dev = netdev->dev.parent;
+ if (!dev)
+ return NULL;
+
+ if (!dev->driver)
+ return NULL;
+
+ return dev->driver->owner;
+}
+
+/**
+ * fcoe_ethdrv_get() - Hold the Ethernet driver
+ * @netdev: the target netdev
+ *
+ * Holds the Ethernet driver module by try_module_get() for
+ * the corresponding netdev.
+ *
+ * Returns: 0 for succsss
+ */
+static int fcoe_ethdrv_get(const struct net_device *netdev)
+{
+ struct module *owner;
+
+ owner = fcoe_netdev_to_module_owner(netdev);
+ if (owner) {
+ printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n",
+ module_name(owner), netdev->name);
+ return try_module_get(owner);
+ }
+ return -ENODEV;
+}
+
+/**
+ * fcoe_ethdrv_put() - Release the Ethernet driver
+ * @netdev: the target netdev
+ *
+ * Releases the Ethernet driver module by module_put for
+ * the corresponding netdev.
+ *
+ * Returns: 0 for succsss
+ */
+static int fcoe_ethdrv_put(const struct net_device *netdev)
+{
+ struct module *owner;
+
+ owner = fcoe_netdev_to_module_owner(netdev);
+ if (owner) {
+ printk(KERN_DEBUG "fcoe:release driver module %s for %s\n",
+ module_name(owner), netdev->name);
+ module_put(owner);
+ return 0;
+ }
+ return -ENODEV;
+}
+
+/**
+ * fcoe_destroy() - handles the destroy from sysfs
+ * @buffer: expcted to be a eth if name
+ * @kp: associated kernel param
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
+{
+ int rc;
+ struct net_device *netdev;
+
+ netdev = fcoe_if_to_netdev(buffer);
+ if (!netdev) {
+ rc = -ENODEV;
+ goto out_nodev;
+ }
+ /* look for existing lport */
+ if (!fcoe_hostlist_lookup(netdev)) {
+ rc = -ENODEV;
+ goto out_putdev;
+ }
+ rc = fcoe_if_destroy(netdev);
+ if (rc) {
+ printk(KERN_ERR "fcoe: fcoe_if_destroy(%s) failed\n",
+ netdev->name);
+ rc = -EIO;
+ goto out_putdev;
+ }
+ fcoe_ethdrv_put(netdev);
+ rc = 0;
+out_putdev:
+ dev_put(netdev);
+out_nodev:
+ return rc;
+}
+
+/**
+ * fcoe_create() - Handles the create call from sysfs
+ * @buffer: expcted to be a eth if name
+ * @kp: associated kernel param
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_create(const char *buffer, struct kernel_param *kp)
+{
+ int rc;
+ struct net_device *netdev;
+
+ netdev = fcoe_if_to_netdev(buffer);
+ if (!netdev) {
+ rc = -ENODEV;
+ goto out_nodev;
+ }
+ /* look for existing lport */
+ if (fcoe_hostlist_lookup(netdev)) {
+ rc = -EEXIST;
+ goto out_putdev;
+ }
+ fcoe_ethdrv_get(netdev);
+
+ rc = fcoe_if_create(netdev);
+ if (rc) {
+ printk(KERN_ERR "fcoe: fcoe_if_create(%s) failed\n",
+ netdev->name);
+ fcoe_ethdrv_put(netdev);
+ rc = -EIO;
+ goto out_putdev;
+ }
+ rc = 0;
+out_putdev:
+ dev_put(netdev);
+out_nodev:
+ return rc;
+}
+
+module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(create, "string");
+MODULE_PARM_DESC(create, "Create fcoe port using net device passed in.");
+module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(destroy, "string");
+MODULE_PARM_DESC(destroy, "Destroy fcoe port");
+
+/**
+ * fcoe_link_ok() - Check if link is ok for the fc_lport
+ * @lp: ptr to the fc_lport
+ *
+ * Any permanently-disqualifying conditions have been previously checked.
+ * This also updates the speed setting, which may change with link for 100/1000.
+ *
+ * This function should probably be checking for PAUSE support at some point
+ * in the future. Currently Per-priority-pause is not determinable using
+ * ethtool, so we shouldn't be restrictive until that problem is resolved.
+ *
+ * Returns: 0 if link is OK for use by FCoE.
+ *
+ */
+int fcoe_link_ok(struct fc_lport *lp)
+{
+ struct fcoe_softc *fc = lport_priv(lp);
+ struct net_device *dev = fc->real_dev;
+ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+ int rc = 0;
+
+ if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) {
+ dev = fc->phys_dev;
+ if (dev->ethtool_ops->get_settings) {
+ dev->ethtool_ops->get_settings(dev, &ecmd);
+ lp->link_supported_speeds &=
+ ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
+ if (ecmd.supported & (SUPPORTED_1000baseT_Half |
+ SUPPORTED_1000baseT_Full))
+ lp->link_supported_speeds |= FC_PORTSPEED_1GBIT;
+ if (ecmd.supported & SUPPORTED_10000baseT_Full)
+ lp->link_supported_speeds |=
+ FC_PORTSPEED_10GBIT;
+ if (ecmd.speed == SPEED_1000)
+ lp->link_speed = FC_PORTSPEED_1GBIT;
+ if (ecmd.speed == SPEED_10000)
+ lp->link_speed = FC_PORTSPEED_10GBIT;
+ }
+ } else
+ rc = -1;
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(fcoe_link_ok);
+
+/**
+ * fcoe_percpu_clean() - Clear the pending skbs for an lport
+ * @lp: the fc_lport
+ */
+void fcoe_percpu_clean(struct fc_lport *lp)
+{
+ struct fcoe_percpu_s *pp;
+ struct fcoe_rcv_info *fr;
+ struct sk_buff_head *list;
+ struct sk_buff *skb, *next;
+ struct sk_buff *head;
+ unsigned int cpu;
+
+ for_each_possible_cpu(cpu) {
+ pp = &per_cpu(fcoe_percpu, cpu);
+ spin_lock_bh(&pp->fcoe_rx_list.lock);
+ list = &pp->fcoe_rx_list;
+ head = list->next;
+ for (skb = head; skb != (struct sk_buff *)list;
+ skb = next) {
+ next = skb->next;
+ fr = fcoe_dev_from_skb(skb);
+ if (fr->fr_dev == lp) {
+ __skb_unlink(skb, list);
+ kfree_skb(skb);
+ }
+ }
+ spin_unlock_bh(&pp->fcoe_rx_list.lock);
+ }
+}
+EXPORT_SYMBOL_GPL(fcoe_percpu_clean);
+
+/**
+ * fcoe_clean_pending_queue() - Dequeue a skb and free it
+ * @lp: the corresponding fc_lport
+ *
+ * Returns: none
+ */
+void fcoe_clean_pending_queue(struct fc_lport *lp)
+{
+ struct fcoe_softc *fc = lport_priv(lp);
+ struct sk_buff *skb;
+
+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
+ while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+ kfree_skb(skb);
+ spin_lock_bh(&fc->fcoe_pending_queue.lock);
+ }
+ spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+}
+EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
+
+/**
+ * fcoe_reset() - Resets the fcoe
+ * @shost: shost the reset is from
+ *
+ * Returns: always 0
+ */
+int fcoe_reset(struct Scsi_Host *shost)
+{
+ struct fc_lport *lport = shost_priv(shost);
+ fc_lport_reset(lport);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_reset);
+
+/**
+ * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device
+ * @device: this is currently ptr to net_device
+ *
+ * Returns: NULL or the located fcoe_softc
+ */
+static struct fcoe_softc *
+fcoe_hostlist_lookup_softc(const struct net_device *dev)
+{
+ struct fcoe_softc *fc;
+
+ read_lock(&fcoe_hostlist_lock);
+ list_for_each_entry(fc, &fcoe_hostlist, list) {
+ if (fc->real_dev == dev) {
+ read_unlock(&fcoe_hostlist_lock);
+ return fc;
+ }
+ }
+ read_unlock(&fcoe_hostlist_lock);
+ return NULL;
+}
+
+/**
+ * fcoe_hostlist_lookup() - Find the corresponding lport by netdev
+ * @netdev: ptr to net_device
+ *
+ * Returns: 0 for success
+ */
+struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
+{
+ struct fcoe_softc *fc;
+
+ fc = fcoe_hostlist_lookup_softc(netdev);
+
+ return (fc) ? fc->ctlr.lp : NULL;
+}
+EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup);
+
+/**
+ * fcoe_hostlist_add() - Add a lport to lports list
+ * @lp: ptr to the fc_lport to badded
+ *
+ * Returns: 0 for success
+ */
+int fcoe_hostlist_add(const struct fc_lport *lp)
+{
+ struct fcoe_softc *fc;
+
+ fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
+ if (!fc) {
+ fc = lport_priv(lp);
+ write_lock_bh(&fcoe_hostlist_lock);
+ list_add_tail(&fc->list, &fcoe_hostlist);
+ write_unlock_bh(&fcoe_hostlist_lock);
+ }
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_hostlist_add);
+
+/**
+ * fcoe_hostlist_remove() - remove a lport from lports list
+ * @lp: ptr to the fc_lport to badded
+ *
+ * Returns: 0 for success
+ */
+int fcoe_hostlist_remove(const struct fc_lport *lp)
+{
+ struct fcoe_softc *fc;
+
+ fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
+ BUG_ON(!fc);
+ write_lock_bh(&fcoe_hostlist_lock);
+ list_del(&fc->list);
+ write_unlock_bh(&fcoe_hostlist_lock);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_hostlist_remove);
+
+/**
+ * fcoe_init() - fcoe module loading initialization
+ *
+ * Returns 0 on success, negative on failure
+ */
+static int __init fcoe_init(void)
+{
+ unsigned int cpu;
+ int rc = 0;
+ struct fcoe_percpu_s *p;
+
+ INIT_LIST_HEAD(&fcoe_hostlist);
+ rwlock_init(&fcoe_hostlist_lock);
+
+ for_each_possible_cpu(cpu) {
+ p = &per_cpu(fcoe_percpu, cpu);
+ skb_queue_head_init(&p->fcoe_rx_list);
+ }
+
+ for_each_online_cpu(cpu)
+ fcoe_percpu_thread_create(cpu);
+
+ /* Initialize per CPU interrupt thread */
+ rc = register_hotcpu_notifier(&fcoe_cpu_notifier);
+ if (rc)
+ goto out_free;
+
+ /* Setup link change notification */
+ fcoe_dev_setup();
+
+ setup_timer(&fcoe_timer, fcoe_watchdog, 0);
+
+ mod_timer(&fcoe_timer, jiffies + (10 * HZ));
+
+ fcoe_if_init();
+
+ return 0;
+
+out_free:
+ for_each_online_cpu(cpu) {
+ fcoe_percpu_thread_destroy(cpu);
+ }
+
+ return rc;
+}
+module_init(fcoe_init);
+
+/**
+ * fcoe_exit() - fcoe module unloading cleanup
+ *
+ * Returns 0 on success, negative on failure
+ */
+static void __exit fcoe_exit(void)
+{
+ unsigned int cpu;
+ struct fcoe_softc *fc, *tmp;
+
+ fcoe_dev_cleanup();
+
+ /* Stop the timer */
+ del_timer_sync(&fcoe_timer);
+
+ /* releases the associated fcoe hosts */
+ list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
+ fcoe_if_destroy(fc->real_dev);
+
+ unregister_hotcpu_notifier(&fcoe_cpu_notifier);
+
+ for_each_online_cpu(cpu) {
+ fcoe_percpu_thread_destroy(cpu);
+ }
+
+ /* detach from scsi transport */
+ fcoe_if_exit();
+}
+module_exit(fcoe_exit);
diff --git a/drivers/scsi/fcoe/fcoe.h b/drivers/scsi/fcoe/fcoe.h
new file mode 100644
index 00000000000..917aae88689
--- /dev/null
+++ b/drivers/scsi/fcoe/fcoe.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright(c) 2009 Intel Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Maintained at www.Open-FCoE.org
+ */
+
+#ifndef _FCOE_H_
+#define _FCOE_H_
+
+#include <linux/skbuff.h>
+#include <linux/kthread.h>
+
+#define FCOE_MAX_QUEUE_DEPTH 256
+#define FCOE_LOW_QUEUE_DEPTH 32
+
+#define FCOE_WORD_TO_BYTE 4
+
+#define FCOE_VERSION "0.1"
+#define FCOE_NAME "fcoe"
+#define FCOE_VENDOR "Open-FCoE.org"
+
+#define FCOE_MAX_LUN 255
+#define FCOE_MAX_FCP_TARGET 256
+
+#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
+
+#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
+#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
+
+/*
+ * this percpu struct for fcoe
+ */
+struct fcoe_percpu_s {
+ struct task_struct *thread;
+ struct sk_buff_head fcoe_rx_list;
+ struct page *crc_eof_page;
+ int crc_eof_offset;
+};
+
+/*
+ * the fcoe sw transport private data
+ */
+struct fcoe_softc {
+ struct list_head list;
+ struct net_device *real_dev;
+ struct net_device *phys_dev; /* device with ethtool_ops */
+ struct packet_type fcoe_packet_type;
+ struct packet_type fip_packet_type;
+ struct sk_buff_head fcoe_pending_queue;
+ u8 fcoe_pending_queue_active;
+ struct fcoe_ctlr ctlr;
+};
+
+#define fcoe_from_ctlr(fc) container_of(fc, struct fcoe_softc, ctlr)
+
+static inline struct net_device *fcoe_netdev(
+ const struct fc_lport *lp)
+{
+ return ((struct fcoe_softc *)lport_priv(lp))->real_dev;
+}
+
+#endif /* _FCOE_H_ */
diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c
deleted file mode 100644
index dc4cd5e2576..00000000000
--- a/drivers/scsi/fcoe/fcoe_sw.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Maintained at www.Open-FCoE.org
- */
-
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/if_vlan.h>
-#include <net/rtnetlink.h>
-
-#include <scsi/fc/fc_els.h>
-#include <scsi/fc/fc_encaps.h>
-#include <scsi/fc/fc_fs.h>
-#include <scsi/scsi_transport.h>
-#include <scsi/scsi_transport_fc.h>
-
-#include <scsi/libfc.h>
-#include <scsi/libfcoe.h>
-#include <scsi/fc_transport_fcoe.h>
-
-#define FCOE_SW_VERSION "0.1"
-#define FCOE_SW_NAME "fcoesw"
-#define FCOE_SW_VENDOR "Open-FCoE.org"
-
-#define FCOE_MAX_LUN 255
-#define FCOE_MAX_FCP_TARGET 256
-
-#define FCOE_MAX_OUTSTANDING_COMMANDS 1024
-
-#define FCOE_MIN_XID 0x0001 /* the min xid supported by fcoe_sw */
-#define FCOE_MAX_XID 0x07ef /* the max xid supported by fcoe_sw */
-
-static struct scsi_transport_template *scsi_transport_fcoe_sw;
-
-struct fc_function_template fcoe_sw_transport_function = {
- .show_host_node_name = 1,
- .show_host_port_name = 1,
- .show_host_supported_classes = 1,
- .show_host_supported_fc4s = 1,
- .show_host_active_fc4s = 1,
- .show_host_maxframe_size = 1,
-
- .show_host_port_id = 1,
- .show_host_supported_speeds = 1,
- .get_host_speed = fc_get_host_speed,
- .show_host_speed = 1,
- .show_host_port_type = 1,
- .get_host_port_state = fc_get_host_port_state,
- .show_host_port_state = 1,
- .show_host_symbolic_name = 1,
-
- .dd_fcrport_size = sizeof(struct fc_rport_libfc_priv),
- .show_rport_maxframe_size = 1,
- .show_rport_supported_classes = 1,
-
- .show_host_fabric_name = 1,
- .show_starget_node_name = 1,
- .show_starget_port_name = 1,
- .show_starget_port_id = 1,
- .set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
- .show_rport_dev_loss_tmo = 1,
- .get_fc_host_stats = fc_get_host_stats,
- .issue_fc_host_lip = fcoe_reset,
-
- .terminate_rport_io = fc_rport_terminate_io,
-};
-
-static struct scsi_host_template fcoe_sw_shost_template = {
- .module = THIS_MODULE,
- .name = "FCoE Driver",
- .proc_name = FCOE_SW_NAME,
- .queuecommand = fc_queuecommand,
- .eh_abort_handler = fc_eh_abort,
- .eh_device_reset_handler = fc_eh_device_reset,
- .eh_host_reset_handler = fc_eh_host_reset,
- .slave_alloc = fc_slave_alloc,
- .change_queue_depth = fc_change_queue_depth,
- .change_queue_type = fc_change_queue_type,
- .this_id = -1,
- .cmd_per_lun = 32,
- .can_queue = FCOE_MAX_OUTSTANDING_COMMANDS,
- .use_clustering = ENABLE_CLUSTERING,
- .sg_tablesize = SG_ALL,
- .max_sectors = 0xffff,
-};
-
-/*
- * fcoe_sw_lport_config - sets up the fc_lport
- * @lp: ptr to the fc_lport
- * @shost: ptr to the parent scsi host
- *
- * Returns: 0 for success
- *
- */
-static int fcoe_sw_lport_config(struct fc_lport *lp)
-{
- int i = 0;
-
- lp->link_status = 0;
- lp->max_retry_count = 3;
- lp->e_d_tov = 2 * 1000; /* FC-FS default */
- lp->r_a_tov = 2 * 2 * 1000;
- lp->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
- FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
-
- /*
- * allocate per cpu stats block
- */
- for_each_online_cpu(i)
- lp->dev_stats[i] = kzalloc(sizeof(struct fcoe_dev_stats),
- GFP_KERNEL);
-
- /* lport fc_lport related configuration */
- fc_lport_config(lp);
-
- return 0;
-}
-
-/*
- * fcoe_sw_netdev_config - sets up fcoe_softc for lport and network
- * related properties
- * @lp : ptr to the fc_lport
- * @netdev : ptr to the associated netdevice struct
- *
- * Must be called after fcoe_sw_lport_config() as it will use lport mutex
- *
- * Returns : 0 for success
- *
- */
-static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev)
-{
- u32 mfs;
- u64 wwnn, wwpn;
- struct fcoe_softc *fc;
- u8 flogi_maddr[ETH_ALEN];
-
- /* Setup lport private data to point to fcoe softc */
- fc = lport_priv(lp);
- fc->lp = lp;
- fc->real_dev = netdev;
- fc->phys_dev = netdev;
-
- /* Require support for get_pauseparam ethtool op. */
- if (netdev->priv_flags & IFF_802_1Q_VLAN)
- fc->phys_dev = vlan_dev_real_dev(netdev);
-
- /* Do not support for bonding device */
- if ((fc->real_dev->priv_flags & IFF_MASTER_ALB) ||
- (fc->real_dev->priv_flags & IFF_SLAVE_INACTIVE) ||
- (fc->real_dev->priv_flags & IFF_MASTER_8023AD)) {
- return -EOPNOTSUPP;
- }
-
- /*
- * Determine max frame size based on underlying device and optional
- * user-configured limit. If the MFS is too low, fcoe_link_ok()
- * will return 0, so do this first.
- */
- mfs = fc->real_dev->mtu - (sizeof(struct fcoe_hdr) +
- sizeof(struct fcoe_crc_eof));
- if (fc_set_mfs(lp, mfs))
- return -EINVAL;
-
- lp->link_status = ~FC_PAUSE & ~FC_LINK_UP;
- if (!fcoe_link_ok(lp))
- lp->link_status |= FC_LINK_UP;
-
- /* offload features support */
- if (fc->real_dev->features & NETIF_F_SG)
- lp->sg_supp = 1;
-
-
- skb_queue_head_init(&fc->fcoe_pending_queue);
-
- /* setup Source Mac Address */
- memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr,
- fc->real_dev->addr_len);
-
- wwnn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 1, 0);
- fc_set_wwnn(lp, wwnn);
- /* XXX - 3rd arg needs to be vlan id */
- wwpn = fcoe_wwn_from_mac(fc->real_dev->dev_addr, 2, 0);
- fc_set_wwpn(lp, wwpn);
-
- /*
- * Add FCoE MAC address as second unicast MAC address
- * or enter promiscuous mode if not capable of listening
- * for multiple unicast MACs.
- */
- rtnl_lock();
- memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
- dev_unicast_add(fc->real_dev, flogi_maddr, ETH_ALEN);
- rtnl_unlock();
-
- /*
- * setup the receive function from ethernet driver
- * on the ethertype for the given device
- */
- fc->fcoe_packet_type.func = fcoe_rcv;
- fc->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
- fc->fcoe_packet_type.dev = fc->real_dev;
- dev_add_pack(&fc->fcoe_packet_type);
-
- return 0;
-}
-
-/*
- * fcoe_sw_shost_config - sets up fc_lport->host
- * @lp : ptr to the fc_lport
- * @shost : ptr to the associated scsi host
- * @dev : device associated to scsi host
- *
- * Must be called after fcoe_sw_lport_config) and fcoe_sw_netdev_config()
- *
- * Returns : 0 for success
- *
- */
-static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost,
- struct device *dev)
-{
- int rc = 0;
-
- /* lport scsi host config */
- lp->host = shost;
-
- lp->host->max_lun = FCOE_MAX_LUN;
- lp->host->max_id = FCOE_MAX_FCP_TARGET;
- lp->host->max_channel = 0;
- lp->host->transportt = scsi_transport_fcoe_sw;
-
- /* add the new host to the SCSI-ml */
- rc = scsi_add_host(lp->host, dev);
- if (rc) {
- FC_DBG("fcoe_sw_shost_config:error on scsi_add_host\n");
- return rc;
- }
- sprintf(fc_host_symbolic_name(lp->host), "%s v%s over %s",
- FCOE_SW_NAME, FCOE_SW_VERSION,
- fcoe_netdev(lp)->name);
-
- return 0;
-}
-
-/*
- * fcoe_sw_em_config - allocates em for this lport
- * @lp: the port that em is to allocated for
- *
- * Returns : 0 on success
- */
-static inline int fcoe_sw_em_config(struct fc_lport *lp)
-{
- BUG_ON(lp->emp);
-
- lp->emp = fc_exch_mgr_alloc(lp, FC_CLASS_3,
- FCOE_MIN_XID, FCOE_MAX_XID);
- if (!lp->emp)
- return -ENOMEM;
-
- return 0;
-}
-
-/*
- * fcoe_sw_destroy - FCoE software HBA tear-down function
- * @netdev: ptr to the associated net_device
- *
- * Returns: 0 if link is OK for use by FCoE.
- */
-static int fcoe_sw_destroy(struct net_device *netdev)
-{
- int cpu;
- struct fc_lport *lp = NULL;
- struct fcoe_softc *fc;
- u8 flogi_maddr[ETH_ALEN];
-
- BUG_ON(!netdev);
-
- printk(KERN_DEBUG "fcoe_sw_destroy:interface on %s\n",
- netdev->name);
-
- lp = fcoe_hostlist_lookup(netdev);
- if (!lp)
- return -ENODEV;
-
- fc = fcoe_softc(lp);
-
- /* Logout of the fabric */
- fc_fabric_logoff(lp);
-
- /* Remove the instance from fcoe's list */
- fcoe_hostlist_remove(lp);
-
- /* Don't listen for Ethernet packets anymore */
- dev_remove_pack(&fc->fcoe_packet_type);
-
- /* Cleanup the fc_lport */
- fc_lport_destroy(lp);
- fc_fcp_destroy(lp);
-
- /* Detach from the scsi-ml */
- fc_remove_host(lp->host);
- scsi_remove_host(lp->host);
-
- /* There are no more rports or I/O, free the EM */
- if (lp->emp)
- fc_exch_mgr_free(lp->emp);
-
- /* Delete secondary MAC addresses */
- rtnl_lock();
- memcpy(flogi_maddr, (u8[6]) FC_FCOE_FLOGI_MAC, ETH_ALEN);
- dev_unicast_delete(fc->real_dev, flogi_maddr, ETH_ALEN);
- if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
- dev_unicast_delete(fc->real_dev, fc->data_src_addr, ETH_ALEN);
- rtnl_unlock();
-
- /* Free the per-CPU revieve threads */
- fcoe_percpu_clean(lp);
-
- /* Free existing skbs */
- fcoe_clean_pending_queue(lp);
-
- /* Free memory used by statistical counters */
- for_each_online_cpu(cpu)
- kfree(lp->dev_stats[cpu]);
-
- /* Release the net_device and Scsi_Host */
- dev_put(fc->real_dev);
- scsi_host_put(lp->host);
-
- return 0;
-}
-
-static struct libfc_function_template fcoe_sw_libfc_fcn_templ = {
- .frame_send = fcoe_xmit,
-};
-
-/*
- * fcoe_sw_create - this function creates the fcoe interface
- * @netdev: pointer the associated netdevice
- *
- * Creates fc_lport struct and scsi_host for lport, configures lport
- * and starts fabric login.
- *
- * Returns : 0 on success
- */
-static int fcoe_sw_create(struct net_device *netdev)
-{
- int rc;
- struct fc_lport *lp = NULL;
- struct fcoe_softc *fc;
- struct Scsi_Host *shost;
-
- BUG_ON(!netdev);
-
- printk(KERN_DEBUG "fcoe_sw_create:interface on %s\n",
- netdev->name);
-
- lp = fcoe_hostlist_lookup(netdev);
- if (lp)
- return -EEXIST;
-
- shost = fcoe_host_alloc(&fcoe_sw_shost_template,
- sizeof(struct fcoe_softc));
- if (!shost) {
- FC_DBG("Could not allocate host structure\n");
- return -ENOMEM;
- }
- lp = shost_priv(shost);
- fc = lport_priv(lp);
-
- /* configure fc_lport, e.g., em */
- rc = fcoe_sw_lport_config(lp);
- if (rc) {
- FC_DBG("Could not configure lport\n");
- goto out_host_put;
- }
-
- /* configure lport network properties */
- rc = fcoe_sw_netdev_config(lp, netdev);
- if (rc) {
- FC_DBG("Could not configure netdev for lport\n");
- goto out_host_put;
- }
-
- /* configure lport scsi host properties */
- rc = fcoe_sw_shost_config(lp, shost, &netdev->dev);
- if (rc) {
- FC_DBG("Could not configure shost for lport\n");
- goto out_host_put;
- }
-
- /* lport exch manager allocation */
- rc = fcoe_sw_em_config(lp);
- if (rc) {
- FC_DBG("Could not configure em for lport\n");
- goto out_host_put;
- }
-
- /* Initialize the library */
- rc = fcoe_libfc_config(lp, &fcoe_sw_libfc_fcn_templ);
- if (rc) {
- FC_DBG("Could not configure libfc for lport!\n");
- goto out_lp_destroy;
- }
-
- /* add to lports list */
- fcoe_hostlist_add(lp);
-
- lp->boot_time = jiffies;
-
- fc_fabric_login(lp);
-
- dev_hold(netdev);
-
- return rc;
-
-out_lp_destroy:
- fc_exch_mgr_free(lp->emp); /* Free the EM */
-out_host_put:
- scsi_host_put(lp->host);
- return rc;
-}
-
-/*
- * fcoe_sw_match - the fcoe sw transport match function
- *
- * Returns : false always
- */
-static bool fcoe_sw_match(struct net_device *netdev)
-{
- /* FIXME - for sw transport, always return false */
- return false;
-}
-
-/* the sw hba fcoe transport */
-struct fcoe_transport fcoe_sw_transport = {
- .name = "fcoesw",
- .create = fcoe_sw_create,
- .destroy = fcoe_sw_destroy,
- .match = fcoe_sw_match,
- .vendor = 0x0,
- .device = 0xffff,
-};
-
-/*
- * fcoe_sw_init - registers fcoe_sw_transport
- *
- * Returns : 0 on success
- */
-int __init fcoe_sw_init(void)
-{
- /* attach to scsi transport */
- scsi_transport_fcoe_sw =
- fc_attach_transport(&fcoe_sw_transport_function);
- if (!scsi_transport_fcoe_sw) {
- printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n");
- return -ENODEV;
- }
- /* register sw transport */
- fcoe_transport_register(&fcoe_sw_transport);
- return 0;
-}
-
-/*
- * fcoe_sw_exit - unregisters fcoe_sw_transport
- *
- * Returns : 0 on success
- */
-int __exit fcoe_sw_exit(void)
-{
- /* dettach the transport */
- fc_release_transport(scsi_transport_fcoe_sw);
- fcoe_transport_unregister(&fcoe_sw_transport);
- return 0;
-}
diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c
index e419f486cdb..f410f4abb54 100644
--- a/drivers/scsi/fcoe/libfcoe.c
+++ b/drivers/scsi/fcoe/libfcoe.c
@@ -1,5 +1,6 @@
/*
- * Copyright(c) 2007 - 2008 Intel Corporation. All rights reserved.
+ * Copyright (c) 2008-2009 Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2009 Intel Corporation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -17,1237 +18,1263 @@
* Maintained at www.Open-FCoE.org
*/
+#include <linux/types.h>
#include <linux/module.h>
-#include <linux/version.h>
#include <linux/kernel.h>
+#include <linux/list.h>
#include <linux/spinlock.h>
-#include <linux/skbuff.h>
+#include <linux/timer.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
#include <linux/if_ether.h>
#include <linux/if_vlan.h>
-#include <linux/kthread.h>
-#include <linux/crc32.h>
-#include <linux/cpu.h>
-#include <linux/fs.h>
-#include <linux/sysfs.h>
-#include <linux/ctype.h>
-#include <scsi/scsi_tcq.h>
-#include <scsi/scsicam.h>
-#include <scsi/scsi_transport.h>
-#include <scsi/scsi_transport_fc.h>
+#include <linux/netdevice.h>
+#include <linux/errno.h>
+#include <linux/bitops.h>
#include <net/rtnetlink.h>
+#include <scsi/fc/fc_els.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_fip.h>
#include <scsi/fc/fc_encaps.h>
+#include <scsi/fc/fc_fcoe.h>
#include <scsi/libfc.h>
-#include <scsi/fc_frame.h>
#include <scsi/libfcoe.h>
-#include <scsi/fc_transport_fcoe.h>
-static int debug_fcoe;
+MODULE_AUTHOR("Open-FCoE.org");
+MODULE_DESCRIPTION("FIP discovery protocol support for FCoE HBAs");
+MODULE_LICENSE("GPL v2");
+
+#define FCOE_CTLR_MIN_FKA 500 /* min keep alive (mS) */
+#define FCOE_CTLR_DEF_FKA FIP_DEF_FKA /* default keep alive (mS) */
-#define FCOE_MAX_QUEUE_DEPTH 256
+static void fcoe_ctlr_timeout(unsigned long);
+static void fcoe_ctlr_link_work(struct work_struct *);
+static void fcoe_ctlr_recv_work(struct work_struct *);
-/* destination address mode */
-#define FCOE_GW_ADDR_MODE 0x00
-#define FCOE_FCOUI_ADDR_MODE 0x01
+static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
-#define FCOE_WORD_TO_BYTE 4
+static u32 fcoe_ctlr_debug; /* 1 for basic, 2 for noisy debug */
-MODULE_AUTHOR("Open-FCoE.org");
-MODULE_DESCRIPTION("FCoE");
-MODULE_LICENSE("GPL");
-
-/* fcoe host list */
-LIST_HEAD(fcoe_hostlist);
-DEFINE_RWLOCK(fcoe_hostlist_lock);
-DEFINE_TIMER(fcoe_timer, NULL, 0, 0);
-struct fcoe_percpu_s *fcoe_percpu[NR_CPUS];
-
-
-/* Function Prototyes */
-static int fcoe_check_wait_queue(struct fc_lport *);
-static void fcoe_insert_wait_queue_head(struct fc_lport *, struct sk_buff *);
-static void fcoe_insert_wait_queue(struct fc_lport *, struct sk_buff *);
-static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *);
-#ifdef CONFIG_HOTPLUG_CPU
-static int fcoe_cpu_callback(struct notifier_block *, ulong, void *);
-#endif /* CONFIG_HOTPLUG_CPU */
-static int fcoe_device_notification(struct notifier_block *, ulong, void *);
-static void fcoe_dev_setup(void);
-static void fcoe_dev_cleanup(void);
-
-/* notification function from net device */
-static struct notifier_block fcoe_notifier = {
- .notifier_call = fcoe_device_notification,
-};
-
-
-#ifdef CONFIG_HOTPLUG_CPU
-static struct notifier_block fcoe_cpu_notifier = {
- .notifier_call = fcoe_cpu_callback,
-};
+#define FIP_DBG_LVL(level, fmt, args...) \
+ do { \
+ if (fcoe_ctlr_debug >= (level)) \
+ FC_DBG(fmt, ##args); \
+ } while (0)
+
+#define FIP_DBG(fmt, args...) FIP_DBG_LVL(1, fmt, ##args)
+
+/*
+ * Return non-zero if FCF fcoe_size has been validated.
+ */
+static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf)
+{
+ return (fcf->flags & FIP_FL_SOL) != 0;
+}
+
+/*
+ * Return non-zero if the FCF is usable.
+ */
+static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf)
+{
+ u16 flags = FIP_FL_SOL | FIP_FL_AVAIL;
+
+ return (fcf->flags & flags) == flags;
+}
/**
- * fcoe_create_percpu_data - creates the associated cpu data
- * @cpu: index for the cpu where fcoe cpu data will be created
- *
- * create percpu stats block, from cpu add notifier
- *
- * Returns: none
- **/
-static void fcoe_create_percpu_data(int cpu)
+ * fcoe_ctlr_init() - Initialize the FCoE Controller instance.
+ * @fip: FCoE controller.
+ */
+void fcoe_ctlr_init(struct fcoe_ctlr *fip)
{
- struct fc_lport *lp;
- struct fcoe_softc *fc;
-
- write_lock_bh(&fcoe_hostlist_lock);
- list_for_each_entry(fc, &fcoe_hostlist, list) {
- lp = fc->lp;
- if (lp->dev_stats[cpu] == NULL)
- lp->dev_stats[cpu] =
- kzalloc(sizeof(struct fcoe_dev_stats),
- GFP_KERNEL);
- }
- write_unlock_bh(&fcoe_hostlist_lock);
+ fip->state = FIP_ST_LINK_WAIT;
+ INIT_LIST_HEAD(&fip->fcfs);
+ spin_lock_init(&fip->lock);
+ fip->flogi_oxid = FC_XID_UNKNOWN;
+ setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
+ INIT_WORK(&fip->link_work, fcoe_ctlr_link_work);
+ INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work);
+ skb_queue_head_init(&fip->fip_recv_list);
}
+EXPORT_SYMBOL(fcoe_ctlr_init);
/**
- * fcoe_destroy_percpu_data - destroys the associated cpu data
- * @cpu: index for the cpu where fcoe cpu data will destroyed
+ * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller.
+ * @fip: FCoE controller.
*
- * destroy percpu stats block called by cpu add/remove notifier
- *
- * Retuns: none
- **/
-static void fcoe_destroy_percpu_data(int cpu)
+ * Called with &fcoe_ctlr lock held.
+ */
+static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
{
- struct fc_lport *lp;
- struct fcoe_softc *fc;
+ struct fcoe_fcf *fcf;
+ struct fcoe_fcf *next;
- write_lock_bh(&fcoe_hostlist_lock);
- list_for_each_entry(fc, &fcoe_hostlist, list) {
- lp = fc->lp;
- kfree(lp->dev_stats[cpu]);
- lp->dev_stats[cpu] = NULL;
+ fip->sel_fcf = NULL;
+ list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
+ list_del(&fcf->list);
+ kfree(fcf);
}
- write_unlock_bh(&fcoe_hostlist_lock);
+ fip->fcf_count = 0;
+ fip->sel_time = 0;
}
/**
- * fcoe_cpu_callback - fcoe cpu hotplug event callback
- * @nfb: callback data block
- * @action: event triggering the callback
- * @hcpu: index for the cpu of this event
+ * fcoe_ctrl_destroy() - Disable and tear-down the FCoE controller.
+ * @fip: FCoE controller.
+ *
+ * This is called by FCoE drivers before freeing the &fcoe_ctlr.
*
- * this creates or destroys per cpu data for fcoe
+ * The receive handler will have been deleted before this to guarantee
+ * that no more recv_work will be scheduled.
*
- * Returns NOTIFY_OK always.
- **/
-static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action,
- void *hcpu)
+ * The timer routine will simply return once we set FIP_ST_DISABLED.
+ * This guarantees that no further timeouts or work will be scheduled.
+ */
+void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
{
- unsigned int cpu = (unsigned long)hcpu;
-
- switch (action) {
- case CPU_ONLINE:
- fcoe_create_percpu_data(cpu);
- break;
- case CPU_DEAD:
- fcoe_destroy_percpu_data(cpu);
- break;
- default:
- break;
- }
- return NOTIFY_OK;
+ flush_work(&fip->recv_work);
+ spin_lock_bh(&fip->lock);
+ fip->state = FIP_ST_DISABLED;
+ fcoe_ctlr_reset_fcfs(fip);
+ spin_unlock_bh(&fip->lock);
+ del_timer_sync(&fip->timer);
+ flush_work(&fip->link_work);
}
-#endif /* CONFIG_HOTPLUG_CPU */
+EXPORT_SYMBOL(fcoe_ctlr_destroy);
/**
- * fcoe_rcv - this is the fcoe receive function called by NET_RX_SOFTIRQ
- * @skb: the receive skb
- * @dev: associated net device
- * @ptype: context
- * @odldev: last device
+ * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port.
+ * @fip: FCoE controller.
*
- * this function will receive the packet and build fc frame and pass it up
- *
- * Returns: 0 for success
- **/
-int fcoe_rcv(struct sk_buff *skb, struct net_device *dev,
- struct packet_type *ptype, struct net_device *olddev)
+ * Returns the maximum packet size including the FCoE header and trailer,
+ * but not including any Ethernet or VLAN headers.
+ */
+static inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip)
{
- struct fc_lport *lp;
- struct fcoe_rcv_info *fr;
- struct fcoe_softc *fc;
- struct fcoe_dev_stats *stats;
- struct fc_frame_header *fh;
- unsigned short oxid;
- int cpu_idx;
- struct fcoe_percpu_s *fps;
-
- fc = container_of(ptype, struct fcoe_softc, fcoe_packet_type);
- lp = fc->lp;
- if (unlikely(lp == NULL)) {
- FC_DBG("cannot find hba structure");
- goto err2;
- }
-
- if (unlikely(debug_fcoe)) {
- FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p tail:%p "
- "end:%p sum:%d dev:%s", skb->len, skb->data_len,
- skb->head, skb->data, skb_tail_pointer(skb),
- skb_end_pointer(skb), skb->csum,
- skb->dev ? skb->dev->name : "<NULL>");
+ /*
+ * Determine the max FCoE frame size allowed, including
+ * FCoE header and trailer.
+ * Note: lp->mfs is currently the payload size, not the frame size.
+ */
+ return fip->lp->mfs + sizeof(struct fc_frame_header) +
+ sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof);
+}
- }
+/**
+ * fcoe_ctlr_solicit() - Send a solicitation.
+ * @fip: FCoE controller.
+ * @fcf: Destination FCF. If NULL, a multicast solicitation is sent.
+ */
+static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
+{
+ struct sk_buff *skb;
+ struct fip_sol {
+ struct ethhdr eth;
+ struct fip_header fip;
+ struct {
+ struct fip_mac_desc mac;
+ struct fip_wwn_desc wwnn;
+ struct fip_size_desc size;
+ } __attribute__((packed)) desc;
+ } __attribute__((packed)) *sol;
+ u32 fcoe_size;
+
+ skb = dev_alloc_skb(sizeof(*sol));
+ if (!skb)
+ return;
- /* check for FCOE packet type */
- if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
- FC_DBG("wrong FC type frame");
- goto err;
- }
+ sol = (struct fip_sol *)skb->data;
- /*
- * Check for minimum frame length, and make sure required FCoE
- * and FC headers are pulled into the linear data area.
- */
- if (unlikely((skb->len < FCOE_MIN_FRAME) ||
- !pskb_may_pull(skb, FCOE_HEADER_LEN)))
- goto err;
+ memset(sol, 0, sizeof(*sol));
+ memcpy(sol->eth.h_dest, fcf ? fcf->fcf_mac : fcoe_all_fcfs, ETH_ALEN);
+ memcpy(sol->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+ sol->eth.h_proto = htons(ETH_P_FIP);
- skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
- fh = (struct fc_frame_header *) skb_transport_header(skb);
+ sol->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+ sol->fip.fip_op = htons(FIP_OP_DISC);
+ sol->fip.fip_subcode = FIP_SC_SOL;
+ sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW);
+ sol->fip.fip_flags = htons(FIP_FL_FPMA);
- oxid = ntohs(fh->fh_ox_id);
+ sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
+ sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW;
+ memcpy(sol->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
- fr = fcoe_dev_from_skb(skb);
- fr->fr_dev = lp;
- fr->ptype = ptype;
- cpu_idx = 0;
-#ifdef CONFIG_SMP
- /*
- * The incoming frame exchange id(oxid) is ANDed with num of online
- * cpu bits to get cpu_idx and then this cpu_idx is used for selecting
- * a per cpu kernel thread from fcoe_percpu. In case the cpu is
- * offline or no kernel thread for derived cpu_idx then cpu_idx is
- * initialize to first online cpu index.
- */
- cpu_idx = oxid & (num_online_cpus() - 1);
- if (!fcoe_percpu[cpu_idx] || !cpu_online(cpu_idx))
- cpu_idx = first_cpu(cpu_online_map);
-#endif
- fps = fcoe_percpu[cpu_idx];
+ sol->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
+ sol->desc.wwnn.fd_desc.fip_dlen = sizeof(sol->desc.wwnn) / FIP_BPW;
+ put_unaligned_be64(fip->lp->wwnn, &sol->desc.wwnn.fd_wwn);
- spin_lock_bh(&fps->fcoe_rx_list.lock);
- __skb_queue_tail(&fps->fcoe_rx_list, skb);
- if (fps->fcoe_rx_list.qlen == 1)
- wake_up_process(fps->thread);
+ fcoe_size = fcoe_ctlr_fcoe_size(fip);
+ sol->desc.size.fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
+ sol->desc.size.fd_desc.fip_dlen = sizeof(sol->desc.size) / FIP_BPW;
+ sol->desc.size.fd_size = htons(fcoe_size);
- spin_unlock_bh(&fps->fcoe_rx_list.lock);
+ skb_put(skb, sizeof(*sol));
+ skb->protocol = htons(ETH_P_802_3);
+ skb_reset_mac_header(skb);
+ skb_reset_network_header(skb);
+ fip->send(fip, skb);
- return 0;
-err:
-#ifdef CONFIG_SMP
- stats = lp->dev_stats[smp_processor_id()];
-#else
- stats = lp->dev_stats[0];
-#endif
- if (stats)
- stats->ErrorFrames++;
-
-err2:
- kfree_skb(skb);
- return -1;
+ if (!fcf)
+ fip->sol_time = jiffies;
}
-EXPORT_SYMBOL_GPL(fcoe_rcv);
/**
- * fcoe_start_io - pass to netdev to start xmit for fcoe
- * @skb: the skb to be xmitted
+ * fcoe_ctlr_link_up() - Start FCoE controller.
+ * @fip: FCoE controller.
*
- * Returns: 0 for success
- **/
-static inline int fcoe_start_io(struct sk_buff *skb)
+ * Called from the LLD when the network link is ready.
+ */
+void fcoe_ctlr_link_up(struct fcoe_ctlr *fip)
{
- int rc;
-
- skb_get(skb);
- rc = dev_queue_xmit(skb);
- if (rc != 0)
- return rc;
- kfree_skb(skb);
- return 0;
+ spin_lock_bh(&fip->lock);
+ if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) {
+ fip->last_link = 1;
+ fip->link = 1;
+ spin_unlock_bh(&fip->lock);
+ fc_linkup(fip->lp);
+ } else if (fip->state == FIP_ST_LINK_WAIT) {
+ fip->state = FIP_ST_AUTO;
+ fip->last_link = 1;
+ fip->link = 1;
+ spin_unlock_bh(&fip->lock);
+ FIP_DBG("%s", "setting AUTO mode.\n");
+ fc_linkup(fip->lp);
+ fcoe_ctlr_solicit(fip, NULL);
+ } else
+ spin_unlock_bh(&fip->lock);
}
+EXPORT_SYMBOL(fcoe_ctlr_link_up);
/**
- * fcoe_get_paged_crc_eof - in case we need alloc a page for crc_eof
- * @skb: the skb to be xmitted
- * @tlen: total len
+ * fcoe_ctlr_reset() - Reset FIP.
+ * @fip: FCoE controller.
+ * @new_state: FIP state to be entered.
*
- * Returns: 0 for success
- **/
-static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
+ * Returns non-zero if the link was up and now isn't.
+ */
+static int fcoe_ctlr_reset(struct fcoe_ctlr *fip, enum fip_state new_state)
{
- struct fcoe_percpu_s *fps;
- struct page *page;
- int cpu_idx;
-
- cpu_idx = get_cpu();
- fps = fcoe_percpu[cpu_idx];
- page = fps->crc_eof_page;
- if (!page) {
- page = alloc_page(GFP_ATOMIC);
- if (!page) {
- put_cpu();
- return -ENOMEM;
- }
- fps->crc_eof_page = page;
- WARN_ON(fps->crc_eof_offset != 0);
+ struct fc_lport *lp = fip->lp;
+ int link_dropped;
+
+ spin_lock_bh(&fip->lock);
+ fcoe_ctlr_reset_fcfs(fip);
+ del_timer(&fip->timer);
+ fip->state = new_state;
+ fip->ctlr_ka_time = 0;
+ fip->port_ka_time = 0;
+ fip->sol_time = 0;
+ fip->flogi_oxid = FC_XID_UNKNOWN;
+ fip->map_dest = 0;
+ fip->last_link = 0;
+ link_dropped = fip->link;
+ fip->link = 0;
+ spin_unlock_bh(&fip->lock);
+
+ if (link_dropped)
+ fc_linkdown(lp);
+
+ if (new_state == FIP_ST_ENABLED) {
+ fcoe_ctlr_solicit(fip, NULL);
+ fc_linkup(lp);
+ link_dropped = 0;
}
-
- get_page(page);
- skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
- fps->crc_eof_offset, tlen);
- skb->len += tlen;
- skb->data_len += tlen;
- skb->truesize += tlen;
- fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
-
- if (fps->crc_eof_offset >= PAGE_SIZE) {
- fps->crc_eof_page = NULL;
- fps->crc_eof_offset = 0;
- put_page(page);
- }
- put_cpu();
- return 0;
+ return link_dropped;
}
/**
- * fcoe_fc_crc - calculates FC CRC in this fcoe skb
- * @fp: the fc_frame containg data to be checksummed
+ * fcoe_ctlr_link_down() - Stop FCoE controller.
+ * @fip: FCoE controller.
*
- * This uses crc32() to calculate the crc for fc frame
- * Return : 32 bit crc
+ * Returns non-zero if the link was up and now isn't.
*
- **/
-u32 fcoe_fc_crc(struct fc_frame *fp)
+ * Called from the LLD when the network link is not ready.
+ * There may be multiple calls while the link is down.
+ */
+int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
{
- struct sk_buff *skb = fp_skb(fp);
- struct skb_frag_struct *frag;
- unsigned char *data;
- unsigned long off, len, clen;
- u32 crc;
- unsigned i;
-
- crc = crc32(~0, skb->data, skb_headlen(skb));
-
- for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
- frag = &skb_shinfo(skb)->frags[i];
- off = frag->page_offset;
- len = frag->size;
- while (len > 0) {
- clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
- data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
- KM_SKB_DATA_SOFTIRQ);
- crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
- kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
- off += clen;
- len -= clen;
- }
- }
- return crc;
+ return fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT);
}
-EXPORT_SYMBOL_GPL(fcoe_fc_crc);
+EXPORT_SYMBOL(fcoe_ctlr_link_down);
/**
- * fcoe_xmit - FCoE frame transmit function
- * @lp: the associated local port
- * @fp: the fc_frame to be transmitted
+ * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF.
+ * @fip: FCoE controller.
+ * @ports: 0 for controller keep-alive, 1 for port keep-alive.
+ * @sa: source MAC address.
*
- * Return : 0 for success
+ * A controller keep-alive is sent every fka_period (typically 8 seconds).
+ * The source MAC is the native MAC address.
*
- **/
-int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp)
+ * A port keep-alive is sent every 90 seconds while logged in.
+ * The source MAC is the assigned mapped source address.
+ * The destination is the FCF's F-port.
+ */
+static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip, int ports, u8 *sa)
{
- int wlen, rc = 0;
- u32 crc;
- struct ethhdr *eh;
- struct fcoe_crc_eof *cp;
struct sk_buff *skb;
- struct fcoe_dev_stats *stats;
- struct fc_frame_header *fh;
- unsigned int hlen; /* header length implies the version */
- unsigned int tlen; /* trailer length */
- unsigned int elen; /* eth header, may include vlan */
- int flogi_in_progress = 0;
- struct fcoe_softc *fc;
- u8 sof, eof;
- struct fcoe_hdr *hp;
-
- WARN_ON((fr_len(fp) % sizeof(u32)) != 0);
-
- fc = fcoe_softc(lp);
- /*
- * if it is a flogi then we need to learn gw-addr
- * and my own fcid
- */
- fh = fc_frame_header_get(fp);
- if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
- if (fc_frame_payload_op(fp) == ELS_FLOGI) {
- fc->flogi_oxid = ntohs(fh->fh_ox_id);
- fc->address_mode = FCOE_FCOUI_ADDR_MODE;
- fc->flogi_progress = 1;
- flogi_in_progress = 1;
- } else if (fc->flogi_progress && ntoh24(fh->fh_s_id) != 0) {
- /*
- * Here we must've gotten an SID by accepting an FLOGI
- * from a point-to-point connection. Switch to using
- * the source mac based on the SID. The destination
- * MAC in this case would have been set by receving the
- * FLOGI.
- */
- fc_fcoe_set_mac(fc->data_src_addr, fh->fh_s_id);
- fc->flogi_progress = 0;
- }
- }
-
- skb = fp_skb(fp);
- sof = fr_sof(fp);
- eof = fr_eof(fp);
-
- elen = (fc->real_dev->priv_flags & IFF_802_1Q_VLAN) ?
- sizeof(struct vlan_ethhdr) : sizeof(struct ethhdr);
- hlen = sizeof(struct fcoe_hdr);
- tlen = sizeof(struct fcoe_crc_eof);
- wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE;
-
- /* crc offload */
- if (likely(lp->crc_offload)) {
- skb->ip_summed = CHECKSUM_COMPLETE;
- skb->csum_start = skb_headroom(skb);
- skb->csum_offset = skb->len;
- crc = 0;
- } else {
- skb->ip_summed = CHECKSUM_NONE;
- crc = fcoe_fc_crc(fp);
- }
+ struct fip_kal {
+ struct ethhdr eth;
+ struct fip_header fip;
+ struct fip_mac_desc mac;
+ } __attribute__((packed)) *kal;
+ struct fip_vn_desc *vn;
+ u32 len;
+ struct fc_lport *lp;
+ struct fcoe_fcf *fcf;
- /* copy fc crc and eof to the skb buff */
- if (skb_is_nonlinear(skb)) {
- skb_frag_t *frag;
- if (fcoe_get_paged_crc_eof(skb, tlen)) {
- kfree(skb);
- return -ENOMEM;
- }
- frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
- cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
- + frag->page_offset;
- } else {
- cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
- }
+ fcf = fip->sel_fcf;
+ lp = fip->lp;
+ if (!fcf || !fc_host_port_id(lp->host))
+ return;
- memset(cp, 0, sizeof(*cp));
- cp->fcoe_eof = eof;
- cp->fcoe_crc32 = cpu_to_le32(~crc);
+ len = fcoe_ctlr_fcoe_size(fip) + sizeof(struct ethhdr);
+ BUG_ON(len < sizeof(*kal) + sizeof(*vn));
+ skb = dev_alloc_skb(len);
+ if (!skb)
+ return;
- if (skb_is_nonlinear(skb)) {
- kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
- cp = NULL;
+ kal = (struct fip_kal *)skb->data;
+ memset(kal, 0, len);
+ memcpy(kal->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
+ memcpy(kal->eth.h_source, sa, ETH_ALEN);
+ kal->eth.h_proto = htons(ETH_P_FIP);
+
+ kal->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+ kal->fip.fip_op = htons(FIP_OP_CTRL);
+ kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE;
+ kal->fip.fip_dl_len = htons((sizeof(kal->mac) +
+ ports * sizeof(*vn)) / FIP_BPW);
+ kal->fip.fip_flags = htons(FIP_FL_FPMA);
+
+ kal->mac.fd_desc.fip_dtype = FIP_DT_MAC;
+ kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW;
+ memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+
+ if (ports) {
+ vn = (struct fip_vn_desc *)(kal + 1);
+ vn->fd_desc.fip_dtype = FIP_DT_VN_ID;
+ vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW;
+ memcpy(vn->fd_mac, fip->data_src_addr, ETH_ALEN);
+ hton24(vn->fd_fc_id, fc_host_port_id(lp->host));
+ put_unaligned_be64(lp->wwpn, &vn->fd_wwpn);
}
- /* adjust skb netowrk/transport offsets to match mac/fcoe/fc */
- skb_push(skb, elen + hlen);
+ skb_put(skb, len);
+ skb->protocol = htons(ETH_P_802_3);
skb_reset_mac_header(skb);
skb_reset_network_header(skb);
- skb->mac_len = elen;
- skb->protocol = htons(ETH_P_802_3);
- skb->dev = fc->real_dev;
-
- /* fill up mac and fcoe headers */
- eh = eth_hdr(skb);
- eh->h_proto = htons(ETH_P_FCOE);
- if (fc->address_mode == FCOE_FCOUI_ADDR_MODE)
- fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
- else
- /* insert GW address */
- memcpy(eh->h_dest, fc->dest_addr, ETH_ALEN);
-
- if (unlikely(flogi_in_progress))
- memcpy(eh->h_source, fc->ctl_src_addr, ETH_ALEN);
- else
- memcpy(eh->h_source, fc->data_src_addr, ETH_ALEN);
-
- hp = (struct fcoe_hdr *)(eh + 1);
- memset(hp, 0, sizeof(*hp));
- if (FC_FCOE_VER)
- FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
- hp->fcoe_sof = sof;
-
- /* update tx stats: regardless if LLD fails */
- stats = lp->dev_stats[smp_processor_id()];
- if (stats) {
- stats->TxFrames++;
- stats->TxWords += wlen;
- }
-
- /* send down to lld */
- fr_dev(fp) = lp;
- if (fc->fcoe_pending_queue.qlen)
- rc = fcoe_check_wait_queue(lp);
-
- if (rc == 0)
- rc = fcoe_start_io(skb);
-
- if (rc) {
- fcoe_insert_wait_queue(lp, skb);
- if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
- fc_pause(lp);
- }
-
- return 0;
+ fip->send(fip, skb);
}
-EXPORT_SYMBOL_GPL(fcoe_xmit);
-/*
- * fcoe_percpu_receive_thread - recv thread per cpu
- * @arg: ptr to the fcoe per cpu struct
+/**
+ * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it.
+ * @fip: FCoE controller.
+ * @dtype: FIP descriptor type for the frame.
+ * @skb: FCoE ELS frame including FC header but no FCoE headers.
+ *
+ * Returns non-zero error code on failure.
*
- * Return: 0 for success
+ * The caller must check that the length is a multiple of 4.
*
+ * The @skb must have enough headroom (28 bytes) and tailroom (8 bytes).
+ * Headroom includes the FIP encapsulation description, FIP header, and
+ * Ethernet header. The tailroom is for the FIP MAC descriptor.
*/
-int fcoe_percpu_receive_thread(void *arg)
+static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip,
+ u8 dtype, struct sk_buff *skb)
{
- struct fcoe_percpu_s *p = arg;
- u32 fr_len;
- struct fc_lport *lp;
- struct fcoe_rcv_info *fr;
- struct fcoe_dev_stats *stats;
- struct fc_frame_header *fh;
- struct sk_buff *skb;
- struct fcoe_crc_eof crc_eof;
- struct fc_frame *fp;
- u8 *mac = NULL;
- struct fcoe_softc *fc;
- struct fcoe_hdr *hp;
-
- set_user_nice(current, 19);
-
- while (!kthread_should_stop()) {
-
- spin_lock_bh(&p->fcoe_rx_list.lock);
- while ((skb = __skb_dequeue(&p->fcoe_rx_list)) == NULL) {
- set_current_state(TASK_INTERRUPTIBLE);
- spin_unlock_bh(&p->fcoe_rx_list.lock);
- schedule();
- set_current_state(TASK_RUNNING);
- if (kthread_should_stop())
- return 0;
- spin_lock_bh(&p->fcoe_rx_list.lock);
- }
- spin_unlock_bh(&p->fcoe_rx_list.lock);
- fr = fcoe_dev_from_skb(skb);
- lp = fr->fr_dev;
- if (unlikely(lp == NULL)) {
- FC_DBG("invalid HBA Structure");
- kfree_skb(skb);
- continue;
- }
-
- stats = lp->dev_stats[smp_processor_id()];
-
- if (unlikely(debug_fcoe)) {
- FC_DBG("skb_info: len:%d data_len:%d head:%p data:%p "
- "tail:%p end:%p sum:%d dev:%s",
- skb->len, skb->data_len,
- skb->head, skb->data, skb_tail_pointer(skb),
- skb_end_pointer(skb), skb->csum,
- skb->dev ? skb->dev->name : "<NULL>");
- }
-
- /*
- * Save source MAC address before discarding header.
- */
- fc = lport_priv(lp);
- if (unlikely(fc->flogi_progress))
- mac = eth_hdr(skb)->h_source;
-
- if (skb_is_nonlinear(skb))
- skb_linearize(skb); /* not ideal */
-
- /*
- * Frame length checks and setting up the header pointers
- * was done in fcoe_rcv already.
- */
- hp = (struct fcoe_hdr *) skb_network_header(skb);
- fh = (struct fc_frame_header *) skb_transport_header(skb);
-
- if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
- if (stats) {
- if (stats->ErrorFrames < 5)
- FC_DBG("unknown FCoE version %x",
- FC_FCOE_DECAPS_VER(hp));
- stats->ErrorFrames++;
- }
- kfree_skb(skb);
- continue;
- }
-
- skb_pull(skb, sizeof(struct fcoe_hdr));
- fr_len = skb->len - sizeof(struct fcoe_crc_eof);
-
- if (stats) {
- stats->RxFrames++;
- stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
- }
+ struct fip_encaps_head {
+ struct ethhdr eth;
+ struct fip_header fip;
+ struct fip_encaps encaps;
+ } __attribute__((packed)) *cap;
+ struct fip_mac_desc *mac;
+ struct fcoe_fcf *fcf;
+ size_t dlen;
+
+ fcf = fip->sel_fcf;
+ if (!fcf)
+ return -ENODEV;
+ dlen = sizeof(struct fip_encaps) + skb->len; /* len before push */
+ cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap));
+
+ memset(cap, 0, sizeof(*cap));
+ memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
+ memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+ cap->eth.h_proto = htons(ETH_P_FIP);
+
+ cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+ cap->fip.fip_op = htons(FIP_OP_LS);
+ cap->fip.fip_subcode = FIP_SC_REQ;
+ cap->fip.fip_dl_len = htons((dlen + sizeof(*mac)) / FIP_BPW);
+ cap->fip.fip_flags = htons(FIP_FL_FPMA);
+
+ cap->encaps.fd_desc.fip_dtype = dtype;
+ cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW;
+
+ mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac));
+ memset(mac, 0, sizeof(mac));
+ mac->fd_desc.fip_dtype = FIP_DT_MAC;
+ mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW;
+ if (dtype != ELS_FLOGI)
+ memcpy(mac->fd_mac, fip->data_src_addr, ETH_ALEN);
- fp = (struct fc_frame *)skb;
- fc_frame_init(fp);
- fr_dev(fp) = lp;
- fr_sof(fp) = hp->fcoe_sof;
-
- /* Copy out the CRC and EOF trailer for access */
- if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
- kfree_skb(skb);
- continue;
- }
- fr_eof(fp) = crc_eof.fcoe_eof;
- fr_crc(fp) = crc_eof.fcoe_crc32;
- if (pskb_trim(skb, fr_len)) {
- kfree_skb(skb);
- continue;
- }
-
- /*
- * We only check CRC if no offload is available and if it is
- * it's solicited data, in which case, the FCP layer would
- * check it during the copy.
- */
- if (lp->crc_offload)
- fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
- else
- fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
-
- fh = fc_frame_header_get(fp);
- if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
- fh->fh_type == FC_TYPE_FCP) {
- fc_exch_recv(lp, lp->emp, fp);
- continue;
- }
- if (fr_flags(fp) & FCPHF_CRC_UNCHECKED) {
- if (le32_to_cpu(fr_crc(fp)) !=
- ~crc32(~0, skb->data, fr_len)) {
- if (debug_fcoe || stats->InvalidCRCCount < 5)
- printk(KERN_WARNING "fcoe: dropping "
- "frame with CRC error\n");
- stats->InvalidCRCCount++;
- stats->ErrorFrames++;
- fc_frame_free(fp);
- continue;
- }
- fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
- }
- /* non flogi and non data exchanges are handled here */
- if (unlikely(fc->flogi_progress))
- fcoe_recv_flogi(fc, fp, mac);
- fc_exch_recv(lp, lp->emp, fp);
- }
+ skb->protocol = htons(ETH_P_802_3);
+ skb_reset_mac_header(skb);
+ skb_reset_network_header(skb);
return 0;
}
/**
- * fcoe_recv_flogi - flogi receive function
- * @fc: associated fcoe_softc
- * @fp: the recieved frame
- * @sa: the source address of this flogi
+ * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate.
+ * @fip: FCoE controller.
+ * @skb: FCoE ELS frame including FC header but no FCoE headers.
*
- * This is responsible to parse the flogi response and sets the corresponding
- * mac address for the initiator, eitehr OUI based or GW based.
+ * Returns a non-zero error code if the frame should not be sent.
+ * Returns zero if the caller should send the frame with FCoE encapsulation.
*
- * Returns: none
- **/
-static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa)
+ * The caller must check that the length is a multiple of 4.
+ * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
+ */
+int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
struct fc_frame_header *fh;
+ u16 old_xid;
u8 op;
- fh = fc_frame_header_get(fp);
- if (fh->fh_type != FC_TYPE_ELS)
- return;
- op = fc_frame_payload_op(fp);
- if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
- fc->flogi_oxid == ntohs(fh->fh_ox_id)) {
- /*
- * FLOGI accepted.
- * If the src mac addr is FC_OUI-based, then we mark the
- * address_mode flag to use FC_OUI-based Ethernet DA.
- * Otherwise we use the FCoE gateway addr
- */
- if (!compare_ether_addr(sa, (u8[6]) FC_FCOE_FLOGI_MAC)) {
- fc->address_mode = FCOE_FCOUI_ADDR_MODE;
- } else {
- memcpy(fc->dest_addr, sa, ETH_ALEN);
- fc->address_mode = FCOE_GW_ADDR_MODE;
- }
+ if (fip->state == FIP_ST_NON_FIP)
+ return 0;
+ fh = (struct fc_frame_header *)skb->data;
+ op = *(u8 *)(fh + 1);
+
+ switch (op) {
+ case ELS_FLOGI:
+ old_xid = fip->flogi_oxid;
+ fip->flogi_oxid = ntohs(fh->fh_ox_id);
+ if (fip->state == FIP_ST_AUTO) {
+ if (old_xid == FC_XID_UNKNOWN)
+ fip->flogi_count = 0;
+ fip->flogi_count++;
+ if (fip->flogi_count < 3)
+ goto drop;
+ fip->map_dest = 1;
+ return 0;
+ }
+ op = FIP_DT_FLOGI;
+ break;
+ case ELS_FDISC:
+ if (ntoh24(fh->fh_s_id))
+ return 0;
+ op = FIP_DT_FDISC;
+ break;
+ case ELS_LOGO:
+ if (fip->state != FIP_ST_ENABLED)
+ return 0;
+ if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
+ return 0;
+ op = FIP_DT_LOGO;
+ break;
+ case ELS_LS_ACC:
+ if (fip->flogi_oxid == FC_XID_UNKNOWN)
+ return 0;
+ if (!ntoh24(fh->fh_s_id))
+ return 0;
+ if (fip->state == FIP_ST_AUTO)
+ return 0;
/*
- * Remove any previously-set unicast MAC filter.
- * Add secondary FCoE MAC address filter for our OUI.
- */
- rtnl_lock();
- if (compare_ether_addr(fc->data_src_addr, (u8[6]) { 0 }))
- dev_unicast_delete(fc->real_dev, fc->data_src_addr,
- ETH_ALEN);
- fc_fcoe_set_mac(fc->data_src_addr, fh->fh_d_id);
- dev_unicast_add(fc->real_dev, fc->data_src_addr, ETH_ALEN);
- rtnl_unlock();
-
- fc->flogi_progress = 0;
- } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
- /*
- * Save source MAC for point-to-point responses.
+ * Here we must've gotten an SID by accepting an FLOGI
+ * from a point-to-point connection. Switch to using
+ * the source mac based on the SID. The destination
+ * MAC in this case would have been set by receving the
+ * FLOGI.
*/
- memcpy(fc->dest_addr, sa, ETH_ALEN);
- fc->address_mode = FCOE_GW_ADDR_MODE;
+ fip->flogi_oxid = FC_XID_UNKNOWN;
+ fc_fcoe_set_mac(fip->data_src_addr, fh->fh_s_id);
+ return 0;
+ default:
+ if (fip->state != FIP_ST_ENABLED)
+ goto drop;
+ return 0;
}
+ if (fcoe_ctlr_encaps(fip, op, skb))
+ goto drop;
+ fip->send(fip, skb);
+ return -EINPROGRESS;
+drop:
+ kfree_skb(skb);
+ return -EINVAL;
}
+EXPORT_SYMBOL(fcoe_ctlr_els_send);
-/**
- * fcoe_watchdog - fcoe timer callback
- * @vp:
+/*
+ * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller.
+ * @fip: FCoE controller.
+ *
+ * Called with lock held.
*
- * This checks the pending queue length for fcoe and put fcoe to be paused state
- * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the
- * fcoe_hostlist.
+ * An FCF is considered old if we have missed three advertisements.
+ * That is, there have been no valid advertisement from it for three
+ * times its keep-alive period including fuzz.
*
- * Returns: 0 for success
- **/
-void fcoe_watchdog(ulong vp)
+ * In addition, determine the time when an FCF selection can occur.
+ */
+static void fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
{
- struct fc_lport *lp;
- struct fcoe_softc *fc;
- int paused = 0;
-
- read_lock(&fcoe_hostlist_lock);
- list_for_each_entry(fc, &fcoe_hostlist, list) {
- lp = fc->lp;
- if (lp) {
- if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
- paused = 1;
- if (fcoe_check_wait_queue(lp) < FCOE_MAX_QUEUE_DEPTH) {
- if (paused)
- fc_unpause(lp);
- }
+ struct fcoe_fcf *fcf;
+ struct fcoe_fcf *next;
+ unsigned long sel_time = 0;
+
+ list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
+ if (time_after(jiffies, fcf->time + fcf->fka_period * 3 +
+ msecs_to_jiffies(FIP_FCF_FUZZ * 3))) {
+ if (fip->sel_fcf == fcf)
+ fip->sel_fcf = NULL;
+ list_del(&fcf->list);
+ WARN_ON(!fip->fcf_count);
+ fip->fcf_count--;
+ kfree(fcf);
+ } else if (fcoe_ctlr_mtu_valid(fcf) &&
+ (!sel_time || time_before(sel_time, fcf->time))) {
+ sel_time = fcf->time;
}
}
- read_unlock(&fcoe_hostlist_lock);
-
- fcoe_timer.expires = jiffies + (1 * HZ);
- add_timer(&fcoe_timer);
+ if (sel_time) {
+ sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+ fip->sel_time = sel_time;
+ if (time_before(sel_time, fip->timer.expires))
+ mod_timer(&fip->timer, sel_time);
+ } else {
+ fip->sel_time = 0;
+ }
}
-
/**
- * fcoe_check_wait_queue - put the skb into fcoe pending xmit queue
- * @lp: the fc_port for this skb
- * @skb: the associated skb to be xmitted
+ * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry.
+ * @skb: received FIP advertisement frame
+ * @fcf: resulting FCF entry.
*
- * This empties the wait_queue, dequeue the head of the wait_queue queue
- * and calls fcoe_start_io() for each packet, if all skb have been
- * transmitted, return 0 if a error occurs, then restore wait_queue and
- * try again later.
- *
- * The wait_queue is used when the skb transmit fails. skb will go
- * in the wait_queue which will be emptied by the time function OR
- * by the next skb transmit.
- *
- * Returns: 0 for success
- **/
-static int fcoe_check_wait_queue(struct fc_lport *lp)
+ * Returns zero on a valid parsed advertisement,
+ * otherwise returns non zero value.
+ */
+static int fcoe_ctlr_parse_adv(struct sk_buff *skb, struct fcoe_fcf *fcf)
{
- int rc, unpause = 0;
- int paused = 0;
- struct sk_buff *skb;
- struct fcoe_softc *fc;
-
- fc = fcoe_softc(lp);
- spin_lock_bh(&fc->fcoe_pending_queue.lock);
-
- /*
- * is this interface paused?
- */
- if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
- paused = 1;
- if (fc->fcoe_pending_queue.qlen) {
- while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
- spin_unlock_bh(&fc->fcoe_pending_queue.lock);
- rc = fcoe_start_io(skb);
- if (rc) {
- fcoe_insert_wait_queue_head(lp, skb);
- return rc;
+ struct fip_header *fiph;
+ struct fip_desc *desc = NULL;
+ struct fip_wwn_desc *wwn;
+ struct fip_fab_desc *fab;
+ struct fip_fka_desc *fka;
+ unsigned long t;
+ size_t rlen;
+ size_t dlen;
+
+ memset(fcf, 0, sizeof(*fcf));
+ fcf->fka_period = msecs_to_jiffies(FCOE_CTLR_DEF_FKA);
+
+ fiph = (struct fip_header *)skb->data;
+ fcf->flags = ntohs(fiph->fip_flags);
+
+ rlen = ntohs(fiph->fip_dl_len) * 4;
+ if (rlen + sizeof(*fiph) > skb->len)
+ return -EINVAL;
+
+ desc = (struct fip_desc *)(fiph + 1);
+ while (rlen > 0) {
+ dlen = desc->fip_dlen * FIP_BPW;
+ if (dlen < sizeof(*desc) || dlen > rlen)
+ return -EINVAL;
+ switch (desc->fip_dtype) {
+ case FIP_DT_PRI:
+ if (dlen != sizeof(struct fip_pri_desc))
+ goto len_err;
+ fcf->pri = ((struct fip_pri_desc *)desc)->fd_pri;
+ break;
+ case FIP_DT_MAC:
+ if (dlen != sizeof(struct fip_mac_desc))
+ goto len_err;
+ memcpy(fcf->fcf_mac,
+ ((struct fip_mac_desc *)desc)->fd_mac,
+ ETH_ALEN);
+ if (!is_valid_ether_addr(fcf->fcf_mac)) {
+ FIP_DBG("invalid MAC addr in FIP adv\n");
+ return -EINVAL;
}
- spin_lock_bh(&fc->fcoe_pending_queue.lock);
+ break;
+ case FIP_DT_NAME:
+ if (dlen != sizeof(struct fip_wwn_desc))
+ goto len_err;
+ wwn = (struct fip_wwn_desc *)desc;
+ fcf->switch_name = get_unaligned_be64(&wwn->fd_wwn);
+ break;
+ case FIP_DT_FAB:
+ if (dlen != sizeof(struct fip_fab_desc))
+ goto len_err;
+ fab = (struct fip_fab_desc *)desc;
+ fcf->fabric_name = get_unaligned_be64(&fab->fd_wwn);
+ fcf->vfid = ntohs(fab->fd_vfid);
+ fcf->fc_map = ntoh24(fab->fd_map);
+ break;
+ case FIP_DT_FKA:
+ if (dlen != sizeof(struct fip_fka_desc))
+ goto len_err;
+ fka = (struct fip_fka_desc *)desc;
+ t = ntohl(fka->fd_fka_period);
+ if (t >= FCOE_CTLR_MIN_FKA)
+ fcf->fka_period = msecs_to_jiffies(t);
+ break;
+ case FIP_DT_MAP_OUI:
+ case FIP_DT_FCOE_SIZE:
+ case FIP_DT_FLOGI:
+ case FIP_DT_FDISC:
+ case FIP_DT_LOGO:
+ case FIP_DT_ELP:
+ default:
+ FIP_DBG("unexpected descriptor type %x in FIP adv\n",
+ desc->fip_dtype);
+ /* standard says ignore unknown descriptors >= 128 */
+ if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+ return -EINVAL;
+ continue;
}
- if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH)
- unpause = 1;
+ desc = (struct fip_desc *)((char *)desc + dlen);
+ rlen -= dlen;
}
- spin_unlock_bh(&fc->fcoe_pending_queue.lock);
- if ((unpause) && (paused))
- fc_unpause(lp);
- return fc->fcoe_pending_queue.qlen;
+ if (!fcf->fc_map || (fcf->fc_map & 0x10000))
+ return -EINVAL;
+ if (!fcf->switch_name || !fcf->fabric_name)
+ return -EINVAL;
+ return 0;
+
+len_err:
+ FIP_DBG("FIP length error in descriptor type %x len %zu\n",
+ desc->fip_dtype, dlen);
+ return -EINVAL;
}
/**
- * fcoe_insert_wait_queue_head - puts skb to fcoe pending queue head
- * @lp: the fc_port for this skb
- * @skb: the associated skb to be xmitted
- *
- * Returns: none
- **/
-static void fcoe_insert_wait_queue_head(struct fc_lport *lp,
- struct sk_buff *skb)
+ * fcoe_ctlr_recv_adv() - Handle an incoming advertisement.
+ * @fip: FCoE controller.
+ * @skb: Received FIP packet.
+ */
+static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
- struct fcoe_softc *fc;
+ struct fcoe_fcf *fcf;
+ struct fcoe_fcf new;
+ struct fcoe_fcf *found;
+ unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
+ int first = 0;
+ int mtu_valid;
+
+ if (fcoe_ctlr_parse_adv(skb, &new))
+ return;
- fc = fcoe_softc(lp);
- spin_lock_bh(&fc->fcoe_pending_queue.lock);
- __skb_queue_head(&fc->fcoe_pending_queue, skb);
- spin_unlock_bh(&fc->fcoe_pending_queue.lock);
-}
+ spin_lock_bh(&fip->lock);
+ first = list_empty(&fip->fcfs);
+ found = NULL;
+ list_for_each_entry(fcf, &fip->fcfs, list) {
+ if (fcf->switch_name == new.switch_name &&
+ fcf->fabric_name == new.fabric_name &&
+ fcf->fc_map == new.fc_map &&
+ compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) {
+ found = fcf;
+ break;
+ }
+ }
+ if (!found) {
+ if (fip->fcf_count >= FCOE_CTLR_FCF_LIMIT)
+ goto out;
-/**
- * fcoe_insert_wait_queue - put the skb into fcoe pending queue tail
- * @lp: the fc_port for this skb
- * @skb: the associated skb to be xmitted
- *
- * Returns: none
- **/
-static void fcoe_insert_wait_queue(struct fc_lport *lp,
- struct sk_buff *skb)
-{
- struct fcoe_softc *fc;
+ fcf = kmalloc(sizeof(*fcf), GFP_ATOMIC);
+ if (!fcf)
+ goto out;
- fc = fcoe_softc(lp);
- spin_lock_bh(&fc->fcoe_pending_queue.lock);
- __skb_queue_tail(&fc->fcoe_pending_queue, skb);
- spin_unlock_bh(&fc->fcoe_pending_queue.lock);
-}
+ fip->fcf_count++;
+ memcpy(fcf, &new, sizeof(new));
+ list_add(&fcf->list, &fip->fcfs);
+ } else {
+ /*
+ * Flags in advertisements are ignored once the FCF is
+ * selected. Flags in unsolicited advertisements are
+ * ignored after a usable solicited advertisement
+ * has been received.
+ */
+ if (fcf == fip->sel_fcf) {
+ fip->ctlr_ka_time -= fcf->fka_period;
+ fip->ctlr_ka_time += new.fka_period;
+ if (time_before(fip->ctlr_ka_time, fip->timer.expires))
+ mod_timer(&fip->timer, fip->ctlr_ka_time);
+ } else if (!fcoe_ctlr_fcf_usable(fcf))
+ fcf->flags = new.flags;
+ fcf->fka_period = new.fka_period;
+ memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
+ }
+ mtu_valid = fcoe_ctlr_mtu_valid(fcf);
+ fcf->time = jiffies;
+ FIP_DBG_LVL(found ? 2 : 1, "%s FCF for fab %llx map %x val %d\n",
+ found ? "old" : "new",
+ fcf->fabric_name, fcf->fc_map, mtu_valid);
-/**
- * fcoe_dev_setup - setup link change notification interface
- *
- **/
-static void fcoe_dev_setup(void)
-{
/*
- * here setup a interface specific wd time to
- * monitor the link state
+ * If this advertisement is not solicited and our max receive size
+ * hasn't been verified, send a solicited advertisement.
*/
- register_netdevice_notifier(&fcoe_notifier);
-}
+ if (!mtu_valid)
+ fcoe_ctlr_solicit(fip, fcf);
-/**
- * fcoe_dev_setup - cleanup link change notification interface
- **/
-static void fcoe_dev_cleanup(void)
-{
- unregister_netdevice_notifier(&fcoe_notifier);
+ /*
+ * If its been a while since we did a solicit, and this is
+ * the first advertisement we've received, do a multicast
+ * solicitation to gather as many advertisements as we can
+ * before selection occurs.
+ */
+ if (first && time_after(jiffies, fip->sol_time + sol_tov))
+ fcoe_ctlr_solicit(fip, NULL);
+
+ /*
+ * If this is the first validated FCF, note the time and
+ * set a timer to trigger selection.
+ */
+ if (mtu_valid && !fip->sel_time && fcoe_ctlr_fcf_usable(fcf)) {
+ fip->sel_time = jiffies +
+ msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+ if (!timer_pending(&fip->timer) ||
+ time_before(fip->sel_time, fip->timer.expires))
+ mod_timer(&fip->timer, fip->sel_time);
+ }
+out:
+ spin_unlock_bh(&fip->lock);
}
/**
- * fcoe_device_notification - netdev event notification callback
- * @notifier: context of the notification
- * @event: type of event
- * @ptr: fixed array for output parsed ifname
- *
- * This function is called by the ethernet driver in case of link change event
- *
- * Returns: 0 for success
- **/
-static int fcoe_device_notification(struct notifier_block *notifier,
- ulong event, void *ptr)
+ * fcoe_ctlr_recv_els() - Handle an incoming FIP-encapsulated ELS frame.
+ * @fip: FCoE controller.
+ * @skb: Received FIP packet.
+ */
+static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
- struct fc_lport *lp = NULL;
- struct net_device *real_dev = ptr;
- struct fcoe_softc *fc;
+ struct fc_lport *lp = fip->lp;
+ struct fip_header *fiph;
+ struct fc_frame *fp;
+ struct fc_frame_header *fh = NULL;
+ struct fip_desc *desc;
+ struct fip_encaps *els;
struct fcoe_dev_stats *stats;
- u16 new_status;
- u32 mfs;
- int rc = NOTIFY_OK;
-
- read_lock(&fcoe_hostlist_lock);
- list_for_each_entry(fc, &fcoe_hostlist, list) {
- if (fc->real_dev == real_dev) {
- lp = fc->lp;
+ enum fip_desc_type els_dtype = 0;
+ u8 els_op;
+ u8 sub;
+ u8 granted_mac[ETH_ALEN] = { 0 };
+ size_t els_len = 0;
+ size_t rlen;
+ size_t dlen;
+
+ fiph = (struct fip_header *)skb->data;
+ sub = fiph->fip_subcode;
+ if (sub != FIP_SC_REQ && sub != FIP_SC_REP)
+ goto drop;
+
+ rlen = ntohs(fiph->fip_dl_len) * 4;
+ if (rlen + sizeof(*fiph) > skb->len)
+ goto drop;
+
+ desc = (struct fip_desc *)(fiph + 1);
+ while (rlen > 0) {
+ dlen = desc->fip_dlen * FIP_BPW;
+ if (dlen < sizeof(*desc) || dlen > rlen)
+ goto drop;
+ switch (desc->fip_dtype) {
+ case FIP_DT_MAC:
+ if (dlen != sizeof(struct fip_mac_desc))
+ goto len_err;
+ memcpy(granted_mac,
+ ((struct fip_mac_desc *)desc)->fd_mac,
+ ETH_ALEN);
+ if (!is_valid_ether_addr(granted_mac)) {
+ FIP_DBG("invalid MAC addrs in FIP ELS\n");
+ goto drop;
+ }
+ break;
+ case FIP_DT_FLOGI:
+ case FIP_DT_FDISC:
+ case FIP_DT_LOGO:
+ case FIP_DT_ELP:
+ if (fh)
+ goto drop;
+ if (dlen < sizeof(*els) + sizeof(*fh) + 1)
+ goto len_err;
+ els_len = dlen - sizeof(*els);
+ els = (struct fip_encaps *)desc;
+ fh = (struct fc_frame_header *)(els + 1);
+ els_dtype = desc->fip_dtype;
break;
+ default:
+ FIP_DBG("unexpected descriptor type %x "
+ "in FIP adv\n", desc->fip_dtype);
+ /* standard says ignore unknown descriptors >= 128 */
+ if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+ goto drop;
+ continue;
}
- }
- read_unlock(&fcoe_hostlist_lock);
- if (lp == NULL) {
- rc = NOTIFY_DONE;
- goto out;
+ desc = (struct fip_desc *)((char *)desc + dlen);
+ rlen -= dlen;
}
- new_status = lp->link_status;
- switch (event) {
- case NETDEV_DOWN:
- case NETDEV_GOING_DOWN:
- new_status &= ~FC_LINK_UP;
- break;
- case NETDEV_UP:
- case NETDEV_CHANGE:
- new_status &= ~FC_LINK_UP;
- if (!fcoe_link_ok(lp))
- new_status |= FC_LINK_UP;
- break;
- case NETDEV_CHANGEMTU:
- mfs = fc->real_dev->mtu -
- (sizeof(struct fcoe_hdr) +
- sizeof(struct fcoe_crc_eof));
- if (mfs >= FC_MIN_MAX_FRAME)
- fc_set_mfs(lp, mfs);
- new_status &= ~FC_LINK_UP;
- if (!fcoe_link_ok(lp))
- new_status |= FC_LINK_UP;
- break;
- case NETDEV_REGISTER:
- break;
- default:
- FC_DBG("unknown event %ld call", event);
- }
- if (lp->link_status != new_status) {
- if ((new_status & FC_LINK_UP) == FC_LINK_UP)
- fc_linkup(lp);
- else {
- stats = lp->dev_stats[smp_processor_id()];
- if (stats)
- stats->LinkFailureCount++;
- fc_linkdown(lp);
- fcoe_clean_pending_queue(lp);
- }
- }
-out:
- return rc;
-}
+ if (!fh)
+ goto drop;
+ els_op = *(u8 *)(fh + 1);
-/**
- * fcoe_if_to_netdev - parse a name buffer to get netdev
- * @ifname: fixed array for output parsed ifname
- * @buffer: incoming buffer to be copied
- *
- * Returns: NULL or ptr to netdeive
- **/
-static struct net_device *fcoe_if_to_netdev(const char *buffer)
-{
- char *cp;
- char ifname[IFNAMSIZ + 2];
-
- if (buffer) {
- strlcpy(ifname, buffer, IFNAMSIZ);
- cp = ifname + strlen(ifname);
- while (--cp >= ifname && *cp == '\n')
- *cp = '\0';
- return dev_get_by_name(&init_net, ifname);
+ if (els_dtype == FIP_DT_FLOGI && sub == FIP_SC_REP &&
+ fip->flogi_oxid == ntohs(fh->fh_ox_id) &&
+ els_op == ELS_LS_ACC && is_valid_ether_addr(granted_mac)) {
+ fip->flogi_oxid = FC_XID_UNKNOWN;
+ fip->update_mac(fip, fip->data_src_addr, granted_mac);
+ memcpy(fip->data_src_addr, granted_mac, ETH_ALEN);
}
- return NULL;
+
+ /*
+ * Convert skb into an fc_frame containing only the ELS.
+ */
+ skb_pull(skb, (u8 *)fh - skb->data);
+ skb_trim(skb, els_len);
+ fp = (struct fc_frame *)skb;
+ fc_frame_init(fp);
+ fr_sof(fp) = FC_SOF_I3;
+ fr_eof(fp) = FC_EOF_T;
+ fr_dev(fp) = lp;
+
+ stats = fc_lport_get_stats(lp);
+ stats->RxFrames++;
+ stats->RxWords += skb->len / FIP_BPW;
+
+ fc_exch_recv(lp, lp->emp, fp);
+ return;
+
+len_err:
+ FIP_DBG("FIP length error in descriptor type %x len %zu\n",
+ desc->fip_dtype, dlen);
+drop:
+ kfree_skb(skb);
}
/**
- * fcoe_netdev_to_module_owner - finds out the nic drive moddule of the netdev
- * @netdev: the target netdev
+ * fcoe_ctlr_recv_els() - Handle an incoming link reset frame.
+ * @fip: FCoE controller.
+ * @fh: Received FIP header.
*
- * Returns: ptr to the struct module, NULL for failure
- **/
-static struct module *fcoe_netdev_to_module_owner(
- const struct net_device *netdev)
+ * There may be multiple VN_Port descriptors.
+ * The overall length has already been checked.
+ */
+static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
+ struct fip_header *fh)
{
- struct device *dev;
-
- if (!netdev)
- return NULL;
-
- dev = netdev->dev.parent;
- if (!dev)
- return NULL;
+ struct fip_desc *desc;
+ struct fip_mac_desc *mp;
+ struct fip_wwn_desc *wp;
+ struct fip_vn_desc *vp;
+ size_t rlen;
+ size_t dlen;
+ struct fcoe_fcf *fcf = fip->sel_fcf;
+ struct fc_lport *lp = fip->lp;
+ u32 desc_mask;
+
+ FIP_DBG("Clear Virtual Link received\n");
+ if (!fcf)
+ return;
+ if (!fcf || !fc_host_port_id(lp->host))
+ return;
- if (!dev->driver)
- return NULL;
+ /*
+ * mask of required descriptors. Validating each one clears its bit.
+ */
+ desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | BIT(FIP_DT_VN_ID);
+
+ rlen = ntohs(fh->fip_dl_len) * FIP_BPW;
+ desc = (struct fip_desc *)(fh + 1);
+ while (rlen >= sizeof(*desc)) {
+ dlen = desc->fip_dlen * FIP_BPW;
+ if (dlen > rlen)
+ return;
+ switch (desc->fip_dtype) {
+ case FIP_DT_MAC:
+ mp = (struct fip_mac_desc *)desc;
+ if (dlen < sizeof(*mp))
+ return;
+ if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac))
+ return;
+ desc_mask &= ~BIT(FIP_DT_MAC);
+ break;
+ case FIP_DT_NAME:
+ wp = (struct fip_wwn_desc *)desc;
+ if (dlen < sizeof(*wp))
+ return;
+ if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name)
+ return;
+ desc_mask &= ~BIT(FIP_DT_NAME);
+ break;
+ case FIP_DT_VN_ID:
+ vp = (struct fip_vn_desc *)desc;
+ if (dlen < sizeof(*vp))
+ return;
+ if (compare_ether_addr(vp->fd_mac,
+ fip->data_src_addr) == 0 &&
+ get_unaligned_be64(&vp->fd_wwpn) == lp->wwpn &&
+ ntoh24(vp->fd_fc_id) == fc_host_port_id(lp->host))
+ desc_mask &= ~BIT(FIP_DT_VN_ID);
+ break;
+ default:
+ /* standard says ignore unknown descriptors >= 128 */
+ if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+ return;
+ break;
+ }
+ desc = (struct fip_desc *)((char *)desc + dlen);
+ rlen -= dlen;
+ }
- return dev->driver->owner;
+ /*
+ * reset only if all required descriptors were present and valid.
+ */
+ if (desc_mask) {
+ FIP_DBG("missing descriptors mask %x\n", desc_mask);
+ } else {
+ FIP_DBG("performing Clear Virtual Link\n");
+ fcoe_ctlr_reset(fip, FIP_ST_ENABLED);
+ }
}
/**
- * fcoe_ethdrv_get - holds the nic driver module by try_module_get() for
- * the corresponding netdev.
- * @netdev: the target netdev
+ * fcoe_ctlr_recv() - Receive a FIP frame.
+ * @fip: FCoE controller.
+ * @skb: Received FIP packet.
*
- * Returns: 0 for succsss
- **/
-static int fcoe_ethdrv_get(const struct net_device *netdev)
+ * This is called from NET_RX_SOFTIRQ.
+ */
+void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
- struct module *owner;
-
- owner = fcoe_netdev_to_module_owner(netdev);
- if (owner) {
- printk(KERN_DEBUG "fcoe:hold driver module %s for %s\n",
- module_name(owner), netdev->name);
- return try_module_get(owner);
- }
- return -ENODEV;
+ spin_lock_bh(&fip->fip_recv_list.lock);
+ __skb_queue_tail(&fip->fip_recv_list, skb);
+ spin_unlock_bh(&fip->fip_recv_list.lock);
+ schedule_work(&fip->recv_work);
}
+EXPORT_SYMBOL(fcoe_ctlr_recv);
/**
- * fcoe_ethdrv_get - releases the nic driver module by module_put for
- * the corresponding netdev.
- * @netdev: the target netdev
+ * fcoe_ctlr_recv_handler() - Receive a FIP frame.
+ * @fip: FCoE controller.
+ * @skb: Received FIP packet.
*
- * Returns: 0 for succsss
- **/
-static int fcoe_ethdrv_put(const struct net_device *netdev)
+ * Returns non-zero if the frame is dropped.
+ */
+static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
{
- struct module *owner;
+ struct fip_header *fiph;
+ struct ethhdr *eh;
+ enum fip_state state;
+ u16 op;
+ u8 sub;
+
+ if (skb_linearize(skb))
+ goto drop;
+ if (skb->len < sizeof(*fiph))
+ goto drop;
+ eh = eth_hdr(skb);
+ if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
+ compare_ether_addr(eh->h_dest, FIP_ALL_ENODE_MACS))
+ goto drop;
+ fiph = (struct fip_header *)skb->data;
+ op = ntohs(fiph->fip_op);
+ sub = fiph->fip_subcode;
+
+ FIP_DBG_LVL(2, "ver %x op %x/%x dl %x fl %x\n",
+ FIP_VER_DECAPS(fiph->fip_ver), op, sub,
+ ntohs(fiph->fip_dl_len), ntohs(fiph->fip_flags));
+
+ if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
+ goto drop;
+ if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
+ goto drop;
+
+ spin_lock_bh(&fip->lock);
+ state = fip->state;
+ if (state == FIP_ST_AUTO) {
+ fip->map_dest = 0;
+ fip->state = FIP_ST_ENABLED;
+ state = FIP_ST_ENABLED;
+ FIP_DBG("using FIP mode\n");
+ }
+ spin_unlock_bh(&fip->lock);
+ if (state != FIP_ST_ENABLED)
+ goto drop;
- owner = fcoe_netdev_to_module_owner(netdev);
- if (owner) {
- printk(KERN_DEBUG "fcoe:release driver module %s for %s\n",
- module_name(owner), netdev->name);
- module_put(owner);
+ if (op == FIP_OP_LS) {
+ fcoe_ctlr_recv_els(fip, skb); /* consumes skb */
return 0;
}
- return -ENODEV;
+ if (op == FIP_OP_DISC && sub == FIP_SC_ADV)
+ fcoe_ctlr_recv_adv(fip, skb);
+ else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK)
+ fcoe_ctlr_recv_clr_vlink(fip, fiph);
+ kfree_skb(skb);
+ return 0;
+drop:
+ kfree_skb(skb);
+ return -1;
}
/**
- * fcoe_destroy- handles the destroy from sysfs
- * @buffer: expcted to be a eth if name
- * @kp: associated kernel param
+ * fcoe_ctlr_select() - Select the best FCF, if possible.
+ * @fip: FCoE controller.
+ *
+ * If there are conflicting advertisements, no FCF can be chosen.
*
- * Returns: 0 for success
- **/
-static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
+ * Called with lock held.
+ */
+static void fcoe_ctlr_select(struct fcoe_ctlr *fip)
{
- int rc;
- struct net_device *netdev;
-
- netdev = fcoe_if_to_netdev(buffer);
- if (!netdev) {
- rc = -ENODEV;
- goto out_nodev;
- }
- /* look for existing lport */
- if (!fcoe_hostlist_lookup(netdev)) {
- rc = -ENODEV;
- goto out_putdev;
- }
- /* pass to transport */
- rc = fcoe_transport_release(netdev);
- if (rc) {
- printk(KERN_ERR "fcoe: fcoe_transport_release(%s) failed\n",
- netdev->name);
- rc = -EIO;
- goto out_putdev;
+ struct fcoe_fcf *fcf;
+ struct fcoe_fcf *best = NULL;
+
+ list_for_each_entry(fcf, &fip->fcfs, list) {
+ FIP_DBG("consider FCF for fab %llx VFID %d map %x val %d\n",
+ fcf->fabric_name, fcf->vfid,
+ fcf->fc_map, fcoe_ctlr_mtu_valid(fcf));
+ if (!fcoe_ctlr_fcf_usable(fcf)) {
+ FIP_DBG("FCF for fab %llx map %x %svalid %savailable\n",
+ fcf->fabric_name, fcf->fc_map,
+ (fcf->flags & FIP_FL_SOL) ? "" : "in",
+ (fcf->flags & FIP_FL_AVAIL) ? "" : "un");
+ continue;
+ }
+ if (!best) {
+ best = fcf;
+ continue;
+ }
+ if (fcf->fabric_name != best->fabric_name ||
+ fcf->vfid != best->vfid ||
+ fcf->fc_map != best->fc_map) {
+ FIP_DBG("conflicting fabric, VFID, or FC-MAP\n");
+ return;
+ }
+ if (fcf->pri < best->pri)
+ best = fcf;
}
- fcoe_ethdrv_put(netdev);
- rc = 0;
-out_putdev:
- dev_put(netdev);
-out_nodev:
- return rc;
+ fip->sel_fcf = best;
}
/**
- * fcoe_create - handles the create call from sysfs
- * @buffer: expcted to be a eth if name
- * @kp: associated kernel param
+ * fcoe_ctlr_timeout() - FIP timer function.
+ * @arg: &fcoe_ctlr pointer.
*
- * Returns: 0 for success
- **/
-static int fcoe_create(const char *buffer, struct kernel_param *kp)
+ * Ages FCFs. Triggers FCF selection if possible. Sends keep-alives.
+ */
+static void fcoe_ctlr_timeout(unsigned long arg)
{
- int rc;
- struct net_device *netdev;
-
- netdev = fcoe_if_to_netdev(buffer);
- if (!netdev) {
- rc = -ENODEV;
- goto out_nodev;
+ struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg;
+ struct fcoe_fcf *sel;
+ struct fcoe_fcf *fcf;
+ unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
+ DECLARE_MAC_BUF(buf);
+ u8 send_ctlr_ka;
+ u8 send_port_ka;
+
+ spin_lock_bh(&fip->lock);
+ if (fip->state == FIP_ST_DISABLED) {
+ spin_unlock_bh(&fip->lock);
+ return;
}
- /* look for existing lport */
- if (fcoe_hostlist_lookup(netdev)) {
- rc = -EEXIST;
- goto out_putdev;
+
+ fcf = fip->sel_fcf;
+ fcoe_ctlr_age_fcfs(fip);
+
+ sel = fip->sel_fcf;
+ if (!sel && fip->sel_time && time_after_eq(jiffies, fip->sel_time)) {
+ fcoe_ctlr_select(fip);
+ sel = fip->sel_fcf;
+ fip->sel_time = 0;
}
- fcoe_ethdrv_get(netdev);
-
- /* pass to transport */
- rc = fcoe_transport_attach(netdev);
- if (rc) {
- printk(KERN_ERR "fcoe: fcoe_transport_attach(%s) failed\n",
- netdev->name);
- fcoe_ethdrv_put(netdev);
- rc = -EIO;
- goto out_putdev;
+
+ if (sel != fcf) {
+ fcf = sel; /* the old FCF may have been freed */
+ if (sel) {
+ printk(KERN_INFO "host%d: FIP selected "
+ "Fibre-Channel Forwarder MAC %s\n",
+ fip->lp->host->host_no,
+ print_mac(buf, sel->fcf_mac));
+ memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
+ fip->port_ka_time = jiffies +
+ msecs_to_jiffies(FIP_VN_KA_PERIOD);
+ fip->ctlr_ka_time = jiffies + sel->fka_period;
+ fip->link = 1;
+ } else {
+ printk(KERN_NOTICE "host%d: "
+ "FIP Fibre-Channel Forwarder timed out. "
+ "Starting FCF discovery.\n",
+ fip->lp->host->host_no);
+ fip->link = 0;
+ }
+ schedule_work(&fip->link_work);
}
- rc = 0;
-out_putdev:
- dev_put(netdev);
-out_nodev:
- return rc;
-}
-module_param_call(create, fcoe_create, NULL, NULL, S_IWUSR);
-__MODULE_PARM_TYPE(create, "string");
-MODULE_PARM_DESC(create, "Create fcoe port using net device passed in.");
-module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
-__MODULE_PARM_TYPE(destroy, "string");
-MODULE_PARM_DESC(destroy, "Destroy fcoe port");
+ send_ctlr_ka = 0;
+ send_port_ka = 0;
+ if (sel) {
+ if (time_after_eq(jiffies, fip->ctlr_ka_time)) {
+ fip->ctlr_ka_time = jiffies + sel->fka_period;
+ send_ctlr_ka = 1;
+ }
+ if (time_after(next_timer, fip->ctlr_ka_time))
+ next_timer = fip->ctlr_ka_time;
-/*
- * fcoe_link_ok - check if link is ok for the fc_lport
- * @lp: ptr to the fc_lport
- *
- * Any permanently-disqualifying conditions have been previously checked.
- * This also updates the speed setting, which may change with link for 100/1000.
- *
- * This function should probably be checking for PAUSE support at some point
- * in the future. Currently Per-priority-pause is not determinable using
- * ethtool, so we shouldn't be restrictive until that problem is resolved.
- *
- * Returns: 0 if link is OK for use by FCoE.
- *
- */
-int fcoe_link_ok(struct fc_lport *lp)
-{
- struct fcoe_softc *fc = fcoe_softc(lp);
- struct net_device *dev = fc->real_dev;
- struct ethtool_cmd ecmd = { ETHTOOL_GSET };
- int rc = 0;
-
- if ((dev->flags & IFF_UP) && netif_carrier_ok(dev)) {
- dev = fc->phys_dev;
- if (dev->ethtool_ops->get_settings) {
- dev->ethtool_ops->get_settings(dev, &ecmd);
- lp->link_supported_speeds &=
- ~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
- if (ecmd.supported & (SUPPORTED_1000baseT_Half |
- SUPPORTED_1000baseT_Full))
- lp->link_supported_speeds |= FC_PORTSPEED_1GBIT;
- if (ecmd.supported & SUPPORTED_10000baseT_Full)
- lp->link_supported_speeds |=
- FC_PORTSPEED_10GBIT;
- if (ecmd.speed == SPEED_1000)
- lp->link_speed = FC_PORTSPEED_1GBIT;
- if (ecmd.speed == SPEED_10000)
- lp->link_speed = FC_PORTSPEED_10GBIT;
+ if (time_after_eq(jiffies, fip->port_ka_time)) {
+ fip->port_ka_time += jiffies +
+ msecs_to_jiffies(FIP_VN_KA_PERIOD);
+ send_port_ka = 1;
}
- } else
- rc = -1;
+ if (time_after(next_timer, fip->port_ka_time))
+ next_timer = fip->port_ka_time;
+ mod_timer(&fip->timer, next_timer);
+ } else if (fip->sel_time) {
+ next_timer = fip->sel_time +
+ msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+ mod_timer(&fip->timer, next_timer);
+ }
+ spin_unlock_bh(&fip->lock);
- return rc;
+ if (send_ctlr_ka)
+ fcoe_ctlr_send_keep_alive(fip, 0, fip->ctl_src_addr);
+ if (send_port_ka)
+ fcoe_ctlr_send_keep_alive(fip, 1, fip->data_src_addr);
}
-EXPORT_SYMBOL_GPL(fcoe_link_ok);
-/*
- * fcoe_percpu_clean - frees skb of the corresponding lport from the per
- * cpu queue.
- * @lp: the fc_lport
+/**
+ * fcoe_ctlr_link_work() - worker thread function for link changes.
+ * @work: pointer to link_work member inside &fcoe_ctlr.
+ *
+ * See if the link status has changed and if so, report it.
+ *
+ * This is here because fc_linkup() and fc_linkdown() must not
+ * be called from the timer directly, since they use a mutex.
*/
-void fcoe_percpu_clean(struct fc_lport *lp)
+static void fcoe_ctlr_link_work(struct work_struct *work)
{
- int idx;
- struct fcoe_percpu_s *pp;
- struct fcoe_rcv_info *fr;
- struct sk_buff_head *list;
- struct sk_buff *skb, *next;
- struct sk_buff *head;
-
- for (idx = 0; idx < NR_CPUS; idx++) {
- if (fcoe_percpu[idx]) {
- pp = fcoe_percpu[idx];
- spin_lock_bh(&pp->fcoe_rx_list.lock);
- list = &pp->fcoe_rx_list;
- head = list->next;
- for (skb = head; skb != (struct sk_buff *)list;
- skb = next) {
- next = skb->next;
- fr = fcoe_dev_from_skb(skb);
- if (fr->fr_dev == lp) {
- __skb_unlink(skb, list);
- kfree_skb(skb);
- }
- }
- spin_unlock_bh(&pp->fcoe_rx_list.lock);
- }
+ struct fcoe_ctlr *fip;
+ int link;
+ int last_link;
+
+ fip = container_of(work, struct fcoe_ctlr, link_work);
+ spin_lock_bh(&fip->lock);
+ last_link = fip->last_link;
+ link = fip->link;
+ fip->last_link = link;
+ spin_unlock_bh(&fip->lock);
+
+ if (last_link != link) {
+ if (link)
+ fc_linkup(fip->lp);
+ else
+ fcoe_ctlr_reset(fip, FIP_ST_LINK_WAIT);
}
}
-EXPORT_SYMBOL_GPL(fcoe_percpu_clean);
/**
- * fcoe_clean_pending_queue - dequeue skb and free it
- * @lp: the corresponding fc_lport
- *
- * Returns: none
- **/
-void fcoe_clean_pending_queue(struct fc_lport *lp)
+ * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames.
+ * @recv_work: pointer to recv_work member inside &fcoe_ctlr.
+ */
+static void fcoe_ctlr_recv_work(struct work_struct *recv_work)
{
- struct fcoe_softc *fc = lport_priv(lp);
+ struct fcoe_ctlr *fip;
struct sk_buff *skb;
- spin_lock_bh(&fc->fcoe_pending_queue.lock);
- while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) {
- spin_unlock_bh(&fc->fcoe_pending_queue.lock);
- kfree_skb(skb);
- spin_lock_bh(&fc->fcoe_pending_queue.lock);
+ fip = container_of(recv_work, struct fcoe_ctlr, recv_work);
+ spin_lock_bh(&fip->fip_recv_list.lock);
+ while ((skb = __skb_dequeue(&fip->fip_recv_list))) {
+ spin_unlock_bh(&fip->fip_recv_list.lock);
+ fcoe_ctlr_recv_handler(fip, skb);
+ spin_lock_bh(&fip->fip_recv_list.lock);
}
- spin_unlock_bh(&fc->fcoe_pending_queue.lock);
+ spin_unlock_bh(&fip->fip_recv_list.lock);
}
-EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
/**
- * libfc_host_alloc - allocate a Scsi_Host with room for the fc_lport
- * @sht: ptr to the scsi host templ
- * @priv_size: size of private data after fc_lport
+ * fcoe_ctlr_recv_flogi() - snoop Pre-FIP receipt of FLOGI response or request.
+ * @fip: FCoE controller.
+ * @fp: FC frame.
+ * @sa: Ethernet source MAC address from received FCoE frame.
*
- * Returns: ptr to Scsi_Host
- * TODO - to libfc?
- */
-static inline struct Scsi_Host *libfc_host_alloc(
- struct scsi_host_template *sht, int priv_size)
-{
- return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size);
-}
-
-/**
- * fcoe_host_alloc - allocate a Scsi_Host with room for the fcoe_softc
- * @sht: ptr to the scsi host templ
- * @priv_size: size of private data after fc_lport
+ * Snoop potential response to FLOGI or even incoming FLOGI.
*
- * Returns: ptr to Scsi_Host
- */
-struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *sht, int priv_size)
-{
- return libfc_host_alloc(sht, sizeof(struct fcoe_softc) + priv_size);
-}
-EXPORT_SYMBOL_GPL(fcoe_host_alloc);
-
-/*
- * fcoe_reset - resets the fcoe
- * @shost: shost the reset is from
+ * The caller has checked that we are waiting for login as indicated
+ * by fip->flogi_oxid != FC_XID_UNKNOWN.
+ *
+ * The caller is responsible for freeing the frame.
*
- * Returns: always 0
+ * Return non-zero if the frame should not be delivered to libfc.
*/
-int fcoe_reset(struct Scsi_Host *shost)
+int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_frame *fp, u8 *sa)
{
- struct fc_lport *lport = shost_priv(shost);
- fc_lport_reset(lport);
+ struct fc_frame_header *fh;
+ u8 op;
+ u8 mac[ETH_ALEN];
+
+ fh = fc_frame_header_get(fp);
+ if (fh->fh_type != FC_TYPE_ELS)
+ return 0;
+
+ op = fc_frame_payload_op(fp);
+ if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
+ fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
+
+ spin_lock_bh(&fip->lock);
+ if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) {
+ spin_unlock_bh(&fip->lock);
+ return -EINVAL;
+ }
+ fip->state = FIP_ST_NON_FIP;
+ FIP_DBG("received FLOGI LS_ACC using non-FIP mode\n");
+
+ /*
+ * FLOGI accepted.
+ * If the src mac addr is FC_OUI-based, then we mark the
+ * address_mode flag to use FC_OUI-based Ethernet DA.
+ * Otherwise we use the FCoE gateway addr
+ */
+ if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) {
+ fip->map_dest = 1;
+ } else {
+ memcpy(fip->dest_addr, sa, ETH_ALEN);
+ fip->map_dest = 0;
+ }
+ fip->flogi_oxid = FC_XID_UNKNOWN;
+ memcpy(mac, fip->data_src_addr, ETH_ALEN);
+ fc_fcoe_set_mac(fip->data_src_addr, fh->fh_d_id);
+ spin_unlock_bh(&fip->lock);
+
+ fip->update_mac(fip, mac, fip->data_src_addr);
+ } else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
+ /*
+ * Save source MAC for point-to-point responses.
+ */
+ spin_lock_bh(&fip->lock);
+ if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) {
+ memcpy(fip->dest_addr, sa, ETH_ALEN);
+ fip->map_dest = 0;
+ if (fip->state == FIP_ST_NON_FIP)
+ FIP_DBG("received FLOGI REQ, "
+ "using non-FIP mode\n");
+ fip->state = FIP_ST_NON_FIP;
+ }
+ spin_unlock_bh(&fip->lock);
+ }
return 0;
}
-EXPORT_SYMBOL_GPL(fcoe_reset);
+EXPORT_SYMBOL(fcoe_ctlr_recv_flogi);
-/*
- * fcoe_wwn_from_mac - converts 48-bit IEEE MAC address to 64-bit FC WWN.
+/**
+ * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN.
* @mac: mac address
* @scheme: check port
* @port: port indicator for converting
@@ -1286,92 +1313,14 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
return wwn;
}
EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
-/*
- * fcoe_hostlist_lookup_softc - find the corresponding lport by a given device
- * @device: this is currently ptr to net_device
- *
- * Returns: NULL or the located fcoe_softc
- */
-static struct fcoe_softc *fcoe_hostlist_lookup_softc(
- const struct net_device *dev)
-{
- struct fcoe_softc *fc;
-
- read_lock(&fcoe_hostlist_lock);
- list_for_each_entry(fc, &fcoe_hostlist, list) {
- if (fc->real_dev == dev) {
- read_unlock(&fcoe_hostlist_lock);
- return fc;
- }
- }
- read_unlock(&fcoe_hostlist_lock);
- return NULL;
-}
-
-/*
- * fcoe_hostlist_lookup - find the corresponding lport by netdev
- * @netdev: ptr to net_device
- *
- * Returns: 0 for success
- */
-struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev)
-{
- struct fcoe_softc *fc;
-
- fc = fcoe_hostlist_lookup_softc(netdev);
-
- return (fc) ? fc->lp : NULL;
-}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup);
-
-/*
- * fcoe_hostlist_add - add a lport to lports list
- * @lp: ptr to the fc_lport to badded
- *
- * Returns: 0 for success
- */
-int fcoe_hostlist_add(const struct fc_lport *lp)
-{
- struct fcoe_softc *fc;
-
- fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
- if (!fc) {
- fc = fcoe_softc(lp);
- write_lock_bh(&fcoe_hostlist_lock);
- list_add_tail(&fc->list, &fcoe_hostlist);
- write_unlock_bh(&fcoe_hostlist_lock);
- }
- return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_add);
-
-/*
- * fcoe_hostlist_remove - remove a lport from lports list
- * @lp: ptr to the fc_lport to badded
- *
- * Returns: 0 for success
- */
-int fcoe_hostlist_remove(const struct fc_lport *lp)
-{
- struct fcoe_softc *fc;
-
- fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp));
- BUG_ON(!fc);
- write_lock_bh(&fcoe_hostlist_lock);
- list_del(&fc->list);
- write_unlock_bh(&fcoe_hostlist_lock);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_hostlist_remove);
/**
- * fcoe_libfc_config - sets up libfc related properties for lport
+ * fcoe_libfc_config() - sets up libfc related properties for lport
* @lp: ptr to the fc_lport
* @tt: libfc function template
*
* Returns : 0 for success
- **/
+ */
int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt)
{
/* Set the function pointers set by the LLDD */
@@ -1387,124 +1336,3 @@ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt)
return 0;
}
EXPORT_SYMBOL_GPL(fcoe_libfc_config);
-
-/**
- * fcoe_init - fcoe module loading initialization
- *
- * Initialization routine
- * 1. Will create fc transport software structure
- * 2. initialize the link list of port information structure
- *
- * Returns 0 on success, negative on failure
- **/
-static int __init fcoe_init(void)
-{
- int cpu;
- struct fcoe_percpu_s *p;
-
-
- INIT_LIST_HEAD(&fcoe_hostlist);
- rwlock_init(&fcoe_hostlist_lock);
-
-#ifdef CONFIG_HOTPLUG_CPU
- register_cpu_notifier(&fcoe_cpu_notifier);
-#endif /* CONFIG_HOTPLUG_CPU */
-
- /*
- * initialize per CPU interrupt thread
- */
- for_each_online_cpu(cpu) {
- p = kzalloc(sizeof(struct fcoe_percpu_s), GFP_KERNEL);
- if (p) {
- p->thread = kthread_create(fcoe_percpu_receive_thread,
- (void *)p,
- "fcoethread/%d", cpu);
-
- /*
- * if there is no error then bind the thread to the cpu
- * initialize the semaphore and skb queue head
- */
- if (likely(!IS_ERR(p->thread))) {
- p->cpu = cpu;
- fcoe_percpu[cpu] = p;
- skb_queue_head_init(&p->fcoe_rx_list);
- kthread_bind(p->thread, cpu);
- wake_up_process(p->thread);
- } else {
- fcoe_percpu[cpu] = NULL;
- kfree(p);
-
- }
- }
- }
-
- /*
- * setup link change notification
- */
- fcoe_dev_setup();
-
- init_timer(&fcoe_timer);
- fcoe_timer.data = 0;
- fcoe_timer.function = fcoe_watchdog;
- fcoe_timer.expires = (jiffies + (10 * HZ));
- add_timer(&fcoe_timer);
-
- /* initiatlize the fcoe transport */
- fcoe_transport_init();
-
- fcoe_sw_init();
-
- return 0;
-}
-module_init(fcoe_init);
-
-/**
- * fcoe_exit - fcoe module unloading cleanup
- *
- * Returns 0 on success, negative on failure
- **/
-static void __exit fcoe_exit(void)
-{
- u32 idx;
- struct fcoe_softc *fc, *tmp;
- struct fcoe_percpu_s *p;
- struct sk_buff *skb;
-
- /*
- * Stop all call back interfaces
- */
-#ifdef CONFIG_HOTPLUG_CPU
- unregister_cpu_notifier(&fcoe_cpu_notifier);
-#endif /* CONFIG_HOTPLUG_CPU */
- fcoe_dev_cleanup();
-
- /*
- * stop timer
- */
- del_timer_sync(&fcoe_timer);
-
- /* releases the assocaited fcoe transport for each lport */
- list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list)
- fcoe_transport_release(fc->real_dev);
-
- for (idx = 0; idx < NR_CPUS; idx++) {
- if (fcoe_percpu[idx]) {
- kthread_stop(fcoe_percpu[idx]->thread);
- p = fcoe_percpu[idx];
- spin_lock_bh(&p->fcoe_rx_list.lock);
- while ((skb = __skb_dequeue(&p->fcoe_rx_list)) != NULL)
- kfree_skb(skb);
- spin_unlock_bh(&p->fcoe_rx_list.lock);
- if (fcoe_percpu[idx]->crc_eof_page)
- put_page(fcoe_percpu[idx]->crc_eof_page);
- kfree(fcoe_percpu[idx]);
- }
- }
-
- /* remove sw trasnport */
- fcoe_sw_exit();
-
- /* detach the transport */
- fcoe_transport_exit();
-}
-module_exit(fcoe_exit);
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index aa670a1d151..89d41a424b3 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -176,7 +176,6 @@ void scsi_remove_host(struct Scsi_Host *shost)
transport_unregister_device(&shost->shost_gendev);
device_unregister(&shost->shost_dev);
device_del(&shost->shost_gendev);
- scsi_proc_hostdir_rm(shost->hostt);
}
EXPORT_SYMBOL(scsi_remove_host);
@@ -270,6 +269,8 @@ static void scsi_host_dev_release(struct device *dev)
struct Scsi_Host *shost = dev_to_shost(dev);
struct device *parent = dev->parent;
+ scsi_proc_hostdir_rm(shost->hostt);
+
if (shost->ehandler)
kthread_stop(shost->ehandler);
if (shost->work_q)
diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c
index a48e4990fe1..af1f0af0c5a 100644
--- a/drivers/scsi/hptiop.c
+++ b/drivers/scsi/hptiop.c
@@ -580,8 +580,7 @@ static void hptiop_finish_scsi_req(struct hptiop_hba *hba, u32 tag,
break;
default:
- scp->result = ((DRIVER_INVALID|SUGGEST_ABORT)<<24) |
- (DID_ABORT<<16);
+ scp->result = DRIVER_INVALID << 24 | DID_ABORT << 16;
break;
}
@@ -1251,6 +1250,7 @@ static struct pci_device_id hptiop_id_table[] = {
{ PCI_VDEVICE(TTI, 0x3530), (kernel_ulong_t)&hptiop_itl_ops },
{ PCI_VDEVICE(TTI, 0x3560), (kernel_ulong_t)&hptiop_itl_ops },
{ PCI_VDEVICE(TTI, 0x4322), (kernel_ulong_t)&hptiop_itl_ops },
+ { PCI_VDEVICE(TTI, 0x4321), (kernel_ulong_t)&hptiop_itl_ops },
{ PCI_VDEVICE(TTI, 0x4210), (kernel_ulong_t)&hptiop_itl_ops },
{ PCI_VDEVICE(TTI, 0x4211), (kernel_ulong_t)&hptiop_itl_ops },
{ PCI_VDEVICE(TTI, 0x4310), (kernel_ulong_t)&hptiop_itl_ops },
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index a1a511bdec8..ea4abee7a2a 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -75,7 +75,7 @@ MODULE_PARM_DESC(max_lun, "Maximum allowed LUN. "
module_param_named(max_targets, max_targets, uint, S_IRUGO);
MODULE_PARM_DESC(max_targets, "Maximum allowed targets. "
"[Default=" __stringify(IBMVFC_MAX_TARGETS) "]");
-module_param_named(disc_threads, disc_threads, uint, S_IRUGO | S_IWUSR);
+module_param_named(disc_threads, disc_threads, uint, S_IRUGO);
MODULE_PARM_DESC(disc_threads, "Number of device discovery threads to use. "
"[Default=" __stringify(IBMVFC_MAX_DISC_THREADS) "]");
module_param_named(debug, ibmvfc_debug, uint, S_IRUGO | S_IWUSR);
@@ -640,6 +640,7 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost)
ibmvfc_dbg(vhost, "Releasing CRQ\n");
free_irq(vdev->irq, vhost);
+ tasklet_kill(&vhost->tasklet);
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
@@ -1573,9 +1574,6 @@ static int ibmvfc_queuecommand(struct scsi_cmnd *cmnd,
vfc_cmd->resp_len = sizeof(vfc_cmd->rsp);
vfc_cmd->cancel_key = (unsigned long)cmnd->device->hostdata;
vfc_cmd->tgt_scsi_id = rport->port_id;
- if ((rport->supported_classes & FC_COS_CLASS3) &&
- (fc_host_supported_classes(vhost->host) & FC_COS_CLASS3))
- vfc_cmd->flags = IBMVFC_CLASS_3_ERR;
vfc_cmd->iu.xfer_len = scsi_bufflen(cmnd);
int_to_scsilun(cmnd->device->lun, &vfc_cmd->iu.lun);
memcpy(vfc_cmd->iu.cdb, cmnd->cmnd, cmnd->cmd_len);
@@ -2702,6 +2700,25 @@ static struct ibmvfc_crq *ibmvfc_next_crq(struct ibmvfc_host *vhost)
static irqreturn_t ibmvfc_interrupt(int irq, void *dev_instance)
{
struct ibmvfc_host *vhost = (struct ibmvfc_host *)dev_instance;
+ unsigned long flags;
+
+ spin_lock_irqsave(vhost->host->host_lock, flags);
+ vio_disable_interrupts(to_vio_dev(vhost->dev));
+ tasklet_schedule(&vhost->tasklet);
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ return IRQ_HANDLED;
+}
+
+/**
+ * ibmvfc_tasklet - Interrupt handler tasklet
+ * @data: ibmvfc host struct
+ *
+ * Returns:
+ * Nothing
+ **/
+static void ibmvfc_tasklet(void *data)
+{
+ struct ibmvfc_host *vhost = data;
struct vio_dev *vdev = to_vio_dev(vhost->dev);
struct ibmvfc_crq *crq;
struct ibmvfc_async_crq *async;
@@ -2709,7 +2726,6 @@ static irqreturn_t ibmvfc_interrupt(int irq, void *dev_instance)
int done = 0;
spin_lock_irqsave(vhost->host->host_lock, flags);
- vio_disable_interrupts(to_vio_dev(vhost->dev));
while (!done) {
/* Pull all the valid messages off the CRQ */
while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
@@ -2737,7 +2753,6 @@ static irqreturn_t ibmvfc_interrupt(int irq, void *dev_instance)
}
spin_unlock_irqrestore(vhost->host->host_lock, flags);
- return IRQ_HANDLED;
}
/**
@@ -2770,6 +2785,40 @@ static void ibmvfc_retry_tgt_init(struct ibmvfc_target *tgt,
ibmvfc_init_tgt(tgt, job_step);
}
+/* Defined in FC-LS */
+static const struct {
+ int code;
+ int retry;
+ int logged_in;
+} prli_rsp [] = {
+ { 0, 1, 0 },
+ { 1, 0, 1 },
+ { 2, 1, 0 },
+ { 3, 1, 0 },
+ { 4, 0, 0 },
+ { 5, 0, 0 },
+ { 6, 0, 1 },
+ { 7, 0, 0 },
+ { 8, 1, 0 },
+};
+
+/**
+ * ibmvfc_get_prli_rsp - Find PRLI response index
+ * @flags: PRLI response flags
+ *
+ **/
+static int ibmvfc_get_prli_rsp(u16 flags)
+{
+ int i;
+ int code = (flags & 0x0f00) >> 8;
+
+ for (i = 0; i < ARRAY_SIZE(prli_rsp); i++)
+ if (prli_rsp[i].code == code)
+ return i;
+
+ return 0;
+}
+
/**
* ibmvfc_tgt_prli_done - Completion handler for Process Login
* @evt: ibmvfc event struct
@@ -2780,15 +2829,36 @@ static void ibmvfc_tgt_prli_done(struct ibmvfc_event *evt)
struct ibmvfc_target *tgt = evt->tgt;
struct ibmvfc_host *vhost = evt->vhost;
struct ibmvfc_process_login *rsp = &evt->xfer_iu->prli;
+ struct ibmvfc_prli_svc_parms *parms = &rsp->parms;
u32 status = rsp->common.status;
+ int index;
vhost->discovery_threads--;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
switch (status) {
case IBMVFC_MAD_SUCCESS:
- tgt_dbg(tgt, "Process Login succeeded\n");
- tgt->need_login = 0;
- ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT);
+ tgt_dbg(tgt, "Process Login succeeded: %X %02X %04X\n",
+ parms->type, parms->flags, parms->service_parms);
+
+ if (parms->type == IBMVFC_SCSI_FCP_TYPE) {
+ index = ibmvfc_get_prli_rsp(parms->flags);
+ if (prli_rsp[index].logged_in) {
+ if (parms->flags & IBMVFC_PRLI_EST_IMG_PAIR) {
+ tgt->need_login = 0;
+ tgt->ids.roles = 0;
+ if (parms->service_parms & IBMVFC_PRLI_TARGET_FUNC)
+ tgt->ids.roles |= FC_PORT_ROLE_FCP_TARGET;
+ if (parms->service_parms & IBMVFC_PRLI_INITIATOR_FUNC)
+ tgt->ids.roles |= FC_PORT_ROLE_FCP_INITIATOR;
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_ADD_RPORT);
+ } else
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ } else if (prli_rsp[index].retry)
+ ibmvfc_retry_tgt_init(tgt, ibmvfc_tgt_send_prli);
+ else
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
+ } else
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_DEL_RPORT);
break;
case IBMVFC_MAD_DRIVER_FAILED:
break;
@@ -2877,7 +2947,6 @@ static void ibmvfc_tgt_plogi_done(struct ibmvfc_event *evt)
tgt->ids.node_name = wwn_to_u64(rsp->service_parms.node_name);
tgt->ids.port_name = wwn_to_u64(rsp->service_parms.port_name);
tgt->ids.port_id = tgt->scsi_id;
- tgt->ids.roles = FC_PORT_ROLE_FCP_TARGET;
memcpy(&tgt->service_parms, &rsp->service_parms,
sizeof(tgt->service_parms));
memcpy(&tgt->service_parms_change, &rsp->service_parms_change,
@@ -3054,6 +3123,7 @@ static void ibmvfc_tgt_adisc_done(struct ibmvfc_event *evt)
vhost->discovery_threads--;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+ del_timer(&tgt->timer);
switch (status) {
case IBMVFC_MAD_SUCCESS:
@@ -3110,9 +3180,89 @@ static void ibmvfc_init_passthru(struct ibmvfc_event *evt)
}
/**
+ * ibmvfc_tgt_adisc_cancel_done - Completion handler when cancelling an ADISC
+ * @evt: ibmvfc event struct
+ *
+ * Just cleanup this event struct. Everything else is handled by
+ * the ADISC completion handler. If the ADISC never actually comes
+ * back, we still have the timer running on the ADISC event struct
+ * which will fire and cause the CRQ to get reset.
+ *
+ **/
+static void ibmvfc_tgt_adisc_cancel_done(struct ibmvfc_event *evt)
+{
+ struct ibmvfc_host *vhost = evt->vhost;
+ struct ibmvfc_target *tgt = evt->tgt;
+
+ tgt_dbg(tgt, "ADISC cancel complete\n");
+ vhost->abort_threads--;
+ ibmvfc_free_event(evt);
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
+ wake_up(&vhost->work_wait_q);
+}
+
+/**
+ * ibmvfc_adisc_timeout - Handle an ADISC timeout
+ * @tgt: ibmvfc target struct
+ *
+ * If an ADISC times out, send a cancel. If the cancel times
+ * out, reset the CRQ. When the ADISC comes back as cancelled,
+ * log back into the target.
+ **/
+static void ibmvfc_adisc_timeout(struct ibmvfc_target *tgt)
+{
+ struct ibmvfc_host *vhost = tgt->vhost;
+ struct ibmvfc_event *evt;
+ struct ibmvfc_tmf *tmf;
+ unsigned long flags;
+ int rc;
+
+ tgt_dbg(tgt, "ADISC timeout\n");
+ spin_lock_irqsave(vhost->host->host_lock, flags);
+ if (vhost->abort_threads >= disc_threads ||
+ tgt->action != IBMVFC_TGT_ACTION_INIT_WAIT ||
+ vhost->state != IBMVFC_INITIALIZING ||
+ vhost->action != IBMVFC_HOST_ACTION_QUERY_TGTS) {
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ return;
+ }
+
+ vhost->abort_threads++;
+ kref_get(&tgt->kref);
+ evt = ibmvfc_get_event(vhost);
+ ibmvfc_init_event(evt, ibmvfc_tgt_adisc_cancel_done, IBMVFC_MAD_FORMAT);
+
+ evt->tgt = tgt;
+ tmf = &evt->iu.tmf;
+ memset(tmf, 0, sizeof(*tmf));
+ tmf->common.version = 1;
+ tmf->common.opcode = IBMVFC_TMF_MAD;
+ tmf->common.length = sizeof(*tmf);
+ tmf->scsi_id = tgt->scsi_id;
+ tmf->cancel_key = tgt->cancel_key;
+
+ rc = ibmvfc_send_event(evt, vhost, default_timeout);
+
+ if (rc) {
+ tgt_err(tgt, "Failed to send cancel event for ADISC. rc=%d\n", rc);
+ vhost->abort_threads--;
+ kref_put(&tgt->kref, ibmvfc_release_tgt);
+ __ibmvfc_reset_host(vhost);
+ } else
+ tgt_dbg(tgt, "Attempting to cancel ADISC\n");
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+}
+
+/**
* ibmvfc_tgt_adisc - Initiate an ADISC for specified target
* @tgt: ibmvfc target struct
*
+ * When sending an ADISC we end up with two timers running. The
+ * first timer is the timer in the ibmvfc target struct. If this
+ * fires, we send a cancel to the target. The second timer is the
+ * timer on the ibmvfc event for the ADISC, which is longer. If that
+ * fires, it means the ADISC timed out and our attempt to cancel it
+ * also failed, so we need to reset the CRQ.
**/
static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
{
@@ -3133,6 +3283,7 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
mad = &evt->iu.passthru;
mad->iu.flags = IBMVFC_FC_ELS;
mad->iu.scsi_id = tgt->scsi_id;
+ mad->iu.cancel_key = tgt->cancel_key;
mad->fc_iu.payload[0] = IBMVFC_ADISC;
memcpy(&mad->fc_iu.payload[2], &vhost->login_buf->resp.port_name,
@@ -3141,9 +3292,19 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
sizeof(vhost->login_buf->resp.node_name));
mad->fc_iu.payload[6] = vhost->login_buf->resp.scsi_id & 0x00ffffff;
+ if (timer_pending(&tgt->timer))
+ mod_timer(&tgt->timer, jiffies + (IBMVFC_ADISC_TIMEOUT * HZ));
+ else {
+ tgt->timer.data = (unsigned long) tgt;
+ tgt->timer.expires = jiffies + (IBMVFC_ADISC_TIMEOUT * HZ);
+ tgt->timer.function = (void (*)(unsigned long))ibmvfc_adisc_timeout;
+ add_timer(&tgt->timer);
+ }
+
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
- if (ibmvfc_send_event(evt, vhost, default_timeout)) {
+ if (ibmvfc_send_event(evt, vhost, IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT)) {
vhost->discovery_threads--;
+ del_timer(&tgt->timer);
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
kref_put(&tgt->kref, ibmvfc_release_tgt);
} else
@@ -3266,10 +3427,13 @@ static int ibmvfc_alloc_target(struct ibmvfc_host *vhost, u64 scsi_id)
return -ENOMEM;
}
+ memset(tgt, 0, sizeof(*tgt));
tgt->scsi_id = scsi_id;
tgt->new_scsi_id = scsi_id;
tgt->vhost = vhost;
tgt->need_login = 1;
+ tgt->cancel_key = vhost->task_set++;
+ init_timer(&tgt->timer);
kref_init(&tgt->kref);
ibmvfc_init_tgt(tgt, ibmvfc_tgt_implicit_logout);
spin_lock_irqsave(vhost->host->host_lock, flags);
@@ -3576,9 +3740,18 @@ static void ibmvfc_log_ae(struct ibmvfc_host *vhost, int events)
static void ibmvfc_tgt_add_rport(struct ibmvfc_target *tgt)
{
struct ibmvfc_host *vhost = tgt->vhost;
- struct fc_rport *rport;
+ struct fc_rport *rport = tgt->rport;
unsigned long flags;
+ if (rport) {
+ tgt_dbg(tgt, "Setting rport roles\n");
+ fc_remote_port_rolechg(rport, tgt->ids.roles);
+ spin_lock_irqsave(vhost->host->host_lock, flags);
+ ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_NONE);
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ return;
+ }
+
tgt_dbg(tgt, "Adding rport\n");
rport = fc_remote_port_add(vhost->host, 0, &tgt->ids);
spin_lock_irqsave(vhost->host->host_lock, flags);
@@ -3655,6 +3828,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
spin_unlock_irqrestore(vhost->host->host_lock, flags);
if (rport)
fc_remote_port_delete(rport);
+ del_timer_sync(&tgt->timer);
kref_put(&tgt->kref, ibmvfc_release_tgt);
return;
}
@@ -3798,6 +3972,8 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
retrc = 0;
+ tasklet_init(&vhost->tasklet, (void *)ibmvfc_tasklet, (unsigned long)vhost);
+
if ((rc = request_irq(vdev->irq, ibmvfc_interrupt, 0, IBMVFC_NAME, vhost))) {
dev_err(dev, "Couldn't register irq 0x%x. rc=%d\n", vdev->irq, rc);
goto req_irq_failed;
@@ -3813,6 +3989,7 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
return retrc;
req_irq_failed:
+ tasklet_kill(&vhost->tasklet);
do {
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
@@ -3979,6 +4156,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
vhost->dev = dev;
vhost->partition_number = -1;
vhost->log_level = log_level;
+ vhost->task_set = 1;
strcpy(vhost->partition_name, "UNKNOWN");
init_waitqueue_head(&vhost->work_wait_q);
init_waitqueue_head(&vhost->init_wait_q);
@@ -4113,6 +4291,7 @@ static struct fc_function_template ibmvfc_transport_functions = {
.show_host_supported_classes = 1,
.show_host_port_type = 1,
.show_host_port_id = 1,
+ .show_host_maxframe_size = 1,
.get_host_port_state = ibmvfc_get_host_port_state,
.show_host_port_state = 1,
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 87dafd0f8d4..ca1dcf7a756 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -29,10 +29,14 @@
#include "viosrp.h"
#define IBMVFC_NAME "ibmvfc"
-#define IBMVFC_DRIVER_VERSION "1.0.4"
-#define IBMVFC_DRIVER_DATE "(November 14, 2008)"
-
-#define IBMVFC_DEFAULT_TIMEOUT 15
+#define IBMVFC_DRIVER_VERSION "1.0.5"
+#define IBMVFC_DRIVER_DATE "(March 19, 2009)"
+
+#define IBMVFC_DEFAULT_TIMEOUT 60
+#define IBMVFC_ADISC_CANCEL_TIMEOUT 45
+#define IBMVFC_ADISC_TIMEOUT 15
+#define IBMVFC_ADISC_PLUS_CANCEL_TIMEOUT \
+ (IBMVFC_ADISC_TIMEOUT + IBMVFC_ADISC_CANCEL_TIMEOUT)
#define IBMVFC_INIT_TIMEOUT 120
#define IBMVFC_MAX_REQUESTS_DEFAULT 100
@@ -53,9 +57,9 @@
* Ensure we have resources for ERP and initialization:
* 1 for ERP
* 1 for initialization
- * 1 for each discovery thread
+ * 2 for each discovery thread
*/
-#define IBMVFC_NUM_INTERNAL_REQ (1 + 1 + disc_threads)
+#define IBMVFC_NUM_INTERNAL_REQ (1 + 1 + (disc_threads * 2))
#define IBMVFC_MAD_SUCCESS 0x00
#define IBMVFC_MAD_NOT_SUPPORTED 0xF1
@@ -585,10 +589,12 @@ struct ibmvfc_target {
enum ibmvfc_target_action action;
int need_login;
int init_retries;
+ u32 cancel_key;
struct ibmvfc_service_parms service_parms;
struct ibmvfc_service_parms service_parms_change;
struct fc_rport_identifiers ids;
void (*job_step) (struct ibmvfc_target *);
+ struct timer_list timer;
struct kref kref;
};
@@ -672,6 +678,7 @@ struct ibmvfc_host {
int task_set;
int init_retries;
int discovery_threads;
+ int abort_threads;
int client_migrated;
int reinit;
int delay_init;
@@ -684,6 +691,7 @@ struct ibmvfc_host {
char partition_name[97];
void (*job_step) (struct ibmvfc_host *);
struct task_struct *work_thread;
+ struct tasklet_struct tasklet;
wait_queue_head_t init_wait_q;
wait_queue_head_t work_wait_q;
};
diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c
index 74d07d137da..c9aa7611e40 100644
--- a/drivers/scsi/ibmvscsi/ibmvscsi.c
+++ b/drivers/scsi/ibmvscsi/ibmvscsi.c
@@ -432,6 +432,7 @@ static int map_sg_data(struct scsi_cmnd *cmd,
sdev_printk(KERN_ERR, cmd->device,
"Can't allocate memory "
"for indirect table\n");
+ scsi_dma_unmap(cmd);
return 0;
}
}
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index 07829009a8b..def473f0a98 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -152,13 +152,13 @@ module_param_named(log_level, ipr_log_level, uint, 0);
MODULE_PARM_DESC(log_level, "Set to 0 - 4 for increasing verbosity of device driver");
module_param_named(testmode, ipr_testmode, int, 0);
MODULE_PARM_DESC(testmode, "DANGEROUS!!! Allows unsupported configurations");
-module_param_named(fastfail, ipr_fastfail, int, 0);
+module_param_named(fastfail, ipr_fastfail, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(fastfail, "Reduce timeouts and retries");
module_param_named(transop_timeout, ipr_transop_timeout, int, 0);
MODULE_PARM_DESC(transop_timeout, "Time in seconds to wait for adapter to come operational (default: 300)");
module_param_named(enable_cache, ipr_enable_cache, int, 0);
MODULE_PARM_DESC(enable_cache, "Enable adapter's non-volatile write cache (default: 1)");
-module_param_named(debug, ipr_debug, int, 0);
+module_param_named(debug, ipr_debug, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Enable device driver debugging logging. Set to 1 to enable. (default: 0)");
module_param_named(dual_ioa_raid, ipr_dual_ioa_raid, int, 0);
MODULE_PARM_DESC(dual_ioa_raid, "Enable dual adapter RAID support. Set to 1 to enable. (default: 1)");
@@ -354,6 +354,8 @@ struct ipr_error_table_t ipr_error_table[] = {
"9076: Configuration error, missing remote IOA"},
{0x06679100, 0, IPR_DEFAULT_LOG_LEVEL,
"4050: Enclosure does not support a required multipath function"},
+ {0x06690000, 0, IPR_DEFAULT_LOG_LEVEL,
+ "4070: Logically bad block written on device"},
{0x06690200, 0, IPR_DEFAULT_LOG_LEVEL,
"9041: Array protection temporarily suspended"},
{0x06698200, 0, IPR_DEFAULT_LOG_LEVEL,
@@ -7147,6 +7149,7 @@ static void ipr_free_all_resources(struct ipr_ioa_cfg *ioa_cfg)
ENTER;
free_irq(pdev->irq, ioa_cfg);
+ pci_disable_msi(pdev);
iounmap(ioa_cfg->hdw_dma_regs);
pci_release_regions(pdev);
ipr_free_mem(ioa_cfg);
@@ -7432,6 +7435,11 @@ static int __devinit ipr_probe_ioa(struct pci_dev *pdev,
goto out;
}
+ if (!(rc = pci_enable_msi(pdev)))
+ dev_info(&pdev->dev, "MSI enabled\n");
+ else if (ipr_debug)
+ dev_info(&pdev->dev, "Cannot enable MSI\n");
+
dev_info(&pdev->dev, "Found IOA with IRQ: %d\n", pdev->irq);
host = scsi_host_alloc(&driver_template, sizeof(*ioa_cfg));
@@ -7574,6 +7582,7 @@ out_release_regions:
out_scsi_host_put:
scsi_host_put(host);
out_disable:
+ pci_disable_msi(pdev);
pci_disable_device(pdev);
goto out;
}
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index 8f872f816fe..79a3ae4fb2c 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -37,8 +37,8 @@
/*
* Literals
*/
-#define IPR_DRIVER_VERSION "2.4.1"
-#define IPR_DRIVER_DATE "(April 24, 2007)"
+#define IPR_DRIVER_VERSION "2.4.2"
+#define IPR_DRIVER_DATE "(January 21, 2009)"
/*
* IPR_MAX_CMD_PER_LUN: This defines the maximum number of outstanding
diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c
index ef683f0d2b5..457d76a4cfe 100644
--- a/drivers/scsi/ips.c
+++ b/drivers/scsi/ips.c
@@ -1004,8 +1004,7 @@ static int __ips_eh_reset(struct scsi_cmnd *SC)
DEBUG_VAR(1, "(%s%d) Failing active commands", ips_name, ha->host_num);
while ((scb = ips_removeq_scb_head(&ha->scb_activelist))) {
- scb->scsi_cmd->result =
- (DID_RESET << 16) | (SUGGEST_RETRY << 24);
+ scb->scsi_cmd->result = DID_RESET << 16;
scb->scsi_cmd->scsi_done(scb->scsi_cmd);
ips_freescb(ha, scb);
}
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 23808dfe22b..b3e5e08e44a 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -48,13 +48,6 @@ MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
"Alex Aizman <itn780@yahoo.com>");
MODULE_DESCRIPTION("iSCSI/TCP data-path");
MODULE_LICENSE("GPL");
-#undef DEBUG_TCP
-
-#ifdef DEBUG_TCP
-#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
-#else
-#define debug_tcp(fmt...)
-#endif
static struct scsi_transport_template *iscsi_sw_tcp_scsi_transport;
static struct scsi_host_template iscsi_sw_tcp_sht;
@@ -63,6 +56,21 @@ static struct iscsi_transport iscsi_sw_tcp_transport;
static unsigned int iscsi_max_lun = 512;
module_param_named(max_lun, iscsi_max_lun, uint, S_IRUGO);
+static int iscsi_sw_tcp_dbg;
+module_param_named(debug_iscsi_tcp, iscsi_sw_tcp_dbg, int,
+ S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug_iscsi_tcp, "Turn on debugging for iscsi_tcp module "
+ "Set to 1 to turn on, and zero to turn off. Default is off.");
+
+#define ISCSI_SW_TCP_DBG(_conn, dbg_fmt, arg...) \
+ do { \
+ if (iscsi_sw_tcp_dbg) \
+ iscsi_conn_printk(KERN_INFO, _conn, \
+ "%s " dbg_fmt, \
+ __func__, ##arg); \
+ } while (0);
+
+
/**
* iscsi_sw_tcp_recv - TCP receive in sendfile fashion
* @rd_desc: read descriptor
@@ -77,7 +85,7 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
unsigned int consumed, total_consumed = 0;
int status;
- debug_tcp("in %d bytes\n", skb->len - offset);
+ ISCSI_SW_TCP_DBG(conn, "in %d bytes\n", skb->len - offset);
do {
status = 0;
@@ -86,7 +94,8 @@ static int iscsi_sw_tcp_recv(read_descriptor_t *rd_desc, struct sk_buff *skb,
total_consumed += consumed;
} while (consumed != 0 && status != ISCSI_TCP_SKB_DONE);
- debug_tcp("read %d bytes status %d\n", skb->len - offset, status);
+ ISCSI_SW_TCP_DBG(conn, "read %d bytes status %d\n",
+ skb->len - offset, status);
return total_consumed;
}
@@ -131,7 +140,8 @@ static void iscsi_sw_tcp_state_change(struct sock *sk)
if ((sk->sk_state == TCP_CLOSE_WAIT ||
sk->sk_state == TCP_CLOSE) &&
!atomic_read(&sk->sk_rmem_alloc)) {
- debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n");
+ ISCSI_SW_TCP_DBG(conn, "iscsi_tcp_state_change: "
+ "TCP_CLOSE|TCP_CLOSE_WAIT\n");
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
}
@@ -155,8 +165,8 @@ static void iscsi_sw_tcp_write_space(struct sock *sk)
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
tcp_sw_conn->old_write_space(sk);
- debug_tcp("iscsi_write_space: cid %d\n", conn->id);
- scsi_queue_work(conn->session->host, &conn->xmitwork);
+ ISCSI_SW_TCP_DBG(conn, "iscsi_write_space\n");
+ iscsi_conn_queue_work(conn);
}
static void iscsi_sw_tcp_conn_set_callbacks(struct iscsi_conn *conn)
@@ -283,7 +293,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
}
}
- debug_tcp("xmit %d bytes\n", consumed);
+ ISCSI_SW_TCP_DBG(conn, "xmit %d bytes\n", consumed);
conn->txdata_octets += consumed;
return consumed;
@@ -291,7 +301,7 @@ static int iscsi_sw_tcp_xmit(struct iscsi_conn *conn)
error:
/* Transmit error. We could initiate error recovery
* here. */
- debug_tcp("Error sending PDU, errno=%d\n", rc);
+ ISCSI_SW_TCP_DBG(conn, "Error sending PDU, errno=%d\n", rc);
iscsi_conn_failure(conn, rc);
return -EIO;
}
@@ -334,9 +344,10 @@ static int iscsi_sw_tcp_send_hdr_done(struct iscsi_tcp_conn *tcp_conn,
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
tcp_sw_conn->out.segment = tcp_sw_conn->out.data_segment;
- debug_tcp("Header done. Next segment size %u total_size %u\n",
- tcp_sw_conn->out.segment.size,
- tcp_sw_conn->out.segment.total_size);
+ ISCSI_SW_TCP_DBG(tcp_conn->iscsi_conn,
+ "Header done. Next segment size %u total_size %u\n",
+ tcp_sw_conn->out.segment.size,
+ tcp_sw_conn->out.segment.total_size);
return 0;
}
@@ -346,8 +357,8 @@ static void iscsi_sw_tcp_send_hdr_prep(struct iscsi_conn *conn, void *hdr,
struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
- debug_tcp("%s(%p%s)\n", __func__, tcp_conn,
- conn->hdrdgst_en? ", digest enabled" : "");
+ ISCSI_SW_TCP_DBG(conn, "%s\n", conn->hdrdgst_en ?
+ "digest enabled" : "digest disabled");
/* Clear the data segment - needs to be filled in by the
* caller using iscsi_tcp_send_data_prep() */
@@ -389,9 +400,9 @@ iscsi_sw_tcp_send_data_prep(struct iscsi_conn *conn, struct scatterlist *sg,
struct hash_desc *tx_hash = NULL;
unsigned int hdr_spec_len;
- debug_tcp("%s(%p, offset=%d, datalen=%d%s)\n", __func__,
- tcp_conn, offset, len,
- conn->datadgst_en? ", digest enabled" : "");
+ ISCSI_SW_TCP_DBG(conn, "offset=%d, datalen=%d %s\n", offset, len,
+ conn->datadgst_en ?
+ "digest enabled" : "digest disabled");
/* Make sure the datalen matches what the caller
said he would send. */
@@ -415,8 +426,8 @@ iscsi_sw_tcp_send_linear_data_prep(struct iscsi_conn *conn, void *data,
struct hash_desc *tx_hash = NULL;
unsigned int hdr_spec_len;
- debug_tcp("%s(%p, datalen=%d%s)\n", __func__, tcp_conn, len,
- conn->datadgst_en? ", digest enabled" : "");
+ ISCSI_SW_TCP_DBG(conn, "datalen=%zd %s\n", len, conn->datadgst_en ?
+ "digest enabled" : "digest disabled");
/* Make sure the datalen matches what the caller
said he would send. */
@@ -754,8 +765,7 @@ iscsi_sw_tcp_conn_get_stats(struct iscsi_cls_conn *cls_conn,
static struct iscsi_cls_session *
iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
- uint16_t qdepth, uint32_t initial_cmdsn,
- uint32_t *hostno)
+ uint16_t qdepth, uint32_t initial_cmdsn)
{
struct iscsi_cls_session *cls_session;
struct iscsi_session *session;
@@ -766,10 +776,11 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
return NULL;
}
- shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, qdepth);
+ shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1);
if (!shost)
return NULL;
shost->transportt = iscsi_sw_tcp_scsi_transport;
+ shost->cmd_per_lun = qdepth;
shost->max_lun = iscsi_max_lun;
shost->max_id = 0;
shost->max_channel = 0;
@@ -777,7 +788,6 @@ iscsi_sw_tcp_session_create(struct iscsi_endpoint *ep, uint16_t cmds_max,
if (iscsi_host_add(shost, NULL))
goto free_host;
- *hostno = shost->host_no;
cls_session = iscsi_session_setup(&iscsi_sw_tcp_transport, shost,
cmds_max,
@@ -813,6 +823,12 @@ static void iscsi_sw_tcp_session_destroy(struct iscsi_cls_session *cls_session)
iscsi_host_free(shost);
}
+static int iscsi_sw_tcp_slave_alloc(struct scsi_device *sdev)
+{
+ set_bit(QUEUE_FLAG_BIDI, &sdev->request_queue->queue_flags);
+ return 0;
+}
+
static int iscsi_sw_tcp_slave_configure(struct scsi_device *sdev)
{
blk_queue_bounce_limit(sdev->request_queue, BLK_BOUNCE_ANY);
@@ -833,6 +849,7 @@ static struct scsi_host_template iscsi_sw_tcp_sht = {
.eh_device_reset_handler= iscsi_eh_device_reset,
.eh_target_reset_handler= iscsi_eh_target_reset,
.use_clustering = DISABLE_CLUSTERING,
+ .slave_alloc = iscsi_sw_tcp_slave_alloc,
.slave_configure = iscsi_sw_tcp_slave_configure,
.proc_name = "iscsi_tcp",
.this_id = -1,
diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c
index 4a4e6954ec7..f23c4ca9a2e 100644
--- a/drivers/scsi/lasi700.c
+++ b/drivers/scsi/lasi700.c
@@ -103,7 +103,7 @@ lasi700_probe(struct parisc_device *dev)
hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL);
if (!hostdata) {
- dev_printk(KERN_ERR, dev, "Failed to allocate host data\n");
+ dev_printk(KERN_ERR, &dev->dev, "Failed to allocate host data\n");
return -ENOMEM;
}
diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c
index dd1564c9e04..e57556ea5b4 100644
--- a/drivers/scsi/libfc/fc_disc.c
+++ b/drivers/scsi/libfc/fc_disc.c
@@ -64,7 +64,7 @@ static void fc_disc_single(struct fc_disc *, struct fc_disc_port *);
static void fc_disc_restart(struct fc_disc *);
/**
- * fc_disc_lookup_rport - lookup a remote port by port_id
+ * fc_disc_lookup_rport() - lookup a remote port by port_id
* @lport: Fibre Channel host port instance
* @port_id: remote port port_id to match
*/
@@ -92,7 +92,7 @@ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport,
}
/**
- * fc_disc_stop_rports - delete all the remote ports associated with the lport
+ * fc_disc_stop_rports() - delete all the remote ports associated with the lport
* @disc: The discovery job to stop rports on
*
* Locking Note: This function expects that the lport mutex is locked before
@@ -117,7 +117,7 @@ void fc_disc_stop_rports(struct fc_disc *disc)
}
/**
- * fc_disc_rport_callback - Event handler for rport events
+ * fc_disc_rport_callback() - Event handler for rport events
* @lport: The lport which is receiving the event
* @rport: The rport which the event has occured on
* @event: The event that occured
@@ -151,7 +151,7 @@ static void fc_disc_rport_callback(struct fc_lport *lport,
}
/**
- * fc_disc_recv_rscn_req - Handle Registered State Change Notification (RSCN)
+ * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN)
* @sp: Current sequence of the RSCN exchange
* @fp: RSCN Frame
* @lport: Fibre Channel host port instance
@@ -246,7 +246,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp,
list_del(&dp->peers);
rport = lport->tt.rport_lookup(lport, dp->ids.port_id);
if (rport) {
- rdata = RPORT_TO_PRIV(rport);
+ rdata = rport->dd_data;
list_del(&rdata->peers);
lport->tt.rport_logoff(rport);
}
@@ -265,7 +265,7 @@ reject:
}
/**
- * fc_disc_recv_req - Handle incoming requests
+ * fc_disc_recv_req() - Handle incoming requests
* @sp: Current sequence of the request exchange
* @fp: The frame
* @lport: The FC local port
@@ -294,7 +294,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp,
}
/**
- * fc_disc_restart - Restart discovery
+ * fc_disc_restart() - Restart discovery
* @lport: FC discovery context
*
* Locking Note: This function expects that the disc mutex
@@ -322,7 +322,7 @@ static void fc_disc_restart(struct fc_disc *disc)
}
/**
- * fc_disc_start - Fibre Channel Target discovery
+ * fc_disc_start() - Fibre Channel Target discovery
* @lport: FC local port
*
* Returns non-zero if discovery cannot be started.
@@ -383,7 +383,7 @@ static struct fc_rport_operations fc_disc_rport_ops = {
};
/**
- * fc_disc_new_target - Handle new target found by discovery
+ * fc_disc_new_target() - Handle new target found by discovery
* @lport: FC local port
* @rport: The previous FC remote port (NULL if new remote port)
* @ids: Identifiers for the new FC remote port
@@ -396,7 +396,7 @@ static int fc_disc_new_target(struct fc_disc *disc,
struct fc_rport_identifiers *ids)
{
struct fc_lport *lport = disc->lport;
- struct fc_rport_libfc_priv *rp;
+ struct fc_rport_libfc_priv *rdata;
int error = 0;
if (rport && ids->port_name) {
@@ -430,15 +430,15 @@ static int fc_disc_new_target(struct fc_disc *disc,
dp.ids.port_name = ids->port_name;
dp.ids.node_name = ids->node_name;
dp.ids.roles = ids->roles;
- rport = fc_rport_rogue_create(&dp);
+ rport = lport->tt.rport_create(&dp);
}
if (!rport)
error = -ENOMEM;
}
if (rport) {
- rp = rport->dd_data;
- rp->ops = &fc_disc_rport_ops;
- rp->rp_state = RPORT_ST_INIT;
+ rdata = rport->dd_data;
+ rdata->ops = &fc_disc_rport_ops;
+ rdata->rp_state = RPORT_ST_INIT;
lport->tt.rport_login(rport);
}
}
@@ -446,20 +446,20 @@ static int fc_disc_new_target(struct fc_disc *disc,
}
/**
- * fc_disc_del_target - Delete a target
+ * fc_disc_del_target() - Delete a target
* @disc: FC discovery context
* @rport: The remote port to be removed
*/
static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport)
{
struct fc_lport *lport = disc->lport;
- struct fc_rport_libfc_priv *rdata = RPORT_TO_PRIV(rport);
+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
list_del(&rdata->peers);
lport->tt.rport_logoff(rport);
}
/**
- * fc_disc_done - Discovery has been completed
+ * fc_disc_done() - Discovery has been completed
* @disc: FC discovery context
*/
static void fc_disc_done(struct fc_disc *disc)
@@ -479,7 +479,7 @@ static void fc_disc_done(struct fc_disc *disc)
}
/**
- * fc_disc_error - Handle error on dNS request
+ * fc_disc_error() - Handle error on dNS request
* @disc: FC discovery context
* @fp: The frame pointer
*/
@@ -519,7 +519,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp)
}
/**
- * fc_disc_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request
+ * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request
* @lport: FC discovery context
*
* Locking Note: This function expects that the disc_mutex is locked
@@ -553,7 +553,7 @@ err:
}
/**
- * fc_disc_gpn_ft_parse - Parse the list of IDs and names resulting from a request
+ * fc_disc_gpn_ft_parse() - Parse the list of IDs and names resulting from a request
* @lport: Fibre Channel host port instance
* @buf: GPN_FT response buffer
* @len: size of response buffer
@@ -617,7 +617,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
if ((dp.ids.port_id != fc_host_port_id(lport->host)) &&
(dp.ids.port_name != lport->wwpn)) {
- rport = fc_rport_rogue_create(&dp);
+ rport = lport->tt.rport_create(&dp);
if (rport) {
rdata = rport->dd_data;
rdata->ops = &fc_disc_rport_ops;
@@ -658,7 +658,10 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len)
return error;
}
-/*
+/**
+ * fc_disc_timeout() - Retry handler for the disc component
+ * @work: Structure holding disc obj that needs retry discovery
+ *
* Handle retry of memory allocation for remote ports.
*/
static void fc_disc_timeout(struct work_struct *work)
@@ -673,7 +676,7 @@ static void fc_disc_timeout(struct work_struct *work)
}
/**
- * fc_disc_gpn_ft_resp - Handle a response frame from Get Port Names (GPN_FT)
+ * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT)
* @sp: Current sequence of GPN_FT exchange
* @fp: response frame
* @lp_arg: Fibre Channel host port instance
@@ -712,9 +715,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
fr_len(fp));
} else if (ntohs(cp->ct_cmd) == FC_FS_ACC) {
- /*
- * Accepted. Parse response.
- */
+ /* Accepted, parse the response. */
buf = cp + 1;
len -= sizeof(*cp);
} else if (ntohs(cp->ct_cmd) == FC_FS_RJT) {
@@ -746,7 +747,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp,
}
/**
- * fc_disc_single - Discover the directory information for a single target
+ * fc_disc_single() - Discover the directory information for a single target
* @lport: FC local port
* @dp: The port to rediscover
*
@@ -769,7 +770,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp)
if (rport)
fc_disc_del_target(disc, rport);
- new_rport = fc_rport_rogue_create(dp);
+ new_rport = lport->tt.rport_create(dp);
if (new_rport) {
rdata = new_rport->dd_data;
rdata->ops = &fc_disc_rport_ops;
@@ -782,7 +783,7 @@ out:
}
/**
- * fc_disc_stop - Stop discovery for a given lport
+ * fc_disc_stop() - Stop discovery for a given lport
* @lport: The lport that discovery should stop for
*/
void fc_disc_stop(struct fc_lport *lport)
@@ -796,7 +797,7 @@ void fc_disc_stop(struct fc_lport *lport)
}
/**
- * fc_disc_stop_final - Stop discovery for a given lport
+ * fc_disc_stop_final() - Stop discovery for a given lport
* @lport: The lport that discovery should stop for
*
* This function will block until discovery has been
@@ -809,7 +810,7 @@ void fc_disc_stop_final(struct fc_lport *lport)
}
/**
- * fc_disc_init - Initialize the discovery block
+ * fc_disc_init() - Initialize the discovery block
* @lport: FC local port
*/
int fc_disc_init(struct fc_lport *lport)
diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c
index 66db08a5f27..992af05aacf 100644
--- a/drivers/scsi/libfc/fc_exch.c
+++ b/drivers/scsi/libfc/fc_exch.c
@@ -32,8 +32,6 @@
#include <scsi/libfc.h>
#include <scsi/fc_encode.h>
-#define FC_DEF_R_A_TOV (10 * 1000) /* resource allocation timeout */
-
/*
* fc_exch_debug can be set in debugger or at compile time to get more logs.
*/
@@ -283,7 +281,7 @@ static void fc_exch_release(struct fc_exch *ep)
ep->destructor(&ep->seq, ep->arg);
if (ep->lp->tt.exch_put)
ep->lp->tt.exch_put(ep->lp, mp, ep->xid);
- WARN_ON(!ep->esb_stat & ESB_ST_COMPLETE);
+ WARN_ON(!(ep->esb_stat & ESB_ST_COMPLETE));
mempool_free(ep, mp->ep_pool);
}
}
@@ -491,7 +489,7 @@ static u16 fc_em_alloc_xid(struct fc_exch_mgr *mp, const struct fc_frame *fp)
struct fc_exch *ep = NULL;
if (mp->max_read) {
- if (fc_frame_is_read(fp)) {
+ if (fc_fcp_is_read(fr_fsp(fp))) {
min = mp->min_xid;
max = mp->max_read;
plast = &mp->last_read;
@@ -627,7 +625,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
{
struct fc_exch *ep;
struct fc_frame_header *fh;
- u16 rxid;
ep = mp->lp->tt.exch_get(mp->lp, fp);
if (ep) {
@@ -654,18 +651,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
if ((ntoh24(fh->fh_f_ctl) & FC_FC_SEQ_INIT) == 0)
ep->esb_stat &= ~ESB_ST_SEQ_INIT;
- /*
- * Set the responder ID in the frame header.
- * The old one should've been 0xffff.
- * If it isn't, don't assign one.
- * Incoming basic link service frames may specify
- * a referenced RX_ID.
- */
- if (fh->fh_type != FC_TYPE_BLS) {
- rxid = ntohs(fh->fh_rx_id);
- WARN_ON(rxid != FC_XID_UNKNOWN);
- fh->fh_rx_id = htons(ep->rxid);
- }
fc_exch_hold(ep); /* hold for caller */
spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */
}
@@ -677,8 +662,8 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp)
* If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold
* on the ep that should be released by the caller.
*/
-static enum fc_pf_rjt_reason
-fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp)
+static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp,
+ struct fc_frame *fp)
{
struct fc_frame_header *fh = fc_frame_header_get(fp);
struct fc_exch *ep = NULL;
@@ -996,9 +981,9 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp)
* Send BLS Reject.
* This is for rejecting BA_ABTS only.
*/
-static void
-fc_exch_send_ba_rjt(struct fc_frame *rx_fp, enum fc_ba_rjt_reason reason,
- enum fc_ba_rjt_explan explan)
+static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp,
+ enum fc_ba_rjt_reason reason,
+ enum fc_ba_rjt_explan explan)
{
struct fc_frame *fp;
struct fc_frame_header *rx_fh;
@@ -1096,7 +1081,7 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp)
ap->ba_high_seq_cnt = fh->fh_seq_cnt;
ap->ba_low_seq_cnt = htons(sp->cnt);
}
- sp = fc_seq_start_next(sp);
+ sp = fc_seq_start_next_locked(sp);
spin_unlock_bh(&ep->ex_lock);
fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS);
fc_frame_free(rx_fp);
@@ -1480,10 +1465,11 @@ static void fc_exch_reset(struct fc_exch *ep)
* If sid is non-zero, reset only exchanges we source from that FID.
* If did is non-zero, reset only exchanges destined to that FID.
*/
-void fc_exch_mgr_reset(struct fc_exch_mgr *mp, u32 sid, u32 did)
+void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did)
{
struct fc_exch *ep;
struct fc_exch *next;
+ struct fc_exch_mgr *mp = lp->emp;
spin_lock_bh(&mp->em_lock);
restart:
@@ -1607,7 +1593,7 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg)
if (IS_ERR(fp)) {
int err = PTR_ERR(fp);
- if (err == -FC_EX_CLOSED)
+ if (err == -FC_EX_CLOSED || err == -FC_EX_TIMEOUT)
goto cleanup;
FC_DBG("Cannot process RRQ, because of frame error %d\n", err);
return;
@@ -1855,6 +1841,8 @@ struct fc_seq *fc_exch_seq_send(struct fc_lport *lp,
fc_exch_setup_hdr(ep, fp, ep->f_ctl);
sp->cnt++;
+ fc_fcp_ddp_setup(fr_fsp(fp), ep->xid);
+
if (unlikely(lp->tt.frame_send(lp, fp)))
goto err;
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 404e63ff46b..f555ae99ad4 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -41,7 +41,7 @@
MODULE_AUTHOR("Open-FCoE.org");
MODULE_DESCRIPTION("libfc");
-MODULE_LICENSE("GPL");
+MODULE_LICENSE("GPL v2");
static int fc_fcp_debug;
@@ -161,7 +161,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp)
}
/**
- * fc_fcp_pkt_release - release hold on scsi_pkt packet
+ * fc_fcp_pkt_release() - release hold on scsi_pkt packet
* @fsp: fcp packet struct
*
* This is used by upper layer scsi driver.
@@ -183,8 +183,7 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp)
}
/**
- * fc_fcp_pkt_destory - release hold on scsi_pkt packet
- *
+ * fc_fcp_pkt_destory() - release hold on scsi_pkt packet
* @seq: exchange sequence
* @fsp: fcp packet struct
*
@@ -199,7 +198,7 @@ static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp)
}
/**
- * fc_fcp_lock_pkt - lock a packet and get a ref to it.
+ * fc_fcp_lock_pkt() - lock a packet and get a ref to it.
* @fsp: fcp packet
*
* We should only return error if we return a command to scsi-ml before
@@ -260,12 +259,62 @@ static void fc_fcp_retry_cmd(struct fc_fcp_pkt *fsp)
}
fsp->state &= ~FC_SRB_ABORT_PENDING;
- fsp->io_status = SUGGEST_RETRY << 24;
+ fsp->io_status = 0;
fsp->status_code = FC_ERROR;
fc_fcp_complete_locked(fsp);
}
/*
+ * fc_fcp_ddp_setup - calls to LLD's ddp_setup to set up DDP
+ * transfer for a read I/O indicated by the fc_fcp_pkt.
+ * @fsp: ptr to the fc_fcp_pkt
+ *
+ * This is called in exch_seq_send() when we have a newly allocated
+ * exchange with a valid exchange id to setup ddp.
+ *
+ * returns: none
+ */
+void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid)
+{
+ struct fc_lport *lp;
+
+ if (!fsp)
+ return;
+
+ lp = fsp->lp;
+ if ((fsp->req_flags & FC_SRB_READ) &&
+ (lp->lro_enabled) && (lp->tt.ddp_setup)) {
+ if (lp->tt.ddp_setup(lp, xid, scsi_sglist(fsp->cmd),
+ scsi_sg_count(fsp->cmd)))
+ fsp->xfer_ddp = xid;
+ }
+}
+EXPORT_SYMBOL(fc_fcp_ddp_setup);
+
+/*
+ * fc_fcp_ddp_done - calls to LLD's ddp_done to release any
+ * DDP related resources for this I/O if it is initialized
+ * as a ddp transfer
+ * @fsp: ptr to the fc_fcp_pkt
+ *
+ * returns: none
+ */
+static void fc_fcp_ddp_done(struct fc_fcp_pkt *fsp)
+{
+ struct fc_lport *lp;
+
+ if (!fsp)
+ return;
+
+ lp = fsp->lp;
+ if (fsp->xfer_ddp && lp->tt.ddp_done) {
+ fsp->xfer_len = lp->tt.ddp_done(lp, fsp->xfer_ddp);
+ fsp->xfer_ddp = 0;
+ }
+}
+
+
+/*
* Receive SCSI data from target.
* Called after receiving solicited data.
*/
@@ -290,10 +339,11 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
len = fr_len(fp) - sizeof(*fh);
buf = fc_frame_payload_get(fp, 0);
+ /* if this I/O is ddped, update xfer len */
+ fc_fcp_ddp_done(fsp);
+
if (offset + len > fsp->data_len) {
- /*
- * this should never happen
- */
+ /* this should never happen */
if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) &&
fc_frame_crc_check(fp))
goto crc_err;
@@ -357,10 +407,12 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
if (~crc != le32_to_cpu(fr_crc(fp))) {
crc_err:
- stats = lp->dev_stats[smp_processor_id()];
+ stats = fc_lport_get_stats(lp);
stats->ErrorFrames++;
+ /* FIXME - per cpu count, not total count! */
if (stats->InvalidCRCCount++ < 5)
- FC_DBG("CRC error on data frame\n");
+ printk(KERN_WARNING "CRC error on data frame for port (%6x)\n",
+ fc_host_port_id(lp->host));
/*
* Assume the frame is total garbage.
* We may have copied it over the good part
@@ -387,8 +439,8 @@ crc_err:
fc_fcp_complete_locked(fsp);
}
-/*
- * fc_fcp_send_data - Send SCSI data to target.
+/**
+ * fc_fcp_send_data() - Send SCSI data to target.
* @fsp: ptr to fc_fcp_pkt
* @sp: ptr to this sequence
* @offset: starting offset for this data request
@@ -438,7 +490,13 @@ static int fc_fcp_send_data(struct fc_fcp_pkt *fsp, struct fc_seq *seq,
* burst length (t_blen) to seq_blen, otherwise set t_blen
* to max FC frame payload previously set in fsp->max_payload.
*/
- t_blen = lp->seq_offload ? seq_blen : fsp->max_payload;
+ t_blen = fsp->max_payload;
+ if (lp->seq_offload) {
+ t_blen = min(seq_blen, (size_t)lp->lso_max);
+ FC_DEBUG_FCP("fsp=%p:lso:blen=%zx lso_max=0x%x t_blen=%zx\n",
+ fsp, seq_blen, lp->lso_max, t_blen);
+ }
+
WARN_ON(t_blen < FC_MIN_MAX_PAYLOAD);
if (t_blen > 512)
t_blen &= ~(512 - 1); /* round down to block size */
@@ -610,8 +668,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
}
}
-/*
- * fc_fcp_reduce_can_queue - drop can_queue
+/**
+ * fc_fcp_reduce_can_queue() - drop can_queue
* @lp: lport to drop queueing for
*
* If we are getting memory allocation failures, then we may
@@ -642,9 +700,11 @@ done:
spin_unlock_irqrestore(lp->host->host_lock, flags);
}
-/*
- * exch mgr calls this routine to process scsi
- * exchanges.
+/**
+ * fc_fcp_recv() - Reveive FCP frames
+ * @seq: The sequence the frame is on
+ * @fp: The FC frame
+ * @arg: The related FCP packet
*
* Return : None
* Context : called from Soft IRQ context
@@ -745,6 +805,9 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
fsp->scsi_comp_flags = flags;
expected_len = fsp->data_len;
+ /* if ddp, update xfer len */
+ fc_fcp_ddp_done(fsp);
+
if (unlikely((flags & ~FCP_CONF_REQ) || fc_rp->fr_status)) {
rp_ex = (void *)(fc_rp + 1);
if (flags & (FCP_RSP_LEN_VAL | FCP_SNS_LEN_VAL)) {
@@ -832,7 +895,7 @@ err:
}
/**
- * fc_fcp_complete_locked - complete processing of a fcp packet
+ * fc_fcp_complete_locked() - complete processing of a fcp packet
* @fsp: fcp packet
*
* This function may sleep if a timer is pending. The packet lock must be
@@ -860,7 +923,7 @@ static void fc_fcp_complete_locked(struct fc_fcp_pkt *fsp)
(!(fsp->scsi_comp_flags & FCP_RESID_UNDER) ||
fsp->xfer_len < fsp->data_len - fsp->scsi_resid)) {
fsp->status_code = FC_DATA_UNDRUN;
- fsp->io_status = SUGGEST_RETRY << 24;
+ fsp->io_status = 0;
}
}
@@ -900,7 +963,7 @@ static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error)
}
/**
- * fc_fcp_cleanup_each_cmd - run fn on each active command
+ * fc_fcp_cleanup_each_cmd() - Cleanup active commads
* @lp: logical port
* @id: target id
* @lun: lun
@@ -952,7 +1015,7 @@ static void fc_fcp_abort_io(struct fc_lport *lp)
}
/**
- * fc_fcp_pkt_send - send a fcp packet to the lower level.
+ * fc_fcp_pkt_send() - send a fcp packet to the lower level.
* @lp: fc lport
* @fsp: fc packet.
*
@@ -1007,7 +1070,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lp, struct fc_fcp_pkt *fsp,
}
memcpy(fc_frame_payload_get(fp, len), &fsp->cdb_cmd, len);
- fr_cmd(fp) = fsp->cmd;
+ fr_fsp(fp) = fsp;
rport = fsp->rport;
fsp->max_payload = rport->maxframe_size;
rp = rport->dd_data;
@@ -1268,7 +1331,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
rp = rport->dd_data;
if (!fsp->seq_ptr || rp->rp_state != RPORT_ST_READY) {
fsp->status_code = FC_HRD_ERROR;
- fsp->io_status = SUGGEST_RETRY << 24;
+ fsp->io_status = 0;
fc_fcp_complete_locked(fsp);
return;
}
@@ -1621,7 +1684,7 @@ out:
static inline int fc_fcp_lport_queue_ready(struct fc_lport *lp)
{
/* lock ? */
- return (lp->state == LPORT_ST_READY) && (lp->link_status & FC_LINK_UP);
+ return (lp->state == LPORT_ST_READY) && lp->link_up && !lp->qfull;
}
/**
@@ -1691,7 +1754,7 @@ int fc_queuecommand(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
/*
* setup the data direction
*/
- stats = lp->dev_stats[smp_processor_id()];
+ stats = fc_lport_get_stats(lp);
if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
fsp->req_flags = FC_SRB_READ;
stats->InputRequests++;
@@ -1727,7 +1790,7 @@ out:
EXPORT_SYMBOL(fc_queuecommand);
/**
- * fc_io_compl - Handle responses for completed commands
+ * fc_io_compl() - Handle responses for completed commands
* @fsp: scsi packet
*
* Translates a error to a Linux SCSI error.
@@ -1741,6 +1804,9 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
struct fc_lport *lp;
unsigned long flags;
+ /* release outstanding ddp context */
+ fc_fcp_ddp_done(fsp);
+
fsp->state |= FC_SRB_COMPL;
if (!(fsp->state & FC_SRB_FCP_PROCESSING_TMO)) {
spin_unlock_bh(&fsp->scsi_pkt_lock);
@@ -1810,12 +1876,12 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
sc_cmd->result = DID_ERROR << 16;
break;
case FC_DATA_UNDRUN:
- if (fsp->cdb_status == 0) {
+ if ((fsp->cdb_status == 0) && !(fsp->req_flags & FC_SRB_READ)) {
/*
* scsi status is good but transport level
- * underrun. for read it should be an error??
+ * underrun.
*/
- sc_cmd->result = (DID_OK << 16) | fsp->cdb_status;
+ sc_cmd->result = DID_OK << 16;
} else {
/*
* scsi got underrun, this is an error
@@ -1857,7 +1923,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp)
}
/**
- * fc_fcp_complete - complete processing of a fcp packet
+ * fc_fcp_complete() - complete processing of a fcp packet
* @fsp: fcp packet
*
* This function may sleep if a fsp timer is pending.
@@ -1874,9 +1940,10 @@ void fc_fcp_complete(struct fc_fcp_pkt *fsp)
EXPORT_SYMBOL(fc_fcp_complete);
/**
- * fc_eh_abort - Abort a command...from scsi host template
+ * fc_eh_abort() - Abort a command
* @sc_cmd: scsi command to abort
*
+ * From scsi host template.
* send ABTS to the target device and wait for the response
* sc_cmd is the pointer to the command to be aborted.
*/
@@ -1890,7 +1957,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)
lp = shost_priv(sc_cmd->device->host);
if (lp->state != LPORT_ST_READY)
return rc;
- else if (!(lp->link_status & FC_LINK_UP))
+ else if (!lp->link_up)
return rc;
spin_lock_irqsave(lp->host->host_lock, flags);
@@ -1920,7 +1987,7 @@ release_pkt:
EXPORT_SYMBOL(fc_eh_abort);
/**
- * fc_eh_device_reset: Reset a single LUN
+ * fc_eh_device_reset() Reset a single LUN
* @sc_cmd: scsi command
*
* Set from scsi host template to send tm cmd to the target and wait for the
@@ -1973,7 +2040,7 @@ out:
EXPORT_SYMBOL(fc_eh_device_reset);
/**
- * fc_eh_host_reset - The reset function will reset the ports on the host.
+ * fc_eh_host_reset() - The reset function will reset the ports on the host.
* @sc_cmd: scsi command
*/
int fc_eh_host_reset(struct scsi_cmnd *sc_cmd)
@@ -1999,7 +2066,7 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd)
EXPORT_SYMBOL(fc_eh_host_reset);
/**
- * fc_slave_alloc - configure queue depth
+ * fc_slave_alloc() - configure queue depth
* @sdev: scsi device
*
* Configures queue depth based on host's cmd_per_len. If not set
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 0b9bdb1fb80..b8178ef398d 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -139,7 +139,7 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
}
/**
- * fc_lport_rport_callback - Event handler for rport events
+ * fc_lport_rport_callback() - Event handler for rport events
* @lport: The lport which is receiving the event
* @rport: The rport which the event has occured on
* @event: The event that occured
@@ -195,7 +195,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport,
}
/**
- * fc_lport_state - Return a string which represents the lport's state
+ * fc_lport_state() - Return a string which represents the lport's state
* @lport: The lport whose state is to converted to a string
*/
static const char *fc_lport_state(struct fc_lport *lport)
@@ -209,7 +209,7 @@ static const char *fc_lport_state(struct fc_lport *lport)
}
/**
- * fc_lport_ptp_setup - Create an rport for point-to-point mode
+ * fc_lport_ptp_setup() - Create an rport for point-to-point mode
* @lport: The lport to attach the ptp rport to
* @fid: The FID of the ptp rport
* @remote_wwpn: The WWPN of the ptp rport
@@ -232,7 +232,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
lport->ptp_rp = NULL;
}
- lport->ptp_rp = fc_rport_rogue_create(&dp);
+ lport->ptp_rp = lport->tt.rport_create(&dp);
lport->tt.rport_login(lport->ptp_rp);
@@ -250,7 +250,7 @@ void fc_get_host_port_state(struct Scsi_Host *shost)
{
struct fc_lport *lp = shost_priv(shost);
- if ((lp->link_status & FC_LINK_UP) == FC_LINK_UP)
+ if (lp->link_up)
fc_host_port_state(shost) = FC_PORTSTATE_ONLINE;
else
fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE;
@@ -267,10 +267,10 @@ EXPORT_SYMBOL(fc_get_host_speed);
struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
{
- int i;
struct fc_host_statistics *fcoe_stats;
struct fc_lport *lp = shost_priv(shost);
struct timespec v0, v1;
+ unsigned int cpu;
fcoe_stats = &lp->host_stats;
memset(fcoe_stats, 0, sizeof(struct fc_host_statistics));
@@ -279,10 +279,11 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
jiffies_to_timespec(lp->boot_time, &v1);
fcoe_stats->seconds_since_last_reset = (v0.tv_sec - v1.tv_sec);
- for_each_online_cpu(i) {
- struct fcoe_dev_stats *stats = lp->dev_stats[i];
- if (stats == NULL)
- continue;
+ for_each_possible_cpu(cpu) {
+ struct fcoe_dev_stats *stats;
+
+ stats = per_cpu_ptr(lp->dev_stats, cpu);
+
fcoe_stats->tx_frames += stats->TxFrames;
fcoe_stats->tx_words += stats->TxWords;
fcoe_stats->rx_frames += stats->RxFrames;
@@ -351,7 +352,7 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type)
}
/**
- * fc_lport_recv_rlir_req - Handle received Registered Link Incident Report.
+ * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report.
* @lport: Fibre Channel local port recieving the RLIR
* @sp: current sequence in the RLIR exchange
* @fp: RLIR request frame
@@ -370,7 +371,7 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp,
}
/**
- * fc_lport_recv_echo_req - Handle received ECHO request
+ * fc_lport_recv_echo_req() - Handle received ECHO request
* @lport: Fibre Channel local port recieving the ECHO
* @sp: current sequence in the ECHO exchange
* @fp: ECHO request frame
@@ -412,7 +413,7 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp,
}
/**
- * fc_lport_recv_echo_req - Handle received Request Node ID data request
+ * fc_lport_recv_echo_req() - Handle received Request Node ID data request
* @lport: Fibre Channel local port recieving the RNID
* @sp: current sequence in the RNID exchange
* @fp: RNID request frame
@@ -479,7 +480,7 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
}
/**
- * fc_lport_recv_adisc_req - Handle received Address Discovery Request
+ * fc_lport_recv_adisc_req() - Handle received Address Discovery Request
* @lport: Fibre Channel local port recieving the ADISC
* @sp: current sequence in the ADISC exchange
* @fp: ADISC request frame
@@ -529,7 +530,7 @@ static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp,
}
/**
- * fc_lport_recv_logo_req - Handle received fabric LOGO request
+ * fc_lport_recv_logo_req() - Handle received fabric LOGO request
* @lport: Fibre Channel local port recieving the LOGO
* @sp: current sequence in the LOGO exchange
* @fp: LOGO request frame
@@ -546,7 +547,7 @@ static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp,
}
/**
- * fc_fabric_login - Start the lport state machine
+ * fc_fabric_login() - Start the lport state machine
* @lport: The lport that should log into the fabric
*
* Locking Note: This function should not be called
@@ -568,7 +569,7 @@ int fc_fabric_login(struct fc_lport *lport)
EXPORT_SYMBOL(fc_fabric_login);
/**
- * fc_linkup - Handler for transport linkup events
+ * fc_linkup() - Handler for transport linkup events
* @lport: The lport whose link is up
*/
void fc_linkup(struct fc_lport *lport)
@@ -577,8 +578,8 @@ void fc_linkup(struct fc_lport *lport)
fc_host_port_id(lport->host));
mutex_lock(&lport->lp_mutex);
- if ((lport->link_status & FC_LINK_UP) != FC_LINK_UP) {
- lport->link_status |= FC_LINK_UP;
+ if (!lport->link_up) {
+ lport->link_up = 1;
if (lport->state == LPORT_ST_RESET)
fc_lport_enter_flogi(lport);
@@ -588,7 +589,7 @@ void fc_linkup(struct fc_lport *lport)
EXPORT_SYMBOL(fc_linkup);
/**
- * fc_linkdown - Handler for transport linkdown events
+ * fc_linkdown() - Handler for transport linkdown events
* @lport: The lport whose link is down
*/
void fc_linkdown(struct fc_lport *lport)
@@ -597,8 +598,8 @@ void fc_linkdown(struct fc_lport *lport)
FC_DEBUG_LPORT("Link is down for port (%6x)\n",
fc_host_port_id(lport->host));
- if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) {
- lport->link_status &= ~(FC_LINK_UP);
+ if (lport->link_up) {
+ lport->link_up = 0;
fc_lport_enter_reset(lport);
lport->tt.fcp_cleanup(lport);
}
@@ -607,48 +608,25 @@ void fc_linkdown(struct fc_lport *lport)
EXPORT_SYMBOL(fc_linkdown);
/**
- * fc_pause - Pause the flow of frames
- * @lport: The lport to be paused
- */
-void fc_pause(struct fc_lport *lport)
-{
- mutex_lock(&lport->lp_mutex);
- lport->link_status |= FC_PAUSE;
- mutex_unlock(&lport->lp_mutex);
-}
-EXPORT_SYMBOL(fc_pause);
-
-/**
- * fc_unpause - Unpause the flow of frames
- * @lport: The lport to be unpaused
- */
-void fc_unpause(struct fc_lport *lport)
-{
- mutex_lock(&lport->lp_mutex);
- lport->link_status &= ~(FC_PAUSE);
- mutex_unlock(&lport->lp_mutex);
-}
-EXPORT_SYMBOL(fc_unpause);
-
-/**
- * fc_fabric_logoff - Logout of the fabric
+ * fc_fabric_logoff() - Logout of the fabric
* @lport: fc_lport pointer to logoff the fabric
*
* Return value:
* 0 for success, -1 for failure
- **/
+ */
int fc_fabric_logoff(struct fc_lport *lport)
{
lport->tt.disc_stop_final(lport);
mutex_lock(&lport->lp_mutex);
fc_lport_enter_logo(lport);
mutex_unlock(&lport->lp_mutex);
+ cancel_delayed_work_sync(&lport->retry_work);
return 0;
}
EXPORT_SYMBOL(fc_fabric_logoff);
/**
- * fc_lport_destroy - unregister a fc_lport
+ * fc_lport_destroy() - unregister a fc_lport
* @lport: fc_lport pointer to unregister
*
* Return value:
@@ -658,26 +636,25 @@ EXPORT_SYMBOL(fc_fabric_logoff);
* clean-up all the allocated memory
* and free up other system resources.
*
- **/
+ */
int fc_lport_destroy(struct fc_lport *lport)
{
lport->tt.frame_send = fc_frame_drop;
lport->tt.fcp_abort_io(lport);
- lport->tt.exch_mgr_reset(lport->emp, 0, 0);
+ lport->tt.exch_mgr_reset(lport, 0, 0);
return 0;
}
EXPORT_SYMBOL(fc_lport_destroy);
/**
- * fc_set_mfs - sets up the mfs for the corresponding fc_lport
+ * fc_set_mfs() - sets up the mfs for the corresponding fc_lport
* @lport: fc_lport pointer to unregister
* @mfs: the new mfs for fc_lport
*
* Set mfs for the given fc_lport to the new mfs.
*
* Return: 0 for success
- *
- **/
+ */
int fc_set_mfs(struct fc_lport *lport, u32 mfs)
{
unsigned int old_mfs;
@@ -706,7 +683,7 @@ int fc_set_mfs(struct fc_lport *lport, u32 mfs)
EXPORT_SYMBOL(fc_set_mfs);
/**
- * fc_lport_disc_callback - Callback for discovery events
+ * fc_lport_disc_callback() - Callback for discovery events
* @lport: FC local port
* @event: The discovery event
*/
@@ -731,7 +708,7 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event)
}
/**
- * fc_rport_enter_ready - Enter the ready state and start discovery
+ * fc_rport_enter_ready() - Enter the ready state and start discovery
* @lport: Fibre Channel local port that is ready
*
* Locking Note: The lport lock is expected to be held before calling
@@ -748,7 +725,7 @@ static void fc_lport_enter_ready(struct fc_lport *lport)
}
/**
- * fc_lport_recv_flogi_req - Receive a FLOGI request
+ * fc_lport_recv_flogi_req() - Receive a FLOGI request
* @sp_in: The sequence the FLOGI is on
* @rx_fp: The frame the FLOGI is in
* @lport: The lport that recieved the request
@@ -786,10 +763,11 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
remote_wwpn = get_unaligned_be64(&flp->fl_wwpn);
if (remote_wwpn == lport->wwpn) {
FC_DBG("FLOGI from port with same WWPN %llx "
- "possible configuration error\n", remote_wwpn);
+ "possible configuration error\n",
+ (unsigned long long)remote_wwpn);
goto out;
}
- FC_DBG("FLOGI from port WWPN %llx\n", remote_wwpn);
+ FC_DBG("FLOGI from port WWPN %llx\n", (unsigned long long)remote_wwpn);
/*
* XXX what is the right thing to do for FIDs?
@@ -838,7 +816,7 @@ out:
}
/**
- * fc_lport_recv_req - The generic lport request handler
+ * fc_lport_recv_req() - The generic lport request handler
* @lport: The lport that received the request
* @sp: The sequence the request is on
* @fp: The frame the request is in
@@ -934,7 +912,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
}
/**
- * fc_lport_reset - Reset an lport
+ * fc_lport_reset() - Reset an lport
* @lport: The lport which should be reset
*
* Locking Note: This functions should not be called with the
@@ -942,6 +920,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
*/
int fc_lport_reset(struct fc_lport *lport)
{
+ cancel_delayed_work_sync(&lport->retry_work);
mutex_lock(&lport->lp_mutex);
fc_lport_enter_reset(lport);
mutex_unlock(&lport->lp_mutex);
@@ -950,7 +929,7 @@ int fc_lport_reset(struct fc_lport *lport)
EXPORT_SYMBOL(fc_lport_reset);
/**
- * fc_rport_enter_reset - Reset the local port
+ * fc_rport_enter_reset() - Reset the local port
* @lport: Fibre Channel local port to be reset
*
* Locking Note: The lport lock is expected to be held before calling
@@ -973,16 +952,16 @@ static void fc_lport_enter_reset(struct fc_lport *lport)
lport->tt.disc_stop(lport);
- lport->tt.exch_mgr_reset(lport->emp, 0, 0);
+ lport->tt.exch_mgr_reset(lport, 0, 0);
fc_host_fabric_name(lport->host) = 0;
fc_host_port_id(lport->host) = 0;
- if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP)
+ if (lport->link_up)
fc_lport_enter_flogi(lport);
}
/**
- * fc_lport_error - Handler for any errors
+ * fc_lport_error() - Handler for any errors
* @lport: The fc_lport object
* @fp: The frame pointer
*
@@ -1029,8 +1008,8 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
}
/**
- * fc_lport_rft_id_resp - Handle response to Register Fibre
- * Channel Types by ID (RPN_ID) request
+ * fc_lport_rft_id_resp() - Handle response to Register Fibre
+ * Channel Types by ID (RPN_ID) request
* @sp: current sequence in RPN_ID exchange
* @fp: response frame
* @lp_arg: Fibre Channel host port instance
@@ -1053,17 +1032,17 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a RFT_ID response\n");
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
if (lport->state != LPORT_ST_RFT_ID) {
FC_DBG("Received a RFT_ID response, but in state %s\n",
fc_lport_state(lport));
goto out;
}
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct));
@@ -1081,8 +1060,8 @@ err:
}
/**
- * fc_lport_rpn_id_resp - Handle response to Register Port
- * Name by ID (RPN_ID) request
+ * fc_lport_rpn_id_resp() - Handle response to Register Port
+ * Name by ID (RPN_ID) request
* @sp: current sequence in RPN_ID exchange
* @fp: response frame
* @lp_arg: Fibre Channel host port instance
@@ -1105,17 +1084,17 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a RPN_ID response\n");
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
if (lport->state != LPORT_ST_RPN_ID) {
FC_DBG("Received a RPN_ID response, but in state %s\n",
fc_lport_state(lport));
goto out;
}
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
fh = fc_frame_header_get(fp);
ct = fc_frame_payload_get(fp, sizeof(*ct));
if (fh && ct && fh->fh_type == FC_TYPE_CT &&
@@ -1133,7 +1112,7 @@ err:
}
/**
- * fc_lport_scr_resp - Handle response to State Change Register (SCR) request
+ * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request
* @sp: current sequence in SCR exchange
* @fp: response frame
* @lp_arg: Fibre Channel lport port instance that sent the registration request
@@ -1155,17 +1134,17 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a SCR response\n");
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
if (lport->state != LPORT_ST_SCR) {
FC_DBG("Received a SCR response, but in state %s\n",
fc_lport_state(lport));
goto out;
}
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
fc_lport_enter_ready(lport);
@@ -1179,7 +1158,7 @@ err:
}
/**
- * fc_lport_enter_scr - Send a State Change Register (SCR) request
+ * fc_lport_enter_scr() - Send a State Change Register (SCR) request
* @lport: Fibre Channel local port to register for state changes
*
* Locking Note: The lport lock is expected to be held before calling
@@ -1206,7 +1185,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport)
}
/**
- * fc_lport_enter_rft_id - Register FC4-types with the name server
+ * fc_lport_enter_rft_id() - Register FC4-types with the name server
* @lport: Fibre Channel local port to register
*
* Locking Note: The lport lock is expected to be held before calling
@@ -1248,7 +1227,7 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport)
}
/**
- * fc_rport_enter_rft_id - Register port name with the name server
+ * fc_rport_enter_rft_id() - Register port name with the name server
* @lport: Fibre Channel local port to register
*
* Locking Note: The lport lock is expected to be held before calling
@@ -1281,7 +1260,7 @@ static struct fc_rport_operations fc_lport_rport_ops = {
};
/**
- * fc_rport_enter_dns - Create a rport to the name server
+ * fc_rport_enter_dns() - Create a rport to the name server
* @lport: Fibre Channel local port requesting a rport for the name server
*
* Locking Note: The lport lock is expected to be held before calling
@@ -1304,7 +1283,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport)
fc_lport_state_enter(lport, LPORT_ST_DNS);
- rport = fc_rport_rogue_create(&dp);
+ rport = lport->tt.rport_create(&dp);
if (!rport)
goto err;
@@ -1318,7 +1297,7 @@ err:
}
/**
- * fc_lport_timeout - Handler for the retry_work timer.
+ * fc_lport_timeout() - Handler for the retry_work timer.
* @work: The work struct of the fc_lport
*/
static void fc_lport_timeout(struct work_struct *work)
@@ -1359,7 +1338,7 @@ static void fc_lport_timeout(struct work_struct *work)
}
/**
- * fc_lport_logo_resp - Handle response to LOGO request
+ * fc_lport_logo_resp() - Handle response to LOGO request
* @sp: current sequence in LOGO exchange
* @fp: response frame
* @lp_arg: Fibre Channel lport port instance that sent the LOGO request
@@ -1381,17 +1360,17 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a LOGO response\n");
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
if (lport->state != LPORT_ST_LOGO) {
FC_DBG("Received a LOGO response, but in state %s\n",
fc_lport_state(lport));
goto out;
}
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC)
fc_lport_enter_reset(lport);
@@ -1405,7 +1384,7 @@ err:
}
/**
- * fc_rport_enter_logo - Logout of the fabric
+ * fc_rport_enter_logo() - Logout of the fabric
* @lport: Fibre Channel local port to be logged out
*
* Locking Note: The lport lock is expected to be held before calling
@@ -1437,7 +1416,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport)
}
/**
- * fc_lport_flogi_resp - Handle response to FLOGI request
+ * fc_lport_flogi_resp() - Handle response to FLOGI request
* @sp: current sequence in FLOGI exchange
* @fp: response frame
* @lp_arg: Fibre Channel lport port instance that sent the FLOGI request
@@ -1465,17 +1444,17 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_LPORT("Received a FLOGI response\n");
+ if (IS_ERR(fp)) {
+ fc_lport_error(lport, fp);
+ goto err;
+ }
+
if (lport->state != LPORT_ST_FLOGI) {
FC_DBG("Received a FLOGI response, but in state %s\n",
fc_lport_state(lport));
goto out;
}
- if (IS_ERR(fp)) {
- fc_lport_error(lport, fp);
- goto err;
- }
-
fh = fc_frame_header_get(fp);
did = ntoh24(fh->fh_d_id);
if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) {
@@ -1532,7 +1511,7 @@ err:
}
/**
- * fc_rport_enter_flogi - Send a FLOGI request to the fabric manager
+ * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager
* @lport: Fibre Channel local port to be logged in to the fabric
*
* Locking Note: The lport lock is expected to be held before calling
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c
index e780d8caf70..0472bb73221 100644
--- a/drivers/scsi/libfc/fc_rport.c
+++ b/drivers/scsi/libfc/fc_rport.c
@@ -81,6 +81,7 @@ static void fc_rport_recv_logo_req(struct fc_rport *,
struct fc_seq *, struct fc_frame *);
static void fc_rport_timeout(struct work_struct *);
static void fc_rport_error(struct fc_rport *, struct fc_frame *);
+static void fc_rport_error_retry(struct fc_rport *, struct fc_frame *);
static void fc_rport_work(struct work_struct *);
static const char *fc_rport_state_names[] = {
@@ -145,7 +146,7 @@ struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp)
}
/**
- * fc_rport_state - return a string for the state the rport is in
+ * fc_rport_state() - return a string for the state the rport is in
* @rport: The rport whose state we want to get a string for
*/
static const char *fc_rport_state(struct fc_rport *rport)
@@ -160,7 +161,7 @@ static const char *fc_rport_state(struct fc_rport *rport)
}
/**
- * fc_set_rport_loss_tmo - Set the remote port loss timeout in seconds.
+ * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds.
* @rport: Pointer to Fibre Channel remote port structure
* @timeout: timeout in seconds
*/
@@ -174,12 +175,12 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout)
EXPORT_SYMBOL(fc_set_rport_loss_tmo);
/**
- * fc_plogi_get_maxframe - Get max payload from the common service parameters
+ * fc_plogi_get_maxframe() - Get max payload from the common service parameters
* @flp: FLOGI payload structure
* @maxval: upper limit, may be less than what is in the service parameters
*/
-static unsigned int
-fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval)
+static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp,
+ unsigned int maxval)
{
unsigned int mfs;
@@ -197,7 +198,7 @@ fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval)
}
/**
- * fc_rport_state_enter - Change the rport's state
+ * fc_rport_state_enter() - Change the rport's state
* @rport: The rport whose state should change
* @new: The new state of the rport
*
@@ -214,6 +215,7 @@ static void fc_rport_state_enter(struct fc_rport *rport,
static void fc_rport_work(struct work_struct *work)
{
+ u32 port_id;
struct fc_rport_libfc_priv *rdata =
container_of(work, struct fc_rport_libfc_priv, event_work);
enum fc_rport_event event;
@@ -279,14 +281,18 @@ static void fc_rport_work(struct work_struct *work)
rport_ops->event_callback(lport, rport, event);
if (trans_state == FC_PORTSTATE_ROGUE)
put_device(&rport->dev);
- else
+ else {
+ port_id = rport->port_id;
fc_remote_port_delete(rport);
+ lport->tt.exch_mgr_reset(lport, 0, port_id);
+ lport->tt.exch_mgr_reset(lport, port_id, 0);
+ }
} else
mutex_unlock(&rdata->rp_mutex);
}
/**
- * fc_rport_login - Start the remote port login state machine
+ * fc_rport_login() - Start the remote port login state machine
* @rport: Fibre Channel remote port
*
* Locking Note: Called without the rport lock held. This
@@ -309,7 +315,7 @@ int fc_rport_login(struct fc_rport *rport)
}
/**
- * fc_rport_logoff - Logoff and remove an rport
+ * fc_rport_logoff() - Logoff and remove an rport
* @rport: Fibre Channel remote port to be removed
*
* Locking Note: Called without the rport lock held. This
@@ -347,7 +353,7 @@ int fc_rport_logoff(struct fc_rport *rport)
}
/**
- * fc_rport_enter_ready - The rport is ready
+ * fc_rport_enter_ready() - The rport is ready
* @rport: Fibre Channel remote port that is ready
*
* Locking Note: The rport lock is expected to be held before calling
@@ -366,7 +372,7 @@ static void fc_rport_enter_ready(struct fc_rport *rport)
}
/**
- * fc_rport_timeout - Handler for the retry_work timer.
+ * fc_rport_timeout() - Handler for the retry_work timer.
* @work: The work struct of the fc_rport_libfc_priv
*
* Locking Note: Called without the rport lock held. This
@@ -405,59 +411,75 @@ static void fc_rport_timeout(struct work_struct *work)
}
/**
- * fc_rport_error - Handler for any errors
+ * fc_rport_error() - Error handler, called once retries have been exhausted
* @rport: The fc_rport object
* @fp: The frame pointer
*
- * If the error was caused by a resource allocation failure
- * then wait for half a second and retry, otherwise retry
- * immediately.
- *
* Locking Note: The rport lock is expected to be held before
* calling this routine
*/
static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp)
{
struct fc_rport_libfc_priv *rdata = rport->dd_data;
- unsigned long delay = 0;
FC_DEBUG_RPORT("Error %ld in state %s, retries %d\n",
PTR_ERR(fp), fc_rport_state(rport), rdata->retries);
- if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) {
- /*
- * Memory allocation failure, or the exchange timed out.
- * Retry after delay
- */
- if (rdata->retries < rdata->local_port->max_retry_count) {
- rdata->retries++;
- if (!fp)
- delay = msecs_to_jiffies(500);
- get_device(&rport->dev);
- schedule_delayed_work(&rdata->retry_work, delay);
- } else {
- switch (rdata->rp_state) {
- case RPORT_ST_PLOGI:
- case RPORT_ST_PRLI:
- case RPORT_ST_LOGO:
- rdata->event = RPORT_EV_FAILED;
- queue_work(rport_event_queue,
- &rdata->event_work);
- break;
- case RPORT_ST_RTV:
- fc_rport_enter_ready(rport);
- break;
- case RPORT_ST_NONE:
- case RPORT_ST_READY:
- case RPORT_ST_INIT:
- break;
- }
- }
+ switch (rdata->rp_state) {
+ case RPORT_ST_PLOGI:
+ case RPORT_ST_PRLI:
+ case RPORT_ST_LOGO:
+ rdata->event = RPORT_EV_FAILED;
+ queue_work(rport_event_queue,
+ &rdata->event_work);
+ break;
+ case RPORT_ST_RTV:
+ fc_rport_enter_ready(rport);
+ break;
+ case RPORT_ST_NONE:
+ case RPORT_ST_READY:
+ case RPORT_ST_INIT:
+ break;
}
}
/**
- * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response
+ * fc_rport_error_retry() - Error handler when retries are desired
+ * @rport: The fc_rport object
+ * @fp: The frame pointer
+ *
+ * If the error was an exchange timeout retry immediately,
+ * otherwise wait for E_D_TOV.
+ *
+ * Locking Note: The rport lock is expected to be held before
+ * calling this routine
+ */
+static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp)
+{
+ struct fc_rport_libfc_priv *rdata = rport->dd_data;
+ unsigned long delay = FC_DEF_E_D_TOV;
+
+ /* make sure this isn't an FC_EX_CLOSED error, never retry those */
+ if (PTR_ERR(fp) == -FC_EX_CLOSED)
+ return fc_rport_error(rport, fp);
+
+ if (rdata->retries < rdata->local_port->max_retry_count) {
+ FC_DEBUG_RPORT("Error %ld in state %s, retrying\n",
+ PTR_ERR(fp), fc_rport_state(rport));
+ rdata->retries++;
+ /* no additional delay on exchange timeouts */
+ if (PTR_ERR(fp) == -FC_EX_TIMEOUT)
+ delay = 0;
+ get_device(&rport->dev);
+ schedule_delayed_work(&rdata->retry_work, delay);
+ return;
+ }
+
+ return fc_rport_error(rport, fp);
+}
+
+/**
+ * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response
* @sp: current sequence in the PLOGI exchange
* @fp: response frame
* @rp_arg: Fibre Channel remote port
@@ -483,17 +505,17 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n",
rport->port_id);
+ if (IS_ERR(fp)) {
+ fc_rport_error_retry(rport, fp);
+ goto err;
+ }
+
if (rdata->rp_state != RPORT_ST_PLOGI) {
FC_DBG("Received a PLOGI response, but in state %s\n",
fc_rport_state(rport));
goto out;
}
- if (IS_ERR(fp)) {
- fc_rport_error(rport, fp);
- goto err;
- }
-
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC &&
(plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) {
@@ -522,7 +544,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp,
else
fc_rport_enter_prli(rport);
} else
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
out:
fc_frame_free(fp);
@@ -532,7 +554,7 @@ err:
}
/**
- * fc_rport_enter_plogi - Send Port Login (PLOGI) request to peer
+ * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer
* @rport: Fibre Channel remote port to send PLOGI to
*
* Locking Note: The rport lock is expected to be held before calling
@@ -552,20 +574,20 @@ static void fc_rport_enter_plogi(struct fc_rport *rport)
rport->maxframe_size = FC_MIN_MAX_PAYLOAD;
fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi));
if (!fp) {
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
return;
}
rdata->e_d_tov = lport->e_d_tov;
if (!lport->tt.elsct_send(lport, rport, fp, ELS_PLOGI,
fc_rport_plogi_resp, rport, lport->e_d_tov))
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
else
get_device(&rport->dev);
}
/**
- * fc_rport_prli_resp - Process Login (PRLI) response handler
+ * fc_rport_prli_resp() - Process Login (PRLI) response handler
* @sp: current sequence in the PRLI exchange
* @fp: response frame
* @rp_arg: Fibre Channel remote port
@@ -592,17 +614,17 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n",
rport->port_id);
+ if (IS_ERR(fp)) {
+ fc_rport_error_retry(rport, fp);
+ goto err;
+ }
+
if (rdata->rp_state != RPORT_ST_PRLI) {
FC_DBG("Received a PRLI response, but in state %s\n",
fc_rport_state(rport));
goto out;
}
- if (IS_ERR(fp)) {
- fc_rport_error(rport, fp);
- goto err;
- }
-
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
pp = fc_frame_payload_get(fp, sizeof(*pp));
@@ -635,7 +657,7 @@ err:
}
/**
- * fc_rport_logo_resp - Logout (LOGO) response handler
+ * fc_rport_logo_resp() - Logout (LOGO) response handler
* @sp: current sequence in the LOGO exchange
* @fp: response frame
* @rp_arg: Fibre Channel remote port
@@ -657,7 +679,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
rport->port_id);
if (IS_ERR(fp)) {
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
goto err;
}
@@ -684,7 +706,7 @@ err:
}
/**
- * fc_rport_enter_prli - Send Process Login (PRLI) request to peer
+ * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer
* @rport: Fibre Channel remote port to send PRLI to
*
* Locking Note: The rport lock is expected to be held before calling
@@ -707,19 +729,19 @@ static void fc_rport_enter_prli(struct fc_rport *rport)
fp = fc_frame_alloc(lport, sizeof(*pp));
if (!fp) {
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
return;
}
if (!lport->tt.elsct_send(lport, rport, fp, ELS_PRLI,
fc_rport_prli_resp, rport, lport->e_d_tov))
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
else
get_device(&rport->dev);
}
/**
- * fc_rport_els_rtv_resp - Request Timeout Value response handler
+ * fc_rport_els_rtv_resp() - Request Timeout Value response handler
* @sp: current sequence in the RTV exchange
* @fp: response frame
* @rp_arg: Fibre Channel remote port
@@ -742,17 +764,17 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n",
rport->port_id);
+ if (IS_ERR(fp)) {
+ fc_rport_error(rport, fp);
+ goto err;
+ }
+
if (rdata->rp_state != RPORT_ST_RTV) {
FC_DBG("Received a RTV response, but in state %s\n",
fc_rport_state(rport));
goto out;
}
- if (IS_ERR(fp)) {
- fc_rport_error(rport, fp);
- goto err;
- }
-
op = fc_frame_payload_op(fp);
if (op == ELS_LS_ACC) {
struct fc_els_rtv_acc *rtv;
@@ -785,7 +807,7 @@ err:
}
/**
- * fc_rport_enter_rtv - Send Request Timeout Value (RTV) request to peer
+ * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer
* @rport: Fibre Channel remote port to send RTV to
*
* Locking Note: The rport lock is expected to be held before calling
@@ -804,19 +826,19 @@ static void fc_rport_enter_rtv(struct fc_rport *rport)
fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv));
if (!fp) {
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
return;
}
if (!lport->tt.elsct_send(lport, rport, fp, ELS_RTV,
fc_rport_rtv_resp, rport, lport->e_d_tov))
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
else
get_device(&rport->dev);
}
/**
- * fc_rport_enter_logo - Send Logout (LOGO) request to peer
+ * fc_rport_enter_logo() - Send Logout (LOGO) request to peer
* @rport: Fibre Channel remote port to send LOGO to
*
* Locking Note: The rport lock is expected to be held before calling
@@ -835,20 +857,20 @@ static void fc_rport_enter_logo(struct fc_rport *rport)
fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo));
if (!fp) {
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
return;
}
if (!lport->tt.elsct_send(lport, rport, fp, ELS_LOGO,
fc_rport_logo_resp, rport, lport->e_d_tov))
- fc_rport_error(rport, fp);
+ fc_rport_error_retry(rport, fp);
else
get_device(&rport->dev);
}
/**
- * fc_rport_recv_req - Receive a request from a rport
+ * fc_rport_recv_req() - Receive a request from a rport
* @sp: current sequence in the PLOGI exchange
* @fp: response frame
* @rp_arg: Fibre Channel remote port
@@ -909,7 +931,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp,
}
/**
- * fc_rport_recv_plogi_req - Handle incoming Port Login (PLOGI) request
+ * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request
* @rport: Fibre Channel remote port that initiated PLOGI
* @sp: current sequence in the PLOGI exchange
* @fp: PLOGI request frame
@@ -966,7 +988,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
switch (rdata->rp_state) {
case RPORT_ST_INIT:
FC_DEBUG_RPORT("incoming PLOGI from %6x wwpn %llx state INIT "
- "- reject\n", sid, wwpn);
+ "- reject\n", sid, (unsigned long long)wwpn);
reject = ELS_RJT_UNSUP;
break;
case RPORT_ST_PLOGI:
@@ -1031,7 +1053,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport,
}
/**
- * fc_rport_recv_prli_req - Handle incoming Process Login (PRLI) request
+ * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request
* @rport: Fibre Channel remote port that initiated PRLI
* @sp: current sequence in the PRLI exchange
* @fp: PRLI request frame
@@ -1182,7 +1204,7 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport,
}
/**
- * fc_rport_recv_prlo_req - Handle incoming Process Logout (PRLO) request
+ * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request
* @rport: Fibre Channel remote port that initiated PRLO
* @sp: current sequence in the PRLO exchange
* @fp: PRLO request frame
@@ -1213,7 +1235,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp,
}
/**
- * fc_rport_recv_logo_req - Handle incoming Logout (LOGO) request
+ * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request
* @rport: Fibre Channel remote port that initiated LOGO
* @sp: current sequence in the LOGO exchange
* @fp: LOGO request frame
@@ -1249,6 +1271,9 @@ static void fc_rport_flush_queue(void)
int fc_rport_init(struct fc_lport *lport)
{
+ if (!lport->tt.rport_create)
+ lport->tt.rport_create = fc_rport_rogue_create;
+
if (!lport->tt.rport_login)
lport->tt.rport_login = fc_rport_login;
@@ -1285,7 +1310,7 @@ void fc_rport_terminate_io(struct fc_rport *rport)
struct fc_rport_libfc_priv *rdata = rport->dd_data;
struct fc_lport *lport = rdata->local_port;
- lport->tt.exch_mgr_reset(lport->emp, 0, rport->port_id);
- lport->tt.exch_mgr_reset(lport->emp, rport->port_id, 0);
+ lport->tt.exch_mgr_reset(lport, 0, rport->port_id);
+ lport->tt.exch_mgr_reset(lport, rport->port_id, 0);
}
EXPORT_SYMBOL(fc_rport_terminate_io);
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c
index 257c24115de..68962835916 100644
--- a/drivers/scsi/libiscsi.c
+++ b/drivers/scsi/libiscsi.c
@@ -38,6 +38,28 @@
#include <scsi/scsi_transport_iscsi.h>
#include <scsi/libiscsi.h>
+static int iscsi_dbg_lib;
+module_param_named(debug_libiscsi, iscsi_dbg_lib, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug_libiscsi, "Turn on debugging for libiscsi module. "
+ "Set to 1 to turn on, and zero to turn off. Default "
+ "is off.");
+
+#define ISCSI_DBG_CONN(_conn, dbg_fmt, arg...) \
+ do { \
+ if (iscsi_dbg_lib) \
+ iscsi_conn_printk(KERN_INFO, _conn, \
+ "%s " dbg_fmt, \
+ __func__, ##arg); \
+ } while (0);
+
+#define ISCSI_DBG_SESSION(_session, dbg_fmt, arg...) \
+ do { \
+ if (iscsi_dbg_lib) \
+ iscsi_session_printk(KERN_INFO, _session, \
+ "%s " dbg_fmt, \
+ __func__, ##arg); \
+ } while (0);
+
/* Serial Number Arithmetic, 32 bits, less than, RFC1982 */
#define SNA32_CHECK 2147483648UL
@@ -54,6 +76,15 @@ static int iscsi_sna_lte(u32 n1, u32 n2)
(n1 > n2 && (n2 - n1 < SNA32_CHECK)));
}
+inline void iscsi_conn_queue_work(struct iscsi_conn *conn)
+{
+ struct Scsi_Host *shost = conn->session->host;
+ struct iscsi_host *ihost = shost_priv(shost);
+
+ queue_work(ihost->workq, &conn->xmitwork);
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_queue_work);
+
void
iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
{
@@ -81,8 +112,7 @@ iscsi_update_cmdsn(struct iscsi_session *session, struct iscsi_nopin *hdr)
if (!list_empty(&session->leadconn->xmitqueue) ||
!list_empty(&session->leadconn->mgmtqueue)) {
if (!(session->tt->caps & CAP_DATA_PATH_OFFLOAD))
- scsi_queue_work(session->host,
- &session->leadconn->xmitwork);
+ iscsi_conn_queue_work(session->leadconn);
}
}
}
@@ -176,10 +206,11 @@ static int iscsi_prep_ecdb_ahs(struct iscsi_task *task)
ecdb_ahdr->reserved = 0;
memcpy(ecdb_ahdr->ecdb, cmd->cmnd + ISCSI_CDB_SIZE, rlen);
- debug_scsi("iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
- "rlen %d pad_len %d ahs_length %d iscsi_headers_size %u\n",
- cmd->cmd_len, rlen, pad_len, ahslength, task->hdr_len);
-
+ ISCSI_DBG_SESSION(task->conn->session,
+ "iscsi_prep_ecdb_ahs: varlen_cdb_len %d "
+ "rlen %d pad_len %d ahs_length %d iscsi_headers_size "
+ "%u\n", cmd->cmd_len, rlen, pad_len, ahslength,
+ task->hdr_len);
return 0;
}
@@ -201,10 +232,11 @@ static int iscsi_prep_bidi_ahs(struct iscsi_task *task)
rlen_ahdr->reserved = 0;
rlen_ahdr->read_length = cpu_to_be32(scsi_in(sc)->length);
- debug_scsi("bidi-in rlen_ahdr->read_length(%d) "
- "rlen_ahdr->ahslength(%d)\n",
- be32_to_cpu(rlen_ahdr->read_length),
- be16_to_cpu(rlen_ahdr->ahslength));
+ ISCSI_DBG_SESSION(task->conn->session,
+ "bidi-in rlen_ahdr->read_length(%d) "
+ "rlen_ahdr->ahslength(%d)\n",
+ be32_to_cpu(rlen_ahdr->read_length),
+ be16_to_cpu(rlen_ahdr->ahslength));
return 0;
}
@@ -335,13 +367,15 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task)
list_move_tail(&task->running, &conn->run_list);
conn->scsicmd_pdus_cnt++;
- debug_scsi("iscsi prep [%s cid %d sc %p cdb 0x%x itt 0x%x len %d "
- "bidi_len %d cmdsn %d win %d]\n", scsi_bidi_cmnd(sc) ?
- "bidirectional" : sc->sc_data_direction == DMA_TO_DEVICE ?
- "write" : "read", conn->id, sc, sc->cmnd[0], task->itt,
- scsi_bufflen(sc),
- scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
- session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1);
+ ISCSI_DBG_SESSION(session, "iscsi prep [%s cid %d sc %p cdb 0x%x "
+ "itt 0x%x len %d bidi_len %d cmdsn %d win %d]\n",
+ scsi_bidi_cmnd(sc) ? "bidirectional" :
+ sc->sc_data_direction == DMA_TO_DEVICE ?
+ "write" : "read", conn->id, sc, sc->cmnd[0],
+ task->itt, scsi_bufflen(sc),
+ scsi_bidi_cmnd(sc) ? scsi_in(sc)->length : 0,
+ session->cmdsn,
+ session->max_cmdsn - session->exp_cmdsn + 1);
return 0;
}
@@ -483,9 +517,9 @@ static int iscsi_prep_mgmt_task(struct iscsi_conn *conn,
task->state = ISCSI_TASK_RUNNING;
list_move_tail(&task->running, &conn->mgmt_run_list);
- debug_scsi("mgmtpdu [op 0x%x hdr->itt 0x%x datalen %d]\n",
- hdr->opcode & ISCSI_OPCODE_MASK, hdr->itt,
- task->data_count);
+ ISCSI_DBG_SESSION(session, "mgmtpdu [op 0x%x hdr->itt 0x%x "
+ "datalen %d]\n", hdr->opcode & ISCSI_OPCODE_MASK,
+ hdr->itt, task->data_count);
return 0;
}
@@ -560,7 +594,7 @@ __iscsi_conn_send_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
goto free_task;
} else
- scsi_queue_work(conn->session->host, &conn->xmitwork);
+ iscsi_conn_queue_work(conn);
return task;
@@ -637,8 +671,9 @@ invalid_datalen:
memcpy(sc->sense_buffer, data + 2,
min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
- debug_scsi("copied %d bytes of sense\n",
- min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
+ ISCSI_DBG_SESSION(session, "copied %d bytes of sense\n",
+ min_t(uint16_t, senselen,
+ SCSI_SENSE_BUFFERSIZE));
}
if (rhdr->flags & (ISCSI_FLAG_CMD_BIDI_UNDERFLOW |
@@ -666,8 +701,8 @@ invalid_datalen:
sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status;
}
out:
- debug_scsi("done [sc %lx res %d itt 0x%x]\n",
- (long)sc, sc->result, task->itt);
+ ISCSI_DBG_SESSION(session, "done [sc %p res %d itt 0x%x]\n",
+ sc, sc->result, task->itt);
conn->scsirsp_pdus_cnt++;
__iscsi_put_task(task);
@@ -835,8 +870,8 @@ int __iscsi_complete_pdu(struct iscsi_conn *conn, struct iscsi_hdr *hdr,
else
itt = ~0U;
- debug_scsi("[op 0x%x cid %d itt 0x%x len %d]\n",
- opcode, conn->id, itt, datalen);
+ ISCSI_DBG_SESSION(session, "[op 0x%x cid %d itt 0x%x len %d]\n",
+ opcode, conn->id, itt, datalen);
if (itt == ~0U) {
iscsi_update_cmdsn(session, (struct iscsi_nopin*)hdr);
@@ -1034,10 +1069,9 @@ struct iscsi_task *iscsi_itt_to_ctask(struct iscsi_conn *conn, itt_t itt)
}
EXPORT_SYMBOL_GPL(iscsi_itt_to_ctask);
-void iscsi_session_failure(struct iscsi_cls_session *cls_session,
+void iscsi_session_failure(struct iscsi_session *session,
enum iscsi_err err)
{
- struct iscsi_session *session = cls_session->dd_data;
struct iscsi_conn *conn;
struct device *dev;
unsigned long flags;
@@ -1095,10 +1129,10 @@ static int iscsi_check_cmdsn_window_closed(struct iscsi_conn *conn)
* Check for iSCSI window and take care of CmdSN wrap-around
*/
if (!iscsi_sna_lte(session->queued_cmdsn, session->max_cmdsn)) {
- debug_scsi("iSCSI CmdSN closed. ExpCmdSn %u MaxCmdSN %u "
- "CmdSN %u/%u\n", session->exp_cmdsn,
- session->max_cmdsn, session->cmdsn,
- session->queued_cmdsn);
+ ISCSI_DBG_SESSION(session, "iSCSI CmdSN closed. ExpCmdSn "
+ "%u MaxCmdSN %u CmdSN %u/%u\n",
+ session->exp_cmdsn, session->max_cmdsn,
+ session->cmdsn, session->queued_cmdsn);
return -ENOSPC;
}
return 0;
@@ -1133,7 +1167,7 @@ void iscsi_requeue_task(struct iscsi_task *task)
struct iscsi_conn *conn = task->conn;
list_move_tail(&task->running, &conn->requeue);
- scsi_queue_work(conn->session->host, &conn->xmitwork);
+ iscsi_conn_queue_work(conn);
}
EXPORT_SYMBOL_GPL(iscsi_requeue_task);
@@ -1152,7 +1186,7 @@ static int iscsi_data_xmit(struct iscsi_conn *conn)
spin_lock_bh(&conn->session->lock);
if (unlikely(conn->suspend_tx)) {
- debug_scsi("conn %d Tx suspended!\n", conn->id);
+ ISCSI_DBG_SESSION(conn->session, "Tx suspended!\n");
spin_unlock_bh(&conn->session->lock);
return -ENODATA;
}
@@ -1386,7 +1420,7 @@ int iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *))
goto prepd_reject;
}
} else
- scsi_queue_work(session->host, &conn->xmitwork);
+ iscsi_conn_queue_work(conn);
session->queued_cmdsn++;
spin_unlock(&session->lock);
@@ -1398,7 +1432,8 @@ prepd_reject:
iscsi_complete_command(task);
reject:
spin_unlock(&session->lock);
- debug_scsi("cmd 0x%x rejected (%d)\n", sc->cmnd[0], reason);
+ ISCSI_DBG_SESSION(session, "cmd 0x%x rejected (%d)\n",
+ sc->cmnd[0], reason);
spin_lock(host->host_lock);
return SCSI_MLQUEUE_TARGET_BUSY;
@@ -1407,7 +1442,8 @@ prepd_fault:
iscsi_complete_command(task);
fault:
spin_unlock(&session->lock);
- debug_scsi("iscsi: cmd 0x%x is not queued (%d)\n", sc->cmnd[0], reason);
+ ISCSI_DBG_SESSION(session, "iscsi: cmd 0x%x is not queued (%d)\n",
+ sc->cmnd[0], reason);
if (!scsi_bidi_cmnd(sc))
scsi_set_resid(sc, scsi_bufflen(sc));
else {
@@ -1422,8 +1458,6 @@ EXPORT_SYMBOL_GPL(iscsi_queuecommand);
int iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
{
- if (depth > ISCSI_MAX_CMD_PER_LUN)
- depth = ISCSI_MAX_CMD_PER_LUN;
scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
return sdev->queue_depth;
}
@@ -1457,8 +1491,10 @@ int iscsi_eh_target_reset(struct scsi_cmnd *sc)
spin_lock_bh(&session->lock);
if (session->state == ISCSI_STATE_TERMINATE) {
failed:
- debug_scsi("failing target reset: session terminated "
- "[CID %d age %d]\n", conn->id, session->age);
+ iscsi_session_printk(KERN_INFO, session,
+ "failing target reset: Could not log "
+ "back into target [age %d]\n",
+ session->age);
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
return FAILED;
@@ -1472,7 +1508,7 @@ failed:
*/
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
- debug_scsi("iscsi_eh_target_reset wait for relogin\n");
+ ISCSI_DBG_SESSION(session, "wait for relogin\n");
wait_event_interruptible(conn->ehwait,
session->state == ISCSI_STATE_TERMINATE ||
session->state == ISCSI_STATE_LOGGED_IN ||
@@ -1501,7 +1537,7 @@ static void iscsi_tmf_timedout(unsigned long data)
spin_lock(&session->lock);
if (conn->tmf_state == TMF_QUEUED) {
conn->tmf_state = TMF_TIMEDOUT;
- debug_scsi("tmf timedout\n");
+ ISCSI_DBG_SESSION(session, "tmf timedout\n");
/* unblock eh_abort() */
wake_up(&conn->ehwait);
}
@@ -1521,7 +1557,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
spin_unlock_bh(&session->lock);
iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
spin_lock_bh(&session->lock);
- debug_scsi("tmf exec failure\n");
+ ISCSI_DBG_SESSION(session, "tmf exec failure\n");
return -EPERM;
}
conn->tmfcmd_pdus_cnt++;
@@ -1529,7 +1565,7 @@ static int iscsi_exec_task_mgmt_fn(struct iscsi_conn *conn,
conn->tmf_timer.function = iscsi_tmf_timedout;
conn->tmf_timer.data = (unsigned long)conn;
add_timer(&conn->tmf_timer);
- debug_scsi("tmf set timeout\n");
+ ISCSI_DBG_SESSION(session, "tmf set timeout\n");
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
@@ -1567,22 +1603,27 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
{
struct iscsi_task *task, *tmp;
- if (conn->task && (conn->task->sc->device->lun == lun || lun == -1))
- conn->task = NULL;
+ if (conn->task) {
+ if (lun == -1 ||
+ (conn->task->sc && conn->task->sc->device->lun == lun))
+ conn->task = NULL;
+ }
/* flush pending */
list_for_each_entry_safe(task, tmp, &conn->xmitqueue, running) {
if (lun == task->sc->device->lun || lun == -1) {
- debug_scsi("failing pending sc %p itt 0x%x\n",
- task->sc, task->itt);
+ ISCSI_DBG_SESSION(conn->session,
+ "failing pending sc %p itt 0x%x\n",
+ task->sc, task->itt);
fail_command(conn, task, error << 16);
}
}
list_for_each_entry_safe(task, tmp, &conn->requeue, running) {
if (lun == task->sc->device->lun || lun == -1) {
- debug_scsi("failing requeued sc %p itt 0x%x\n",
- task->sc, task->itt);
+ ISCSI_DBG_SESSION(conn->session,
+ "failing requeued sc %p itt 0x%x\n",
+ task->sc, task->itt);
fail_command(conn, task, error << 16);
}
}
@@ -1590,8 +1631,9 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
/* fail all other running */
list_for_each_entry_safe(task, tmp, &conn->run_list, running) {
if (lun == task->sc->device->lun || lun == -1) {
- debug_scsi("failing in progress sc %p itt 0x%x\n",
- task->sc, task->itt);
+ ISCSI_DBG_SESSION(conn->session,
+ "failing in progress sc %p itt 0x%x\n",
+ task->sc, task->itt);
fail_command(conn, task, error << 16);
}
}
@@ -1599,9 +1641,12 @@ static void fail_all_commands(struct iscsi_conn *conn, unsigned lun,
void iscsi_suspend_tx(struct iscsi_conn *conn)
{
+ struct Scsi_Host *shost = conn->session->host;
+ struct iscsi_host *ihost = shost_priv(shost);
+
set_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
- scsi_flush_work(conn->session->host);
+ flush_workqueue(ihost->workq);
}
EXPORT_SYMBOL_GPL(iscsi_suspend_tx);
@@ -1609,7 +1654,7 @@ static void iscsi_start_tx(struct iscsi_conn *conn)
{
clear_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx);
if (!(conn->session->tt->caps & CAP_DATA_PATH_OFFLOAD))
- scsi_queue_work(conn->session->host, &conn->xmitwork);
+ iscsi_conn_queue_work(conn);
}
static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
@@ -1622,7 +1667,7 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
cls_session = starget_to_session(scsi_target(scmd->device));
session = cls_session->dd_data;
- debug_scsi("scsi cmd %p timedout\n", scmd);
+ ISCSI_DBG_SESSION(session, "scsi cmd %p timedout\n", scmd);
spin_lock(&session->lock);
if (session->state != ISCSI_STATE_LOGGED_IN) {
@@ -1662,8 +1707,8 @@ static enum blk_eh_timer_return iscsi_eh_cmd_timed_out(struct scsi_cmnd *scmd)
rc = BLK_EH_RESET_TIMER;
done:
spin_unlock(&session->lock);
- debug_scsi("return %s\n", rc == BLK_EH_RESET_TIMER ?
- "timer reset" : "nh");
+ ISCSI_DBG_SESSION(session, "return %s\n", rc == BLK_EH_RESET_TIMER ?
+ "timer reset" : "nh");
return rc;
}
@@ -1697,13 +1742,13 @@ static void iscsi_check_transport_timeouts(unsigned long data)
if (time_before_eq(last_recv + recv_timeout, jiffies)) {
/* send a ping to try to provoke some traffic */
- debug_scsi("Sending nopout as ping on conn %p\n", conn);
+ ISCSI_DBG_CONN(conn, "Sending nopout as ping\n");
iscsi_send_nopout(conn, NULL);
next_timeout = conn->last_ping + (conn->ping_timeout * HZ);
} else
next_timeout = last_recv + recv_timeout;
- debug_scsi("Setting next tmo %lu\n", next_timeout);
+ ISCSI_DBG_CONN(conn, "Setting next tmo %lu\n", next_timeout);
mod_timer(&conn->transport_timer, next_timeout);
done:
spin_unlock(&session->lock);
@@ -1740,7 +1785,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
* got the command.
*/
if (!sc->SCp.ptr) {
- debug_scsi("sc never reached iscsi layer or it completed.\n");
+ ISCSI_DBG_SESSION(session, "sc never reached iscsi layer or "
+ "it completed.\n");
spin_unlock_bh(&session->lock);
mutex_unlock(&session->eh_mutex);
return SUCCESS;
@@ -1762,11 +1808,13 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
age = session->age;
task = (struct iscsi_task *)sc->SCp.ptr;
- debug_scsi("aborting [sc %p itt 0x%x]\n", sc, task->itt);
+ ISCSI_DBG_SESSION(session, "aborting [sc %p itt 0x%x]\n",
+ sc, task->itt);
/* task completed before time out */
if (!task->sc) {
- debug_scsi("sc completed while abort in progress\n");
+ ISCSI_DBG_SESSION(session, "sc completed while abort in "
+ "progress\n");
goto success;
}
@@ -1815,7 +1863,8 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
if (!sc->SCp.ptr) {
conn->tmf_state = TMF_INITIAL;
/* task completed before tmf abort response */
- debug_scsi("sc completed while abort in progress\n");
+ ISCSI_DBG_SESSION(session, "sc completed while abort "
+ "in progress\n");
goto success;
}
/* fall through */
@@ -1827,15 +1876,16 @@ int iscsi_eh_abort(struct scsi_cmnd *sc)
success:
spin_unlock_bh(&session->lock);
success_unlocked:
- debug_scsi("abort success [sc %lx itt 0x%x]\n", (long)sc, task->itt);
+ ISCSI_DBG_SESSION(session, "abort success [sc %p itt 0x%x]\n",
+ sc, task->itt);
mutex_unlock(&session->eh_mutex);
return SUCCESS;
failed:
spin_unlock_bh(&session->lock);
failed_unlocked:
- debug_scsi("abort failed [sc %p itt 0x%x]\n", sc,
- task ? task->itt : 0);
+ ISCSI_DBG_SESSION(session, "abort failed [sc %p itt 0x%x]\n", sc,
+ task ? task->itt : 0);
mutex_unlock(&session->eh_mutex);
return FAILED;
}
@@ -1862,7 +1912,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
cls_session = starget_to_session(scsi_target(sc->device));
session = cls_session->dd_data;
- debug_scsi("LU Reset [sc %p lun %u]\n", sc, sc->device->lun);
+ ISCSI_DBG_SESSION(session, "LU Reset [sc %p lun %u]\n",
+ sc, sc->device->lun);
mutex_lock(&session->eh_mutex);
spin_lock_bh(&session->lock);
@@ -1916,8 +1967,8 @@ int iscsi_eh_device_reset(struct scsi_cmnd *sc)
unlock:
spin_unlock_bh(&session->lock);
done:
- debug_scsi("iscsi_eh_device_reset %s\n",
- rc == SUCCESS ? "SUCCESS" : "FAILED");
+ ISCSI_DBG_SESSION(session, "dev reset result = %s\n",
+ rc == SUCCESS ? "SUCCESS" : "FAILED");
mutex_unlock(&session->eh_mutex);
return rc;
}
@@ -1944,12 +1995,14 @@ iscsi_pool_init(struct iscsi_pool *q, int max, void ***items, int item_size)
num_arrays++;
q->pool = kzalloc(num_arrays * max * sizeof(void*), GFP_KERNEL);
if (q->pool == NULL)
- goto enomem;
+ return -ENOMEM;
q->queue = kfifo_init((void*)q->pool, max * sizeof(void*),
GFP_KERNEL, NULL);
- if (q->queue == ERR_PTR(-ENOMEM))
+ if (IS_ERR(q->queue)) {
+ q->queue = NULL;
goto enomem;
+ }
for (i = 0; i < max; i++) {
q->pool[i] = kzalloc(item_size, GFP_KERNEL);
@@ -1979,8 +2032,7 @@ void iscsi_pool_free(struct iscsi_pool *q)
for (i = 0; i < q->max; i++)
kfree(q->pool[i]);
- if (q->pool)
- kfree(q->pool);
+ kfree(q->pool);
kfree(q->queue);
}
EXPORT_SYMBOL_GPL(iscsi_pool_free);
@@ -1998,6 +2050,11 @@ int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
if (!shost->can_queue)
shost->can_queue = ISCSI_DEF_XMIT_CMDS_MAX;
+ if (!shost->cmd_per_lun)
+ shost->cmd_per_lun = ISCSI_DEF_CMD_PER_LUN;
+
+ if (!shost->transportt->eh_timed_out)
+ shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
return scsi_add_host(shost, pdev);
}
EXPORT_SYMBOL_GPL(iscsi_host_add);
@@ -2006,13 +2063,13 @@ EXPORT_SYMBOL_GPL(iscsi_host_add);
* iscsi_host_alloc - allocate a host and driver data
* @sht: scsi host template
* @dd_data_size: driver host data size
- * @qdepth: default device queue depth
+ * @xmit_can_sleep: bool indicating if LLD will queue IO from a work queue
*
* This should be called by partial offload and software iscsi drivers.
* To access the driver specific memory use the iscsi_host_priv() macro.
*/
struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
- int dd_data_size, uint16_t qdepth)
+ int dd_data_size, bool xmit_can_sleep)
{
struct Scsi_Host *shost;
struct iscsi_host *ihost;
@@ -2020,29 +2077,31 @@ struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
if (!shost)
return NULL;
- shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
+ ihost = shost_priv(shost);
- if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
- if (qdepth != 0)
- printk(KERN_ERR "iscsi: invalid queue depth of %d. "
- "Queue depth must be between 1 and %d.\n",
- qdepth, ISCSI_MAX_CMD_PER_LUN);
- qdepth = ISCSI_DEF_CMD_PER_LUN;
+ if (xmit_can_sleep) {
+ snprintf(ihost->workq_name, sizeof(ihost->workq_name),
+ "iscsi_q_%d", shost->host_no);
+ ihost->workq = create_singlethread_workqueue(ihost->workq_name);
+ if (!ihost->workq)
+ goto free_host;
}
- shost->cmd_per_lun = qdepth;
- ihost = shost_priv(shost);
spin_lock_init(&ihost->lock);
ihost->state = ISCSI_HOST_SETUP;
ihost->num_sessions = 0;
init_waitqueue_head(&ihost->session_removal_wq);
return shost;
+
+free_host:
+ scsi_host_put(shost);
+ return NULL;
}
EXPORT_SYMBOL_GPL(iscsi_host_alloc);
static void iscsi_notify_host_removed(struct iscsi_cls_session *cls_session)
{
- iscsi_session_failure(cls_session, ISCSI_ERR_INVALID_HOST);
+ iscsi_session_failure(cls_session->dd_data, ISCSI_ERR_INVALID_HOST);
}
/**
@@ -2068,6 +2127,8 @@ void iscsi_host_remove(struct Scsi_Host *shost)
flush_signals(current);
scsi_remove_host(shost);
+ if (ihost->workq)
+ destroy_workqueue(ihost->workq);
}
EXPORT_SYMBOL_GPL(iscsi_host_remove);
@@ -2466,14 +2527,16 @@ flush_control_queues(struct iscsi_session *session, struct iscsi_conn *conn)
/* handle pending */
list_for_each_entry_safe(task, tmp, &conn->mgmtqueue, running) {
- debug_scsi("flushing pending mgmt task itt 0x%x\n", task->itt);
+ ISCSI_DBG_SESSION(session, "flushing pending mgmt task "
+ "itt 0x%x\n", task->itt);
/* release ref from prep task */
__iscsi_put_task(task);
}
/* handle running */
list_for_each_entry_safe(task, tmp, &conn->mgmt_run_list, running) {
- debug_scsi("flushing running mgmt task itt 0x%x\n", task->itt);
+ ISCSI_DBG_SESSION(session, "flushing running mgmt task "
+ "itt 0x%x\n", task->itt);
/* release ref from prep task */
__iscsi_put_task(task);
}
@@ -2523,7 +2586,7 @@ static void iscsi_start_session_recovery(struct iscsi_session *session,
conn->datadgst_en = 0;
if (session->state == ISCSI_STATE_IN_RECOVERY &&
old_stop_stage != STOP_CONN_RECOVER) {
- debug_scsi("blocking session\n");
+ ISCSI_DBG_SESSION(session, "blocking session\n");
iscsi_block_session(session->cls_session);
}
}
diff --git a/drivers/scsi/libiscsi_tcp.c b/drivers/scsi/libiscsi_tcp.c
index e7705d3532c..91f8ce4d8d0 100644
--- a/drivers/scsi/libiscsi_tcp.c
+++ b/drivers/scsi/libiscsi_tcp.c
@@ -49,13 +49,21 @@ MODULE_AUTHOR("Mike Christie <michaelc@cs.wisc.edu>, "
"Alex Aizman <itn780@yahoo.com>");
MODULE_DESCRIPTION("iSCSI/TCP data-path");
MODULE_LICENSE("GPL");
-#undef DEBUG_TCP
-#ifdef DEBUG_TCP
-#define debug_tcp(fmt...) printk(KERN_INFO "tcp: " fmt)
-#else
-#define debug_tcp(fmt...)
-#endif
+static int iscsi_dbg_libtcp;
+module_param_named(debug_libiscsi_tcp, iscsi_dbg_libtcp, int,
+ S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug_libiscsi_tcp, "Turn on debugging for libiscsi_tcp "
+ "module. Set to 1 to turn on, and zero to turn off. Default "
+ "is off.");
+
+#define ISCSI_DBG_TCP(_conn, dbg_fmt, arg...) \
+ do { \
+ if (iscsi_dbg_libtcp) \
+ iscsi_conn_printk(KERN_INFO, _conn, \
+ "%s " dbg_fmt, \
+ __func__, ##arg); \
+ } while (0);
static int iscsi_tcp_hdr_recv_done(struct iscsi_tcp_conn *tcp_conn,
struct iscsi_segment *segment);
@@ -123,18 +131,13 @@ static void iscsi_tcp_segment_map(struct iscsi_segment *segment, int recv)
if (page_count(sg_page(sg)) >= 1 && !recv)
return;
- debug_tcp("iscsi_tcp_segment_map %s %p\n", recv ? "recv" : "xmit",
- segment);
segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
}
void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
{
- debug_tcp("iscsi_tcp_segment_unmap %p\n", segment);
-
if (segment->sg_mapped) {
- debug_tcp("iscsi_tcp_segment_unmap valid\n");
kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
segment->sg_mapped = NULL;
segment->data = NULL;
@@ -180,8 +183,9 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
struct scatterlist sg;
unsigned int pad;
- debug_tcp("copied %u %u size %u %s\n", segment->copied, copied,
- segment->size, recv ? "recv" : "xmit");
+ ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copied %u %u size %u %s\n",
+ segment->copied, copied, segment->size,
+ recv ? "recv" : "xmit");
if (segment->hash && copied) {
/*
* If a segment is kmapd we must unmap it before sending
@@ -214,8 +218,8 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
iscsi_tcp_segment_unmap(segment);
/* Do we have more scatterlist entries? */
- debug_tcp("total copied %u total size %u\n", segment->total_copied,
- segment->total_size);
+ ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "total copied %u total size %u\n",
+ segment->total_copied, segment->total_size);
if (segment->total_copied < segment->total_size) {
/* Proceed to the next entry in the scatterlist. */
iscsi_tcp_segment_init_sg(segment, sg_next(segment->sg),
@@ -229,7 +233,8 @@ int iscsi_tcp_segment_done(struct iscsi_tcp_conn *tcp_conn,
if (!(tcp_conn->iscsi_conn->session->tt->caps & CAP_PADDING_OFFLOAD)) {
pad = iscsi_padding(segment->total_copied);
if (pad != 0) {
- debug_tcp("consume %d pad bytes\n", pad);
+ ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
+ "consume %d pad bytes\n", pad);
segment->total_size += pad;
segment->size = pad;
segment->data = segment->padbuf;
@@ -278,13 +283,13 @@ iscsi_tcp_segment_recv(struct iscsi_tcp_conn *tcp_conn,
while (!iscsi_tcp_segment_done(tcp_conn, segment, 1, copy)) {
if (copied == len) {
- debug_tcp("iscsi_tcp_segment_recv copied %d bytes\n",
- len);
+ ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
+ "copied %d bytes\n", len);
break;
}
copy = min(len - copied, segment->size - segment->copied);
- debug_tcp("iscsi_tcp_segment_recv copying %d\n", copy);
+ ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "copying %d\n", copy);
memcpy(segment->data + segment->copied, ptr + copied, copy);
copied += copy;
}
@@ -311,7 +316,7 @@ iscsi_tcp_dgst_verify(struct iscsi_tcp_conn *tcp_conn,
if (memcmp(segment->recv_digest, segment->digest,
segment->digest_len)) {
- debug_scsi("digest mismatch\n");
+ ISCSI_DBG_TCP(tcp_conn->iscsi_conn, "digest mismatch\n");
return 0;
}
@@ -355,12 +360,8 @@ iscsi_segment_seek_sg(struct iscsi_segment *segment,
struct scatterlist *sg;
unsigned int i;
- debug_scsi("iscsi_segment_seek_sg offset %u size %llu\n",
- offset, size);
__iscsi_segment_init(segment, size, done, hash);
for_each_sg(sg_list, sg, sg_count, i) {
- debug_scsi("sg %d, len %u offset %u\n", i, sg->length,
- sg->offset);
if (offset < sg->length) {
iscsi_tcp_segment_init_sg(segment, sg, offset);
return 0;
@@ -382,8 +383,9 @@ EXPORT_SYMBOL_GPL(iscsi_segment_seek_sg);
*/
void iscsi_tcp_hdr_recv_prep(struct iscsi_tcp_conn *tcp_conn)
{
- debug_tcp("iscsi_tcp_hdr_recv_prep(%p%s)\n", tcp_conn,
- tcp_conn->iscsi_conn->hdrdgst_en ? ", digest enabled" : "");
+ ISCSI_DBG_TCP(tcp_conn->iscsi_conn,
+ "(%s)\n", tcp_conn->iscsi_conn->hdrdgst_en ?
+ "digest enabled" : "digest disabled");
iscsi_segment_init_linear(&tcp_conn->in.segment,
tcp_conn->in.hdr_buf, sizeof(struct iscsi_hdr),
iscsi_tcp_hdr_recv_done, NULL);
@@ -446,7 +448,7 @@ void iscsi_tcp_cleanup_task(struct iscsi_task *task)
while (__kfifo_get(tcp_task->r2tqueue, (void*)&r2t, sizeof(void*))) {
__kfifo_put(tcp_task->r2tpool.queue, (void*)&r2t,
sizeof(void*));
- debug_scsi("iscsi_tcp_cleanup_task pending r2t dropped\n");
+ ISCSI_DBG_TCP(task->conn, "pending r2t dropped\n");
}
r2t = tcp_task->r2t;
@@ -476,8 +478,8 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
return 0;
if (tcp_task->exp_datasn != datasn) {
- debug_tcp("%s: task->exp_datasn(%d) != rhdr->datasn(%d)\n",
- __func__, tcp_task->exp_datasn, datasn);
+ ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->datasn(%d)"
+ "\n", tcp_task->exp_datasn, datasn);
return ISCSI_ERR_DATASN;
}
@@ -485,9 +487,9 @@ static int iscsi_tcp_data_in(struct iscsi_conn *conn, struct iscsi_task *task)
tcp_task->data_offset = be32_to_cpu(rhdr->offset);
if (tcp_task->data_offset + tcp_conn->in.datalen > total_in_length) {
- debug_tcp("%s: data_offset(%d) + data_len(%d) > total_length_in(%d)\n",
- __func__, tcp_task->data_offset,
- tcp_conn->in.datalen, total_in_length);
+ ISCSI_DBG_TCP(conn, "data_offset(%d) + data_len(%d) > "
+ "total_length_in(%d)\n", tcp_task->data_offset,
+ tcp_conn->in.datalen, total_in_length);
return ISCSI_ERR_DATA_OFFSET;
}
@@ -518,8 +520,8 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
}
if (tcp_task->exp_datasn != r2tsn){
- debug_tcp("%s: task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
- __func__, tcp_task->exp_datasn, r2tsn);
+ ISCSI_DBG_TCP(conn, "task->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
+ tcp_task->exp_datasn, r2tsn);
return ISCSI_ERR_R2TSN;
}
@@ -552,9 +554,9 @@ static int iscsi_tcp_r2t_rsp(struct iscsi_conn *conn, struct iscsi_task *task)
}
if (r2t->data_length > session->max_burst)
- debug_scsi("invalid R2T with data len %u and max burst %u."
- "Attempting to execute request.\n",
- r2t->data_length, session->max_burst);
+ ISCSI_DBG_TCP(conn, "invalid R2T with data len %u and max "
+ "burst %u. Attempting to execute request.\n",
+ r2t->data_length, session->max_burst);
r2t->data_offset = be32_to_cpu(rhdr->data_offset);
if (r2t->data_offset + r2t->data_length > scsi_out(task->sc)->length) {
@@ -641,8 +643,8 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
if (rc)
return rc;
- debug_tcp("opcode 0x%x ahslen %d datalen %d\n",
- opcode, ahslen, tcp_conn->in.datalen);
+ ISCSI_DBG_TCP(conn, "opcode 0x%x ahslen %d datalen %d\n",
+ opcode, ahslen, tcp_conn->in.datalen);
switch(opcode) {
case ISCSI_OP_SCSI_DATA_IN:
@@ -674,10 +676,10 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr)
!(conn->session->tt->caps & CAP_DIGEST_OFFLOAD))
rx_hash = tcp_conn->rx_hash;
- debug_tcp("iscsi_tcp_begin_data_in(%p, offset=%d, "
- "datalen=%d)\n", tcp_conn,
- tcp_task->data_offset,
- tcp_conn->in.datalen);
+ ISCSI_DBG_TCP(conn, "iscsi_tcp_begin_data_in( "
+ "offset=%d, datalen=%d)\n",
+ tcp_task->data_offset,
+ tcp_conn->in.datalen);
rc = iscsi_segment_seek_sg(&tcp_conn->in.segment,
sdb->table.sgl,
sdb->table.nents,
@@ -854,10 +856,10 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
unsigned int consumed = 0;
int rc = 0;
- debug_tcp("in %d bytes\n", skb->len - offset);
+ ISCSI_DBG_TCP(conn, "in %d bytes\n", skb->len - offset);
if (unlikely(conn->suspend_rx)) {
- debug_tcp("conn %d Rx suspended!\n", conn->id);
+ ISCSI_DBG_TCP(conn, "Rx suspended!\n");
*status = ISCSI_TCP_SUSPENDED;
return 0;
}
@@ -874,15 +876,16 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
avail = skb_seq_read(consumed, &ptr, &seq);
if (avail == 0) {
- debug_tcp("no more data avail. Consumed %d\n",
- consumed);
+ ISCSI_DBG_TCP(conn, "no more data avail. Consumed %d\n",
+ consumed);
*status = ISCSI_TCP_SKB_DONE;
skb_abort_seq_read(&seq);
goto skb_done;
}
BUG_ON(segment->copied >= segment->size);
- debug_tcp("skb %p ptr=%p avail=%u\n", skb, ptr, avail);
+ ISCSI_DBG_TCP(conn, "skb %p ptr=%p avail=%u\n", skb, ptr,
+ avail);
rc = iscsi_tcp_segment_recv(tcp_conn, segment, ptr, avail);
BUG_ON(rc == 0);
consumed += rc;
@@ -895,11 +898,11 @@ int iscsi_tcp_recv_skb(struct iscsi_conn *conn, struct sk_buff *skb,
segment_done:
*status = ISCSI_TCP_SEGMENT_DONE;
- debug_tcp("segment done\n");
+ ISCSI_DBG_TCP(conn, "segment done\n");
rc = segment->done(tcp_conn, segment);
if (rc != 0) {
*status = ISCSI_TCP_CONN_ERR;
- debug_tcp("Error receiving PDU, errno=%d\n", rc);
+ ISCSI_DBG_TCP(conn, "Error receiving PDU, errno=%d\n", rc);
iscsi_conn_failure(conn, rc);
return 0;
}
@@ -929,8 +932,7 @@ int iscsi_tcp_task_init(struct iscsi_task *task)
* mgmt tasks do not have a scatterlist since they come
* in from the iscsi interface.
*/
- debug_scsi("mtask deq [cid %d itt 0x%x]\n", conn->id,
- task->itt);
+ ISCSI_DBG_TCP(conn, "mtask deq [itt 0x%x]\n", task->itt);
return conn->session->tt->init_pdu(task, 0, task->data_count);
}
@@ -939,9 +941,8 @@ int iscsi_tcp_task_init(struct iscsi_task *task)
tcp_task->exp_datasn = 0;
/* Prepare PDU, optionally w/ immediate data */
- debug_scsi("task deq [cid %d itt 0x%x imm %d unsol %d]\n",
- conn->id, task->itt, task->imm_count,
- task->unsol_r2t.data_length);
+ ISCSI_DBG_TCP(conn, "task deq [itt 0x%x imm %d unsol %d]\n",
+ task->itt, task->imm_count, task->unsol_r2t.data_length);
err = conn->session->tt->init_pdu(task, 0, task->imm_count);
if (err)
@@ -965,7 +966,8 @@ static struct iscsi_r2t_info *iscsi_tcp_get_curr_r2t(struct iscsi_task *task)
r2t = tcp_task->r2t;
/* Continue with this R2T? */
if (r2t->data_length <= r2t->sent) {
- debug_scsi(" done with r2t %p\n", r2t);
+ ISCSI_DBG_TCP(task->conn,
+ " done with r2t %p\n", r2t);
__kfifo_put(tcp_task->r2tpool.queue,
(void *)&tcp_task->r2t,
sizeof(void *));
@@ -1019,7 +1021,7 @@ flush:
r2t = iscsi_tcp_get_curr_r2t(task);
if (r2t == NULL) {
/* Waiting for more R2Ts to arrive. */
- debug_tcp("no R2Ts yet\n");
+ ISCSI_DBG_TCP(conn, "no R2Ts yet\n");
return 0;
}
@@ -1028,9 +1030,9 @@ flush:
return rc;
iscsi_prep_data_out_pdu(task, r2t, (struct iscsi_data *) task->hdr);
- debug_scsi("sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
- r2t, r2t->datasn - 1, task->hdr->itt,
- r2t->data_offset + r2t->sent, r2t->data_count);
+ ISCSI_DBG_TCP(conn, "sol dout %p [dsn %d itt 0x%x doff %d dlen %d]\n",
+ r2t, r2t->datasn - 1, task->hdr->itt,
+ r2t->data_offset + r2t->sent, r2t->data_count);
rc = conn->session->tt->init_pdu(task, r2t->data_offset + r2t->sent,
r2t->data_count);
diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c
index b615eda361d..81cdcf46c47 100644
--- a/drivers/scsi/lpfc/lpfc_debugfs.c
+++ b/drivers/scsi/lpfc/lpfc_debugfs.c
@@ -1132,7 +1132,7 @@ lpfc_debugfs_dumpDataDif_release(struct inode *inode, struct file *file)
}
#undef lpfc_debugfs_op_disc_trc
-static struct file_operations lpfc_debugfs_op_disc_trc = {
+static const struct file_operations lpfc_debugfs_op_disc_trc = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_disc_trc_open,
.llseek = lpfc_debugfs_lseek,
@@ -1141,7 +1141,7 @@ static struct file_operations lpfc_debugfs_op_disc_trc = {
};
#undef lpfc_debugfs_op_nodelist
-static struct file_operations lpfc_debugfs_op_nodelist = {
+static const struct file_operations lpfc_debugfs_op_nodelist = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_nodelist_open,
.llseek = lpfc_debugfs_lseek,
@@ -1150,7 +1150,7 @@ static struct file_operations lpfc_debugfs_op_nodelist = {
};
#undef lpfc_debugfs_op_hbqinfo
-static struct file_operations lpfc_debugfs_op_hbqinfo = {
+static const struct file_operations lpfc_debugfs_op_hbqinfo = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_hbqinfo_open,
.llseek = lpfc_debugfs_lseek,
@@ -1159,7 +1159,7 @@ static struct file_operations lpfc_debugfs_op_hbqinfo = {
};
#undef lpfc_debugfs_op_dumpHBASlim
-static struct file_operations lpfc_debugfs_op_dumpHBASlim = {
+static const struct file_operations lpfc_debugfs_op_dumpHBASlim = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_dumpHBASlim_open,
.llseek = lpfc_debugfs_lseek,
@@ -1168,7 +1168,7 @@ static struct file_operations lpfc_debugfs_op_dumpHBASlim = {
};
#undef lpfc_debugfs_op_dumpHostSlim
-static struct file_operations lpfc_debugfs_op_dumpHostSlim = {
+static const struct file_operations lpfc_debugfs_op_dumpHostSlim = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_dumpHostSlim_open,
.llseek = lpfc_debugfs_lseek,
@@ -1177,7 +1177,7 @@ static struct file_operations lpfc_debugfs_op_dumpHostSlim = {
};
#undef lpfc_debugfs_op_dumpData
-static struct file_operations lpfc_debugfs_op_dumpData = {
+static const struct file_operations lpfc_debugfs_op_dumpData = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_dumpData_open,
.llseek = lpfc_debugfs_lseek,
@@ -1187,7 +1187,7 @@ static struct file_operations lpfc_debugfs_op_dumpData = {
};
#undef lpfc_debugfs_op_dumpDif
-static struct file_operations lpfc_debugfs_op_dumpDif = {
+static const struct file_operations lpfc_debugfs_op_dumpDif = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_dumpDif_open,
.llseek = lpfc_debugfs_lseek,
@@ -1197,7 +1197,7 @@ static struct file_operations lpfc_debugfs_op_dumpDif = {
};
#undef lpfc_debugfs_op_slow_ring_trc
-static struct file_operations lpfc_debugfs_op_slow_ring_trc = {
+static const struct file_operations lpfc_debugfs_op_slow_ring_trc = {
.owner = THIS_MODULE,
.open = lpfc_debugfs_slow_ring_trc_open,
.llseek = lpfc_debugfs_lseek,
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c
index a8f30bdaff6..a7302480bc4 100644
--- a/drivers/scsi/lpfc/lpfc_els.c
+++ b/drivers/scsi/lpfc/lpfc_els.c
@@ -5258,6 +5258,7 @@ lpfc_send_els_event(struct lpfc_vport *vport,
sizeof(struct lpfc_name));
break;
default:
+ kfree(els_data);
return;
}
memcpy(els_data->wwpn, &ndlp->nlp_portname, sizeof(struct lpfc_name));
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index b103b6ed497..b1bd3fc7bae 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -1357,7 +1357,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
0x10, 0x1);
- cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24
+ cmd->result = DRIVER_SENSE << 24
| ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
phba->bg_guard_err_cnt++;
printk(KERN_ERR "BLKGRD: guard_tag error\n");
@@ -1368,7 +1368,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
0x10, 0x3);
- cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24
+ cmd->result = DRIVER_SENSE << 24
| ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
phba->bg_reftag_err_cnt++;
@@ -1380,7 +1380,7 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd,
scsi_build_sense_buffer(1, cmd->sense_buffer, ILLEGAL_REQUEST,
0x10, 0x2);
- cmd->result = (DRIVER_SENSE|SUGGEST_DIE) << 24
+ cmd->result = DRIVER_SENSE << 24
| ScsiResult(DID_ABORT, SAM_STAT_CHECK_CONDITION);
phba->bg_apptag_err_cnt++;
diff --git a/drivers/scsi/mpt2sas/Kconfig b/drivers/scsi/mpt2sas/Kconfig
new file mode 100644
index 00000000000..4a86855c23b
--- /dev/null
+++ b/drivers/scsi/mpt2sas/Kconfig
@@ -0,0 +1,66 @@
+#
+# Kernel configuration file for the MPT2SAS
+#
+# This code is based on drivers/scsi/mpt2sas/Kconfig
+# Copyright (C) 2007-2008 LSI Corporation
+# (mailto:DL-MPTFusionLinux@lsi.com)
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# NO WARRANTY
+# THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+# CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+# LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+# solely responsible for determining the appropriateness of using and
+# distributing the Program and assumes all risks associated with its
+# exercise of rights under this Agreement, including but not limited to
+# the risks and costs of program errors, damage to or loss of data,
+# programs or equipment, and unavailability or interruption of operations.
+
+# DISCLAIMER OF LIABILITY
+# NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+# USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+# HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+# USA.
+
+config SCSI_MPT2SAS
+ tristate "LSI MPT Fusion SAS 2.0 Device Driver"
+ depends on PCI && SCSI
+ select SCSI_SAS_ATTRS
+ ---help---
+ This driver supports PCI-Express SAS 6Gb/s Host Adapters.
+
+config SCSI_MPT2SAS_MAX_SGE
+ int "LSI MPT Fusion Max number of SG Entries (16 - 128)"
+ depends on PCI && SCSI && SCSI_MPT2SAS
+ default "128"
+ range 16 128
+ ---help---
+ This option allows you to specify the maximum number of scatter-
+ gather entries per I/O. The driver default is 128, which matches
+ SAFE_PHYS_SEGMENTS. However, it may decreased down to 16.
+ Decreasing this parameter will reduce memory requirements
+ on a per controller instance.
+
+config SCSI_MPT2SAS_LOGGING
+ bool "LSI MPT Fusion logging facility"
+ depends on PCI && SCSI && SCSI_MPT2SAS
+ ---help---
+ This turns on a logging facility.
diff --git a/drivers/scsi/mpt2sas/Makefile b/drivers/scsi/mpt2sas/Makefile
new file mode 100644
index 00000000000..728f0475711
--- /dev/null
+++ b/drivers/scsi/mpt2sas/Makefile
@@ -0,0 +1,7 @@
+# mpt2sas makefile
+obj-$(CONFIG_SCSI_MPT2SAS) += mpt2sas.o
+mpt2sas-y += mpt2sas_base.o \
+ mpt2sas_config.o \
+ mpt2sas_scsih.o \
+ mpt2sas_transport.o \
+ mpt2sas_ctl.o
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2.h b/drivers/scsi/mpt2sas/mpi/mpi2.h
new file mode 100644
index 00000000000..7bb2ece8b2e
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2.h
@@ -0,0 +1,1067 @@
+/*
+ * Copyright (c) 2000-2009 LSI Corporation.
+ *
+ *
+ * Name: mpi2.h
+ * Title: MPI Message independent structures and definitions
+ * including System Interface Register Set and
+ * scatter/gather formats.
+ * Creation Date: June 21, 2006
+ *
+ * mpi2.h Version: 02.00.11
+ *
+ * Version History
+ * ---------------
+ *
+ * Date Version Description
+ * -------- -------- ------------------------------------------------------
+ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Moved ReplyPostHostIndex register to offset 0x6C of the
+ * MPI2_SYSTEM_INTERFACE_REGS and modified the define for
+ * MPI2_REPLY_POST_HOST_INDEX_OFFSET.
+ * Added union of request descriptors.
+ * Added union of reply descriptors.
+ * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Added define for MPI2_VERSION_02_00.
+ * Fixed the size of the FunctionDependent5 field in the
+ * MPI2_DEFAULT_REPLY structure.
+ * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Removed the MPI-defined Fault Codes and extended the
+ * product specific codes up to 0xEFFF.
+ * Added a sixth key value for the WriteSequence register
+ * and changed the flush value to 0x0.
+ * Added message function codes for Diagnostic Buffer Post
+ * and Diagnsotic Release.
+ * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
+ * Moved MPI2_VERSION_UNION from mpi2_ioc.h.
+ * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Added #defines for marking a reply descriptor as unused.
+ * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT.
+ * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT.
+ * Moved LUN field defines from mpi2_init.h.
+ * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_H
+#define MPI2_H
+
+
+/*****************************************************************************
+*
+* MPI Version Definitions
+*
+*****************************************************************************/
+
+#define MPI2_VERSION_MAJOR (0x02)
+#define MPI2_VERSION_MINOR (0x00)
+#define MPI2_VERSION_MAJOR_MASK (0xFF00)
+#define MPI2_VERSION_MAJOR_SHIFT (8)
+#define MPI2_VERSION_MINOR_MASK (0x00FF)
+#define MPI2_VERSION_MINOR_SHIFT (0)
+#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \
+ MPI2_VERSION_MINOR)
+
+#define MPI2_VERSION_02_00 (0x0200)
+
+/* versioning for this MPI header set */
+#define MPI2_HEADER_VERSION_UNIT (0x0B)
+#define MPI2_HEADER_VERSION_DEV (0x00)
+#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00)
+#define MPI2_HEADER_VERSION_UNIT_SHIFT (8)
+#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF)
+#define MPI2_HEADER_VERSION_DEV_SHIFT (0)
+#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | MPI2_HEADER_VERSION_DEV)
+
+
+/*****************************************************************************
+*
+* IOC State Definitions
+*
+*****************************************************************************/
+
+#define MPI2_IOC_STATE_RESET (0x00000000)
+#define MPI2_IOC_STATE_READY (0x10000000)
+#define MPI2_IOC_STATE_OPERATIONAL (0x20000000)
+#define MPI2_IOC_STATE_FAULT (0x40000000)
+
+#define MPI2_IOC_STATE_MASK (0xF0000000)
+#define MPI2_IOC_STATE_SHIFT (28)
+
+/* Fault state range for prodcut specific codes */
+#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000)
+#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF)
+
+
+/*****************************************************************************
+*
+* System Interface Register Definitions
+*
+*****************************************************************************/
+
+typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS
+{
+ U32 Doorbell; /* 0x00 */
+ U32 WriteSequence; /* 0x04 */
+ U32 HostDiagnostic; /* 0x08 */
+ U32 Reserved1; /* 0x0C */
+ U32 DiagRWData; /* 0x10 */
+ U32 DiagRWAddressLow; /* 0x14 */
+ U32 DiagRWAddressHigh; /* 0x18 */
+ U32 Reserved2[5]; /* 0x1C */
+ U32 HostInterruptStatus; /* 0x30 */
+ U32 HostInterruptMask; /* 0x34 */
+ U32 DCRData; /* 0x38 */
+ U32 DCRAddress; /* 0x3C */
+ U32 Reserved3[2]; /* 0x40 */
+ U32 ReplyFreeHostIndex; /* 0x48 */
+ U32 Reserved4[8]; /* 0x4C */
+ U32 ReplyPostHostIndex; /* 0x6C */
+ U32 Reserved5; /* 0x70 */
+ U32 HCBSize; /* 0x74 */
+ U32 HCBAddressLow; /* 0x78 */
+ U32 HCBAddressHigh; /* 0x7C */
+ U32 Reserved6[16]; /* 0x80 */
+ U32 RequestDescriptorPostLow; /* 0xC0 */
+ U32 RequestDescriptorPostHigh; /* 0xC4 */
+ U32 Reserved7[14]; /* 0xC8 */
+} MPI2_SYSTEM_INTERFACE_REGS, MPI2_POINTER PTR_MPI2_SYSTEM_INTERFACE_REGS,
+ Mpi2SystemInterfaceRegs_t, MPI2_POINTER pMpi2SystemInterfaceRegs_t;
+
+/*
+ * Defines for working with the Doorbell register.
+ */
+#define MPI2_DOORBELL_OFFSET (0x00000000)
+
+/* IOC --> System values */
+#define MPI2_DOORBELL_USED (0x08000000)
+#define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000)
+#define MPI2_DOORBELL_WHO_INIT_SHIFT (24)
+#define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF)
+#define MPI2_DOORBELL_DATA_MASK (0x0000FFFF)
+
+/* System --> IOC values */
+#define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000)
+#define MPI2_DOORBELL_FUNCTION_SHIFT (24)
+#define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000)
+#define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16)
+
+
+/*
+ * Defines for the WriteSequence register
+ */
+#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004)
+#define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F)
+#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0)
+#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF)
+#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4)
+#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB)
+#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2)
+#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7)
+#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD)
+
+/*
+ * Defines for the HostDiagnostic register
+ */
+#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008)
+
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800)
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000)
+#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800)
+
+#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400)
+#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200)
+#define MPI2_DIAG_HCB_MODE (0x00000100)
+#define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080)
+#define MPI2_DIAG_FLASH_BAD_SIG (0x00000040)
+#define MPI2_DIAG_RESET_HISTORY (0x00000020)
+#define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010)
+#define MPI2_DIAG_RESET_ADAPTER (0x00000004)
+#define MPI2_DIAG_HOLD_IOC_RESET (0x00000002)
+
+/*
+ * Offsets for DiagRWData and address
+ */
+#define MPI2_DIAG_RW_DATA_OFFSET (0x00000010)
+#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014)
+#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018)
+
+/*
+ * Defines for the HostInterruptStatus register
+ */
+#define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030)
+#define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000)
+#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS
+#define MPI2_HIS_RESET_IRQ_STATUS (0x40000000)
+#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008)
+#define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001)
+#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS
+
+/*
+ * Defines for the HostInterruptMask register
+ */
+#define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034)
+#define MPI2_HIM_RESET_IRQ_MASK (0x40000000)
+#define MPI2_HIM_REPLY_INT_MASK (0x00000008)
+#define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK
+#define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001)
+#define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK
+
+/*
+ * Offsets for DCRData and address
+ */
+#define MPI2_DCR_DATA_OFFSET (0x00000038)
+#define MPI2_DCR_ADDRESS_OFFSET (0x0000003C)
+
+/*
+ * Offset for the Reply Free Queue
+ */
+#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048)
+
+/*
+ * Offset for the Reply Descriptor Post Queue
+ */
+#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C)
+
+/*
+ * Defines for the HCBSize and address
+ */
+#define MPI2_HCB_SIZE_OFFSET (0x00000074)
+#define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000)
+#define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001)
+
+#define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078)
+#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C)
+
+/*
+ * Offsets for the Request Queue
+ */
+#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0)
+#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4)
+
+
+/*****************************************************************************
+*
+* Message Descriptors
+*
+*****************************************************************************/
+
+/* Request Descriptors */
+
+/* Default Request Descriptor */
+typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR
+{
+ U8 RequestFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U16 SMID; /* 0x02 */
+ U16 LMID; /* 0x04 */
+ U16 DescriptorTypeDependent; /* 0x06 */
+} MPI2_DEFAULT_REQUEST_DESCRIPTOR,
+ MPI2_POINTER PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR,
+ Mpi2DefaultRequestDescriptor_t, MPI2_POINTER pMpi2DefaultRequestDescriptor_t;
+
+/* defines for the RequestFlags field */
+#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00)
+#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02)
+#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06)
+#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08)
+
+#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01)
+
+
+/* High Priority Request Descriptor */
+typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR
+{
+ U8 RequestFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U16 SMID; /* 0x02 */
+ U16 LMID; /* 0x04 */
+ U16 Reserved1; /* 0x06 */
+} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
+ MPI2_POINTER PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR,
+ Mpi2HighPriorityRequestDescriptor_t,
+ MPI2_POINTER pMpi2HighPriorityRequestDescriptor_t;
+
+
+/* SCSI IO Request Descriptor */
+typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR
+{
+ U8 RequestFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U16 SMID; /* 0x02 */
+ U16 LMID; /* 0x04 */
+ U16 DevHandle; /* 0x06 */
+} MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
+ MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR,
+ Mpi2SCSIIORequestDescriptor_t, MPI2_POINTER pMpi2SCSIIORequestDescriptor_t;
+
+
+/* SCSI Target Request Descriptor */
+typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR
+{
+ U8 RequestFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U16 SMID; /* 0x02 */
+ U16 LMID; /* 0x04 */
+ U16 IoIndex; /* 0x06 */
+} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
+ MPI2_POINTER PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR,
+ Mpi2SCSITargetRequestDescriptor_t,
+ MPI2_POINTER pMpi2SCSITargetRequestDescriptor_t;
+
+/* union of Request Descriptors */
+typedef union _MPI2_REQUEST_DESCRIPTOR_UNION
+{
+ MPI2_DEFAULT_REQUEST_DESCRIPTOR Default;
+ MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority;
+ MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO;
+ MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget;
+ U64 Words;
+} MPI2_REQUEST_DESCRIPTOR_UNION, MPI2_POINTER PTR_MPI2_REQUEST_DESCRIPTOR_UNION,
+ Mpi2RequestDescriptorUnion_t, MPI2_POINTER pMpi2RequestDescriptorUnion_t;
+
+
+/* Reply Descriptors */
+
+/* Default Reply Descriptor */
+typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR
+{
+ U8 ReplyFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U16 DescriptorTypeDependent1; /* 0x02 */
+ U32 DescriptorTypeDependent2; /* 0x04 */
+} MPI2_DEFAULT_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR,
+ Mpi2DefaultReplyDescriptor_t, MPI2_POINTER pMpi2DefaultReplyDescriptor_t;
+
+/* defines for the ReplyFlags field */
+#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F)
+#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00)
+#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02)
+#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03)
+#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F)
+
+/* values for marking a reply descriptor as unused */
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF)
+#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF)
+
+/* Address Reply Descriptor */
+typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR
+{
+ U8 ReplyFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U16 SMID; /* 0x02 */
+ U32 ReplyFrameAddress; /* 0x04 */
+} MPI2_ADDRESS_REPLY_DESCRIPTOR, MPI2_POINTER PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR,
+ Mpi2AddressReplyDescriptor_t, MPI2_POINTER pMpi2AddressReplyDescriptor_t;
+
+#define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00)
+
+
+/* SCSI IO Success Reply Descriptor */
+typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR
+{
+ U8 ReplyFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U16 SMID; /* 0x02 */
+ U16 TaskTag; /* 0x04 */
+ U16 DevHandle; /* 0x06 */
+} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+ MPI2_POINTER PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR,
+ Mpi2SCSIIOSuccessReplyDescriptor_t,
+ MPI2_POINTER pMpi2SCSIIOSuccessReplyDescriptor_t;
+
+
+/* TargetAssist Success Reply Descriptor */
+typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR
+{
+ U8 ReplyFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U16 SMID; /* 0x02 */
+ U8 SequenceNumber; /* 0x04 */
+ U8 Reserved1; /* 0x05 */
+ U16 IoIndex; /* 0x06 */
+} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
+ MPI2_POINTER PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR,
+ Mpi2TargetAssistSuccessReplyDescriptor_t,
+ MPI2_POINTER pMpi2TargetAssistSuccessReplyDescriptor_t;
+
+
+/* Target Command Buffer Reply Descriptor */
+typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR
+{
+ U8 ReplyFlags; /* 0x00 */
+ U8 VF_ID; /* 0x01 */
+ U8 VP_ID; /* 0x02 */
+ U8 Flags; /* 0x03 */
+ U16 InitiatorDevHandle; /* 0x04 */
+ U16 IoIndex; /* 0x06 */
+} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
+ MPI2_POINTER PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR,
+ Mpi2TargetCommandBufferReplyDescriptor_t,
+ MPI2_POINTER pMpi2TargetCommandBufferReplyDescriptor_t;
+
+/* defines for Flags field */
+#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F)
+
+
+/* union of Reply Descriptors */
+typedef union _MPI2_REPLY_DESCRIPTORS_UNION
+{
+ MPI2_DEFAULT_REPLY_DESCRIPTOR Default;
+ MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply;
+ MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess;
+ MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess;
+ MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer;
+ U64 Words;
+} MPI2_REPLY_DESCRIPTORS_UNION, MPI2_POINTER PTR_MPI2_REPLY_DESCRIPTORS_UNION,
+ Mpi2ReplyDescriptorsUnion_t, MPI2_POINTER pMpi2ReplyDescriptorsUnion_t;
+
+
+
+/*****************************************************************************
+*
+* Message Functions
+* 0x80 -> 0x8F reserved for private message use per product
+*
+*
+*****************************************************************************/
+
+#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */
+#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) /* SCSI Task Management */
+#define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */
+#define MPI2_FUNCTION_IOC_FACTS (0x03) /* IOC Facts */
+#define MPI2_FUNCTION_CONFIG (0x04) /* Configuration */
+#define MPI2_FUNCTION_PORT_FACTS (0x05) /* Port Facts */
+#define MPI2_FUNCTION_PORT_ENABLE (0x06) /* Port Enable */
+#define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) /* Event Notification */
+#define MPI2_FUNCTION_EVENT_ACK (0x08) /* Event Acknowledge */
+#define MPI2_FUNCTION_FW_DOWNLOAD (0x09) /* FW Download */
+#define MPI2_FUNCTION_TARGET_ASSIST (0x0B) /* Target Assist */
+#define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) /* Target Status Send */
+#define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) /* Target Mode Abort */
+#define MPI2_FUNCTION_FW_UPLOAD (0x12) /* FW Upload */
+#define MPI2_FUNCTION_RAID_ACTION (0x15) /* RAID Action */
+#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) /* SCSI IO RAID Passthrough */
+#define MPI2_FUNCTION_TOOLBOX (0x17) /* Toolbox */
+#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) /* SCSI Enclosure Processor */
+#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) /* SMP Passthrough */
+#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) /* SAS IO Unit Control */
+#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) /* SATA Passthrough */
+#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) /* Diagnostic Buffer Post */
+#define MPI2_FUNCTION_DIAG_RELEASE (0x1E) /* Diagnostic Release */
+#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) /* Target Command Buffer Post Base */
+#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) /* Target Command Buffer Post List */
+
+
+
+/* Doorbell functions */
+#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40)
+/* #define MPI2_FUNCTION_IO_UNIT_RESET (0x41) */
+#define MPI2_FUNCTION_HANDSHAKE (0x42)
+
+
+/*****************************************************************************
+*
+* IOC Status Values
+*
+*****************************************************************************/
+
+/* mask for IOCStatus status value */
+#define MPI2_IOCSTATUS_MASK (0x7FFF)
+
+/****************************************************************************
+* Common IOCStatus values for all replies
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SUCCESS (0x0000)
+#define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001)
+#define MPI2_IOCSTATUS_BUSY (0x0002)
+#define MPI2_IOCSTATUS_INVALID_SGL (0x0003)
+#define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004)
+#define MPI2_IOCSTATUS_INVALID_VPID (0x0005)
+#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006)
+#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007)
+#define MPI2_IOCSTATUS_INVALID_STATE (0x0008)
+#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009)
+
+/****************************************************************************
+* Config IOCStatus values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022)
+#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023)
+#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024)
+#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025)
+
+/****************************************************************************
+* SCSI IO Reply
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040)
+#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042)
+#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043)
+#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044)
+#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045)
+#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046)
+#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047)
+#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048)
+#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049)
+#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A)
+#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B)
+#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C)
+
+/****************************************************************************
+* For use by SCSI Initiator and SCSI Target end-to-end data protection
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D)
+#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E)
+#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F)
+
+/****************************************************************************
+* SCSI Target values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062)
+#define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063)
+#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064)
+#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065)
+#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A)
+#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D)
+#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E)
+#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F)
+#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070)
+#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071)
+
+/****************************************************************************
+* Serial Attached SCSI values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090)
+#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091)
+
+/****************************************************************************
+* Diagnostic Buffer Post / Diagnostic Release values
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0)
+
+
+/****************************************************************************
+* IOCStatus flag to indicate that log info is available
+****************************************************************************/
+
+#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000)
+
+/****************************************************************************
+* IOCLogInfo Types
+****************************************************************************/
+
+#define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000)
+#define MPI2_IOCLOGINFO_TYPE_SHIFT (28)
+#define MPI2_IOCLOGINFO_TYPE_NONE (0x0)
+#define MPI2_IOCLOGINFO_TYPE_SCSI (0x1)
+#define MPI2_IOCLOGINFO_TYPE_FC (0x2)
+#define MPI2_IOCLOGINFO_TYPE_SAS (0x3)
+#define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4)
+#define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF)
+
+
+/*****************************************************************************
+*
+* Standard Message Structures
+*
+*****************************************************************************/
+
+/****************************************************************************
+* Request Message Header for all request messages
+****************************************************************************/
+
+typedef struct _MPI2_REQUEST_HEADER
+{
+ U16 FunctionDependent1; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 FunctionDependent2; /* 0x04 */
+ U8 FunctionDependent3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+} MPI2_REQUEST_HEADER, MPI2_POINTER PTR_MPI2_REQUEST_HEADER,
+ MPI2RequestHeader_t, MPI2_POINTER pMPI2RequestHeader_t;
+
+
+/****************************************************************************
+* Default Reply
+****************************************************************************/
+
+typedef struct _MPI2_DEFAULT_REPLY
+{
+ U16 FunctionDependent1; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 FunctionDependent2; /* 0x04 */
+ U8 FunctionDependent3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+ U16 FunctionDependent5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_DEFAULT_REPLY, MPI2_POINTER PTR_MPI2_DEFAULT_REPLY,
+ MPI2DefaultReply_t, MPI2_POINTER pMPI2DefaultReply_t;
+
+
+/* common version structure/union used in messages and configuration pages */
+
+typedef struct _MPI2_VERSION_STRUCT
+{
+ U8 Dev; /* 0x00 */
+ U8 Unit; /* 0x01 */
+ U8 Minor; /* 0x02 */
+ U8 Major; /* 0x03 */
+} MPI2_VERSION_STRUCT;
+
+typedef union _MPI2_VERSION_UNION
+{
+ MPI2_VERSION_STRUCT Struct;
+ U32 Word;
+} MPI2_VERSION_UNION;
+
+
+/* LUN field defines, common to many structures */
+#define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF)
+#define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000)
+#define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF)
+#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000)
+#define MPI2_LUN_LEVEL_1_WORD (0xFF00)
+#define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00)
+
+
+/*****************************************************************************
+*
+* Fusion-MPT MPI Scatter Gather Elements
+*
+*****************************************************************************/
+
+/****************************************************************************
+* MPI Simple Element structures
+****************************************************************************/
+
+typedef struct _MPI2_SGE_SIMPLE32
+{
+ U32 FlagsLength;
+ U32 Address;
+} MPI2_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_SGE_SIMPLE32,
+ Mpi2SGESimple32_t, MPI2_POINTER pMpi2SGESimple32_t;
+
+typedef struct _MPI2_SGE_SIMPLE64
+{
+ U32 FlagsLength;
+ U64 Address;
+} MPI2_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_SGE_SIMPLE64,
+ Mpi2SGESimple64_t, MPI2_POINTER pMpi2SGESimple64_t;
+
+typedef struct _MPI2_SGE_SIMPLE_UNION
+{
+ U32 FlagsLength;
+ union
+ {
+ U32 Address32;
+ U64 Address64;
+ } u;
+} MPI2_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_SIMPLE_UNION,
+ Mpi2SGESimpleUnion_t, MPI2_POINTER pMpi2SGESimpleUnion_t;
+
+
+/****************************************************************************
+* MPI Chain Element structures
+****************************************************************************/
+
+typedef struct _MPI2_SGE_CHAIN32
+{
+ U16 Length;
+ U8 NextChainOffset;
+ U8 Flags;
+ U32 Address;
+} MPI2_SGE_CHAIN32, MPI2_POINTER PTR_MPI2_SGE_CHAIN32,
+ Mpi2SGEChain32_t, MPI2_POINTER pMpi2SGEChain32_t;
+
+typedef struct _MPI2_SGE_CHAIN64
+{
+ U16 Length;
+ U8 NextChainOffset;
+ U8 Flags;
+ U64 Address;
+} MPI2_SGE_CHAIN64, MPI2_POINTER PTR_MPI2_SGE_CHAIN64,
+ Mpi2SGEChain64_t, MPI2_POINTER pMpi2SGEChain64_t;
+
+typedef struct _MPI2_SGE_CHAIN_UNION
+{
+ U16 Length;
+ U8 NextChainOffset;
+ U8 Flags;
+ union
+ {
+ U32 Address32;
+ U64 Address64;
+ } u;
+} MPI2_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_SGE_CHAIN_UNION,
+ Mpi2SGEChainUnion_t, MPI2_POINTER pMpi2SGEChainUnion_t;
+
+
+/****************************************************************************
+* MPI Transaction Context Element structures
+****************************************************************************/
+
+typedef struct _MPI2_SGE_TRANSACTION32
+{
+ U8 Reserved;
+ U8 ContextSize;
+ U8 DetailsLength;
+ U8 Flags;
+ U32 TransactionContext[1];
+ U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION32, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION32,
+ Mpi2SGETransaction32_t, MPI2_POINTER pMpi2SGETransaction32_t;
+
+typedef struct _MPI2_SGE_TRANSACTION64
+{
+ U8 Reserved;
+ U8 ContextSize;
+ U8 DetailsLength;
+ U8 Flags;
+ U32 TransactionContext[2];
+ U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION64, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION64,
+ Mpi2SGETransaction64_t, MPI2_POINTER pMpi2SGETransaction64_t;
+
+typedef struct _MPI2_SGE_TRANSACTION96
+{
+ U8 Reserved;
+ U8 ContextSize;
+ U8 DetailsLength;
+ U8 Flags;
+ U32 TransactionContext[3];
+ U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION96, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION96,
+ Mpi2SGETransaction96_t, MPI2_POINTER pMpi2SGETransaction96_t;
+
+typedef struct _MPI2_SGE_TRANSACTION128
+{
+ U8 Reserved;
+ U8 ContextSize;
+ U8 DetailsLength;
+ U8 Flags;
+ U32 TransactionContext[4];
+ U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION128, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION128,
+ Mpi2SGETransaction_t128, MPI2_POINTER pMpi2SGETransaction_t128;
+
+typedef struct _MPI2_SGE_TRANSACTION_UNION
+{
+ U8 Reserved;
+ U8 ContextSize;
+ U8 DetailsLength;
+ U8 Flags;
+ union
+ {
+ U32 TransactionContext32[1];
+ U32 TransactionContext64[2];
+ U32 TransactionContext96[3];
+ U32 TransactionContext128[4];
+ } u;
+ U32 TransactionDetails[1];
+} MPI2_SGE_TRANSACTION_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANSACTION_UNION,
+ Mpi2SGETransactionUnion_t, MPI2_POINTER pMpi2SGETransactionUnion_t;
+
+
+/****************************************************************************
+* MPI SGE union for IO SGL's
+****************************************************************************/
+
+typedef struct _MPI2_MPI_SGE_IO_UNION
+{
+ union
+ {
+ MPI2_SGE_SIMPLE_UNION Simple;
+ MPI2_SGE_CHAIN_UNION Chain;
+ } u;
+} MPI2_MPI_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_IO_UNION,
+ Mpi2MpiSGEIOUnion_t, MPI2_POINTER pMpi2MpiSGEIOUnion_t;
+
+
+/****************************************************************************
+* MPI SGE union for SGL's with Simple and Transaction elements
+****************************************************************************/
+
+typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION
+{
+ union
+ {
+ MPI2_SGE_SIMPLE_UNION Simple;
+ MPI2_SGE_TRANSACTION_UNION Transaction;
+ } u;
+} MPI2_SGE_TRANS_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_SGE_TRANS_SIMPLE_UNION,
+ Mpi2SGETransSimpleUnion_t, MPI2_POINTER pMpi2SGETransSimpleUnion_t;
+
+
+/****************************************************************************
+* All MPI SGE types union
+****************************************************************************/
+
+typedef struct _MPI2_MPI_SGE_UNION
+{
+ union
+ {
+ MPI2_SGE_SIMPLE_UNION Simple;
+ MPI2_SGE_CHAIN_UNION Chain;
+ MPI2_SGE_TRANSACTION_UNION Transaction;
+ } u;
+} MPI2_MPI_SGE_UNION, MPI2_POINTER PTR_MPI2_MPI_SGE_UNION,
+ Mpi2MpiSgeUnion_t, MPI2_POINTER pMpi2MpiSgeUnion_t;
+
+
+/****************************************************************************
+* MPI SGE field definition and masks
+****************************************************************************/
+
+/* Flags field bit definitions */
+
+#define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80)
+#define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40)
+#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30)
+#define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08)
+#define MPI2_SGE_FLAGS_DIRECTION (0x04)
+#define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02)
+#define MPI2_SGE_FLAGS_END_OF_LIST (0x01)
+
+#define MPI2_SGE_FLAGS_SHIFT (24)
+
+#define MPI2_SGE_LENGTH_MASK (0x00FFFFFF)
+#define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF)
+
+/* Element Type */
+
+#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00)
+#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10)
+#define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30)
+#define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30)
+
+/* Address location */
+
+#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00)
+
+/* Direction */
+
+#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00)
+#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04)
+
+/* Address Size */
+
+#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02)
+
+/* Context Size */
+
+#define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00)
+#define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02)
+#define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04)
+#define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06)
+
+#define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000)
+#define MPI2_SGE_CHAIN_OFFSET_SHIFT (16)
+
+/****************************************************************************
+* MPI SGE operation Macros
+****************************************************************************/
+
+/* SIMPLE FlagsLength manipulations... */
+#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT)
+#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> MPI2_SGE_FLAGS_SHIFT)
+#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK)
+#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK)
+
+#define MPI2_SGE_SET_FLAGS_LENGTH(f,l) (MPI2_SGE_SET_FLAGS(f) | MPI2_SGE_LENGTH(l))
+
+#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength)
+#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength)
+#define MPI2_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_SGE_SET_FLAGS_LENGTH(f,l)
+
+/* CAUTION - The following are READ-MODIFY-WRITE! */
+#define MPI2_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_SGE_SET_FLAGS(f)
+#define MPI2_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_SGE_LENGTH(l)
+
+#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> MPI2_SGE_CHAIN_OFFSET_SHIFT)
+
+
+/*****************************************************************************
+*
+* Fusion-MPT IEEE Scatter Gather Elements
+*
+*****************************************************************************/
+
+/****************************************************************************
+* IEEE Simple Element structures
+****************************************************************************/
+
+typedef struct _MPI2_IEEE_SGE_SIMPLE32
+{
+ U32 Address;
+ U32 FlagsLength;
+} MPI2_IEEE_SGE_SIMPLE32, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE32,
+ Mpi2IeeeSgeSimple32_t, MPI2_POINTER pMpi2IeeeSgeSimple32_t;
+
+typedef struct _MPI2_IEEE_SGE_SIMPLE64
+{
+ U64 Address;
+ U32 Length;
+ U16 Reserved1;
+ U8 Reserved2;
+ U8 Flags;
+} MPI2_IEEE_SGE_SIMPLE64, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE64,
+ Mpi2IeeeSgeSimple64_t, MPI2_POINTER pMpi2IeeeSgeSimple64_t;
+
+typedef union _MPI2_IEEE_SGE_SIMPLE_UNION
+{
+ MPI2_IEEE_SGE_SIMPLE32 Simple32;
+ MPI2_IEEE_SGE_SIMPLE64 Simple64;
+} MPI2_IEEE_SGE_SIMPLE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_SIMPLE_UNION,
+ Mpi2IeeeSgeSimpleUnion_t, MPI2_POINTER pMpi2IeeeSgeSimpleUnion_t;
+
+
+/****************************************************************************
+* IEEE Chain Element structures
+****************************************************************************/
+
+typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32;
+
+typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64;
+
+typedef union _MPI2_IEEE_SGE_CHAIN_UNION
+{
+ MPI2_IEEE_SGE_CHAIN32 Chain32;
+ MPI2_IEEE_SGE_CHAIN64 Chain64;
+} MPI2_IEEE_SGE_CHAIN_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_CHAIN_UNION,
+ Mpi2IeeeSgeChainUnion_t, MPI2_POINTER pMpi2IeeeSgeChainUnion_t;
+
+
+/****************************************************************************
+* All IEEE SGE types union
+****************************************************************************/
+
+typedef struct _MPI2_IEEE_SGE_UNION
+{
+ union
+ {
+ MPI2_IEEE_SGE_SIMPLE_UNION Simple;
+ MPI2_IEEE_SGE_CHAIN_UNION Chain;
+ } u;
+} MPI2_IEEE_SGE_UNION, MPI2_POINTER PTR_MPI2_IEEE_SGE_UNION,
+ Mpi2IeeeSgeUnion_t, MPI2_POINTER pMpi2IeeeSgeUnion_t;
+
+
+/****************************************************************************
+* IEEE SGE field definitions and masks
+****************************************************************************/
+
+/* Flags field bit definitions */
+
+#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80)
+
+#define MPI2_IEEE32_SGE_FLAGS_SHIFT (24)
+
+#define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF)
+
+/* Element Type */
+
+#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00)
+#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80)
+
+/* Data Location Address Space */
+
+#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03)
+#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00)
+#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02)
+#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03)
+
+
+/****************************************************************************
+* IEEE SGE operation Macros
+****************************************************************************/
+
+/* SIMPLE FlagsLength manipulations... */
+#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT)
+#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) >> MPI2_IEEE32_SGE_FLAGS_SHIFT)
+#define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK)
+
+#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) | MPI2_IEEE32_SGE_LENGTH(l))
+
+#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength)
+#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength)
+#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg,f,l) (psg)->FlagsLength = MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f,l)
+
+/* CAUTION - The following are READ-MODIFY-WRITE! */
+#define MPI2_IEEE32_pSGE_SET_FLAGS(psg,f) (psg)->FlagsLength |= MPI2_IEEE32_SGE_SET_FLAGS(f)
+#define MPI2_IEEE32_pSGE_SET_LENGTH(psg,l) (psg)->FlagsLength |= MPI2_IEEE32_SGE_LENGTH(l)
+
+
+
+
+/*****************************************************************************
+*
+* Fusion-MPT MPI/IEEE Scatter Gather Unions
+*
+*****************************************************************************/
+
+typedef union _MPI2_SIMPLE_SGE_UNION
+{
+ MPI2_SGE_SIMPLE_UNION MpiSimple;
+ MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
+} MPI2_SIMPLE_SGE_UNION, MPI2_POINTER PTR_MPI2_SIMPLE_SGE_UNION,
+ Mpi2SimpleSgeUntion_t, MPI2_POINTER pMpi2SimpleSgeUntion_t;
+
+
+typedef union _MPI2_SGE_IO_UNION
+{
+ MPI2_SGE_SIMPLE_UNION MpiSimple;
+ MPI2_SGE_CHAIN_UNION MpiChain;
+ MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple;
+ MPI2_IEEE_SGE_CHAIN_UNION IeeeChain;
+} MPI2_SGE_IO_UNION, MPI2_POINTER PTR_MPI2_SGE_IO_UNION,
+ Mpi2SGEIOUnion_t, MPI2_POINTER pMpi2SGEIOUnion_t;
+
+
+/****************************************************************************
+*
+* Values for SGLFlags field, used in many request messages with an SGL
+*
+****************************************************************************/
+
+/* values for MPI SGL Data Location Address Space subfield */
+#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C)
+#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00)
+#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04)
+#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08)
+#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C)
+/* values for SGL Type subfield */
+#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03)
+#define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00)
+#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01)
+#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02)
+
+
+#endif
+
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
new file mode 100644
index 00000000000..2f27cf6d6c6
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
@@ -0,0 +1,2151 @@
+/*
+ * Copyright (c) 2000-2009 LSI Corporation.
+ *
+ *
+ * Name: mpi2_cnfg.h
+ * Title: MPI Configuration messages and pages
+ * Creation Date: November 10, 2006
+ *
+ * mpi2_cnfg.h Version: 02.00.10
+ *
+ * Version History
+ * ---------------
+ *
+ * Date Version Description
+ * -------- -------- ------------------------------------------------------
+ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags.
+ * Added Manufacturing Page 11.
+ * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
+ * define.
+ * 06-26-07 02.00.02 Adding generic structure for product-specific
+ * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
+ * Rework of BIOS Page 2 configuration page.
+ * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
+ * forms.
+ * Added configuration pages IOC Page 8 and Driver
+ * Persistent Mapping Page 0.
+ * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated
+ * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
+ * RAID Physical Disk Pages 0 and 1, RAID Configuration
+ * Page 0).
+ * Added new value for AccessStatus field of SAS Device
+ * Page 0 (_SATA_NEEDS_INITIALIZATION).
+ * 10-31-07 02.00.04 Added missing SEPDevHandle field to
+ * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
+ * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for
+ * NVDATA.
+ * Modified IOC Page 7 to use masks and added field for
+ * SASBroadcastPrimitiveMasks.
+ * Added MPI2_CONFIG_PAGE_BIOS_4.
+ * Added MPI2_CONFIG_PAGE_LOG_0.
+ * 02-29-08 02.00.06 Modified various names to make them 32-character unique.
+ * Added SAS Device IDs.
+ * Updated Integrated RAID configuration pages including
+ * Manufacturing Page 4, IOC Page 6, and RAID Configuration
+ * Page 0.
+ * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
+ * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
+ * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
+ * Added missing MaxNumRoutedSasAddresses field to
+ * MPI2_CONFIG_PAGE_EXPANDER_0.
+ * Added SAS Port Page 0.
+ * Modified structure layout for
+ * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
+ * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
+ * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
+ * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
+ * to 0x000000FF.
+ * Added two new values for the Physical Disk Coercion Size
+ * bits in the Flags field of Manufacturing Page 4.
+ * Added product-specific Manufacturing pages 16 to 31.
+ * Modified Flags bits for controlling write cache on SATA
+ * drives in IO Unit Page 1.
+ * Added new bit to AdditionalControlFlags of SAS IO Unit
+ * Page 1 to control Invalid Topology Correction.
+ * Added additional defines for RAID Volume Page 0
+ * VolumeStatusFlags field.
+ * Modified meaning of RAID Volume Page 0 VolumeSettings
+ * define for auto-configure of hot-swap drives.
+ * Added SupportedPhysDisks field to RAID Volume Page 1 and
+ * added related defines.
+ * Added PhysDiskAttributes field (and related defines) to
+ * RAID Physical Disk Page 0.
+ * Added MPI2_SAS_PHYINFO_PHY_VACANT define.
+ * Added three new DiscoveryStatus bits for SAS IO Unit
+ * Page 0 and SAS Expander Page 0.
+ * Removed multiplexing information from SAS IO Unit pages.
+ * Added BootDeviceWaitTime field to SAS IO Unit Page 4.
+ * Removed Zone Address Resolved bit from PhyInfo and from
+ * Expander Page 0 Flags field.
+ * Added two new AccessStatus values to SAS Device Page 0
+ * for indicating routing problems. Added 3 reserved words
+ * to this page.
+ * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3.
+ * Inserted missing reserved field into structure for IOC
+ * Page 6.
+ * Added more pending task bits to RAID Volume Page 0
+ * VolumeStatusFlags defines.
+ * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
+ * Added a new DiscoveryStatus bit for SAS IO Unit Page 0
+ * and SAS Expander Page 0 to flag a downstream initiator
+ * when in simplified routing mode.
+ * Removed SATA Init Failure defines for DiscoveryStatus
+ * fields of SAS IO Unit Page 0 and SAS Expander Page 0.
+ * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
+ * Added PortGroups, DmaGroup, and ControlGroup fields to
+ * SAS Device Page 0.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_CNFG_H
+#define MPI2_CNFG_H
+
+/*****************************************************************************
+* Configuration Page Header and defines
+*****************************************************************************/
+
+/* Config Page Header */
+typedef struct _MPI2_CONFIG_PAGE_HEADER
+{
+ U8 PageVersion; /* 0x00 */
+ U8 PageLength; /* 0x01 */
+ U8 PageNumber; /* 0x02 */
+ U8 PageType; /* 0x03 */
+} MPI2_CONFIG_PAGE_HEADER, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER,
+ Mpi2ConfigPageHeader_t, MPI2_POINTER pMpi2ConfigPageHeader_t;
+
+typedef union _MPI2_CONFIG_PAGE_HEADER_UNION
+{
+ MPI2_CONFIG_PAGE_HEADER Struct;
+ U8 Bytes[4];
+ U16 Word16[2];
+ U32 Word32;
+} MPI2_CONFIG_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_HEADER_UNION,
+ Mpi2ConfigPageHeaderUnion, MPI2_POINTER pMpi2ConfigPageHeaderUnion;
+
+/* Extended Config Page Header */
+typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER
+{
+ U8 PageVersion; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 PageNumber; /* 0x02 */
+ U8 PageType; /* 0x03 */
+ U16 ExtPageLength; /* 0x04 */
+ U8 ExtPageType; /* 0x06 */
+ U8 Reserved2; /* 0x07 */
+} MPI2_CONFIG_EXTENDED_PAGE_HEADER,
+ MPI2_POINTER PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER,
+ Mpi2ConfigExtendedPageHeader_t, MPI2_POINTER pMpi2ConfigExtendedPageHeader_t;
+
+typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION
+{
+ MPI2_CONFIG_PAGE_HEADER Struct;
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext;
+ U8 Bytes[8];
+ U16 Word16[4];
+ U32 Word32[2];
+} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, MPI2_POINTER PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION,
+ Mpi2ConfigPageExtendedHeaderUnion, MPI2_POINTER pMpi2ConfigPageExtendedHeaderUnion;
+
+
+/* PageType field values */
+#define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00)
+#define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10)
+#define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20)
+#define MPI2_CONFIG_PAGEATTR_MASK (0xF0)
+
+#define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00)
+#define MPI2_CONFIG_PAGETYPE_IOC (0x01)
+#define MPI2_CONFIG_PAGETYPE_BIOS (0x02)
+#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08)
+#define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09)
+#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A)
+#define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F)
+#define MPI2_CONFIG_PAGETYPE_MASK (0x0F)
+
+#define MPI2_CONFIG_TYPENUM_MASK (0x0FFF)
+
+
+/* ExtPageType field values */
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13)
+#define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14)
+#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15)
+#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16)
+#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17)
+#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18)
+
+
+/*****************************************************************************
+* PageAddress defines
+*****************************************************************************/
+
+/* RAID Volume PageAddress format */
+#define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
+#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000)
+
+#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF)
+
+
+/* RAID Physical Disk PageAddress format */
+#define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000)
+#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000)
+#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000)
+
+#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF)
+#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF)
+
+
+/* SAS Expander PageAddress format */
+#define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000)
+#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000)
+
+#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF)
+#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000)
+#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16)
+
+
+/* SAS Device PageAddress format */
+#define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
+#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000)
+
+#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF)
+
+
+/* SAS PHY PageAddress format */
+#define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000)
+#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000)
+
+#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF)
+#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF)
+
+
+/* SAS Port PageAddress format */
+#define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000)
+#define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000)
+
+#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF)
+
+
+/* SAS Enclosure PageAddress format */
+#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000)
+#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000)
+
+#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF)
+
+
+/* RAID Configuration PageAddress format */
+#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000)
+#define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000)
+#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000)
+
+#define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF)
+
+
+/* Driver Persistent Mapping PageAddress format */
+#define MPI2_DPM_PGAD_FORM_MASK (0xF0000000)
+#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000)
+
+#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000)
+#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16)
+#define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF)
+
+
+/****************************************************************************
+* Configuration messages
+****************************************************************************/
+
+/* Configuration Request Message */
+typedef struct _MPI2_CONFIG_REQUEST
+{
+ U8 Action; /* 0x00 */
+ U8 SGLFlags; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 ExtPageLength; /* 0x04 */
+ U8 ExtPageType; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+ U32 Reserved2; /* 0x0C */
+ U32 Reserved3; /* 0x10 */
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */
+ U32 PageAddress; /* 0x18 */
+ MPI2_SGE_IO_UNION PageBufferSGE; /* 0x1C */
+} MPI2_CONFIG_REQUEST, MPI2_POINTER PTR_MPI2_CONFIG_REQUEST,
+ Mpi2ConfigRequest_t, MPI2_POINTER pMpi2ConfigRequest_t;
+
+/* values for the Action field */
+#define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00)
+#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01)
+#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02)
+#define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03)
+#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04)
+#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05)
+#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06)
+#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07)
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* Config Reply Message */
+typedef struct _MPI2_CONFIG_REPLY
+{
+ U8 Action; /* 0x00 */
+ U8 SGLFlags; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 ExtPageLength; /* 0x04 */
+ U8 ExtPageType; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+ U16 Reserved2; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x14 */
+} MPI2_CONFIG_REPLY, MPI2_POINTER PTR_MPI2_CONFIG_REPLY,
+ Mpi2ConfigReply_t, MPI2_POINTER pMpi2ConfigReply_t;
+
+
+
+/*****************************************************************************
+*
+* C o n f i g u r a t i o n P a g e s
+*
+*****************************************************************************/
+
+/****************************************************************************
+* Manufacturing Config pages
+****************************************************************************/
+
+#define MPI2_MFGPAGE_VENDORID_LSI (0x1000)
+
+/* SAS */
+#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070)
+#define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072)
+#define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074)
+#define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076)
+#define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077)
+#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064)
+#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065)
+
+
+/* Manufacturing Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_0
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 ChipName[16]; /* 0x04 */
+ U8 ChipRevision[8]; /* 0x14 */
+ U8 BoardName[16]; /* 0x1C */
+ U8 BoardAssembly[16]; /* 0x2C */
+ U8 BoardTracerNumber[16]; /* 0x3C */
+} MPI2_CONFIG_PAGE_MAN_0,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_0,
+ Mpi2ManufacturingPage0_t, MPI2_POINTER pMpi2ManufacturingPage0_t;
+
+#define MPI2_MANUFACTURING0_PAGEVERSION (0x00)
+
+
+/* Manufacturing Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_1
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 VPD[256]; /* 0x04 */
+} MPI2_CONFIG_PAGE_MAN_1,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_1,
+ Mpi2ManufacturingPage1_t, MPI2_POINTER pMpi2ManufacturingPage1_t;
+
+#define MPI2_MANUFACTURING1_PAGEVERSION (0x00)
+
+
+typedef struct _MPI2_CHIP_REVISION_ID
+{
+ U16 DeviceID; /* 0x00 */
+ U8 PCIRevisionID; /* 0x02 */
+ U8 Reserved; /* 0x03 */
+} MPI2_CHIP_REVISION_ID, MPI2_POINTER PTR_MPI2_CHIP_REVISION_ID,
+ Mpi2ChipRevisionId_t, MPI2_POINTER pMpi2ChipRevisionId_t;
+
+
+/* Manufacturing Page 2 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS
+#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_2
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */
+ U32 HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/* 0x08 */
+} MPI2_CONFIG_PAGE_MAN_2,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_2,
+ Mpi2ManufacturingPage2_t, MPI2_POINTER pMpi2ManufacturingPage2_t;
+
+#define MPI2_MANUFACTURING2_PAGEVERSION (0x00)
+
+
+/* Manufacturing Page 3 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_3_INFO_WORDS
+#define MPI2_MAN_PAGE_3_INFO_WORDS (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_3
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ MPI2_CHIP_REVISION_ID ChipId; /* 0x04 */
+ U32 Info[MPI2_MAN_PAGE_3_INFO_WORDS];/* 0x08 */
+} MPI2_CONFIG_PAGE_MAN_3,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_3,
+ Mpi2ManufacturingPage3_t, MPI2_POINTER pMpi2ManufacturingPage3_t;
+
+#define MPI2_MANUFACTURING3_PAGEVERSION (0x00)
+
+
+/* Manufacturing Page 4 */
+
+typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS
+{
+ U8 PowerSaveFlags; /* 0x00 */
+ U8 InternalOperationsSleepTime; /* 0x01 */
+ U8 InternalOperationsRunTime; /* 0x02 */
+ U8 HostIdleTime; /* 0x03 */
+} MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
+ MPI2_POINTER PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS,
+ Mpi2ManPage4PwrSaveSettings_t, MPI2_POINTER pMpi2ManPage4PwrSaveSettings_t;
+
+/* defines for the PowerSaveFlags field */
+#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03)
+#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00)
+#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01)
+#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02)
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_4
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x04 */
+ U32 Flags; /* 0x08 */
+ U8 InquirySize; /* 0x0C */
+ U8 Reserved2; /* 0x0D */
+ U16 Reserved3; /* 0x0E */
+ U8 InquiryData[56]; /* 0x10 */
+ U32 RAID0VolumeSettings; /* 0x48 */
+ U32 RAID1EVolumeSettings; /* 0x4C */
+ U32 RAID1VolumeSettings; /* 0x50 */
+ U32 RAID10VolumeSettings; /* 0x54 */
+ U32 Reserved4; /* 0x58 */
+ U32 Reserved5; /* 0x5C */
+ MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /* 0x60 */
+ U8 MaxOCEDisks; /* 0x64 */
+ U8 ResyncRate; /* 0x65 */
+ U16 DataScrubDuration; /* 0x66 */
+ U8 MaxHotSpares; /* 0x68 */
+ U8 MaxPhysDisksPerVol; /* 0x69 */
+ U8 MaxPhysDisks; /* 0x6A */
+ U8 MaxVolumes; /* 0x6B */
+} MPI2_CONFIG_PAGE_MAN_4,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_4,
+ Mpi2ManufacturingPage4_t, MPI2_POINTER pMpi2ManufacturingPage4_t;
+
+#define MPI2_MANUFACTURING4_PAGEVERSION (0x0A)
+
+/* Manufacturing Page 4 Flags field */
+#define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000)
+#define MPI2_MANPAGE4_METADATA_512MB (0x00000000)
+
+#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000)
+#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000)
+#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000)
+
+#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00)
+#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000)
+#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400)
+#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800)
+#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00)
+
+#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300)
+#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000)
+#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100)
+#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200)
+
+#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080)
+#define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040)
+#define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020)
+#define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010)
+#define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008)
+#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004)
+#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002)
+#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001)
+
+
+/* Manufacturing Page 5 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES
+#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1)
+#endif
+
+typedef struct _MPI2_MANUFACTURING5_ENTRY
+{
+ U64 WWID; /* 0x00 */
+ U64 DeviceName; /* 0x08 */
+} MPI2_MANUFACTURING5_ENTRY, MPI2_POINTER PTR_MPI2_MANUFACTURING5_ENTRY,
+ Mpi2Manufacturing5Entry_t, MPI2_POINTER pMpi2Manufacturing5Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_5
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 NumPhys; /* 0x04 */
+ U8 Reserved1; /* 0x05 */
+ U16 Reserved2; /* 0x06 */
+ U32 Reserved3; /* 0x08 */
+ U32 Reserved4; /* 0x0C */
+ MPI2_MANUFACTURING5_ENTRY Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/* 0x08 */
+} MPI2_CONFIG_PAGE_MAN_5,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_5,
+ Mpi2ManufacturingPage5_t, MPI2_POINTER pMpi2ManufacturingPage5_t;
+
+#define MPI2_MANUFACTURING5_PAGEVERSION (0x03)
+
+
+/* Manufacturing Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_6
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 ProductSpecificInfo;/* 0x04 */
+} MPI2_CONFIG_PAGE_MAN_6,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_6,
+ Mpi2ManufacturingPage6_t, MPI2_POINTER pMpi2ManufacturingPage6_t;
+
+#define MPI2_MANUFACTURING6_PAGEVERSION (0x00)
+
+
+/* Manufacturing Page 7 */
+
+typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO
+{
+ U32 Pinout; /* 0x00 */
+ U8 Connector[16]; /* 0x04 */
+ U8 Location; /* 0x14 */
+ U8 Reserved1; /* 0x15 */
+ U16 Slot; /* 0x16 */
+ U32 Reserved2; /* 0x18 */
+} MPI2_MANPAGE7_CONNECTOR_INFO, MPI2_POINTER PTR_MPI2_MANPAGE7_CONNECTOR_INFO,
+ Mpi2ManPage7ConnectorInfo_t, MPI2_POINTER pMpi2ManPage7ConnectorInfo_t;
+
+/* defines for the Pinout field */
+#define MPI2_MANPAGE7_PINOUT_SFF_8484_L4 (0x00080000)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484_L3 (0x00040000)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484_L2 (0x00020000)
+#define MPI2_MANPAGE7_PINOUT_SFF_8484_L1 (0x00010000)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470_L4 (0x00000800)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470_L3 (0x00000400)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470_L2 (0x00000200)
+#define MPI2_MANPAGE7_PINOUT_SFF_8470_L1 (0x00000100)
+#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x00000002)
+#define MPI2_MANPAGE7_PINOUT_CONNECTION_UNKNOWN (0x00000001)
+
+/* defines for the Location field */
+#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01)
+#define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02)
+#define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04)
+#define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08)
+#define MPI2_MANPAGE7_LOCATION_AUTO (0x10)
+#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20)
+#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumPhys at runtime.
+ */
+#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX
+#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_7
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x04 */
+ U32 Reserved2; /* 0x08 */
+ U32 Flags; /* 0x0C */
+ U8 EnclosureName[16]; /* 0x10 */
+ U8 NumPhys; /* 0x20 */
+ U8 Reserved3; /* 0x21 */
+ U16 Reserved4; /* 0x22 */
+ MPI2_MANPAGE7_CONNECTOR_INFO ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /* 0x24 */
+} MPI2_CONFIG_PAGE_MAN_7,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_7,
+ Mpi2ManufacturingPage7_t, MPI2_POINTER pMpi2ManufacturingPage7_t;
+
+#define MPI2_MANUFACTURING7_PAGEVERSION (0x00)
+
+/* defines for the Flags field */
+#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001)
+
+
+/*
+ * Generic structure to use for product-specific manufacturing pages
+ * (currently Manufacturing Page 8 through Manufacturing Page 31).
+ */
+
+typedef struct _MPI2_CONFIG_PAGE_MAN_PS
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 ProductSpecificInfo;/* 0x04 */
+} MPI2_CONFIG_PAGE_MAN_PS,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_MAN_PS,
+ Mpi2ManufacturingPagePS_t, MPI2_POINTER pMpi2ManufacturingPagePS_t;
+
+#define MPI2_MANUFACTURING8_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING9_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING10_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING11_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING12_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING13_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING14_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING15_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING16_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING17_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING18_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING19_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING20_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING21_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING22_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING23_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING24_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING25_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING26_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING27_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING28_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING29_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING30_PAGEVERSION (0x00)
+#define MPI2_MANUFACTURING31_PAGEVERSION (0x00)
+
+
+/****************************************************************************
+* IO Unit Config Pages
+****************************************************************************/
+
+/* IO Unit Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U64 UniqueValue; /* 0x04 */
+ MPI2_VERSION_UNION NvdataVersionDefault; /* 0x08 */
+ MPI2_VERSION_UNION NvdataVersionPersistent; /* 0x0A */
+} MPI2_CONFIG_PAGE_IO_UNIT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_0,
+ Mpi2IOUnitPage0_t, MPI2_POINTER pMpi2IOUnitPage0_t;
+
+#define MPI2_IOUNITPAGE0_PAGEVERSION (0x02)
+
+
+/* IO Unit Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Flags; /* 0x04 */
+} MPI2_CONFIG_PAGE_IO_UNIT_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_1,
+ Mpi2IOUnitPage1_t, MPI2_POINTER pMpi2IOUnitPage1_t;
+
+#define MPI2_IOUNITPAGE1_PAGEVERSION (0x04)
+
+/* IO Unit Page 1 Flags defines */
+#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600)
+#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000)
+#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200)
+#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400)
+#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100)
+#define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040)
+#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
+#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004)
+#define MPI2_IOUNITPAGE1_MULTI_PATHING (0x00000002)
+#define MPI2_IOUNITPAGE1_SINGLE_PATHING (0x00000000)
+
+
+/* IO Unit Page 3 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX
+#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 GPIOCount; /* 0x04 */
+ U8 Reserved1; /* 0x05 */
+ U16 Reserved2; /* 0x06 */
+ U16 GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/* 0x08 */
+} MPI2_CONFIG_PAGE_IO_UNIT_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IO_UNIT_3,
+ Mpi2IOUnitPage3_t, MPI2_POINTER pMpi2IOUnitPage3_t;
+
+#define MPI2_IOUNITPAGE3_PAGEVERSION (0x01)
+
+/* defines for IO Unit Page 3 GPIOVal field */
+#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC)
+#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2)
+#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000)
+#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001)
+
+
+/****************************************************************************
+* IOC Config Pages
+****************************************************************************/
+
+/* IOC Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_0
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x04 */
+ U32 Reserved2; /* 0x08 */
+ U16 VendorID; /* 0x0C */
+ U16 DeviceID; /* 0x0E */
+ U8 RevisionID; /* 0x10 */
+ U8 Reserved3; /* 0x11 */
+ U16 Reserved4; /* 0x12 */
+ U32 ClassCode; /* 0x14 */
+ U16 SubsystemVendorID; /* 0x18 */
+ U16 SubsystemID; /* 0x1A */
+} MPI2_CONFIG_PAGE_IOC_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_0,
+ Mpi2IOCPage0_t, MPI2_POINTER pMpi2IOCPage0_t;
+
+#define MPI2_IOCPAGE0_PAGEVERSION (0x02)
+
+
+/* IOC Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_1
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Flags; /* 0x04 */
+ U32 CoalescingTimeout; /* 0x08 */
+ U8 CoalescingDepth; /* 0x0C */
+ U8 PCISlotNum; /* 0x0D */
+ U8 PCIBusNum; /* 0x0E */
+ U8 PCIDomainSegment; /* 0x0F */
+ U32 Reserved1; /* 0x10 */
+ U32 Reserved2; /* 0x14 */
+} MPI2_CONFIG_PAGE_IOC_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_1,
+ Mpi2IOCPage1_t, MPI2_POINTER pMpi2IOCPage1_t;
+
+#define MPI2_IOCPAGE1_PAGEVERSION (0x05)
+
+/* defines for IOC Page 1 Flags field */
+#define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001)
+
+#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF)
+#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF)
+#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF)
+
+/* IOC Page 6 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_6
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 CapabilitiesFlags; /* 0x04 */
+ U8 MaxDrivesRAID0; /* 0x08 */
+ U8 MaxDrivesRAID1; /* 0x09 */
+ U8 MaxDrivesRAID1E; /* 0x0A */
+ U8 MaxDrivesRAID10; /* 0x0B */
+ U8 MinDrivesRAID0; /* 0x0C */
+ U8 MinDrivesRAID1; /* 0x0D */
+ U8 MinDrivesRAID1E; /* 0x0E */
+ U8 MinDrivesRAID10; /* 0x0F */
+ U32 Reserved1; /* 0x10 */
+ U8 MaxGlobalHotSpares; /* 0x14 */
+ U8 MaxPhysDisks; /* 0x15 */
+ U8 MaxVolumes; /* 0x16 */
+ U8 MaxConfigs; /* 0x17 */
+ U8 MaxOCEDisks; /* 0x18 */
+ U8 Reserved2; /* 0x19 */
+ U16 Reserved3; /* 0x1A */
+ U32 SupportedStripeSizeMapRAID0; /* 0x1C */
+ U32 SupportedStripeSizeMapRAID1E; /* 0x20 */
+ U32 SupportedStripeSizeMapRAID10; /* 0x24 */
+ U32 Reserved4; /* 0x28 */
+ U32 Reserved5; /* 0x2C */
+ U16 DefaultMetadataSize; /* 0x30 */
+ U16 Reserved6; /* 0x32 */
+ U16 MaxBadBlockTableEntries; /* 0x34 */
+ U16 Reserved7; /* 0x36 */
+ U32 IRNvsramVersion; /* 0x38 */
+} MPI2_CONFIG_PAGE_IOC_6, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_6,
+ Mpi2IOCPage6_t, MPI2_POINTER pMpi2IOCPage6_t;
+
+#define MPI2_IOCPAGE6_PAGEVERSION (0x04)
+
+/* defines for IOC Page 6 CapabilitiesFlags */
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004)
+#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002)
+#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001)
+
+
+/* IOC Page 7 */
+
+#define MPI2_IOCPAGE7_EVENTMASK_WORDS (4)
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_7
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x04 */
+ U32 EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/* 0x08 */
+ U16 SASBroadcastPrimitiveMasks; /* 0x18 */
+ U16 Reserved2; /* 0x1A */
+ U32 Reserved3; /* 0x1C */
+} MPI2_CONFIG_PAGE_IOC_7, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_7,
+ Mpi2IOCPage7_t, MPI2_POINTER pMpi2IOCPage7_t;
+
+#define MPI2_IOCPAGE7_PAGEVERSION (0x01)
+
+
+/* IOC Page 8 */
+
+typedef struct _MPI2_CONFIG_PAGE_IOC_8
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 NumDevsPerEnclosure; /* 0x04 */
+ U8 Reserved1; /* 0x05 */
+ U16 Reserved2; /* 0x06 */
+ U16 MaxPersistentEntries; /* 0x08 */
+ U16 MaxNumPhysicalMappedIDs; /* 0x0A */
+ U16 Flags; /* 0x0C */
+ U16 Reserved3; /* 0x0E */
+ U16 IRVolumeMappingFlags; /* 0x10 */
+ U16 Reserved4; /* 0x12 */
+ U32 Reserved5; /* 0x14 */
+} MPI2_CONFIG_PAGE_IOC_8, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_IOC_8,
+ Mpi2IOCPage8_t, MPI2_POINTER pMpi2IOCPage8_t;
+
+#define MPI2_IOCPAGE8_PAGEVERSION (0x00)
+
+/* defines for IOC Page 8 Flags field */
+#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020)
+#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010)
+
+#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E)
+#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000)
+#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002)
+
+#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001)
+#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000)
+
+/* defines for IOC Page 8 IRVolumeMappingFlags */
+#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003)
+#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000)
+#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001)
+
+
+/****************************************************************************
+* BIOS Config Pages
+****************************************************************************/
+
+/* BIOS Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_1
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 BiosOptions; /* 0x04 */
+ U32 IOCSettings; /* 0x08 */
+ U32 Reserved1; /* 0x0C */
+ U32 DeviceSettings; /* 0x10 */
+ U16 NumberOfDevices; /* 0x14 */
+ U16 Reserved2; /* 0x16 */
+ U16 IOTimeoutBlockDevicesNonRM; /* 0x18 */
+ U16 IOTimeoutSequential; /* 0x1A */
+ U16 IOTimeoutOther; /* 0x1C */
+ U16 IOTimeoutBlockDevicesRM; /* 0x1E */
+} MPI2_CONFIG_PAGE_BIOS_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_1,
+ Mpi2BiosPage1_t, MPI2_POINTER pMpi2BiosPage1_t;
+
+#define MPI2_BIOSPAGE1_PAGEVERSION (0x04)
+
+/* values for BIOS Page 1 BiosOptions field */
+#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001)
+
+/* values for BIOS Page 1 IOCSettings field */
+#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000)
+#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000)
+
+#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0)
+#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040)
+#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080)
+
+#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030)
+#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000)
+#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010)
+#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020)
+#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030)
+
+#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008)
+
+/* values for BIOS Page 1 DeviceSettings field */
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002)
+#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001)
+
+
+/* BIOS Page 2 */
+
+typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER
+{
+ U32 Reserved1; /* 0x00 */
+ U32 Reserved2; /* 0x04 */
+ U32 Reserved3; /* 0x08 */
+ U32 Reserved4; /* 0x0C */
+ U32 Reserved5; /* 0x10 */
+ U32 Reserved6; /* 0x14 */
+} MPI2_BOOT_DEVICE_ADAPTER_ORDER,
+ MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER,
+ Mpi2BootDeviceAdapterOrder_t, MPI2_POINTER pMpi2BootDeviceAdapterOrder_t;
+
+typedef struct _MPI2_BOOT_DEVICE_SAS_WWID
+{
+ U64 SASAddress; /* 0x00 */
+ U8 LUN[8]; /* 0x08 */
+ U32 Reserved1; /* 0x10 */
+ U32 Reserved2; /* 0x14 */
+} MPI2_BOOT_DEVICE_SAS_WWID, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_SAS_WWID,
+ Mpi2BootDeviceSasWwid_t, MPI2_POINTER pMpi2BootDeviceSasWwid_t;
+
+typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT
+{
+ U64 EnclosureLogicalID; /* 0x00 */
+ U32 Reserved1; /* 0x08 */
+ U32 Reserved2; /* 0x0C */
+ U16 SlotNumber; /* 0x10 */
+ U16 Reserved3; /* 0x12 */
+ U32 Reserved4; /* 0x14 */
+} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
+ MPI2_POINTER PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT,
+ Mpi2BootDeviceEnclosureSlot_t, MPI2_POINTER pMpi2BootDeviceEnclosureSlot_t;
+
+typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME
+{
+ U64 DeviceName; /* 0x00 */
+ U8 LUN[8]; /* 0x08 */
+ U32 Reserved1; /* 0x10 */
+ U32 Reserved2; /* 0x14 */
+} MPI2_BOOT_DEVICE_DEVICE_NAME, MPI2_POINTER PTR_MPI2_BOOT_DEVICE_DEVICE_NAME,
+ Mpi2BootDeviceDeviceName_t, MPI2_POINTER pMpi2BootDeviceDeviceName_t;
+
+typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE
+{
+ MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder;
+ MPI2_BOOT_DEVICE_SAS_WWID SasWwid;
+ MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot;
+ MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName;
+} MPI2_BIOSPAGE2_BOOT_DEVICE, MPI2_POINTER PTR_MPI2_BIOSPAGE2_BOOT_DEVICE,
+ Mpi2BiosPage2BootDevice_t, MPI2_POINTER pMpi2BiosPage2BootDevice_t;
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_2
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x04 */
+ U32 Reserved2; /* 0x08 */
+ U32 Reserved3; /* 0x0C */
+ U32 Reserved4; /* 0x10 */
+ U32 Reserved5; /* 0x14 */
+ U32 Reserved6; /* 0x18 */
+ U8 ReqBootDeviceForm; /* 0x1C */
+ U8 Reserved7; /* 0x1D */
+ U16 Reserved8; /* 0x1E */
+ MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /* 0x20 */
+ U8 ReqAltBootDeviceForm; /* 0x38 */
+ U8 Reserved9; /* 0x39 */
+ U16 Reserved10; /* 0x3A */
+ MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /* 0x3C */
+ U8 CurrentBootDeviceForm; /* 0x58 */
+ U8 Reserved11; /* 0x59 */
+ U16 Reserved12; /* 0x5A */
+ MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /* 0x58 */
+} MPI2_CONFIG_PAGE_BIOS_2, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_2,
+ Mpi2BiosPage2_t, MPI2_POINTER pMpi2BiosPage2_t;
+
+#define MPI2_BIOSPAGE2_PAGEVERSION (0x04)
+
+/* values for BIOS Page 2 BootDeviceForm fields */
+#define MPI2_BIOSPAGE2_FORM_MASK (0x0F)
+#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00)
+#define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05)
+#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06)
+#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07)
+
+
+/* BIOS Page 3 */
+
+typedef struct _MPI2_ADAPTER_INFO
+{
+ U8 PciBusNumber; /* 0x00 */
+ U8 PciDeviceAndFunctionNumber; /* 0x01 */
+ U16 AdapterFlags; /* 0x02 */
+} MPI2_ADAPTER_INFO, MPI2_POINTER PTR_MPI2_ADAPTER_INFO,
+ Mpi2AdapterInfo_t, MPI2_POINTER pMpi2AdapterInfo_t;
+
+#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001)
+#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002)
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_3
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U32 GlobalFlags; /* 0x04 */
+ U32 BiosVersion; /* 0x08 */
+ MPI2_ADAPTER_INFO AdapterOrder[4]; /* 0x0C */
+ U32 Reserved1; /* 0x1C */
+} MPI2_CONFIG_PAGE_BIOS_3, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_3,
+ Mpi2BiosPage3_t, MPI2_POINTER pMpi2BiosPage3_t;
+
+#define MPI2_BIOSPAGE3_PAGEVERSION (0x00)
+
+/* values for BIOS Page 3 GlobalFlags */
+#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002)
+#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004)
+#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010)
+
+#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0)
+#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000)
+#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020)
+#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040)
+
+
+/* BIOS Page 4 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES
+#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1)
+#endif
+
+typedef struct _MPI2_BIOS4_ENTRY
+{
+ U64 ReassignmentWWID; /* 0x00 */
+ U64 ReassignmentDeviceName; /* 0x08 */
+} MPI2_BIOS4_ENTRY, MPI2_POINTER PTR_MPI2_BIOS4_ENTRY,
+ Mpi2MBios4Entry_t, MPI2_POINTER pMpi2Bios4Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_BIOS_4
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 NumPhys; /* 0x04 */
+ U8 Reserved1; /* 0x05 */
+ U16 Reserved2; /* 0x06 */
+ MPI2_BIOS4_ENTRY Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /* 0x08 */
+} MPI2_CONFIG_PAGE_BIOS_4, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_BIOS_4,
+ Mpi2BiosPage4_t, MPI2_POINTER pMpi2BiosPage4_t;
+
+#define MPI2_BIOSPAGE4_PAGEVERSION (0x01)
+
+
+/****************************************************************************
+* RAID Volume Config Pages
+****************************************************************************/
+
+/* RAID Volume Page 0 */
+
+typedef struct _MPI2_RAIDVOL0_PHYS_DISK
+{
+ U8 RAIDSetNum; /* 0x00 */
+ U8 PhysDiskMap; /* 0x01 */
+ U8 PhysDiskNum; /* 0x02 */
+ U8 Reserved; /* 0x03 */
+} MPI2_RAIDVOL0_PHYS_DISK, MPI2_POINTER PTR_MPI2_RAIDVOL0_PHYS_DISK,
+ Mpi2RaidVol0PhysDisk_t, MPI2_POINTER pMpi2RaidVol0PhysDisk_t;
+
+/* defines for the PhysDiskMap field */
+#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01)
+#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02)
+
+typedef struct _MPI2_RAIDVOL0_SETTINGS
+{
+ U16 Settings; /* 0x00 */
+ U8 HotSparePool; /* 0x01 */
+ U8 Reserved; /* 0x02 */
+} MPI2_RAIDVOL0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDVOL0_SETTINGS,
+ Mpi2RaidVol0Settings_t, MPI2_POINTER pMpi2RaidVol0Settings_t;
+
+/* RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */
+#define MPI2_RAID_HOT_SPARE_POOL_0 (0x01)
+#define MPI2_RAID_HOT_SPARE_POOL_1 (0x02)
+#define MPI2_RAID_HOT_SPARE_POOL_2 (0x04)
+#define MPI2_RAID_HOT_SPARE_POOL_3 (0x08)
+#define MPI2_RAID_HOT_SPARE_POOL_4 (0x10)
+#define MPI2_RAID_HOT_SPARE_POOL_5 (0x20)
+#define MPI2_RAID_HOT_SPARE_POOL_6 (0x40)
+#define MPI2_RAID_HOT_SPARE_POOL_7 (0x80)
+
+/* RAID Volume Page 0 VolumeSettings defines */
+#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008)
+#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004)
+
+#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003)
+#define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000)
+#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001)
+#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002)
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength at runtime.
+ */
+#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX
+#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U16 DevHandle; /* 0x04 */
+ U8 VolumeState; /* 0x06 */
+ U8 VolumeType; /* 0x07 */
+ U32 VolumeStatusFlags; /* 0x08 */
+ MPI2_RAIDVOL0_SETTINGS VolumeSettings; /* 0x0C */
+ U64 MaxLBA; /* 0x10 */
+ U32 StripeSize; /* 0x18 */
+ U16 BlockSize; /* 0x1C */
+ U16 Reserved1; /* 0x1E */
+ U8 SupportedPhysDisks; /* 0x20 */
+ U8 ResyncRate; /* 0x21 */
+ U16 DataScrubDuration; /* 0x22 */
+ U8 NumPhysDisks; /* 0x24 */
+ U8 Reserved2; /* 0x25 */
+ U8 Reserved3; /* 0x26 */
+ U8 InactiveStatus; /* 0x27 */
+ MPI2_RAIDVOL0_PHYS_DISK PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /* 0x28 */
+} MPI2_CONFIG_PAGE_RAID_VOL_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_0,
+ Mpi2RaidVolPage0_t, MPI2_POINTER pMpi2RaidVolPage0_t;
+
+#define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A)
+
+/* values for RAID VolumeState */
+#define MPI2_RAID_VOL_STATE_MISSING (0x00)
+#define MPI2_RAID_VOL_STATE_FAILED (0x01)
+#define MPI2_RAID_VOL_STATE_INITIALIZING (0x02)
+#define MPI2_RAID_VOL_STATE_ONLINE (0x03)
+#define MPI2_RAID_VOL_STATE_DEGRADED (0x04)
+#define MPI2_RAID_VOL_STATE_OPTIMAL (0x05)
+
+/* values for RAID VolumeType */
+#define MPI2_RAID_VOL_TYPE_RAID0 (0x00)
+#define MPI2_RAID_VOL_TYPE_RAID1E (0x01)
+#define MPI2_RAID_VOL_TYPE_RAID1 (0x02)
+#define MPI2_RAID_VOL_TYPE_RAID10 (0x05)
+#define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF)
+
+/* values for RAID Volume Page 0 VolumeStatusFlags field */
+#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020)
+#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000)
+#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010)
+#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008)
+#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004)
+#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002)
+#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001)
+
+/* values for RAID Volume Page 0 SupportedPhysDisks field */
+#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08)
+#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04)
+#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02)
+#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01)
+
+/* values for RAID Volume Page 0 InactiveStatus field */
+#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00)
+#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01)
+#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02)
+#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03)
+#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04)
+#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05)
+#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06)
+
+
+/* RAID Volume Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U16 DevHandle; /* 0x04 */
+ U16 Reserved0; /* 0x06 */
+ U8 GUID[24]; /* 0x08 */
+ U8 Name[16]; /* 0x20 */
+ U64 WWID; /* 0x30 */
+ U32 Reserved1; /* 0x38 */
+ U32 Reserved2; /* 0x3C */
+} MPI2_CONFIG_PAGE_RAID_VOL_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_VOL_1,
+ Mpi2RaidVolPage1_t, MPI2_POINTER pMpi2RaidVolPage1_t;
+
+#define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03)
+
+
+/****************************************************************************
+* RAID Physical Disk Config Pages
+****************************************************************************/
+
+/* RAID Physical Disk Page 0 */
+
+typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS
+{
+ U16 Reserved1; /* 0x00 */
+ U8 HotSparePool; /* 0x02 */
+ U8 Reserved2; /* 0x03 */
+} MPI2_RAIDPHYSDISK0_SETTINGS, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_SETTINGS,
+ Mpi2RaidPhysDisk0Settings_t, MPI2_POINTER pMpi2RaidPhysDisk0Settings_t;
+
+/* use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */
+
+typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA
+{
+ U8 VendorID[8]; /* 0x00 */
+ U8 ProductID[16]; /* 0x08 */
+ U8 ProductRevLevel[4]; /* 0x18 */
+ U8 SerialNum[32]; /* 0x1C */
+} MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
+ MPI2_POINTER PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA,
+ Mpi2RaidPhysDisk0InquiryData_t, MPI2_POINTER pMpi2RaidPhysDisk0InquiryData_t;
+
+typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U16 DevHandle; /* 0x04 */
+ U8 Reserved1; /* 0x06 */
+ U8 PhysDiskNum; /* 0x07 */
+ MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /* 0x08 */
+ U32 Reserved2; /* 0x0C */
+ MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /* 0x10 */
+ U32 Reserved3; /* 0x4C */
+ U8 PhysDiskState; /* 0x50 */
+ U8 OfflineReason; /* 0x51 */
+ U8 IncompatibleReason; /* 0x52 */
+ U8 PhysDiskAttributes; /* 0x53 */
+ U32 PhysDiskStatusFlags; /* 0x54 */
+ U64 DeviceMaxLBA; /* 0x58 */
+ U64 HostMaxLBA; /* 0x60 */
+ U64 CoercedMaxLBA; /* 0x68 */
+ U16 BlockSize; /* 0x70 */
+ U16 Reserved5; /* 0x72 */
+ U32 Reserved6; /* 0x74 */
+} MPI2_CONFIG_PAGE_RD_PDISK_0,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_0,
+ Mpi2RaidPhysDiskPage0_t, MPI2_POINTER pMpi2RaidPhysDiskPage0_t;
+
+#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05)
+
+/* PhysDiskState defines */
+#define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00)
+#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01)
+#define MPI2_RAID_PD_STATE_OFFLINE (0x02)
+#define MPI2_RAID_PD_STATE_ONLINE (0x03)
+#define MPI2_RAID_PD_STATE_HOT_SPARE (0x04)
+#define MPI2_RAID_PD_STATE_DEGRADED (0x05)
+#define MPI2_RAID_PD_STATE_REBUILDING (0x06)
+#define MPI2_RAID_PD_STATE_OPTIMAL (0x07)
+
+/* OfflineReason defines */
+#define MPI2_PHYSDISK0_ONLINE (0x00)
+#define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01)
+#define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03)
+#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04)
+#define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05)
+#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06)
+#define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF)
+
+/* IncompatibleReason defines */
+#define MPI2_PHYSDISK0_COMPATIBLE (0x00)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05)
+#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF)
+
+/* PhysDiskAttributes defines */
+#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08)
+#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04)
+#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02)
+#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01)
+
+/* PhysDiskStatusFlags defines */
+#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020)
+#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000)
+#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008)
+#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004)
+#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002)
+#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001)
+
+
+/* RAID Physical Disk Page 1 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.PageLength or NumPhysDiskPaths at runtime.
+ */
+#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX
+#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1)
+#endif
+
+typedef struct _MPI2_RAIDPHYSDISK1_PATH
+{
+ U16 DevHandle; /* 0x00 */
+ U16 Reserved1; /* 0x02 */
+ U64 WWID; /* 0x04 */
+ U64 OwnerWWID; /* 0x0C */
+ U8 OwnerIdentifier; /* 0x14 */
+ U8 Reserved2; /* 0x15 */
+ U16 Flags; /* 0x16 */
+} MPI2_RAIDPHYSDISK1_PATH, MPI2_POINTER PTR_MPI2_RAIDPHYSDISK1_PATH,
+ Mpi2RaidPhysDisk1Path_t, MPI2_POINTER pMpi2RaidPhysDisk1Path_t;
+
+/* RAID Physical Disk Page 1 Physical Disk Path Flags field defines */
+#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004)
+#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002)
+#define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001)
+
+typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1
+{
+ MPI2_CONFIG_PAGE_HEADER Header; /* 0x00 */
+ U8 NumPhysDiskPaths; /* 0x04 */
+ U8 PhysDiskNum; /* 0x05 */
+ U16 Reserved1; /* 0x06 */
+ U32 Reserved2; /* 0x08 */
+ MPI2_RAIDPHYSDISK1_PATH PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/* 0x0C */
+} MPI2_CONFIG_PAGE_RD_PDISK_1,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RD_PDISK_1,
+ Mpi2RaidPhysDiskPage1_t, MPI2_POINTER pMpi2RaidPhysDiskPage1_t;
+
+#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02)
+
+
+/****************************************************************************
+* values for fields used by several types of SAS Config Pages
+****************************************************************************/
+
+/* values for NegotiatedLinkRates fields */
+#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0)
+#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4)
+#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F)
+/* link rates used for Negotiated Physical and Logical Link Rate */
+#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00)
+#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01)
+#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02)
+#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03)
+#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04)
+#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05)
+#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08)
+#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09)
+#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A)
+
+
+/* values for AttachedPhyInfo fields */
+#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040)
+#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020)
+#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010)
+
+#define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F)
+#define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000)
+#define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001)
+#define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002)
+#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003)
+#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004)
+#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005)
+#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006)
+#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007)
+#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008)
+
+
+/* values for PhyInfo fields */
+#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000)
+#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000)
+#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000)
+#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000)
+#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000)
+#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000)
+#define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000)
+
+#define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000)
+#define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000)
+#define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000)
+#define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000)
+#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000)
+#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000)
+#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000)
+#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000)
+#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000)
+#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000)
+
+#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000)
+#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000)
+#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000)
+#define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000)
+
+#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00)
+#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8)
+
+#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0)
+#define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000)
+#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010)
+#define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020)
+
+
+/* values for SAS ProgrammedLinkRate fields */
+#define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0)
+#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00)
+#define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80)
+#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90)
+#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0)
+#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F)
+#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00)
+#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08)
+#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09)
+#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A)
+
+
+/* values for SAS HwLinkRate fields */
+#define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0)
+#define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80)
+#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90)
+#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0)
+#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F)
+#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08)
+#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09)
+#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A)
+
+
+
+/****************************************************************************
+* SAS IO Unit Config Pages
+****************************************************************************/
+
+/* SAS IO Unit Page 0 */
+
+typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA
+{
+ U8 Port; /* 0x00 */
+ U8 PortFlags; /* 0x01 */
+ U8 PhyFlags; /* 0x02 */
+ U8 NegotiatedLinkRate; /* 0x03 */
+ U32 ControllerPhyDeviceInfo;/* 0x04 */
+ U16 AttachedDevHandle; /* 0x08 */
+ U16 ControllerDevHandle; /* 0x0A */
+ U32 DiscoveryStatus; /* 0x0C */
+ U32 Reserved; /* 0x10 */
+} MPI2_SAS_IO_UNIT0_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT0_PHY_DATA,
+ Mpi2SasIOUnit0PhyData_t, MPI2_POINTER pMpi2SasIOUnit0PhyData_t;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT0_PHY_MAX
+#define MPI2_SAS_IOUNIT0_PHY_MAX (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x08 */
+ U8 NumPhys; /* 0x0C */
+ U8 Reserved2; /* 0x0D */
+ U16 Reserved3; /* 0x0E */
+ MPI2_SAS_IO_UNIT0_PHY_DATA PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /* 0x10 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_0,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0,
+ Mpi2SasIOUnitPage0_t, MPI2_POINTER pMpi2SasIOUnitPage0_t;
+
+#define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05)
+
+/* values for SAS IO Unit Page 0 PortFlags */
+#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08)
+#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01)
+
+/* values for SAS IO Unit Page 0 PhyFlags */
+#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10)
+#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08)
+
+/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+/* see mpi2_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
+
+/* values for SAS IO Unit Page 0 DiscoveryStatus */
+#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
+#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000)
+#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000)
+#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
+#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000)
+#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
+#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
+#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000)
+#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
+#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800)
+#define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400)
+#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200)
+#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100)
+#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080)
+#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040)
+#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020)
+#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010)
+#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004)
+#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002)
+#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001)
+
+
+/* SAS IO Unit Page 1 */
+
+typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA
+{
+ U8 Port; /* 0x00 */
+ U8 PortFlags; /* 0x01 */
+ U8 PhyFlags; /* 0x02 */
+ U8 MaxMinLinkRate; /* 0x03 */
+ U32 ControllerPhyDeviceInfo; /* 0x04 */
+ U16 MaxTargetPortConnectTime; /* 0x08 */
+ U16 Reserved1; /* 0x0A */
+} MPI2_SAS_IO_UNIT1_PHY_DATA, MPI2_POINTER PTR_MPI2_SAS_IO_UNIT1_PHY_DATA,
+ Mpi2SasIOUnit1PhyData_t, MPI2_POINTER pMpi2SasIOUnit1PhyData_t;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT1_PHY_MAX
+#define MPI2_SAS_IOUNIT1_PHY_MAX (1)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U16 ControlFlags; /* 0x08 */
+ U16 SASNarrowMaxQueueDepth; /* 0x0A */
+ U16 AdditionalControlFlags; /* 0x0C */
+ U16 SASWideMaxQueueDepth; /* 0x0E */
+ U8 NumPhys; /* 0x10 */
+ U8 SATAMaxQDepth; /* 0x11 */
+ U8 ReportDeviceMissingDelay; /* 0x12 */
+ U8 IODeviceMissingDelay; /* 0x13 */
+ MPI2_SAS_IO_UNIT1_PHY_DATA PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /* 0x14 */
+} MPI2_CONFIG_PAGE_SASIOUNIT_1,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1,
+ Mpi2SasIOUnitPage1_t, MPI2_POINTER pMpi2SasIOUnitPage1_t;
+
+#define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09)
+
+/* values for SAS IO Unit Page 1 ControlFlags */
+#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000)
+
+#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600)
+#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1)
+#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2)
+
+#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020)
+#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010)
+#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008)
+#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004)
+#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002)
+#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001)
+
+/* values for SAS IO Unit Page 1 AdditionalControlFlags */
+#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080)
+#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040)
+#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020)
+#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010)
+#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008)
+#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004)
+#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002)
+#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001)
+
+/* defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */
+#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F)
+#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80)
+
+/* values for SAS IO Unit Page 1 PortFlags */
+#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01)
+
+/* values for SAS IO Unit Page 2 PhyFlags */
+#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10)
+#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08)
+
+/* values for SAS IO Unit Page 0 MaxMinLinkRate */
+#define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0)
+#define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80)
+#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90)
+#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0)
+#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F)
+#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08)
+#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09)
+#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A)
+
+/* see mpi2_sas.h for values for SAS IO Unit Page 1 ControllerPhyDeviceInfo values */
+
+
+/* SAS IO Unit Page 4 */
+
+typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP
+{
+ U8 MaxTargetSpinup; /* 0x00 */
+ U8 SpinupDelay; /* 0x01 */
+ U16 Reserved1; /* 0x02 */
+} MPI2_SAS_IOUNIT4_SPINUP_GROUP, MPI2_POINTER PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP,
+ Mpi2SasIOUnit4SpinupGroup_t, MPI2_POINTER pMpi2SasIOUnit4SpinupGroup_t;
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * four and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_SAS_IOUNIT4_PHY_MAX
+#define MPI2_SAS_IOUNIT4_PHY_MAX (4)
+#endif
+
+typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ MPI2_SAS_IOUNIT4_SPINUP_GROUP SpinupGroupParameters[4]; /* 0x08 */
+ U32 Reserved1; /* 0x18 */
+ U32 Reserved2; /* 0x1C */
+ U32 Reserved3; /* 0x20 */
+ U8 BootDeviceWaitTime; /* 0x24 */
+ U8 Reserved4; /* 0x25 */
+ U16 Reserved5; /* 0x26 */
+ U8 NumPhys; /* 0x28 */
+ U8 PEInitialSpinupDelay; /* 0x29 */
+ U8 PEReplyDelay; /* 0x2A */
+ U8 Flags; /* 0x2B */
+ U8 PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /* 0x2C */
+} MPI2_CONFIG_PAGE_SASIOUNIT_4,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4,
+ Mpi2SasIOUnitPage4_t, MPI2_POINTER pMpi2SasIOUnitPage4_t;
+
+#define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02)
+
+/* defines for Flags field */
+#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01)
+
+/* defines for PHY field */
+#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03)
+
+
+/****************************************************************************
+* SAS Expander Config Pages
+****************************************************************************/
+
+/* SAS Expander Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U8 PhysicalPort; /* 0x08 */
+ U8 ReportGenLength; /* 0x09 */
+ U16 EnclosureHandle; /* 0x0A */
+ U64 SASAddress; /* 0x0C */
+ U32 DiscoveryStatus; /* 0x14 */
+ U16 DevHandle; /* 0x18 */
+ U16 ParentDevHandle; /* 0x1A */
+ U16 ExpanderChangeCount; /* 0x1C */
+ U16 ExpanderRouteIndexes; /* 0x1E */
+ U8 NumPhys; /* 0x20 */
+ U8 SASLevel; /* 0x21 */
+ U16 Flags; /* 0x22 */
+ U16 STPBusInactivityTimeLimit; /* 0x24 */
+ U16 STPMaxConnectTimeLimit; /* 0x26 */
+ U16 STP_SMP_NexusLossTime; /* 0x28 */
+ U16 MaxNumRoutedSasAddresses; /* 0x2A */
+ U64 ActiveZoneManagerSASAddress;/* 0x2C */
+ U16 ZoneLockInactivityLimit; /* 0x34 */
+ U16 Reserved1; /* 0x36 */
+} MPI2_CONFIG_PAGE_EXPANDER_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_0,
+ Mpi2ExpanderPage0_t, MPI2_POINTER pMpi2ExpanderPage0_t;
+
+#define MPI2_SASEXPANDER0_PAGEVERSION (0x05)
+
+/* values for SAS Expander Page 0 DiscoveryStatus field */
+#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000)
+#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
+#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000)
+#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
+#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
+#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000)
+#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
+#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800)
+#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400)
+#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200)
+#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100)
+#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080)
+#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040)
+#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020)
+#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010)
+#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004)
+#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002)
+#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001)
+
+/* values for SAS Expander Page 0 Flags field */
+#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000)
+#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800)
+#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400)
+#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200)
+#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100)
+#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080)
+#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010)
+#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004)
+#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002)
+#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001)
+
+
+/* SAS Expander Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U8 PhysicalPort; /* 0x08 */
+ U8 Reserved1; /* 0x09 */
+ U16 Reserved2; /* 0x0A */
+ U8 NumPhys; /* 0x0C */
+ U8 Phy; /* 0x0D */
+ U16 NumTableEntriesProgrammed; /* 0x0E */
+ U8 ProgrammedLinkRate; /* 0x10 */
+ U8 HwLinkRate; /* 0x11 */
+ U16 AttachedDevHandle; /* 0x12 */
+ U32 PhyInfo; /* 0x14 */
+ U32 AttachedDeviceInfo; /* 0x18 */
+ U16 ExpanderDevHandle; /* 0x1C */
+ U8 ChangeCount; /* 0x1E */
+ U8 NegotiatedLinkRate; /* 0x1F */
+ U8 PhyIdentifier; /* 0x20 */
+ U8 AttachedPhyIdentifier; /* 0x21 */
+ U8 Reserved3; /* 0x22 */
+ U8 DiscoveryInfo; /* 0x23 */
+ U32 AttachedPhyInfo; /* 0x24 */
+ U8 ZoneGroup; /* 0x28 */
+ U8 SelfConfigStatus; /* 0x29 */
+ U16 Reserved4; /* 0x2A */
+} MPI2_CONFIG_PAGE_EXPANDER_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_EXPANDER_1,
+ Mpi2ExpanderPage1_t, MPI2_POINTER pMpi2ExpanderPage1_t;
+
+#define MPI2_SASEXPANDER1_PAGEVERSION (0x02)
+
+/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
+
+/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
+
+/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
+
+/* see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines used for the AttachedDeviceInfo field */
+
+/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
+
+/* values for SAS Expander Page 1 DiscoveryInfo field */
+#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04)
+#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02)
+#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01)
+
+
+/****************************************************************************
+* SAS Device Config Pages
+****************************************************************************/
+
+/* SAS Device Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U16 Slot; /* 0x08 */
+ U16 EnclosureHandle; /* 0x0A */
+ U64 SASAddress; /* 0x0C */
+ U16 ParentDevHandle; /* 0x14 */
+ U8 PhyNum; /* 0x16 */
+ U8 AccessStatus; /* 0x17 */
+ U16 DevHandle; /* 0x18 */
+ U8 AttachedPhyIdentifier; /* 0x1A */
+ U8 ZoneGroup; /* 0x1B */
+ U32 DeviceInfo; /* 0x1C */
+ U16 Flags; /* 0x20 */
+ U8 PhysicalPort; /* 0x22 */
+ U8 MaxPortConnections; /* 0x23 */
+ U64 DeviceName; /* 0x24 */
+ U8 PortGroups; /* 0x2C */
+ U8 DmaGroup; /* 0x2D */
+ U8 ControlGroup; /* 0x2E */
+ U8 Reserved1; /* 0x2F */
+ U32 Reserved2; /* 0x30 */
+ U32 Reserved3; /* 0x34 */
+} MPI2_CONFIG_PAGE_SAS_DEV_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_0,
+ Mpi2SasDevicePage0_t, MPI2_POINTER pMpi2SasDevicePage0_t;
+
+#define MPI2_SASDEVICE0_PAGEVERSION (0x08)
+
+/* values for SAS Device Page 0 AccessStatus field */
+#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03)
+#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04)
+#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05)
+#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06)
+#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07)
+/* specific values for SATA Init failures */
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19)
+#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F)
+
+/* see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */
+
+/* values for SAS Device Page 0 Flags field */
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200)
+#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020)
+#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010)
+#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008)
+#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001)
+
+
+/* SAS Device Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x08 */
+ U64 SASAddress; /* 0x0C */
+ U32 Reserved2; /* 0x14 */
+ U16 DevHandle; /* 0x18 */
+ U16 Reserved3; /* 0x1A */
+ U8 InitialRegDeviceFIS[20];/* 0x1C */
+} MPI2_CONFIG_PAGE_SAS_DEV_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_DEV_1,
+ Mpi2SasDevicePage1_t, MPI2_POINTER pMpi2SasDevicePage1_t;
+
+#define MPI2_SASDEVICE1_PAGEVERSION (0x01)
+
+
+/****************************************************************************
+* SAS PHY Config Pages
+****************************************************************************/
+
+/* SAS PHY Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U16 OwnerDevHandle; /* 0x08 */
+ U16 Reserved1; /* 0x0A */
+ U16 AttachedDevHandle; /* 0x0C */
+ U8 AttachedPhyIdentifier; /* 0x0E */
+ U8 Reserved2; /* 0x0F */
+ U32 AttachedPhyInfo; /* 0x10 */
+ U8 ProgrammedLinkRate; /* 0x14 */
+ U8 HwLinkRate; /* 0x15 */
+ U8 ChangeCount; /* 0x16 */
+ U8 Flags; /* 0x17 */
+ U32 PhyInfo; /* 0x18 */
+ U8 NegotiatedLinkRate; /* 0x1C */
+ U8 Reserved3; /* 0x1D */
+ U16 Reserved4; /* 0x1E */
+} MPI2_CONFIG_PAGE_SAS_PHY_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_0,
+ Mpi2SasPhyPage0_t, MPI2_POINTER pMpi2SasPhyPage0_t;
+
+#define MPI2_SASPHY0_PAGEVERSION (0x03)
+
+/* use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */
+
+/* use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */
+
+/* values for SAS PHY Page 0 Flags field */
+#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01)
+
+/* use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */
+
+/* use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */
+
+/* use MPI2_SAS_PHYINFO_ for the PhyInfo field */
+
+
+/* SAS PHY Page 1 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x08 */
+ U32 InvalidDwordCount; /* 0x0C */
+ U32 RunningDisparityErrorCount; /* 0x10 */
+ U32 LossDwordSynchCount; /* 0x14 */
+ U32 PhyResetProblemCount; /* 0x18 */
+} MPI2_CONFIG_PAGE_SAS_PHY_1, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PHY_1,
+ Mpi2SasPhyPage1_t, MPI2_POINTER pMpi2SasPhyPage1_t;
+
+#define MPI2_SASPHY1_PAGEVERSION (0x01)
+
+
+/****************************************************************************
+* SAS Port Config Pages
+****************************************************************************/
+
+/* SAS Port Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U8 PortNumber; /* 0x08 */
+ U8 PhysicalPort; /* 0x09 */
+ U8 PortWidth; /* 0x0A */
+ U8 PhysicalPortWidth; /* 0x0B */
+ U8 ZoneGroup; /* 0x0C */
+ U8 Reserved1; /* 0x0D */
+ U16 Reserved2; /* 0x0E */
+ U64 SASAddress; /* 0x10 */
+ U32 DeviceInfo; /* 0x18 */
+ U32 Reserved3; /* 0x1C */
+ U32 Reserved4; /* 0x20 */
+} MPI2_CONFIG_PAGE_SAS_PORT_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_PORT_0,
+ Mpi2SasPortPage0_t, MPI2_POINTER pMpi2SasPortPage0_t;
+
+#define MPI2_SASPORT0_PAGEVERSION (0x00)
+
+/* see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */
+
+
+/****************************************************************************
+* SAS Enclosure Config Pages
+****************************************************************************/
+
+/* SAS Enclosure Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x08 */
+ U64 EnclosureLogicalID; /* 0x0C */
+ U16 Flags; /* 0x14 */
+ U16 EnclosureHandle; /* 0x16 */
+ U16 NumSlots; /* 0x18 */
+ U16 StartSlot; /* 0x1A */
+ U16 Reserved2; /* 0x1C */
+ U16 SEPDevHandle; /* 0x1E */
+ U32 Reserved3; /* 0x20 */
+ U32 Reserved4; /* 0x24 */
+} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0,
+ Mpi2SasEnclosurePage0_t, MPI2_POINTER pMpi2SasEnclosurePage0_t;
+
+#define MPI2_SASENCLOSURE0_PAGEVERSION (0x03)
+
+/* values for SAS Enclosure Page 0 Flags field */
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004)
+#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005)
+
+
+/****************************************************************************
+* Log Config Page
+****************************************************************************/
+
+/* Log Page 0 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES
+#define MPI2_LOG_0_NUM_LOG_ENTRIES (1)
+#endif
+
+#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C)
+
+typedef struct _MPI2_LOG_0_ENTRY
+{
+ U64 TimeStamp; /* 0x00 */
+ U32 Reserved1; /* 0x08 */
+ U16 LogSequence; /* 0x0C */
+ U16 LogEntryQualifier; /* 0x0E */
+ U8 VP_ID; /* 0x10 */
+ U8 VF_ID; /* 0x11 */
+ U16 Reserved2; /* 0x12 */
+ U8 LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/* 0x14 */
+} MPI2_LOG_0_ENTRY, MPI2_POINTER PTR_MPI2_LOG_0_ENTRY,
+ Mpi2Log0Entry_t, MPI2_POINTER pMpi2Log0Entry_t;
+
+/* values for Log Page 0 LogEntry LogEntryQualifier field */
+#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000)
+#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001)
+#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002)
+#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000)
+#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF)
+
+typedef struct _MPI2_CONFIG_PAGE_LOG_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U32 Reserved1; /* 0x08 */
+ U32 Reserved2; /* 0x0C */
+ U16 NumLogEntries; /* 0x10 */
+ U16 Reserved3; /* 0x12 */
+ MPI2_LOG_0_ENTRY LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /* 0x14 */
+} MPI2_CONFIG_PAGE_LOG_0, MPI2_POINTER PTR_MPI2_CONFIG_PAGE_LOG_0,
+ Mpi2LogPage0_t, MPI2_POINTER pMpi2LogPage0_t;
+
+#define MPI2_LOG_0_PAGEVERSION (0x02)
+
+
+/****************************************************************************
+* RAID Config Page
+****************************************************************************/
+
+/* RAID Page 0 */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check Header.ExtPageLength or NumPhys at runtime.
+ */
+#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS
+#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1)
+#endif
+
+typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT
+{
+ U16 ElementFlags; /* 0x00 */
+ U16 VolDevHandle; /* 0x02 */
+ U8 HotSparePool; /* 0x04 */
+ U8 PhysDiskNum; /* 0x05 */
+ U16 PhysDiskDevHandle; /* 0x06 */
+} MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
+ MPI2_POINTER PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT,
+ Mpi2RaidConfig0ConfigElement_t, MPI2_POINTER pMpi2RaidConfig0ConfigElement_t;
+
+/* values for the ElementFlags field */
+#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F)
+#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000)
+#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001)
+#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002)
+#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003)
+
+
+typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ U8 NumHotSpares; /* 0x08 */
+ U8 NumPhysDisks; /* 0x09 */
+ U8 NumVolumes; /* 0x0A */
+ U8 ConfigNum; /* 0x0B */
+ U32 Flags; /* 0x0C */
+ U8 ConfigGUID[24]; /* 0x10 */
+ U32 Reserved1; /* 0x28 */
+ U8 NumElements; /* 0x2C */
+ U8 Reserved2; /* 0x2D */
+ U16 Reserved3; /* 0x2E */
+ MPI2_RAIDCONFIG0_CONFIG_ELEMENT ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /* 0x30 */
+} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0,
+ Mpi2RaidConfigurationPage0_t, MPI2_POINTER pMpi2RaidConfigurationPage0_t;
+
+#define MPI2_RAIDCONFIG0_PAGEVERSION (0x00)
+
+/* values for RAID Configuration Page 0 Flags field */
+#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001)
+
+
+/****************************************************************************
+* Driver Persistent Mapping Config Pages
+****************************************************************************/
+
+/* Driver Persistent Mapping Page 0 */
+
+typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY
+{
+ U64 PhysicalIdentifier; /* 0x00 */
+ U16 MappingInformation; /* 0x08 */
+ U16 DeviceIndex; /* 0x0A */
+ U32 PhysicalBitsMapping; /* 0x0C */
+ U32 Reserved1; /* 0x10 */
+} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY,
+ Mpi2DriverMap0Entry_t, MPI2_POINTER pMpi2DriverMap0Entry_t;
+
+typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0
+{
+ MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /* 0x00 */
+ MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /* 0x08 */
+} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
+ MPI2_POINTER PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0,
+ Mpi2DriverMappingPage0_t, MPI2_POINTER pMpi2DriverMappingPage0_t;
+
+#define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00)
+
+/* values for Driver Persistent Mapping Page 0 MappingInformation field */
+#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0)
+#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4)
+#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F)
+
+
+#endif
+
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_init.h b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
new file mode 100644
index 00000000000..f1115f0f0eb
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_init.h
@@ -0,0 +1,420 @@
+/*
+ * Copyright (c) 2000-2008 LSI Corporation.
+ *
+ *
+ * Name: mpi2_init.h
+ * Title: MPI SCSI initiator mode messages and structures
+ * Creation Date: June 23, 2006
+ *
+ * mpi2_init.h Version: 02.00.06
+ *
+ * Version History
+ * ---------------
+ *
+ * Date Version Description
+ * -------- -------- ------------------------------------------------------
+ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t.
+ * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines.
+ * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention.
+ * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
+ * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t.
+ * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO
+ * Control field Task Attribute flags.
+ * Moved LUN field defines to mpi2.h becasue they are
+ * common to many structures.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_INIT_H
+#define MPI2_INIT_H
+
+/*****************************************************************************
+*
+* SCSI Initiator Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* SCSI IO messages and associated structures
+****************************************************************************/
+
+typedef struct
+{
+ U8 CDB[20]; /* 0x00 */
+ U32 PrimaryReferenceTag; /* 0x14 */
+ U16 PrimaryApplicationTag; /* 0x18 */
+ U16 PrimaryApplicationTagMask; /* 0x1A */
+ U32 TransferLength; /* 0x1C */
+} MPI2_SCSI_IO_CDB_EEDP32, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_EEDP32,
+ Mpi2ScsiIoCdbEedp32_t, MPI2_POINTER pMpi2ScsiIoCdbEedp32_t;
+
+/* TBD: I don't think this is needed for MPI2/Gen2 */
+#if 0
+typedef struct
+{
+ U8 CDB[16]; /* 0x00 */
+ U32 DataLength; /* 0x10 */
+ U32 PrimaryReferenceTag; /* 0x14 */
+ U16 PrimaryApplicationTag; /* 0x18 */
+ U16 PrimaryApplicationTagMask; /* 0x1A */
+ U32 TransferLength; /* 0x1C */
+} MPI2_SCSI_IO32_CDB_EEDP16, MPI2_POINTER PTR_MPI2_SCSI_IO32_CDB_EEDP16,
+ Mpi2ScsiIo32CdbEedp16_t, MPI2_POINTER pMpi2ScsiIo32CdbEedp16_t;
+#endif
+
+typedef union
+{
+ U8 CDB32[32];
+ MPI2_SCSI_IO_CDB_EEDP32 EEDP32;
+ MPI2_SGE_SIMPLE_UNION SGE;
+} MPI2_SCSI_IO_CDB_UNION, MPI2_POINTER PTR_MPI2_SCSI_IO_CDB_UNION,
+ Mpi2ScsiIoCdb_t, MPI2_POINTER pMpi2ScsiIoCdb_t;
+
+/* SCSI IO Request Message */
+typedef struct _MPI2_SCSI_IO_REQUEST
+{
+ U16 DevHandle; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved1; /* 0x04 */
+ U8 Reserved2; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+ U32 SenseBufferLowAddress; /* 0x0C */
+ U16 SGLFlags; /* 0x10 */
+ U8 SenseBufferLength; /* 0x12 */
+ U8 Reserved4; /* 0x13 */
+ U8 SGLOffset0; /* 0x14 */
+ U8 SGLOffset1; /* 0x15 */
+ U8 SGLOffset2; /* 0x16 */
+ U8 SGLOffset3; /* 0x17 */
+ U32 SkipCount; /* 0x18 */
+ U32 DataLength; /* 0x1C */
+ U32 BidirectionalDataLength; /* 0x20 */
+ U16 IoFlags; /* 0x24 */
+ U16 EEDPFlags; /* 0x26 */
+ U32 EEDPBlockSize; /* 0x28 */
+ U32 SecondaryReferenceTag; /* 0x2C */
+ U16 SecondaryApplicationTag; /* 0x30 */
+ U16 ApplicationTagTranslationMask; /* 0x32 */
+ U8 LUN[8]; /* 0x34 */
+ U32 Control; /* 0x3C */
+ MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */
+ MPI2_SGE_IO_UNION SGL; /* 0x60 */
+} MPI2_SCSI_IO_REQUEST, MPI2_POINTER PTR_MPI2_SCSI_IO_REQUEST,
+ Mpi2SCSIIORequest_t, MPI2_POINTER pMpi2SCSIIORequest_t;
+
+/* SCSI IO MsgFlags bits */
+
+/* MsgFlags for SenseBufferAddressSpace */
+#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C)
+#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00)
+#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04)
+#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08)
+#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C)
+
+/* SCSI IO SGLFlags bits */
+
+/* base values for Data Location Address Space */
+#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C)
+#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00)
+#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04)
+#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08)
+#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C)
+
+/* base values for Type */
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01)
+#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02)
+
+/* shift values for each sub-field */
+#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12)
+#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8)
+#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4)
+#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0)
+
+/* SCSI IO IoFlags bits */
+
+/* Large CDB Address Space */
+#define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000)
+#define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000)
+#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000)
+
+#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000)
+#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800)
+#define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400)
+#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200)
+#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF)
+
+/* SCSI IO EEDPFlags bits */
+
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000)
+#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000)
+
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100)
+
+#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008)
+
+#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007)
+#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001)
+#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003)
+#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004)
+#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006)
+#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007)
+
+/* SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */
+
+/* SCSI IO Control bits */
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000)
+#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26)
+
+#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000)
+#define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000)
+#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000)
+#define MPI2_SCSIIO_CONTROL_READ (0x02000000)
+#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000)
+
+#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800)
+#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11)
+
+#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700)
+#define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000)
+#define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100)
+#define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200)
+#define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400)
+
+#define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0)
+#define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000)
+#define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040)
+#define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080)
+
+
+/* SCSI IO Error Reply Message */
+typedef struct _MPI2_SCSI_IO_REPLY
+{
+ U16 DevHandle; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved1; /* 0x04 */
+ U8 Reserved2; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+ U8 SCSIStatus; /* 0x0C */
+ U8 SCSIState; /* 0x0D */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U32 TransferCount; /* 0x14 */
+ U32 SenseCount; /* 0x18 */
+ U32 ResponseInfo; /* 0x1C */
+ U16 TaskTag; /* 0x20 */
+ U16 Reserved4; /* 0x22 */
+ U32 BidirectionalTransferCount; /* 0x24 */
+ U32 Reserved5; /* 0x28 */
+ U32 Reserved6; /* 0x2C */
+} MPI2_SCSI_IO_REPLY, MPI2_POINTER PTR_MPI2_SCSI_IO_REPLY,
+ Mpi2SCSIIOReply_t, MPI2_POINTER pMpi2SCSIIOReply_t;
+
+/* SCSI IO Reply SCSIStatus values (SAM-4 status codes) */
+
+#define MPI2_SCSI_STATUS_GOOD (0x00)
+#define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02)
+#define MPI2_SCSI_STATUS_CONDITION_MET (0x04)
+#define MPI2_SCSI_STATUS_BUSY (0x08)
+#define MPI2_SCSI_STATUS_INTERMEDIATE (0x10)
+#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14)
+#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18)
+#define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /* obsolete */
+#define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28)
+#define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30)
+#define MPI2_SCSI_STATUS_TASK_ABORTED (0x40)
+
+/* SCSI IO Reply SCSIState flags */
+
+#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10)
+#define MPI2_SCSI_STATE_TERMINATED (0x08)
+#define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04)
+#define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02)
+#define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01)
+
+#define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF)
+
+
+/****************************************************************************
+* SCSI Task Management messages
+****************************************************************************/
+
+/* SCSI Task Management Request Message */
+typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST
+{
+ U16 DevHandle; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U8 Reserved1; /* 0x04 */
+ U8 TaskType; /* 0x05 */
+ U8 Reserved2; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+ U8 LUN[8]; /* 0x0C */
+ U32 Reserved4[7]; /* 0x14 */
+ U16 TaskMID; /* 0x30 */
+ U16 Reserved5; /* 0x32 */
+} MPI2_SCSI_TASK_MANAGE_REQUEST,
+ MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REQUEST,
+ Mpi2SCSITaskManagementRequest_t,
+ MPI2_POINTER pMpi2SCSITaskManagementRequest_t;
+
+/* TaskType values */
+
+#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01)
+#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02)
+#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03)
+#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05)
+#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07)
+#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09)
+#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION (0x0A)
+
+/* MsgFlags bits */
+
+#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08)
+#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10)
+
+#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01)
+
+
+
+/* SCSI Task Management Reply Message */
+typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY
+{
+ U16 DevHandle; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U8 ResponseCode; /* 0x04 */
+ U8 TaskType; /* 0x05 */
+ U8 Reserved1; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved2; /* 0x0A */
+ U16 Reserved3; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U32 TerminationCount; /* 0x14 */
+} MPI2_SCSI_TASK_MANAGE_REPLY,
+ MPI2_POINTER PTR_MPI2_SCSI_TASK_MANAGE_REPLY,
+ Mpi2SCSITaskManagementReply_t, MPI2_POINTER pMpi2SCSIManagementReply_t;
+
+/* ResponseCode values */
+
+#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00)
+#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02)
+#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04)
+#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05)
+#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08)
+#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09)
+#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80)
+
+
+/****************************************************************************
+* SCSI Enclosure Processor messages
+****************************************************************************/
+
+/* SCSI Enclosure Processor Request Message */
+typedef struct _MPI2_SEP_REQUEST
+{
+ U16 DevHandle; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U8 Action; /* 0x04 */
+ U8 Flags; /* 0x05 */
+ U8 Reserved1; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved2; /* 0x0A */
+ U32 SlotStatus; /* 0x0C */
+ U32 Reserved3; /* 0x10 */
+ U32 Reserved4; /* 0x14 */
+ U32 Reserved5; /* 0x18 */
+ U16 Slot; /* 0x1C */
+ U16 EnclosureHandle; /* 0x1E */
+} MPI2_SEP_REQUEST, MPI2_POINTER PTR_MPI2_SEP_REQUEST,
+ Mpi2SepRequest_t, MPI2_POINTER pMpi2SepRequest_t;
+
+/* Action defines */
+#define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00)
+#define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01)
+
+/* Flags defines */
+#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00)
+#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01)
+
+/* SlotStatus defines */
+#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000)
+#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
+#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
+#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100)
+#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080)
+#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040)
+#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004)
+#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002)
+#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001)
+
+
+/* SCSI Enclosure Processor Reply Message */
+typedef struct _MPI2_SEP_REPLY
+{
+ U16 DevHandle; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U8 Action; /* 0x04 */
+ U8 Flags; /* 0x05 */
+ U8 Reserved1; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved2; /* 0x0A */
+ U16 Reserved3; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U32 SlotStatus; /* 0x14 */
+ U32 Reserved4; /* 0x18 */
+ U16 Slot; /* 0x1C */
+ U16 EnclosureHandle; /* 0x1E */
+} MPI2_SEP_REPLY, MPI2_POINTER PTR_MPI2_SEP_REPLY,
+ Mpi2SepReply_t, MPI2_POINTER pMpi2SepReply_t;
+
+/* SlotStatus defines */
+#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000)
+#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000)
+#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200)
+#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100)
+#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080)
+#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040)
+#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004)
+#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002)
+#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001)
+
+
+#endif
+
+
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
new file mode 100644
index 00000000000..8c5d81870c0
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_ioc.h
@@ -0,0 +1,1295 @@
+/*
+ * Copyright (c) 2000-2009 LSI Corporation.
+ *
+ *
+ * Name: mpi2_ioc.h
+ * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages
+ * Creation Date: October 11, 2006
+ *
+ * mpi2_ioc.h Version: 02.00.10
+ *
+ * Version History
+ * ---------------
+ *
+ * Date Version Description
+ * -------- -------- ------------------------------------------------------
+ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to
+ * MaxTargets.
+ * Added TotalImageSize field to FWDownload Request.
+ * Added reserved words to FWUpload Request.
+ * 06-26-07 02.00.02 Added IR Configuration Change List Event.
+ * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit
+ * request and replaced it with
+ * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
+ * Replaced the MinReplyQueueDepth field of the IOCFacts
+ * reply with MaxReplyDescriptorPostQueueDepth.
+ * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
+ * depth for the Reply Descriptor Post Queue.
+ * Added SASAddress field to Initiator Device Table
+ * Overflow Event data.
+ * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
+ * for SAS Initiator Device Status Change Event data.
+ * Modified Reason Code defines for SAS Topology Change
+ * List Event data, including adding a bit for PHY Vacant
+ * status, and adding a mask for the Reason Code.
+ * Added define for
+ * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
+ * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
+ * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of
+ * the IOCFacts Reply.
+ * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
+ * Moved MPI2_VERSION_UNION to mpi2.h.
+ * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
+ * instead of enables, and added SASBroadcastPrimitiveMasks
+ * field.
+ * Added Log Entry Added Event and related structure.
+ * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
+ * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
+ * Added MaxVolumes and MaxPersistentEntries fields to
+ * IOCFacts reply.
+ * Added ProtocalFlags and IOCCapabilities fields to
+ * MPI2_FW_IMAGE_HEADER.
+ * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
+ * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
+ * a U16 (from a U32).
+ * Removed extra 's' from EventMasks name.
+ * 06-27-08 02.00.08 Fixed an offset in a comment.
+ * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
+ * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
+ * renamed MinReplyFrameSize to ReplyFrameSize.
+ * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
+ * Added two new RAIDOperation values for Integrated RAID
+ * Operations Status Event data.
+ * Added four new IR Configuration Change List Event data
+ * ReasonCode values.
+ * Added two new ReasonCode defines for SAS Device Status
+ * Change Event data.
+ * Added three new DiscoveryStatus bits for the SAS
+ * Discovery event data.
+ * Added Multiplexing Status Change bit to the PhyStatus
+ * field of the SAS Topology Change List event data.
+ * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
+ * BootFlags are now product-specific.
+ * Added defines for the indivdual signature bytes
+ * for MPI2_INIT_IMAGE_FOOTER.
+ * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
+ * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
+ * define.
+ * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
+ * define.
+ * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_IOC_H
+#define MPI2_IOC_H
+
+/*****************************************************************************
+*
+* IOC Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* IOCInit message
+****************************************************************************/
+
+/* IOCInit Request message */
+typedef struct _MPI2_IOC_INIT_REQUEST
+{
+ U8 WhoInit; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 MsgVersion; /* 0x0C */
+ U16 HeaderVersion; /* 0x0E */
+ U32 Reserved5; /* 0x10 */
+ U32 Reserved6; /* 0x14 */
+ U16 Reserved7; /* 0x18 */
+ U16 SystemRequestFrameSize; /* 0x1A */
+ U16 ReplyDescriptorPostQueueDepth; /* 0x1C */
+ U16 ReplyFreeQueueDepth; /* 0x1E */
+ U32 SenseBufferAddressHigh; /* 0x20 */
+ U32 SystemReplyAddressHigh; /* 0x24 */
+ U64 SystemRequestFrameBaseAddress; /* 0x28 */
+ U64 ReplyDescriptorPostQueueAddress;/* 0x30 */
+ U64 ReplyFreeQueueAddress; /* 0x38 */
+ U64 TimeStamp; /* 0x40 */
+} MPI2_IOC_INIT_REQUEST, MPI2_POINTER PTR_MPI2_IOC_INIT_REQUEST,
+ Mpi2IOCInitRequest_t, MPI2_POINTER pMpi2IOCInitRequest_t;
+
+/* WhoInit values */
+#define MPI2_WHOINIT_NOT_INITIALIZED (0x00)
+#define MPI2_WHOINIT_SYSTEM_BIOS (0x01)
+#define MPI2_WHOINIT_ROM_BIOS (0x02)
+#define MPI2_WHOINIT_PCI_PEER (0x03)
+#define MPI2_WHOINIT_HOST_DRIVER (0x04)
+#define MPI2_WHOINIT_MANUFACTURER (0x05)
+
+/* MsgVersion */
+#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00)
+#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8)
+#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF)
+#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0)
+
+/* HeaderVersion */
+#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00)
+#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8)
+#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF)
+#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0)
+
+/* minimum depth for the Reply Descriptor Post Queue */
+#define MPI2_RDPQ_DEPTH_MIN (16)
+
+
+/* IOCInit Reply message */
+typedef struct _MPI2_IOC_INIT_REPLY
+{
+ U8 WhoInit; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Reserved5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_IOC_INIT_REPLY, MPI2_POINTER PTR_MPI2_IOC_INIT_REPLY,
+ Mpi2IOCInitReply_t, MPI2_POINTER pMpi2IOCInitReply_t;
+
+
+/****************************************************************************
+* IOCFacts message
+****************************************************************************/
+
+/* IOCFacts Request message */
+typedef struct _MPI2_IOC_FACTS_REQUEST
+{
+ U16 Reserved1; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+} MPI2_IOC_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_IOC_FACTS_REQUEST,
+ Mpi2IOCFactsRequest_t, MPI2_POINTER pMpi2IOCFactsRequest_t;
+
+
+/* IOCFacts Reply message */
+typedef struct _MPI2_IOC_FACTS_REPLY
+{
+ U16 MsgVersion; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 HeaderVersion; /* 0x04 */
+ U8 IOCNumber; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+ U16 IOCExceptions; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U8 MaxChainDepth; /* 0x14 */
+ U8 WhoInit; /* 0x15 */
+ U8 NumberOfPorts; /* 0x16 */
+ U8 Reserved2; /* 0x17 */
+ U16 RequestCredit; /* 0x18 */
+ U16 ProductID; /* 0x1A */
+ U32 IOCCapabilities; /* 0x1C */
+ MPI2_VERSION_UNION FWVersion; /* 0x20 */
+ U16 IOCRequestFrameSize; /* 0x24 */
+ U16 Reserved3; /* 0x26 */
+ U16 MaxInitiators; /* 0x28 */
+ U16 MaxTargets; /* 0x2A */
+ U16 MaxSasExpanders; /* 0x2C */
+ U16 MaxEnclosures; /* 0x2E */
+ U16 ProtocolFlags; /* 0x30 */
+ U16 HighPriorityCredit; /* 0x32 */
+ U16 MaxReplyDescriptorPostQueueDepth; /* 0x34 */
+ U8 ReplyFrameSize; /* 0x36 */
+ U8 MaxVolumes; /* 0x37 */
+ U16 MaxDevHandle; /* 0x38 */
+ U16 MaxPersistentEntries; /* 0x3A */
+ U32 Reserved4; /* 0x3C */
+} MPI2_IOC_FACTS_REPLY, MPI2_POINTER PTR_MPI2_IOC_FACTS_REPLY,
+ Mpi2IOCFactsReply_t, MPI2_POINTER pMpi2IOCFactsReply_t;
+
+/* MsgVersion */
+#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00)
+#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8)
+#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF)
+#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0)
+
+/* HeaderVersion */
+#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00)
+#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8)
+#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF)
+#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0)
+
+/* IOCExceptions */
+#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100)
+
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040)
+#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060)
+
+#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010)
+#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008)
+#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004)
+#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002)
+#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001)
+
+/* defines for WhoInit field are after the IOCInit Request */
+
+/* ProductID field uses MPI2_FW_HEADER_PID_ */
+
+/* IOCCapabilities */
+#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000)
+#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000)
+#define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800)
+#define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100)
+#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080)
+#define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040)
+#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010)
+#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008)
+#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004)
+
+/* ProtocolFlags */
+#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001)
+#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002)
+
+
+/****************************************************************************
+* PortFacts message
+****************************************************************************/
+
+/* PortFacts Request message */
+typedef struct _MPI2_PORT_FACTS_REQUEST
+{
+ U16 Reserved1; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 PortNumber; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+} MPI2_PORT_FACTS_REQUEST, MPI2_POINTER PTR_MPI2_PORT_FACTS_REQUEST,
+ Mpi2PortFactsRequest_t, MPI2_POINTER pMpi2PortFactsRequest_t;
+
+/* PortFacts Reply message */
+typedef struct _MPI2_PORT_FACTS_REPLY
+{
+ U16 Reserved1; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 PortNumber; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+ U16 Reserved4; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U8 Reserved5; /* 0x14 */
+ U8 PortType; /* 0x15 */
+ U16 Reserved6; /* 0x16 */
+ U16 MaxPostedCmdBuffers; /* 0x18 */
+ U16 Reserved7; /* 0x1A */
+} MPI2_PORT_FACTS_REPLY, MPI2_POINTER PTR_MPI2_PORT_FACTS_REPLY,
+ Mpi2PortFactsReply_t, MPI2_POINTER pMpi2PortFactsReply_t;
+
+/* PortType values */
+#define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00)
+#define MPI2_PORTFACTS_PORTTYPE_FC (0x10)
+#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20)
+#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30)
+#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31)
+
+
+/****************************************************************************
+* PortEnable message
+****************************************************************************/
+
+/* PortEnable Request message */
+typedef struct _MPI2_PORT_ENABLE_REQUEST
+{
+ U16 Reserved1; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U8 Reserved2; /* 0x04 */
+ U8 PortFlags; /* 0x05 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+} MPI2_PORT_ENABLE_REQUEST, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REQUEST,
+ Mpi2PortEnableRequest_t, MPI2_POINTER pMpi2PortEnableRequest_t;
+
+
+/* PortEnable Reply message */
+typedef struct _MPI2_PORT_ENABLE_REPLY
+{
+ U16 Reserved1; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U8 Reserved2; /* 0x04 */
+ U8 PortFlags; /* 0x05 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Reserved5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_PORT_ENABLE_REPLY, MPI2_POINTER PTR_MPI2_PORT_ENABLE_REPLY,
+ Mpi2PortEnableReply_t, MPI2_POINTER pMpi2PortEnableReply_t;
+
+
+/****************************************************************************
+* EventNotification message
+****************************************************************************/
+
+/* EventNotification Request message */
+#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4)
+
+typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST
+{
+ U16 Reserved1; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U32 Reserved5; /* 0x0C */
+ U32 Reserved6; /* 0x10 */
+ U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];/* 0x14 */
+ U16 SASBroadcastPrimitiveMasks; /* 0x24 */
+ U16 Reserved7; /* 0x26 */
+ U32 Reserved8; /* 0x28 */
+} MPI2_EVENT_NOTIFICATION_REQUEST,
+ MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REQUEST,
+ Mpi2EventNotificationRequest_t, MPI2_POINTER pMpi2EventNotificationRequest_t;
+
+
+/* EventNotification Reply message */
+typedef struct _MPI2_EVENT_NOTIFICATION_REPLY
+{
+ U16 EventDataLength; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved1; /* 0x04 */
+ U8 AckRequired; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved2; /* 0x0A */
+ U16 Reserved3; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U16 Event; /* 0x14 */
+ U16 Reserved4; /* 0x16 */
+ U32 EventContext; /* 0x18 */
+ U32 EventData[1]; /* 0x1C */
+} MPI2_EVENT_NOTIFICATION_REPLY, MPI2_POINTER PTR_MPI2_EVENT_NOTIFICATION_REPLY,
+ Mpi2EventNotificationReply_t, MPI2_POINTER pMpi2EventNotificationReply_t;
+
+/* AckRequired */
+#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00)
+#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01)
+
+/* Event */
+#define MPI2_EVENT_LOG_DATA (0x0001)
+#define MPI2_EVENT_STATE_CHANGE (0x0002)
+#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005)
+#define MPI2_EVENT_EVENT_CHANGE (0x000A)
+#define MPI2_EVENT_TASK_SET_FULL (0x000E)
+#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F)
+#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014)
+#define MPI2_EVENT_SAS_DISCOVERY (0x0016)
+#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017)
+#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018)
+#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019)
+#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C)
+#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D)
+#define MPI2_EVENT_IR_VOLUME (0x001E)
+#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F)
+#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020)
+#define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021)
+
+
+/* Log Entry Added Event data */
+
+/* the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */
+#define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C)
+
+typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED
+{
+ U64 TimeStamp; /* 0x00 */
+ U32 Reserved1; /* 0x08 */
+ U16 LogSequence; /* 0x0C */
+ U16 LogEntryQualifier; /* 0x0E */
+ U8 VP_ID; /* 0x10 */
+ U8 VF_ID; /* 0x11 */
+ U16 Reserved2; /* 0x12 */
+ U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH];/* 0x14 */
+} MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED,
+ Mpi2EventDataLogEntryAdded_t, MPI2_POINTER pMpi2EventDataLogEntryAdded_t;
+
+/* Hard Reset Received Event data */
+
+typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED
+{
+ U8 Reserved1; /* 0x00 */
+ U8 Port; /* 0x01 */
+ U16 Reserved2; /* 0x02 */
+} MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED,
+ Mpi2EventDataHardResetReceived_t,
+ MPI2_POINTER pMpi2EventDataHardResetReceived_t;
+
+/* Task Set Full Event data */
+
+typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL
+{
+ U16 DevHandle; /* 0x00 */
+ U16 CurrentDepth; /* 0x02 */
+} MPI2_EVENT_DATA_TASK_SET_FULL, MPI2_POINTER PTR_MPI2_EVENT_DATA_TASK_SET_FULL,
+ Mpi2EventDataTaskSetFull_t, MPI2_POINTER pMpi2EventDataTaskSetFull_t;
+
+
+/* SAS Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE
+{
+ U16 TaskTag; /* 0x00 */
+ U8 ReasonCode; /* 0x02 */
+ U8 Reserved1; /* 0x03 */
+ U8 ASC; /* 0x04 */
+ U8 ASCQ; /* 0x05 */
+ U16 DevHandle; /* 0x06 */
+ U32 Reserved2; /* 0x08 */
+ U64 SASAddress; /* 0x0C */
+ U8 LUN[8]; /* 0x14 */
+} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE,
+ Mpi2EventDataSasDeviceStatusChange_t,
+ MPI2_POINTER pMpi2EventDataSasDeviceStatusChange_t;
+
+/* SAS Device Status Change Event data ReasonCode values */
+#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F)
+#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10)
+
+
+/* Integrated RAID Operation Status Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS
+{
+ U16 VolDevHandle; /* 0x00 */
+ U16 Reserved1; /* 0x02 */
+ U8 RAIDOperation; /* 0x04 */
+ U8 PercentComplete; /* 0x05 */
+ U16 Reserved2; /* 0x06 */
+ U32 Resereved3; /* 0x08 */
+} MPI2_EVENT_DATA_IR_OPERATION_STATUS,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS,
+ Mpi2EventDataIrOperationStatus_t,
+ MPI2_POINTER pMpi2EventDataIrOperationStatus_t;
+
+/* Integrated RAID Operation Status Event data RAIDOperation values */
+#define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00)
+#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01)
+#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02)
+#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03)
+#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04)
+
+
+/* Integrated RAID Volume Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_VOLUME
+{
+ U16 VolDevHandle; /* 0x00 */
+ U8 ReasonCode; /* 0x02 */
+ U8 Reserved1; /* 0x03 */
+ U32 NewValue; /* 0x04 */
+ U32 PreviousValue; /* 0x08 */
+} MPI2_EVENT_DATA_IR_VOLUME, MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_VOLUME,
+ Mpi2EventDataIrVolume_t, MPI2_POINTER pMpi2EventDataIrVolume_t;
+
+/* Integrated RAID Volume Event data ReasonCode values */
+#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01)
+#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02)
+#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03)
+
+
+/* Integrated RAID Physical Disk Event data */
+
+typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK
+{
+ U16 Reserved1; /* 0x00 */
+ U8 ReasonCode; /* 0x02 */
+ U8 PhysDiskNum; /* 0x03 */
+ U16 PhysDiskDevHandle; /* 0x04 */
+ U16 Reserved2; /* 0x06 */
+ U16 Slot; /* 0x08 */
+ U16 EnclosureHandle; /* 0x0A */
+ U32 NewValue; /* 0x0C */
+ U32 PreviousValue; /* 0x10 */
+} MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK,
+ Mpi2EventDataIrPhysicalDisk_t, MPI2_POINTER pMpi2EventDataIrPhysicalDisk_t;
+
+/* Integrated RAID Physical Disk Event data ReasonCode values */
+#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01)
+#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02)
+#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03)
+
+
+/* Integrated RAID Configuration Change List Event data */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumElements at runtime.
+ */
+#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT
+#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1)
+#endif
+
+typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT
+{
+ U16 ElementFlags; /* 0x00 */
+ U16 VolDevHandle; /* 0x02 */
+ U8 ReasonCode; /* 0x04 */
+ U8 PhysDiskNum; /* 0x05 */
+ U16 PhysDiskDevHandle; /* 0x06 */
+} MPI2_EVENT_IR_CONFIG_ELEMENT, MPI2_POINTER PTR_MPI2_EVENT_IR_CONFIG_ELEMENT,
+ Mpi2EventIrConfigElement_t, MPI2_POINTER pMpi2EventIrConfigElement_t;
+
+/* IR Configuration Change List Event data ElementFlags values */
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001)
+#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002)
+
+/* IR Configuration Change List Event data ReasonCode values */
+#define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01)
+#define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02)
+#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03)
+#define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04)
+#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05)
+#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06)
+#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07)
+#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08)
+#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09)
+
+typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST
+{
+ U8 NumElements; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 Reserved2; /* 0x02 */
+ U8 ConfigNum; /* 0x03 */
+ U32 Flags; /* 0x04 */
+ MPI2_EVENT_IR_CONFIG_ELEMENT ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT]; /* 0x08 */
+} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST,
+ Mpi2EventDataIrConfigChangeList_t,
+ MPI2_POINTER pMpi2EventDataIrConfigChangeList_t;
+
+/* IR Configuration Change List Event data Flags values */
+#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001)
+
+
+/* SAS Discovery Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY
+{
+ U8 Flags; /* 0x00 */
+ U8 ReasonCode; /* 0x01 */
+ U8 PhysicalPort; /* 0x02 */
+ U8 Reserved1; /* 0x03 */
+ U32 DiscoveryStatus; /* 0x04 */
+} MPI2_EVENT_DATA_SAS_DISCOVERY,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_DISCOVERY,
+ Mpi2EventDataSasDiscovery_t, MPI2_POINTER pMpi2EventDataSasDiscovery_t;
+
+/* SAS Discovery Event data Flags values */
+#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02)
+#define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01)
+
+/* SAS Discovery Event data ReasonCode values */
+#define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01)
+#define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02)
+
+/* SAS Discovery Event data DiscoveryStatus values */
+#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000)
+#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000)
+#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000)
+#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000)
+#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000)
+#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000)
+#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000)
+#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800)
+#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400)
+#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080)
+#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040)
+#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020)
+#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010)
+#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004)
+#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002)
+#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001)
+
+
+/* SAS Broadcast Primitive Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE
+{
+ U8 PhyNum; /* 0x00 */
+ U8 Port; /* 0x01 */
+ U8 PortWidth; /* 0x02 */
+ U8 Primitive; /* 0x03 */
+} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE,
+ Mpi2EventDataSasBroadcastPrimitive_t,
+ MPI2_POINTER pMpi2EventDataSasBroadcastPrimitive_t;
+
+/* defines for the Primitive field */
+#define MPI2_EVENT_PRIMITIVE_CHANGE (0x01)
+#define MPI2_EVENT_PRIMITIVE_SES (0x02)
+#define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03)
+#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04)
+#define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05)
+#define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06)
+#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07)
+#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08)
+
+
+/* SAS Initiator Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE
+{
+ U8 ReasonCode; /* 0x00 */
+ U8 PhysicalPort; /* 0x01 */
+ U16 DevHandle; /* 0x02 */
+ U64 SASAddress; /* 0x04 */
+} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE,
+ Mpi2EventDataSasInitDevStatusChange_t,
+ MPI2_POINTER pMpi2EventDataSasInitDevStatusChange_t;
+
+/* SAS Initiator Device Status Change event ReasonCode values */
+#define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01)
+#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02)
+
+
+/* SAS Initiator Device Table Overflow Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW
+{
+ U16 MaxInit; /* 0x00 */
+ U16 CurrentInit; /* 0x02 */
+ U64 SASAddress; /* 0x04 */
+} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW,
+ Mpi2EventDataSasInitTableOverflow_t,
+ MPI2_POINTER pMpi2EventDataSasInitTableOverflow_t;
+
+
+/* SAS Topology Change List Event data */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumEntries at runtime.
+ */
+#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT
+#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1)
+#endif
+
+typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY
+{
+ U16 AttachedDevHandle; /* 0x00 */
+ U8 LinkRate; /* 0x02 */
+ U8 PhyStatus; /* 0x03 */
+} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, MPI2_POINTER PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY,
+ Mpi2EventSasTopoPhyEntry_t, MPI2_POINTER pMpi2EventSasTopoPhyEntry_t;
+
+typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST
+{
+ U16 EnclosureHandle; /* 0x00 */
+ U16 ExpanderDevHandle; /* 0x02 */
+ U8 NumPhys; /* 0x04 */
+ U8 Reserved1; /* 0x05 */
+ U16 Reserved2; /* 0x06 */
+ U8 NumEntries; /* 0x08 */
+ U8 StartPhyNum; /* 0x09 */
+ U8 ExpStatus; /* 0x0A */
+ U8 PhysicalPort; /* 0x0B */
+ MPI2_EVENT_SAS_TOPO_PHY_ENTRY PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /* 0x0C*/
+} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST,
+ Mpi2EventDataSasTopologyChangeList_t,
+ MPI2_POINTER pMpi2EventDataSasTopologyChangeList_t;
+
+/* values for the ExpStatus field */
+#define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01)
+#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02)
+#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03)
+#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04)
+
+/* defines for the LinkRate field */
+#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0)
+#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4)
+#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F)
+#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0)
+
+#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00)
+#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01)
+#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02)
+#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03)
+#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04)
+#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09)
+#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A)
+
+/* values for the PhyStatus field */
+#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80)
+#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10)
+/* values for the PhyStatus ReasonCode sub-field */
+#define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F)
+#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01)
+#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02)
+#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03)
+#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04)
+#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05)
+
+
+/* SAS Enclosure Device Status Change Event data */
+
+typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE
+{
+ U16 EnclosureHandle; /* 0x00 */
+ U8 ReasonCode; /* 0x02 */
+ U8 PhysicalPort; /* 0x03 */
+ U64 EnclosureLogicalID; /* 0x04 */
+ U16 NumSlots; /* 0x0C */
+ U16 StartSlot; /* 0x0E */
+ U32 PhyBits; /* 0x10 */
+} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
+ MPI2_POINTER PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE,
+ Mpi2EventDataSasEnclDevStatusChange_t,
+ MPI2_POINTER pMpi2EventDataSasEnclDevStatusChange_t;
+
+/* SAS Enclosure Device Status Change event ReasonCode values */
+#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01)
+#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02)
+
+
+/****************************************************************************
+* EventAck message
+****************************************************************************/
+
+/* EventAck Request message */
+typedef struct _MPI2_EVENT_ACK_REQUEST
+{
+ U16 Reserved1; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Event; /* 0x0C */
+ U16 Reserved5; /* 0x0E */
+ U32 EventContext; /* 0x10 */
+} MPI2_EVENT_ACK_REQUEST, MPI2_POINTER PTR_MPI2_EVENT_ACK_REQUEST,
+ Mpi2EventAckRequest_t, MPI2_POINTER pMpi2EventAckRequest_t;
+
+
+/* EventAck Reply message */
+typedef struct _MPI2_EVENT_ACK_REPLY
+{
+ U16 Reserved1; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Reserved5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_EVENT_ACK_REPLY, MPI2_POINTER PTR_MPI2_EVENT_ACK_REPLY,
+ Mpi2EventAckReply_t, MPI2_POINTER pMpi2EventAckReply_t;
+
+
+/****************************************************************************
+* FWDownload message
+****************************************************************************/
+
+/* FWDownload Request message */
+typedef struct _MPI2_FW_DOWNLOAD_REQUEST
+{
+ U8 ImageType; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U32 TotalImageSize; /* 0x0C */
+ U32 Reserved5; /* 0x10 */
+ MPI2_MPI_SGE_UNION SGL; /* 0x14 */
+} MPI2_FW_DOWNLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REQUEST,
+ Mpi2FWDownloadRequest, MPI2_POINTER pMpi2FWDownloadRequest;
+
+#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01)
+
+#define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01)
+#define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02)
+#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06)
+#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07)
+#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08)
+#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09)
+#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
+
+/* FWDownload TransactionContext Element */
+typedef struct _MPI2_FW_DOWNLOAD_TCSGE
+{
+ U8 Reserved1; /* 0x00 */
+ U8 ContextSize; /* 0x01 */
+ U8 DetailsLength; /* 0x02 */
+ U8 Flags; /* 0x03 */
+ U32 Reserved2; /* 0x04 */
+ U32 ImageOffset; /* 0x08 */
+ U32 ImageSize; /* 0x0C */
+} MPI2_FW_DOWNLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_TCSGE,
+ Mpi2FWDownloadTCSGE_t, MPI2_POINTER pMpi2FWDownloadTCSGE_t;
+
+/* FWDownload Reply message */
+typedef struct _MPI2_FW_DOWNLOAD_REPLY
+{
+ U8 ImageType; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Reserved5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_FW_DOWNLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_DOWNLOAD_REPLY,
+ Mpi2FWDownloadReply_t, MPI2_POINTER pMpi2FWDownloadReply_t;
+
+
+/****************************************************************************
+* FWUpload message
+****************************************************************************/
+
+/* FWUpload Request message */
+typedef struct _MPI2_FW_UPLOAD_REQUEST
+{
+ U8 ImageType; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U32 Reserved5; /* 0x0C */
+ U32 Reserved6; /* 0x10 */
+ MPI2_MPI_SGE_UNION SGL; /* 0x14 */
+} MPI2_FW_UPLOAD_REQUEST, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REQUEST,
+ Mpi2FWUploadRequest_t, MPI2_POINTER pMpi2FWUploadRequest_t;
+
+#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00)
+#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01)
+#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02)
+#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05)
+#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06)
+#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07)
+#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08)
+#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09)
+#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A)
+#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B)
+
+typedef struct _MPI2_FW_UPLOAD_TCSGE
+{
+ U8 Reserved1; /* 0x00 */
+ U8 ContextSize; /* 0x01 */
+ U8 DetailsLength; /* 0x02 */
+ U8 Flags; /* 0x03 */
+ U32 Reserved2; /* 0x04 */
+ U32 ImageOffset; /* 0x08 */
+ U32 ImageSize; /* 0x0C */
+} MPI2_FW_UPLOAD_TCSGE, MPI2_POINTER PTR_MPI2_FW_UPLOAD_TCSGE,
+ Mpi2FWUploadTCSGE_t, MPI2_POINTER pMpi2FWUploadTCSGE_t;
+
+/* FWUpload Reply message */
+typedef struct _MPI2_FW_UPLOAD_REPLY
+{
+ U8 ImageType; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Reserved5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U32 ActualImageSize; /* 0x14 */
+} MPI2_FW_UPLOAD_REPLY, MPI2_POINTER PTR_MPI2_FW_UPLOAD_REPLY,
+ Mpi2FWUploadReply_t, MPI2_POINTER pMPi2FWUploadReply_t;
+
+
+/* FW Image Header */
+typedef struct _MPI2_FW_IMAGE_HEADER
+{
+ U32 Signature; /* 0x00 */
+ U32 Signature0; /* 0x04 */
+ U32 Signature1; /* 0x08 */
+ U32 Signature2; /* 0x0C */
+ MPI2_VERSION_UNION MPIVersion; /* 0x10 */
+ MPI2_VERSION_UNION FWVersion; /* 0x14 */
+ MPI2_VERSION_UNION NVDATAVersion; /* 0x18 */
+ MPI2_VERSION_UNION PackageVersion; /* 0x1C */
+ U16 VendorID; /* 0x20 */
+ U16 ProductID; /* 0x22 */
+ U16 ProtocolFlags; /* 0x24 */
+ U16 Reserved26; /* 0x26 */
+ U32 IOCCapabilities; /* 0x28 */
+ U32 ImageSize; /* 0x2C */
+ U32 NextImageHeaderOffset; /* 0x30 */
+ U32 Checksum; /* 0x34 */
+ U32 Reserved38; /* 0x38 */
+ U32 Reserved3C; /* 0x3C */
+ U32 Reserved40; /* 0x40 */
+ U32 Reserved44; /* 0x44 */
+ U32 Reserved48; /* 0x48 */
+ U32 Reserved4C; /* 0x4C */
+ U32 Reserved50; /* 0x50 */
+ U32 Reserved54; /* 0x54 */
+ U32 Reserved58; /* 0x58 */
+ U32 Reserved5C; /* 0x5C */
+ U32 Reserved60; /* 0x60 */
+ U32 FirmwareVersionNameWhat; /* 0x64 */
+ U8 FirmwareVersionName[32]; /* 0x68 */
+ U32 VendorNameWhat; /* 0x88 */
+ U8 VendorName[32]; /* 0x8C */
+ U32 PackageNameWhat; /* 0x88 */
+ U8 PackageName[32]; /* 0x8C */
+ U32 ReservedD0; /* 0xD0 */
+ U32 ReservedD4; /* 0xD4 */
+ U32 ReservedD8; /* 0xD8 */
+ U32 ReservedDC; /* 0xDC */
+ U32 ReservedE0; /* 0xE0 */
+ U32 ReservedE4; /* 0xE4 */
+ U32 ReservedE8; /* 0xE8 */
+ U32 ReservedEC; /* 0xEC */
+ U32 ReservedF0; /* 0xF0 */
+ U32 ReservedF4; /* 0xF4 */
+ U32 ReservedF8; /* 0xF8 */
+ U32 ReservedFC; /* 0xFC */
+} MPI2_FW_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_FW_IMAGE_HEADER,
+ Mpi2FWImageHeader_t, MPI2_POINTER pMpi2FWImageHeader_t;
+
+/* Signature field */
+#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00)
+#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000)
+#define MPI2_FW_HEADER_SIGNATURE (0xEA000000)
+
+/* Signature0 field */
+#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04)
+#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A)
+
+/* Signature1 field */
+#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08)
+#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5)
+
+/* Signature2 field */
+#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C)
+#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA)
+
+
+/* defines for using the ProductID field */
+#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000)
+#define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000)
+
+#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00)
+#define MPI2_FW_HEADER_PID_PROD_A (0x0000)
+
+#define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF)
+/* SAS */
+#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0010)
+
+/* use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */
+
+/* use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */
+
+
+#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C)
+#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30)
+#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64)
+
+#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840)
+
+#define MPI2_FW_HEADER_SIZE (0x100)
+
+
+/* Extended Image Header */
+typedef struct _MPI2_EXT_IMAGE_HEADER
+
+{
+ U8 ImageType; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U16 Reserved2; /* 0x02 */
+ U32 Checksum; /* 0x04 */
+ U32 ImageSize; /* 0x08 */
+ U32 NextImageHeaderOffset; /* 0x0C */
+ U32 PackageVersion; /* 0x10 */
+ U32 Reserved3; /* 0x14 */
+ U32 Reserved4; /* 0x18 */
+ U32 Reserved5; /* 0x1C */
+ U8 IdentifyString[32]; /* 0x20 */
+} MPI2_EXT_IMAGE_HEADER, MPI2_POINTER PTR_MPI2_EXT_IMAGE_HEADER,
+ Mpi2ExtImageHeader_t, MPI2_POINTER pMpi2ExtImageHeader_t;
+
+/* useful offsets */
+#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00)
+#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08)
+#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C)
+
+#define MPI2_EXT_IMAGE_HEADER_SIZE (0x40)
+
+/* defines for the ImageType field */
+#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00)
+#define MPI2_EXT_IMAGE_TYPE_FW (0x01)
+#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03)
+#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04)
+#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05)
+#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06)
+#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07)
+#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08)
+
+#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MEGARAID)
+
+
+
+/* FLASH Layout Extended Image Data */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check RegionsPerLayout at runtime.
+ */
+#ifndef MPI2_FLASH_NUMBER_OF_REGIONS
+#define MPI2_FLASH_NUMBER_OF_REGIONS (1)
+#endif
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumberOfLayouts at runtime.
+ */
+#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS
+#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1)
+#endif
+
+typedef struct _MPI2_FLASH_REGION
+{
+ U8 RegionType; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U16 Reserved2; /* 0x02 */
+ U32 RegionOffset; /* 0x04 */
+ U32 RegionSize; /* 0x08 */
+ U32 Reserved3; /* 0x0C */
+} MPI2_FLASH_REGION, MPI2_POINTER PTR_MPI2_FLASH_REGION,
+ Mpi2FlashRegion_t, MPI2_POINTER pMpi2FlashRegion_t;
+
+typedef struct _MPI2_FLASH_LAYOUT
+{
+ U32 FlashSize; /* 0x00 */
+ U32 Reserved1; /* 0x04 */
+ U32 Reserved2; /* 0x08 */
+ U32 Reserved3; /* 0x0C */
+ MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS];/* 0x10 */
+} MPI2_FLASH_LAYOUT, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT,
+ Mpi2FlashLayout_t, MPI2_POINTER pMpi2FlashLayout_t;
+
+typedef struct _MPI2_FLASH_LAYOUT_DATA
+{
+ U8 ImageRevision; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 SizeOfRegion; /* 0x02 */
+ U8 Reserved2; /* 0x03 */
+ U16 NumberOfLayouts; /* 0x04 */
+ U16 RegionsPerLayout; /* 0x06 */
+ U16 MinimumSectorAlignment; /* 0x08 */
+ U16 Reserved3; /* 0x0A */
+ U32 Reserved4; /* 0x0C */
+ MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS];/* 0x10 */
+} MPI2_FLASH_LAYOUT_DATA, MPI2_POINTER PTR_MPI2_FLASH_LAYOUT_DATA,
+ Mpi2FlashLayoutData_t, MPI2_POINTER pMpi2FlashLayoutData_t;
+
+/* defines for the RegionType field */
+#define MPI2_FLASH_REGION_UNUSED (0x00)
+#define MPI2_FLASH_REGION_FIRMWARE (0x01)
+#define MPI2_FLASH_REGION_BIOS (0x02)
+#define MPI2_FLASH_REGION_NVDATA (0x03)
+#define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05)
+#define MPI2_FLASH_REGION_MFG_INFORMATION (0x06)
+#define MPI2_FLASH_REGION_CONFIG_1 (0x07)
+#define MPI2_FLASH_REGION_CONFIG_2 (0x08)
+#define MPI2_FLASH_REGION_MEGARAID (0x09)
+#define MPI2_FLASH_REGION_INIT (0x0A)
+
+/* ImageRevision */
+#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00)
+
+
+
+/* Supported Devices Extended Image Data */
+
+/*
+ * Host code (drivers, BIOS, utilities, etc.) should leave this define set to
+ * one and check NumberOfDevices at runtime.
+ */
+#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES
+#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1)
+#endif
+
+typedef struct _MPI2_SUPPORTED_DEVICE
+{
+ U16 DeviceID; /* 0x00 */
+ U16 VendorID; /* 0x02 */
+ U16 DeviceIDMask; /* 0x04 */
+ U16 Reserved1; /* 0x06 */
+ U8 LowPCIRev; /* 0x08 */
+ U8 HighPCIRev; /* 0x09 */
+ U16 Reserved2; /* 0x0A */
+ U32 Reserved3; /* 0x0C */
+} MPI2_SUPPORTED_DEVICE, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICE,
+ Mpi2SupportedDevice_t, MPI2_POINTER pMpi2SupportedDevice_t;
+
+typedef struct _MPI2_SUPPORTED_DEVICES_DATA
+{
+ U8 ImageRevision; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 NumberOfDevices; /* 0x02 */
+ U8 Reserved2; /* 0x03 */
+ U32 Reserved3; /* 0x04 */
+ MPI2_SUPPORTED_DEVICE SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES]; /* 0x08 */
+} MPI2_SUPPORTED_DEVICES_DATA, MPI2_POINTER PTR_MPI2_SUPPORTED_DEVICES_DATA,
+ Mpi2SupportedDevicesData_t, MPI2_POINTER pMpi2SupportedDevicesData_t;
+
+/* ImageRevision */
+#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00)
+
+
+/* Init Extended Image Data */
+
+typedef struct _MPI2_INIT_IMAGE_FOOTER
+
+{
+ U32 BootFlags; /* 0x00 */
+ U32 ImageSize; /* 0x04 */
+ U32 Signature0; /* 0x08 */
+ U32 Signature1; /* 0x0C */
+ U32 Signature2; /* 0x10 */
+ U32 ResetVector; /* 0x14 */
+} MPI2_INIT_IMAGE_FOOTER, MPI2_POINTER PTR_MPI2_INIT_IMAGE_FOOTER,
+ Mpi2InitImageFooter_t, MPI2_POINTER pMpi2InitImageFooter_t;
+
+/* defines for the BootFlags field */
+#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00)
+
+/* defines for the ImageSize field */
+#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04)
+
+/* defines for the Signature0 field */
+#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08)
+#define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA)
+
+/* defines for the Signature1 field */
+#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C)
+#define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5)
+
+/* defines for the Signature2 field */
+#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10)
+#define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A)
+
+/* Signature fields as individual bytes */
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A)
+
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5)
+
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA)
+#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A)
+
+/* defines for the ResetVector field */
+#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14)
+
+
+#endif
+
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_raid.h b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
new file mode 100644
index 00000000000..7134816d904
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_raid.h
@@ -0,0 +1,295 @@
+/*
+ * Copyright (c) 2000-2008 LSI Corporation.
+ *
+ *
+ * Name: mpi2_raid.h
+ * Title: MPI Integrated RAID messages and structures
+ * Creation Date: April 26, 2007
+ *
+ * mpi2_raid.h Version: 02.00.03
+ *
+ * Version History
+ * ---------------
+ *
+ * Date Version Description
+ * -------- -------- ------------------------------------------------------
+ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 08-31-07 02.00.01 Modifications to RAID Action request and reply,
+ * including the Actions and ActionData.
+ * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
+ * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
+ * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
+ * can be sized by the build environment.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_RAID_H
+#define MPI2_RAID_H
+
+/*****************************************************************************
+*
+* Integrated RAID Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* RAID Action messages
+****************************************************************************/
+
+/* ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */
+#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000)
+#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001)
+
+/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
+
+/* ActionDataWord defines for use with MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */
+#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001)
+
+/* ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */
+typedef struct _MPI2_RAID_ACTION_RATE_DATA
+{
+ U8 RateToChange; /* 0x00 */
+ U8 RateOrMode; /* 0x01 */
+ U16 DataScrubDuration; /* 0x02 */
+} MPI2_RAID_ACTION_RATE_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_RATE_DATA,
+ Mpi2RaidActionRateData_t, MPI2_POINTER pMpi2RaidActionRateData_t;
+
+#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00)
+#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01)
+#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02)
+
+/* ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */
+typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION
+{
+ U8 RAIDFunction; /* 0x00 */
+ U8 Flags; /* 0x01 */
+ U16 Reserved1; /* 0x02 */
+} MPI2_RAID_ACTION_START_RAID_FUNCTION,
+ MPI2_POINTER PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION,
+ Mpi2RaidActionStartRaidFunction_t,
+ MPI2_POINTER pMpi2RaidActionStartRaidFunction_t;
+
+/* defines for the RAIDFunction field */
+#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00)
+#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01)
+#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02)
+
+/* defines for the Flags field */
+#define MPI2_RAID_ACTION_START_NEW (0x00)
+#define MPI2_RAID_ACTION_START_RESUME (0x01)
+
+/* ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */
+typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION
+{
+ U8 RAIDFunction; /* 0x00 */
+ U8 Flags; /* 0x01 */
+ U16 Reserved1; /* 0x02 */
+} MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
+ MPI2_POINTER PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION,
+ Mpi2RaidActionStopRaidFunction_t,
+ MPI2_POINTER pMpi2RaidActionStopRaidFunction_t;
+
+/* defines for the RAIDFunction field */
+#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00)
+#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01)
+#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02)
+
+/* defines for the Flags field */
+#define MPI2_RAID_ACTION_STOP_ABORT (0x00)
+#define MPI2_RAID_ACTION_STOP_PAUSE (0x01)
+
+/* ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */
+typedef struct _MPI2_RAID_ACTION_HOT_SPARE
+{
+ U8 HotSparePool; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U16 DevHandle; /* 0x02 */
+} MPI2_RAID_ACTION_HOT_SPARE, MPI2_POINTER PTR_MPI2_RAID_ACTION_HOT_SPARE,
+ Mpi2RaidActionHotSpare_t, MPI2_POINTER pMpi2RaidActionHotSpare_t;
+
+/* ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */
+typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE
+{
+ U8 Flags; /* 0x00 */
+ U8 DeviceFirmwareUpdateModeTimeout; /* 0x01 */
+ U16 Reserved1; /* 0x02 */
+} MPI2_RAID_ACTION_FW_UPDATE_MODE,
+ MPI2_POINTER PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE,
+ Mpi2RaidActionFwUpdateMode_t, MPI2_POINTER pMpi2RaidActionFwUpdateMode_t;
+
+/* ActionDataWord defines for use with MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */
+#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00)
+#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01)
+
+typedef union _MPI2_RAID_ACTION_DATA
+{
+ U32 Word;
+ MPI2_RAID_ACTION_RATE_DATA Rates;
+ MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction;
+ MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction;
+ MPI2_RAID_ACTION_HOT_SPARE HotSpare;
+ MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode;
+} MPI2_RAID_ACTION_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_DATA,
+ Mpi2RaidActionData_t, MPI2_POINTER pMpi2RaidActionData_t;
+
+
+/* RAID Action Request Message */
+typedef struct _MPI2_RAID_ACTION_REQUEST
+{
+ U8 Action; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 VolDevHandle; /* 0x04 */
+ U8 PhysDiskNum; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved2; /* 0x0A */
+ U32 Reserved3; /* 0x0C */
+ MPI2_RAID_ACTION_DATA ActionDataWord; /* 0x10 */
+ MPI2_SGE_SIMPLE_UNION ActionDataSGE; /* 0x14 */
+} MPI2_RAID_ACTION_REQUEST, MPI2_POINTER PTR_MPI2_RAID_ACTION_REQUEST,
+ Mpi2RaidActionRequest_t, MPI2_POINTER pMpi2RaidActionRequest_t;
+
+/* RAID Action request Action values */
+
+#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01)
+#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02)
+#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03)
+#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04)
+#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05)
+#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A)
+#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B)
+#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F)
+#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11)
+#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15)
+#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17)
+#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18)
+#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19)
+#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C)
+#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D)
+#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E)
+#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20)
+#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21)
+#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22)
+
+
+/* RAID Volume Creation Structure */
+
+/*
+ * The following define can be customized for the targeted product.
+ */
+#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS
+#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1)
+#endif
+
+typedef struct _MPI2_RAID_VOLUME_PHYSDISK
+{
+ U8 RAIDSetNum; /* 0x00 */
+ U8 PhysDiskMap; /* 0x01 */
+ U16 PhysDiskDevHandle; /* 0x02 */
+} MPI2_RAID_VOLUME_PHYSDISK, MPI2_POINTER PTR_MPI2_RAID_VOLUME_PHYSDISK,
+ Mpi2RaidVolumePhysDisk_t, MPI2_POINTER pMpi2RaidVolumePhysDisk_t;
+
+/* defines for the PhysDiskMap field */
+#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01)
+#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02)
+
+typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT
+{
+ U8 NumPhysDisks; /* 0x00 */
+ U8 VolumeType; /* 0x01 */
+ U16 Reserved1; /* 0x02 */
+ U32 VolumeCreationFlags; /* 0x04 */
+ U32 VolumeSettings; /* 0x08 */
+ U8 Reserved2; /* 0x0C */
+ U8 ResyncRate; /* 0x0D */
+ U16 DataScrubDuration; /* 0x0E */
+ U64 VolumeMaxLBA; /* 0x10 */
+ U32 StripeSize; /* 0x18 */
+ U8 Name[16]; /* 0x1C */
+ MPI2_RAID_VOLUME_PHYSDISK PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS];/* 0x2C */
+} MPI2_RAID_VOLUME_CREATION_STRUCT,
+ MPI2_POINTER PTR_MPI2_RAID_VOLUME_CREATION_STRUCT,
+ Mpi2RaidVolumeCreationStruct_t, MPI2_POINTER pMpi2RaidVolumeCreationStruct_t;
+
+/* use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */
+
+/* defines for the VolumeCreationFlags field */
+#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80)
+#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x04)
+#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x02)
+#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x01)
+
+
+/* RAID Online Capacity Expansion Structure */
+
+typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION
+{
+ U32 Flags; /* 0x00 */
+ U16 DevHandle0; /* 0x04 */
+ U16 Reserved1; /* 0x06 */
+ U16 DevHandle1; /* 0x08 */
+ U16 Reserved2; /* 0x0A */
+} MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
+ MPI2_POINTER PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION,
+ Mpi2RaidOnlineCapacityExpansion_t,
+ MPI2_POINTER pMpi2RaidOnlineCapacityExpansion_t;
+
+
+/* RAID Volume Indicator Structure */
+
+typedef struct _MPI2_RAID_VOL_INDICATOR
+{
+ U64 TotalBlocks; /* 0x00 */
+ U64 BlocksRemaining; /* 0x08 */
+ U32 Flags; /* 0x10 */
+} MPI2_RAID_VOL_INDICATOR, MPI2_POINTER PTR_MPI2_RAID_VOL_INDICATOR,
+ Mpi2RaidVolIndicator_t, MPI2_POINTER pMpi2RaidVolIndicator_t;
+
+/* defines for RAID Volume Indicator Flags field */
+#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F)
+#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000)
+#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001)
+#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002)
+#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003)
+
+
+/* RAID Action Reply ActionData union */
+typedef union _MPI2_RAID_ACTION_REPLY_DATA
+{
+ U32 Word[5];
+ MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator;
+ U16 VolDevHandle;
+ U8 VolumeState;
+ U8 PhysDiskNum;
+} MPI2_RAID_ACTION_REPLY_DATA, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY_DATA,
+ Mpi2RaidActionReplyData_t, MPI2_POINTER pMpi2RaidActionReplyData_t;
+
+/* use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */
+
+
+/* RAID Action Reply Message */
+typedef struct _MPI2_RAID_ACTION_REPLY
+{
+ U8 Action; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 VolDevHandle; /* 0x04 */
+ U8 PhysDiskNum; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved2; /* 0x0A */
+ U16 Reserved3; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ MPI2_RAID_ACTION_REPLY_DATA ActionData; /* 0x14 */
+} MPI2_RAID_ACTION_REPLY, MPI2_POINTER PTR_MPI2_RAID_ACTION_REPLY,
+ Mpi2RaidActionReply_t, MPI2_POINTER pMpi2RaidActionReply_t;
+
+
+#endif
+
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_sas.h b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
new file mode 100644
index 00000000000..8a42b136cf5
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2000-2007 LSI Corporation.
+ *
+ *
+ * Name: mpi2_sas.h
+ * Title: MPI Serial Attached SCSI structures and definitions
+ * Creation Date: February 9, 2007
+ *
+ * mpi2.h Version: 02.00.02
+ *
+ * Version History
+ * ---------------
+ *
+ * Date Version Description
+ * -------- -------- ------------------------------------------------------
+ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit
+ * Control Request.
+ * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control
+ * Request.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_SAS_H
+#define MPI2_SAS_H
+
+/*
+ * Values for SASStatus.
+ */
+#define MPI2_SASSTATUS_SUCCESS (0x00)
+#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01)
+#define MPI2_SASSTATUS_INVALID_FRAME (0x02)
+#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03)
+#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04)
+#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05)
+#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06)
+#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07)
+#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08)
+#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09)
+#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A)
+#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B)
+#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C)
+#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D)
+#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E)
+#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F)
+#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10)
+#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11)
+#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12)
+#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13)
+#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14)
+
+
+/*
+ * Values for the SAS DeviceInfo field used in SAS Device Status Change Event
+ * data and SAS Configuration pages.
+ */
+#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000)
+#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000)
+#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000)
+#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800)
+#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400)
+#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200)
+#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100)
+#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080)
+#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040)
+#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020)
+#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010)
+#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008)
+
+#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007)
+#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000)
+#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001)
+#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002)
+#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003)
+
+
+/*****************************************************************************
+*
+* SAS Messages
+*
+*****************************************************************************/
+
+/****************************************************************************
+* SMP Passthrough messages
+****************************************************************************/
+
+/* SMP Passthrough Request Message */
+typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST
+{
+ U8 PassthroughFlags; /* 0x00 */
+ U8 PhysicalPort; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 RequestDataLength; /* 0x04 */
+ U8 SGLFlags; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+ U32 Reserved2; /* 0x0C */
+ U64 SASAddress; /* 0x10 */
+ U32 Reserved3; /* 0x18 */
+ U32 Reserved4; /* 0x1C */
+ MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */
+} MPI2_SMP_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REQUEST,
+ Mpi2SmpPassthroughRequest_t, MPI2_POINTER pMpi2SmpPassthroughRequest_t;
+
+/* values for PassthroughFlags field */
+#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80)
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* SMP Passthrough Reply Message */
+typedef struct _MPI2_SMP_PASSTHROUGH_REPLY
+{
+ U8 PassthroughFlags; /* 0x00 */
+ U8 PhysicalPort; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 ResponseDataLength; /* 0x04 */
+ U8 SGLFlags; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+ U8 Reserved2; /* 0x0C */
+ U8 SASStatus; /* 0x0D */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U32 Reserved3; /* 0x14 */
+ U8 ResponseData[4]; /* 0x18 */
+} MPI2_SMP_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SMP_PASSTHROUGH_REPLY,
+ Mpi2SmpPassthroughReply_t, MPI2_POINTER pMpi2SmpPassthroughReply_t;
+
+/* values for PassthroughFlags field */
+#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80)
+
+/* values for SASStatus field are at the top of this file */
+
+
+/****************************************************************************
+* SATA Passthrough messages
+****************************************************************************/
+
+/* SATA Passthrough Request Message */
+typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST
+{
+ U16 DevHandle; /* 0x00 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 PassthroughFlags; /* 0x04 */
+ U8 SGLFlags; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+ U32 Reserved2; /* 0x0C */
+ U32 Reserved3; /* 0x10 */
+ U32 Reserved4; /* 0x14 */
+ U32 DataLength; /* 0x18 */
+ U8 CommandFIS[20]; /* 0x1C */
+ MPI2_SIMPLE_SGE_UNION SGL; /* 0x20 */
+} MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
+ Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
+
+/* values for PassthroughFlags field */
+#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002)
+#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001)
+
+/* values for SGLFlags field are in the SGL section of mpi2.h */
+
+
+/* SATA Passthrough Reply Message */
+typedef struct _MPI2_SATA_PASSTHROUGH_REPLY
+{
+ U16 DevHandle; /* 0x00 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 PassthroughFlags; /* 0x04 */
+ U8 SGLFlags; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved1; /* 0x0A */
+ U8 Reserved2; /* 0x0C */
+ U8 SASStatus; /* 0x0D */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U8 StatusFIS[20]; /* 0x14 */
+ U32 StatusControlRegisters; /* 0x28 */
+ U32 TransferCount; /* 0x2C */
+} MPI2_SATA_PASSTHROUGH_REPLY, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REPLY,
+ Mpi2SataPassthroughReply_t, MPI2_POINTER pMpi2SataPassthroughReply_t;
+
+/* values for SASStatus field are at the top of this file */
+
+
+/****************************************************************************
+* SAS IO Unit Control messages
+****************************************************************************/
+
+/* SAS IO Unit Control Request Message */
+typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST
+{
+ U8 Operation; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 DevHandle; /* 0x04 */
+ U8 IOCParameter; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+ U16 Reserved4; /* 0x0C */
+ U8 PhyNum; /* 0x0E */
+ U8 PrimFlags; /* 0x0F */
+ U32 Primitive; /* 0x10 */
+ U8 LookupMethod; /* 0x14 */
+ U8 Reserved5; /* 0x15 */
+ U16 SlotNumber; /* 0x16 */
+ U64 LookupAddress; /* 0x18 */
+ U32 IOCParameterValue; /* 0x20 */
+ U32 Reserved7; /* 0x24 */
+ U32 Reserved8; /* 0x28 */
+} MPI2_SAS_IOUNIT_CONTROL_REQUEST,
+ MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST,
+ Mpi2SasIoUnitControlRequest_t, MPI2_POINTER pMpi2SasIoUnitControlRequest_t;
+
+/* values for the Operation field */
+#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02)
+#define MPI2_SAS_OP_PHY_LINK_RESET (0x06)
+#define MPI2_SAS_OP_PHY_HARD_RESET (0x07)
+#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08)
+#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A)
+#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B)
+#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C)
+#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D)
+#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E)
+#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F)
+#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80)
+
+/* values for the PrimFlags field */
+#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08)
+#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02)
+#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01)
+
+/* values for the LookupMethod field */
+#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01)
+#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02)
+#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03)
+
+
+/* SAS IO Unit Control Reply Message */
+typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY
+{
+ U8 Operation; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 DevHandle; /* 0x04 */
+ U8 IOCParameter; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved3; /* 0x0A */
+ U16 Reserved4; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_SAS_IOUNIT_CONTROL_REPLY,
+ MPI2_POINTER PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY,
+ Mpi2SasIoUnitControlReply_t, MPI2_POINTER pMpi2SasIoUnitControlReply_t;
+
+
+#endif
+
+
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_tool.h b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
new file mode 100644
index 00000000000..2ff4e936bd3
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2000-2008 LSI Corporation.
+ *
+ *
+ * Name: mpi2_tool.h
+ * Title: MPI diagnostic tool structures and definitions
+ * Creation Date: March 26, 2007
+ *
+ * mpi2_tool.h Version: 02.00.02
+ *
+ * Version History
+ * ---------------
+ *
+ * Date Version Description
+ * -------- -------- ------------------------------------------------------
+ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
+ * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release
+ * structures and defines.
+ * 02-29-08 02.00.02 Modified various names to make them 32-character unique.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_TOOL_H
+#define MPI2_TOOL_H
+
+/*****************************************************************************
+*
+* Toolbox Messages
+*
+*****************************************************************************/
+
+/* defines for the Tools */
+#define MPI2_TOOLBOX_CLEAN_TOOL (0x00)
+#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01)
+#define MPI2_TOOLBOX_BEACON_TOOL (0x05)
+
+/****************************************************************************
+* Toolbox reply
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_REPLY
+{
+ U8 Tool; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Reserved5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_TOOLBOX_REPLY, MPI2_POINTER PTR_MPI2_TOOLBOX_REPLY,
+ Mpi2ToolboxReply_t, MPI2_POINTER pMpi2ToolboxReply_t;
+
+
+/****************************************************************************
+* Toolbox Clean Tool request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST
+{
+ U8 Tool; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U32 Flags; /* 0x0C */
+ } MPI2_TOOLBOX_CLEAN_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_CLEAN_REQUEST,
+ Mpi2ToolboxCleanRequest_t, MPI2_POINTER pMpi2ToolboxCleanRequest_t;
+
+/* values for the Flags field */
+#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000)
+#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000)
+#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000)
+#define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000)
+#define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000)
+#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000)
+#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000)
+#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004)
+#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002)
+#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001)
+
+
+/****************************************************************************
+* Toolbox Memory Move request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST
+{
+ U8 Tool; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ MPI2_SGE_SIMPLE_UNION SGL; /* 0x0C */
+} MPI2_TOOLBOX_MEM_MOVE_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST,
+ Mpi2ToolboxMemMoveRequest_t, MPI2_POINTER pMpi2ToolboxMemMoveRequest_t;
+
+
+/****************************************************************************
+* Toolbox Beacon Tool request
+****************************************************************************/
+
+typedef struct _MPI2_TOOLBOX_BEACON_REQUEST
+{
+ U8 Tool; /* 0x00 */
+ U8 Reserved1; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U8 Reserved5; /* 0x0C */
+ U8 PhysicalPort; /* 0x0D */
+ U8 Reserved6; /* 0x0E */
+ U8 Flags; /* 0x0F */
+} MPI2_TOOLBOX_BEACON_REQUEST, MPI2_POINTER PTR_MPI2_TOOLBOX_BEACON_REQUEST,
+ Mpi2ToolboxBeaconRequest_t, MPI2_POINTER pMpi2ToolboxBeaconRequest_t;
+
+/* values for the Flags field */
+#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00)
+#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01)
+
+
+/*****************************************************************************
+*
+* Diagnostic Buffer Messages
+*
+*****************************************************************************/
+
+
+/****************************************************************************
+* Diagnostic Buffer Post request
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST
+{
+ U8 Reserved1; /* 0x00 */
+ U8 BufferType; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U64 BufferAddress; /* 0x0C */
+ U32 BufferLength; /* 0x14 */
+ U32 Reserved5; /* 0x18 */
+ U32 Reserved6; /* 0x1C */
+ U32 Flags; /* 0x20 */
+ U32 ProductSpecific[23]; /* 0x24 */
+} MPI2_DIAG_BUFFER_POST_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REQUEST,
+ Mpi2DiagBufferPostRequest_t, MPI2_POINTER pMpi2DiagBufferPostRequest_t;
+
+/* values for the BufferType field */
+#define MPI2_DIAG_BUF_TYPE_TRACE (0x00)
+#define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01)
+/* count of the number of buffer types */
+#define MPI2_DIAG_BUF_TYPE_COUNT (0x02)
+
+
+/****************************************************************************
+* Diagnostic Buffer Post reply
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_BUFFER_POST_REPLY
+{
+ U8 Reserved1; /* 0x00 */
+ U8 BufferType; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Reserved5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+ U32 TransferLength; /* 0x14 */
+} MPI2_DIAG_BUFFER_POST_REPLY, MPI2_POINTER PTR_MPI2_DIAG_BUFFER_POST_REPLY,
+ Mpi2DiagBufferPostReply_t, MPI2_POINTER pMpi2DiagBufferPostReply_t;
+
+
+/****************************************************************************
+* Diagnostic Release request
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_RELEASE_REQUEST
+{
+ U8 Reserved1; /* 0x00 */
+ U8 BufferType; /* 0x01 */
+ U8 ChainOffset; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+} MPI2_DIAG_RELEASE_REQUEST, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REQUEST,
+ Mpi2DiagReleaseRequest_t, MPI2_POINTER pMpi2DiagReleaseRequest_t;
+
+
+/****************************************************************************
+* Diagnostic Buffer Post reply
+****************************************************************************/
+
+typedef struct _MPI2_DIAG_RELEASE_REPLY
+{
+ U8 Reserved1; /* 0x00 */
+ U8 BufferType; /* 0x01 */
+ U8 MsgLength; /* 0x02 */
+ U8 Function; /* 0x03 */
+ U16 Reserved2; /* 0x04 */
+ U8 Reserved3; /* 0x06 */
+ U8 MsgFlags; /* 0x07 */
+ U8 VP_ID; /* 0x08 */
+ U8 VF_ID; /* 0x09 */
+ U16 Reserved4; /* 0x0A */
+ U16 Reserved5; /* 0x0C */
+ U16 IOCStatus; /* 0x0E */
+ U32 IOCLogInfo; /* 0x10 */
+} MPI2_DIAG_RELEASE_REPLY, MPI2_POINTER PTR_MPI2_DIAG_RELEASE_REPLY,
+ Mpi2DiagReleaseReply_t, MPI2_POINTER pMpi2DiagReleaseReply_t;
+
+
+#endif
+
diff --git a/drivers/scsi/mpt2sas/mpi/mpi2_type.h b/drivers/scsi/mpt2sas/mpi/mpi2_type.h
new file mode 100644
index 00000000000..cfde017bf16
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpi/mpi2_type.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2000-2007 LSI Corporation.
+ *
+ *
+ * Name: mpi2_type.h
+ * Title: MPI basic type definitions
+ * Creation Date: August 16, 2006
+ *
+ * mpi2_type.h Version: 02.00.00
+ *
+ * Version History
+ * ---------------
+ *
+ * Date Version Description
+ * -------- -------- ------------------------------------------------------
+ * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A.
+ * --------------------------------------------------------------------------
+ */
+
+#ifndef MPI2_TYPE_H
+#define MPI2_TYPE_H
+
+
+/*******************************************************************************
+ * Define MPI2_POINTER if it hasn't already been defined. By default
+ * MPI2_POINTER is defined to be a near pointer. MPI2_POINTER can be defined as
+ * a far pointer by defining MPI2_POINTER as "far *" before this header file is
+ * included.
+ */
+#ifndef MPI2_POINTER
+#define MPI2_POINTER *
+#endif
+
+/* the basic types may have already been included by mpi_type.h */
+#ifndef MPI_TYPE_H
+/*****************************************************************************
+*
+* Basic Types
+*
+*****************************************************************************/
+
+typedef u8 U8;
+typedef __le16 U16;
+typedef __le32 U32;
+typedef __le64 U64 __attribute__((aligned(4)));
+
+/*****************************************************************************
+*
+* Pointer Types
+*
+*****************************************************************************/
+
+typedef U8 *PU8;
+typedef U16 *PU16;
+typedef U32 *PU32;
+typedef U64 *PU64;
+
+#endif
+
+#endif
+
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.c b/drivers/scsi/mpt2sas/mpt2sas_base.c
new file mode 100644
index 00000000000..52427a8324f
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.c
@@ -0,0 +1,3435 @@
+/*
+ * This is the Fusion MPT base driver providing common API layer interface
+ * for access to MPT (Message Passing Technology) firmware.
+ *
+ * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
+ * Copyright (C) 2007-2008 LSI Corporation
+ * (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kdev_t.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/sort.h>
+#include <linux/io.h>
+
+#include "mpt2sas_base.h"
+
+static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS];
+
+#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */
+#define MPT2SAS_MAX_REQUEST_QUEUE 500 /* maximum controller queue depth */
+
+static int max_queue_depth = -1;
+module_param(max_queue_depth, int, 0);
+MODULE_PARM_DESC(max_queue_depth, " max controller queue depth ");
+
+static int max_sgl_entries = -1;
+module_param(max_sgl_entries, int, 0);
+MODULE_PARM_DESC(max_sgl_entries, " max sg entries ");
+
+static int msix_disable = -1;
+module_param(msix_disable, int, 0);
+MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)");
+
+/**
+ * _base_fault_reset_work - workq handling ioc fault conditions
+ * @work: input argument, used to derive ioc
+ * Context: sleep.
+ *
+ * Return nothing.
+ */
+static void
+_base_fault_reset_work(struct work_struct *work)
+{
+ struct MPT2SAS_ADAPTER *ioc =
+ container_of(work, struct MPT2SAS_ADAPTER, fault_reset_work.work);
+ unsigned long flags;
+ u32 doorbell;
+ int rc;
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->ioc_reset_in_progress)
+ goto rearm_timer;
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ doorbell = mpt2sas_base_get_iocstate(ioc, 0);
+ if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+ rc = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ printk(MPT2SAS_WARN_FMT "%s: hard reset: %s\n", ioc->name,
+ __func__, (rc == 0) ? "success" : "failed");
+ doorbell = mpt2sas_base_get_iocstate(ioc, 0);
+ if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT)
+ mpt2sas_base_fault_info(ioc, doorbell &
+ MPI2_DOORBELL_DATA_MASK);
+ }
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ rearm_timer:
+ if (ioc->fault_reset_work_q)
+ queue_delayed_work(ioc->fault_reset_work_q,
+ &ioc->fault_reset_work,
+ msecs_to_jiffies(FAULT_POLLING_INTERVAL));
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+}
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _base_sas_ioc_info - verbose translation of the ioc status
+ * @ioc: pointer to scsi command object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @request_hdr: request mf
+ *
+ * Return nothing.
+ */
+static void
+_base_sas_ioc_info(struct MPT2SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply,
+ MPI2RequestHeader_t *request_hdr)
+{
+ u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ char *desc = NULL;
+ u16 frame_sz;
+ char *func_str = NULL;
+
+ /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */
+ if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+ request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH ||
+ request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION)
+ return;
+
+ switch (ioc_status) {
+
+/****************************************************************************
+* Common IOCStatus values for all replies
+****************************************************************************/
+
+ case MPI2_IOCSTATUS_INVALID_FUNCTION:
+ desc = "invalid function";
+ break;
+ case MPI2_IOCSTATUS_BUSY:
+ desc = "busy";
+ break;
+ case MPI2_IOCSTATUS_INVALID_SGL:
+ desc = "invalid sgl";
+ break;
+ case MPI2_IOCSTATUS_INTERNAL_ERROR:
+ desc = "internal error";
+ break;
+ case MPI2_IOCSTATUS_INVALID_VPID:
+ desc = "invalid vpid";
+ break;
+ case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
+ desc = "insufficient resources";
+ break;
+ case MPI2_IOCSTATUS_INVALID_FIELD:
+ desc = "invalid field";
+ break;
+ case MPI2_IOCSTATUS_INVALID_STATE:
+ desc = "invalid state";
+ break;
+ case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED:
+ desc = "op state not supported";
+ break;
+
+/****************************************************************************
+* Config IOCStatus values
+****************************************************************************/
+
+ case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION:
+ desc = "config invalid action";
+ break;
+ case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE:
+ desc = "config invalid type";
+ break;
+ case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE:
+ desc = "config invalid page";
+ break;
+ case MPI2_IOCSTATUS_CONFIG_INVALID_DATA:
+ desc = "config invalid data";
+ break;
+ case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS:
+ desc = "config no defaults";
+ break;
+ case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT:
+ desc = "config cant commit";
+ break;
+
+/****************************************************************************
+* SCSI IO Reply
+****************************************************************************/
+
+ case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+ case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
+ case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+ case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
+ case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+ case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+ case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+ case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+ case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
+ case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
+ case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+ case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+ break;
+
+/****************************************************************************
+* For use by SCSI Initiator and SCSI Target end-to-end data protection
+****************************************************************************/
+
+ case MPI2_IOCSTATUS_EEDP_GUARD_ERROR:
+ desc = "eedp guard error";
+ break;
+ case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR:
+ desc = "eedp ref tag error";
+ break;
+ case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR:
+ desc = "eedp app tag error";
+ break;
+
+/****************************************************************************
+* SCSI Target values
+****************************************************************************/
+
+ case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX:
+ desc = "target invalid io index";
+ break;
+ case MPI2_IOCSTATUS_TARGET_ABORTED:
+ desc = "target aborted";
+ break;
+ case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE:
+ desc = "target no conn retryable";
+ break;
+ case MPI2_IOCSTATUS_TARGET_NO_CONNECTION:
+ desc = "target no connection";
+ break;
+ case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH:
+ desc = "target xfer count mismatch";
+ break;
+ case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR:
+ desc = "target data offset error";
+ break;
+ case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA:
+ desc = "target too much write data";
+ break;
+ case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT:
+ desc = "target iu too short";
+ break;
+ case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT:
+ desc = "target ack nak timeout";
+ break;
+ case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED:
+ desc = "target nak received";
+ break;
+
+/****************************************************************************
+* Serial Attached SCSI values
+****************************************************************************/
+
+ case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED:
+ desc = "smp request failed";
+ break;
+ case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN:
+ desc = "smp data overrun";
+ break;
+
+/****************************************************************************
+* Diagnostic Buffer Post / Diagnostic Release values
+****************************************************************************/
+
+ case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED:
+ desc = "diagnostic released";
+ break;
+ default:
+ break;
+ }
+
+ if (!desc)
+ return;
+
+ switch (request_hdr->Function) {
+ case MPI2_FUNCTION_CONFIG:
+ frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size;
+ func_str = "config_page";
+ break;
+ case MPI2_FUNCTION_SCSI_TASK_MGMT:
+ frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t);
+ func_str = "task_mgmt";
+ break;
+ case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
+ frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t);
+ func_str = "sas_iounit_ctl";
+ break;
+ case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR:
+ frame_sz = sizeof(Mpi2SepRequest_t);
+ func_str = "enclosure";
+ break;
+ case MPI2_FUNCTION_IOC_INIT:
+ frame_sz = sizeof(Mpi2IOCInitRequest_t);
+ func_str = "ioc_init";
+ break;
+ case MPI2_FUNCTION_PORT_ENABLE:
+ frame_sz = sizeof(Mpi2PortEnableRequest_t);
+ func_str = "port_enable";
+ break;
+ case MPI2_FUNCTION_SMP_PASSTHROUGH:
+ frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size;
+ func_str = "smp_passthru";
+ break;
+ default:
+ frame_sz = 32;
+ func_str = "unknown";
+ break;
+ }
+
+ printk(MPT2SAS_WARN_FMT "ioc_status: %s(0x%04x), request(0x%p),"
+ " (%s)\n", ioc->name, desc, ioc_status, request_hdr, func_str);
+
+ _debug_dump_mf(request_hdr, frame_sz/4);
+}
+
+/**
+ * _base_display_event_data - verbose translation of firmware asyn events
+ * @ioc: pointer to scsi command object
+ * @mpi_reply: reply mf payload returned from firmware
+ *
+ * Return nothing.
+ */
+static void
+_base_display_event_data(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventNotificationReply_t *mpi_reply)
+{
+ char *desc = NULL;
+ u16 event;
+
+ if (!(ioc->logging_level & MPT_DEBUG_EVENTS))
+ return;
+
+ event = le16_to_cpu(mpi_reply->Event);
+
+ switch (event) {
+ case MPI2_EVENT_LOG_DATA:
+ desc = "Log Data";
+ break;
+ case MPI2_EVENT_STATE_CHANGE:
+ desc = "Status Change";
+ break;
+ case MPI2_EVENT_HARD_RESET_RECEIVED:
+ desc = "Hard Reset Received";
+ break;
+ case MPI2_EVENT_EVENT_CHANGE:
+ desc = "Event Change";
+ break;
+ case MPI2_EVENT_TASK_SET_FULL:
+ desc = "Task Set Full";
+ break;
+ case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ desc = "Device Status Change";
+ break;
+ case MPI2_EVENT_IR_OPERATION_STATUS:
+ desc = "IR Operation Status";
+ break;
+ case MPI2_EVENT_SAS_DISCOVERY:
+ desc = "Discovery";
+ break;
+ case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
+ desc = "SAS Broadcast Primitive";
+ break;
+ case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE:
+ desc = "SAS Init Device Status Change";
+ break;
+ case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW:
+ desc = "SAS Init Table Overflow";
+ break;
+ case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+ desc = "SAS Topology Change List";
+ break;
+ case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+ desc = "SAS Enclosure Device Status Change";
+ break;
+ case MPI2_EVENT_IR_VOLUME:
+ desc = "IR Volume";
+ break;
+ case MPI2_EVENT_IR_PHYSICAL_DISK:
+ desc = "IR Physical Disk";
+ break;
+ case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
+ desc = "IR Configuration Change List";
+ break;
+ case MPI2_EVENT_LOG_ENTRY_ADDED:
+ desc = "Log Entry Added";
+ break;
+ }
+
+ if (!desc)
+ return;
+
+ printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, desc);
+}
+#endif
+
+/**
+ * _base_sas_log_info - verbose translation of firmware log info
+ * @ioc: pointer to scsi command object
+ * @log_info: log info
+ *
+ * Return nothing.
+ */
+static void
+_base_sas_log_info(struct MPT2SAS_ADAPTER *ioc , u32 log_info)
+{
+ union loginfo_type {
+ u32 loginfo;
+ struct {
+ u32 subcode:16;
+ u32 code:8;
+ u32 originator:4;
+ u32 bus_type:4;
+ } dw;
+ };
+ union loginfo_type sas_loginfo;
+ char *originator_str = NULL;
+
+ sas_loginfo.loginfo = log_info;
+ if (sas_loginfo.dw.bus_type != 3 /*SAS*/)
+ return;
+
+ /* eat the loginfos associated with task aborts */
+ if (ioc->ignore_loginfos && (log_info == 30050000 || log_info ==
+ 0x31140000 || log_info == 0x31130000))
+ return;
+
+ switch (sas_loginfo.dw.originator) {
+ case 0:
+ originator_str = "IOP";
+ break;
+ case 1:
+ originator_str = "PL";
+ break;
+ case 2:
+ originator_str = "IR";
+ break;
+ }
+
+ printk(MPT2SAS_WARN_FMT "log_info(0x%08x): originator(%s), "
+ "code(0x%02x), sub_code(0x%04x)\n", ioc->name, log_info,
+ originator_str, sas_loginfo.dw.code,
+ sas_loginfo.dw.subcode);
+}
+
+/**
+ * mpt2sas_base_fault_info - verbose translation of firmware FAULT code
+ * @ioc: pointer to scsi command object
+ * @fault_code: fault code
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code)
+{
+ printk(MPT2SAS_ERR_FMT "fault_state(0x%04x)!\n",
+ ioc->name, fault_code);
+}
+
+/**
+ * _base_display_reply_info -
+ * @ioc: pointer to scsi command object
+ * @smid: system request message index
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return nothing.
+ */
+static void
+_base_display_reply_info(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
+ u32 reply)
+{
+ MPI2DefaultReply_t *mpi_reply;
+ u16 ioc_status;
+
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if ((ioc_status & MPI2_IOCSTATUS_MASK) &&
+ (ioc->logging_level & MPT_DEBUG_REPLY)) {
+ _base_sas_ioc_info(ioc , mpi_reply,
+ mpt2sas_base_get_msg_frame(ioc, smid));
+ }
+#endif
+ if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
+ _base_sas_log_info(ioc, le32_to_cpu(mpi_reply->IOCLogInfo));
+}
+
+/**
+ * mpt2sas_base_done - base internal command completion routine
+ * @ioc: pointer to scsi command object
+ * @smid: system request message index
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+{
+ MPI2DefaultReply_t *mpi_reply;
+
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK)
+ return;
+
+ if (ioc->base_cmds.status == MPT2_CMD_NOT_USED)
+ return;
+
+ ioc->base_cmds.status |= MPT2_CMD_COMPLETE;
+ if (mpi_reply) {
+ ioc->base_cmds.status |= MPT2_CMD_REPLY_VALID;
+ memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
+ }
+ ioc->base_cmds.status &= ~MPT2_CMD_PENDING;
+ complete(&ioc->base_cmds.done);
+}
+
+/**
+ * _base_async_event - main callback handler for firmware asyn events
+ * @ioc: pointer to scsi command object
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Return nothing.
+ */
+static void
+_base_async_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
+{
+ Mpi2EventNotificationReply_t *mpi_reply;
+ Mpi2EventAckRequest_t *ack_request;
+ u16 smid;
+
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ if (!mpi_reply)
+ return;
+ if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION)
+ return;
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ _base_display_event_data(ioc, mpi_reply);
+#endif
+ if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED))
+ goto out;
+ smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ goto out;
+ }
+
+ ack_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t));
+ ack_request->Function = MPI2_FUNCTION_EVENT_ACK;
+ ack_request->Event = mpi_reply->Event;
+ ack_request->EventContext = mpi_reply->EventContext;
+ ack_request->VF_ID = VF_ID;
+ mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
+
+ out:
+
+ /* scsih callback handler */
+ mpt2sas_scsih_event_callback(ioc, VF_ID, reply);
+
+ /* ctl callback handler */
+ mpt2sas_ctl_event_callback(ioc, VF_ID, reply);
+}
+
+/**
+ * _base_mask_interrupts - disable interrupts
+ * @ioc: pointer to scsi command object
+ *
+ * Disabling ResetIRQ, Reply and Doorbell Interrupts
+ *
+ * Return nothing.
+ */
+static void
+_base_mask_interrupts(struct MPT2SAS_ADAPTER *ioc)
+{
+ u32 him_register;
+
+ ioc->mask_interrupts = 1;
+ him_register = readl(&ioc->chip->HostInterruptMask);
+ him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK;
+ writel(him_register, &ioc->chip->HostInterruptMask);
+ readl(&ioc->chip->HostInterruptMask);
+}
+
+/**
+ * _base_unmask_interrupts - enable interrupts
+ * @ioc: pointer to scsi command object
+ *
+ * Enabling only Reply Interrupts
+ *
+ * Return nothing.
+ */
+static void
+_base_unmask_interrupts(struct MPT2SAS_ADAPTER *ioc)
+{
+ u32 him_register;
+
+ writel(0, &ioc->chip->HostInterruptStatus);
+ him_register = readl(&ioc->chip->HostInterruptMask);
+ him_register &= ~MPI2_HIM_RIM;
+ writel(him_register, &ioc->chip->HostInterruptMask);
+ ioc->mask_interrupts = 0;
+}
+
+/**
+ * _base_interrupt - MPT adapter (IOC) specific interrupt handler.
+ * @irq: irq number (not used)
+ * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure
+ * @r: pt_regs pointer (not used)
+ *
+ * Return IRQ_HANDLE if processed, else IRQ_NONE.
+ */
+static irqreturn_t
+_base_interrupt(int irq, void *bus_id)
+{
+ u32 post_index, post_index_next, completed_cmds;
+ u8 request_desript_type;
+ u16 smid;
+ u8 cb_idx;
+ u32 reply;
+ u8 VF_ID;
+ int i;
+ struct MPT2SAS_ADAPTER *ioc = bus_id;
+
+ if (ioc->mask_interrupts)
+ return IRQ_NONE;
+
+ post_index = ioc->reply_post_host_index;
+ request_desript_type = ioc->reply_post_free[post_index].
+ Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+ if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+ return IRQ_NONE;
+
+ completed_cmds = 0;
+ do {
+ if (ioc->reply_post_free[post_index].Words == ~0ULL)
+ goto out;
+ reply = 0;
+ cb_idx = 0xFF;
+ smid = le16_to_cpu(ioc->reply_post_free[post_index].
+ Default.DescriptorTypeDependent1);
+ VF_ID = ioc->reply_post_free[post_index].
+ Default.VF_ID;
+ if (request_desript_type ==
+ MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) {
+ reply = le32_to_cpu(ioc->reply_post_free[post_index].
+ AddressReply.ReplyFrameAddress);
+ } else if (request_desript_type ==
+ MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER)
+ goto next;
+ else if (request_desript_type ==
+ MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS)
+ goto next;
+ if (smid)
+ cb_idx = ioc->scsi_lookup[smid - 1].cb_idx;
+ if (smid && cb_idx != 0xFF) {
+ mpt_callbacks[cb_idx](ioc, smid, VF_ID, reply);
+ if (reply)
+ _base_display_reply_info(ioc, smid, VF_ID,
+ reply);
+ mpt2sas_base_free_smid(ioc, smid);
+ }
+ if (!smid)
+ _base_async_event(ioc, VF_ID, reply);
+
+ /* reply free queue handling */
+ if (reply) {
+ ioc->reply_free_host_index =
+ (ioc->reply_free_host_index ==
+ (ioc->reply_free_queue_depth - 1)) ?
+ 0 : ioc->reply_free_host_index + 1;
+ ioc->reply_free[ioc->reply_free_host_index] =
+ cpu_to_le32(reply);
+ writel(ioc->reply_free_host_index,
+ &ioc->chip->ReplyFreeHostIndex);
+ wmb();
+ }
+
+ next:
+ post_index_next = (post_index == (ioc->reply_post_queue_depth -
+ 1)) ? 0 : post_index + 1;
+ request_desript_type =
+ ioc->reply_post_free[post_index_next].Default.ReplyFlags
+ & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK;
+ completed_cmds++;
+ if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED)
+ goto out;
+ post_index = post_index_next;
+ } while (1);
+
+ out:
+
+ if (!completed_cmds)
+ return IRQ_NONE;
+
+ /* reply post descriptor handling */
+ post_index_next = ioc->reply_post_host_index;
+ for (i = 0 ; i < completed_cmds; i++) {
+ post_index = post_index_next;
+ /* poison the reply post descriptor */
+ ioc->reply_post_free[post_index_next].Words = ~0ULL;
+ post_index_next = (post_index ==
+ (ioc->reply_post_queue_depth - 1))
+ ? 0 : post_index + 1;
+ }
+ ioc->reply_post_host_index = post_index_next;
+ writel(post_index_next, &ioc->chip->ReplyPostHostIndex);
+ wmb();
+ return IRQ_HANDLED;
+}
+
+/**
+ * mpt2sas_base_release_callback_handler - clear interupt callback handler
+ * @cb_idx: callback index
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_release_callback_handler(u8 cb_idx)
+{
+ mpt_callbacks[cb_idx] = NULL;
+}
+
+/**
+ * mpt2sas_base_register_callback_handler - obtain index for the interrupt callback handler
+ * @cb_func: callback function
+ *
+ * Returns cb_func.
+ */
+u8
+mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func)
+{
+ u8 cb_idx;
+
+ for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--)
+ if (mpt_callbacks[cb_idx] == NULL)
+ break;
+
+ mpt_callbacks[cb_idx] = cb_func;
+ return cb_idx;
+}
+
+/**
+ * mpt2sas_base_initialize_callback_handler - initialize the interrupt callback handler
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_initialize_callback_handler(void)
+{
+ u8 cb_idx;
+
+ for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++)
+ mpt2sas_base_release_callback_handler(cb_idx);
+}
+
+/**
+ * mpt2sas_base_build_zero_len_sge - build zero length sg entry
+ * @ioc: per adapter object
+ * @paddr: virtual address for SGE
+ *
+ * Create a zero length scatter gather entry to insure the IOCs hardware has
+ * something to use if the target device goes brain dead and tries
+ * to send data even when none is asked for.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr)
+{
+ u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT |
+ MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST |
+ MPI2_SGE_FLAGS_SIMPLE_ELEMENT) <<
+ MPI2_SGE_FLAGS_SHIFT);
+ ioc->base_add_sg_single(paddr, flags_length, -1);
+}
+
+/**
+ * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr.
+ * @paddr: virtual address for SGE
+ * @flags_length: SGE flags and data transfer length
+ * @dma_addr: Physical address
+ *
+ * Return nothing.
+ */
+static void
+_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr)
+{
+ Mpi2SGESimple32_t *sgel = paddr;
+
+ flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING |
+ MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
+ sgel->FlagsLength = cpu_to_le32(flags_length);
+ sgel->Address = cpu_to_le32(dma_addr);
+}
+
+
+/**
+ * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr.
+ * @paddr: virtual address for SGE
+ * @flags_length: SGE flags and data transfer length
+ * @dma_addr: Physical address
+ *
+ * Return nothing.
+ */
+static void
+_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr)
+{
+ Mpi2SGESimple64_t *sgel = paddr;
+
+ flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING |
+ MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT;
+ sgel->FlagsLength = cpu_to_le32(flags_length);
+ sgel->Address = cpu_to_le64(dma_addr);
+}
+
+#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10))
+
+/**
+ * _base_config_dma_addressing - set dma addressing
+ * @ioc: per adapter object
+ * @pdev: PCI device struct
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_config_dma_addressing(struct MPT2SAS_ADAPTER *ioc, struct pci_dev *pdev)
+{
+ struct sysinfo s;
+ char *desc = NULL;
+
+ if (sizeof(dma_addr_t) > 4) {
+ const uint64_t required_mask =
+ dma_get_required_mask(&pdev->dev);
+ if ((required_mask > DMA_32BIT_MASK) && !pci_set_dma_mask(pdev,
+ DMA_64BIT_MASK) && !pci_set_consistent_dma_mask(pdev,
+ DMA_64BIT_MASK)) {
+ ioc->base_add_sg_single = &_base_add_sg_single_64;
+ ioc->sge_size = sizeof(Mpi2SGESimple64_t);
+ desc = "64";
+ goto out;
+ }
+ }
+
+ if (!pci_set_dma_mask(pdev, DMA_32BIT_MASK)
+ && !pci_set_consistent_dma_mask(pdev, DMA_32BIT_MASK)) {
+ ioc->base_add_sg_single = &_base_add_sg_single_32;
+ ioc->sge_size = sizeof(Mpi2SGESimple32_t);
+ desc = "32";
+ } else
+ return -ENODEV;
+
+ out:
+ si_meminfo(&s);
+ printk(MPT2SAS_INFO_FMT "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, "
+ "total mem (%ld kB)\n", ioc->name, desc, convert_to_kb(s.totalram));
+
+ return 0;
+}
+
+/**
+ * _base_save_msix_table - backup msix vector table
+ * @ioc: per adapter object
+ *
+ * This address an errata where diag reset clears out the table
+ */
+static void
+_base_save_msix_table(struct MPT2SAS_ADAPTER *ioc)
+{
+ int i;
+
+ if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
+ return;
+
+ for (i = 0; i < ioc->msix_vector_count; i++)
+ ioc->msix_table_backup[i] = ioc->msix_table[i];
+}
+
+/**
+ * _base_restore_msix_table - this restores the msix vector table
+ * @ioc: per adapter object
+ *
+ */
+static void
+_base_restore_msix_table(struct MPT2SAS_ADAPTER *ioc)
+{
+ int i;
+
+ if (!ioc->msix_enable || ioc->msix_table_backup == NULL)
+ return;
+
+ for (i = 0; i < ioc->msix_vector_count; i++)
+ ioc->msix_table[i] = ioc->msix_table_backup[i];
+}
+
+/**
+ * _base_check_enable_msix - checks MSIX capabable.
+ * @ioc: per adapter object
+ *
+ * Check to see if card is capable of MSIX, and set number
+ * of avaliable msix vectors
+ */
+static int
+_base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
+{
+ int base;
+ u16 message_control;
+ u32 msix_table_offset;
+
+ base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
+ if (!base) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
+ "supported\n", ioc->name));
+ return -EINVAL;
+ }
+
+ /* get msix vector count */
+ pci_read_config_word(ioc->pdev, base + 2, &message_control);
+ ioc->msix_vector_count = (message_control & 0x3FF) + 1;
+
+ /* get msix table */
+ pci_read_config_dword(ioc->pdev, base + 4, &msix_table_offset);
+ msix_table_offset &= 0xFFFFFFF8;
+ ioc->msix_table = (u32 *)((void *)ioc->chip + msix_table_offset);
+
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "msix is supported, "
+ "vector_count(%d), table_offset(0x%08x), table(%p)\n", ioc->name,
+ ioc->msix_vector_count, msix_table_offset, ioc->msix_table));
+ return 0;
+}
+
+/**
+ * _base_disable_msix - disables msix
+ * @ioc: per adapter object
+ *
+ */
+static void
+_base_disable_msix(struct MPT2SAS_ADAPTER *ioc)
+{
+ if (ioc->msix_enable) {
+ pci_disable_msix(ioc->pdev);
+ kfree(ioc->msix_table_backup);
+ ioc->msix_table_backup = NULL;
+ ioc->msix_enable = 0;
+ }
+}
+
+/**
+ * _base_enable_msix - enables msix, failback to io_apic
+ * @ioc: per adapter object
+ *
+ */
+static int
+_base_enable_msix(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct msix_entry entries;
+ int r;
+ u8 try_msix = 0;
+
+ if (msix_disable == -1 || msix_disable == 0)
+ try_msix = 1;
+
+ if (!try_msix)
+ goto try_ioapic;
+
+ if (_base_check_enable_msix(ioc) != 0)
+ goto try_ioapic;
+
+ ioc->msix_table_backup = kcalloc(ioc->msix_vector_count,
+ sizeof(u32), GFP_KERNEL);
+ if (!ioc->msix_table_backup) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "allocation for "
+ "msix_table_backup failed!!!\n", ioc->name));
+ goto try_ioapic;
+ }
+
+ memset(&entries, 0, sizeof(struct msix_entry));
+ r = pci_enable_msix(ioc->pdev, &entries, 1);
+ if (r) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "pci_enable_msix "
+ "failed (r=%d) !!!\n", ioc->name, r));
+ goto try_ioapic;
+ }
+
+ r = request_irq(entries.vector, _base_interrupt, IRQF_SHARED,
+ ioc->name, ioc);
+ if (r) {
+ dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "unable to allocate "
+ "interrupt %d !!!\n", ioc->name, entries.vector));
+ pci_disable_msix(ioc->pdev);
+ goto try_ioapic;
+ }
+
+ ioc->pci_irq = entries.vector;
+ ioc->msix_enable = 1;
+ return 0;
+
+/* failback to io_apic interrupt routing */
+ try_ioapic:
+
+ r = request_irq(ioc->pdev->irq, _base_interrupt, IRQF_SHARED,
+ ioc->name, ioc);
+ if (r) {
+ printk(MPT2SAS_ERR_FMT "unable to allocate interrupt %d!\n",
+ ioc->name, ioc->pdev->irq);
+ r = -EBUSY;
+ goto out_fail;
+ }
+
+ ioc->pci_irq = ioc->pdev->irq;
+ return 0;
+
+ out_fail:
+ return r;
+}
+
+/**
+ * mpt2sas_base_map_resources - map in controller resources (io/irq/memap)
+ * @ioc: per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct pci_dev *pdev = ioc->pdev;
+ u32 memap_sz;
+ u32 pio_sz;
+ int i, r = 0;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n",
+ ioc->name, __func__));
+
+ ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM);
+ if (pci_enable_device_mem(pdev)) {
+ printk(MPT2SAS_WARN_FMT "pci_enable_device_mem: "
+ "failed\n", ioc->name);
+ return -ENODEV;
+ }
+
+
+ if (pci_request_selected_regions(pdev, ioc->bars,
+ MPT2SAS_DRIVER_NAME)) {
+ printk(MPT2SAS_WARN_FMT "pci_request_selected_regions: "
+ "failed\n", ioc->name);
+ r = -ENODEV;
+ goto out_fail;
+ }
+
+ pci_set_master(pdev);
+
+ if (_base_config_dma_addressing(ioc, pdev) != 0) {
+ printk(MPT2SAS_WARN_FMT "no suitable DMA mask for %s\n",
+ ioc->name, pci_name(pdev));
+ r = -ENODEV;
+ goto out_fail;
+ }
+
+ for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) {
+ if (pci_resource_flags(pdev, i) & PCI_BASE_ADDRESS_SPACE_IO) {
+ if (pio_sz)
+ continue;
+ ioc->pio_chip = pci_resource_start(pdev, i);
+ pio_sz = pci_resource_len(pdev, i);
+ } else {
+ if (memap_sz)
+ continue;
+ ioc->chip_phys = pci_resource_start(pdev, i);
+ memap_sz = pci_resource_len(pdev, i);
+ ioc->chip = ioremap(ioc->chip_phys, memap_sz);
+ if (ioc->chip == NULL) {
+ printk(MPT2SAS_ERR_FMT "unable to map adapter "
+ "memory!\n", ioc->name);
+ r = -EINVAL;
+ goto out_fail;
+ }
+ }
+ }
+
+ pci_set_drvdata(pdev, ioc->shost);
+ _base_mask_interrupts(ioc);
+ r = _base_enable_msix(ioc);
+ if (r)
+ goto out_fail;
+
+ printk(MPT2SAS_INFO_FMT "%s: IRQ %d\n",
+ ioc->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" :
+ "IO-APIC enabled"), ioc->pci_irq);
+ printk(MPT2SAS_INFO_FMT "iomem(0x%lx), mapped(0x%p), size(%d)\n",
+ ioc->name, ioc->chip_phys, ioc->chip, memap_sz);
+ printk(MPT2SAS_INFO_FMT "ioport(0x%lx), size(%d)\n",
+ ioc->name, ioc->pio_chip, pio_sz);
+
+ return 0;
+
+ out_fail:
+ if (ioc->chip_phys)
+ iounmap(ioc->chip);
+ ioc->chip_phys = 0;
+ ioc->pci_irq = -1;
+ pci_release_selected_regions(ioc->pdev, ioc->bars);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ return r;
+}
+
+/**
+ * mpt2sas_base_get_msg_frame_dma - obtain request mf pointer phys addr
+ * @ioc: per adapter object
+ * @smid: system request message index(smid zero is invalid)
+ *
+ * Returns phys pointer to message frame.
+ */
+dma_addr_t
+mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ return ioc->request_dma + (smid * ioc->request_sz);
+}
+
+/**
+ * mpt2sas_base_get_msg_frame - obtain request mf pointer
+ * @ioc: per adapter object
+ * @smid: system request message index(smid zero is invalid)
+ *
+ * Returns virt pointer to message frame.
+ */
+void *
+mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ return (void *)(ioc->request + (smid * ioc->request_sz));
+}
+
+/**
+ * mpt2sas_base_get_sense_buffer - obtain a sense buffer assigned to a mf request
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns virt pointer to sense buffer.
+ */
+void *
+mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE));
+}
+
+/**
+ * mpt2sas_base_get_sense_buffer_dma - obtain a sense buffer assigned to a mf request
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns phys pointer to sense buffer.
+ */
+dma_addr_t
+mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ return ioc->sense_dma + ((smid - 1) * SCSI_SENSE_BUFFERSIZE);
+}
+
+/**
+ * mpt2sas_base_get_reply_virt_addr - obtain reply frames virt address
+ * @ioc: per adapter object
+ * @phys_addr: lower 32 physical addr of the reply
+ *
+ * Converts 32bit lower physical addr into a virt address.
+ */
+void *
+mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr)
+{
+ if (!phys_addr)
+ return NULL;
+ return ioc->reply + (phys_addr - (u32)ioc->reply_dma);
+}
+
+/**
+ * mpt2sas_base_get_smid - obtain a free smid
+ * @ioc: per adapter object
+ * @cb_idx: callback index
+ *
+ * Returns smid (zero is invalid)
+ */
+u16
+mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx)
+{
+ unsigned long flags;
+ struct request_tracker *request;
+ u16 smid;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ if (list_empty(&ioc->free_list)) {
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ printk(MPT2SAS_ERR_FMT "%s: smid not available\n",
+ ioc->name, __func__);
+ return 0;
+ }
+
+ request = list_entry(ioc->free_list.next,
+ struct request_tracker, tracker_list);
+ request->cb_idx = cb_idx;
+ smid = request->smid;
+ list_del(&request->tracker_list);
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ return smid;
+}
+
+
+/**
+ * mpt2sas_base_free_smid - put smid back on free_list
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ ioc->scsi_lookup[smid - 1].cb_idx = 0xFF;
+ list_add_tail(&ioc->scsi_lookup[smid - 1].tracker_list,
+ &ioc->free_list);
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+ /*
+ * See _wait_for_commands_to_complete() call with regards to this code.
+ */
+ if (ioc->shost_recovery && ioc->pending_io_count) {
+ if (ioc->pending_io_count == 1)
+ wake_up(&ioc->reset_wq);
+ ioc->pending_io_count--;
+ }
+}
+
+/**
+ * _base_writeq - 64 bit write to MMIO
+ * @ioc: per adapter object
+ * @b: data payload
+ * @addr: address in MMIO space
+ * @writeq_lock: spin lock
+ *
+ * Glue for handling an atomic 64 bit word to MMIO. This special handling takes
+ * care of 32 bit environment where its not quarenteed to send the entire word
+ * in one transfer.
+ */
+#ifndef writeq
+static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
+ spinlock_t *writeq_lock)
+{
+ unsigned long flags;
+ __u64 data_out = cpu_to_le64(b);
+
+ spin_lock_irqsave(writeq_lock, flags);
+ writel((u32)(data_out), addr);
+ writel((u32)(data_out >> 32), (addr + 4));
+ spin_unlock_irqrestore(writeq_lock, flags);
+}
+#else
+static inline void _base_writeq(__u64 b, volatile void __iomem *addr,
+ spinlock_t *writeq_lock)
+{
+ writeq(cpu_to_le64(b), addr);
+}
+#endif
+
+/**
+ * mpt2sas_base_put_smid_scsi_io - send SCSI_IO request to firmware
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @vf_id: virtual function id
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id,
+ u16 handle)
+{
+ Mpi2RequestDescriptorUnion_t descriptor;
+ u64 *request = (u64 *)&descriptor;
+
+
+ descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO;
+ descriptor.SCSIIO.VF_ID = vf_id;
+ descriptor.SCSIIO.SMID = cpu_to_le16(smid);
+ descriptor.SCSIIO.DevHandle = cpu_to_le16(handle);
+ descriptor.SCSIIO.LMID = 0;
+ _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
+ &ioc->scsi_lookup_lock);
+}
+
+
+/**
+ * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @vf_id: virtual function id
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+ u8 vf_id)
+{
+ Mpi2RequestDescriptorUnion_t descriptor;
+ u64 *request = (u64 *)&descriptor;
+
+ descriptor.HighPriority.RequestFlags =
+ MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY;
+ descriptor.HighPriority.VF_ID = vf_id;
+ descriptor.HighPriority.SMID = cpu_to_le16(smid);
+ descriptor.HighPriority.LMID = 0;
+ descriptor.HighPriority.Reserved1 = 0;
+ _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
+ &ioc->scsi_lookup_lock);
+}
+
+/**
+ * mpt2sas_base_put_smid_default - Default, primarily used for config pages
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @vf_id: virtual function id
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id)
+{
+ Mpi2RequestDescriptorUnion_t descriptor;
+ u64 *request = (u64 *)&descriptor;
+
+ descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE;
+ descriptor.Default.VF_ID = vf_id;
+ descriptor.Default.SMID = cpu_to_le16(smid);
+ descriptor.Default.LMID = 0;
+ descriptor.Default.DescriptorTypeDependent = 0;
+ _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
+ &ioc->scsi_lookup_lock);
+}
+
+/**
+ * mpt2sas_base_put_smid_target_assist - send Target Assist/Status to firmware
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @vf_id: virtual function id
+ * @io_index: value used to track the IO
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+ u8 vf_id, u16 io_index)
+{
+ Mpi2RequestDescriptorUnion_t descriptor;
+ u64 *request = (u64 *)&descriptor;
+
+ descriptor.SCSITarget.RequestFlags =
+ MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET;
+ descriptor.SCSITarget.VF_ID = vf_id;
+ descriptor.SCSITarget.SMID = cpu_to_le16(smid);
+ descriptor.SCSITarget.LMID = 0;
+ descriptor.SCSITarget.IoIndex = cpu_to_le16(io_index);
+ _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow,
+ &ioc->scsi_lookup_lock);
+}
+
+/**
+ * _base_display_ioc_capabilities - Disply IOC's capabilities.
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_display_ioc_capabilities(struct MPT2SAS_ADAPTER *ioc)
+{
+ int i = 0;
+ char desc[16];
+ u8 revision;
+ u32 iounit_pg1_flags;
+
+ pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
+ strncpy(desc, ioc->manu_pg0.ChipName, 16);
+ printk(MPT2SAS_INFO_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "
+ "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n",
+ ioc->name, desc,
+ (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
+ (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
+ (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
+ ioc->facts.FWVersion.Word & 0x000000FF,
+ revision,
+ (ioc->bios_pg3.BiosVersion & 0xFF000000) >> 24,
+ (ioc->bios_pg3.BiosVersion & 0x00FF0000) >> 16,
+ (ioc->bios_pg3.BiosVersion & 0x0000FF00) >> 8,
+ ioc->bios_pg3.BiosVersion & 0x000000FF);
+
+ printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
+
+ if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) {
+ printk("Initiator");
+ i++;
+ }
+
+ if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) {
+ printk("%sTarget", i ? "," : "");
+ i++;
+ }
+
+ i = 0;
+ printk("), ");
+ printk("Capabilities=(");
+
+ if (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) {
+ printk("Raid");
+ i++;
+ }
+
+ if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) {
+ printk("%sTLR", i ? "," : "");
+ i++;
+ }
+
+ if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) {
+ printk("%sMulticast", i ? "," : "");
+ i++;
+ }
+
+ if (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) {
+ printk("%sBIDI Target", i ? "," : "");
+ i++;
+ }
+
+ if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) {
+ printk("%sEEDP", i ? "," : "");
+ i++;
+ }
+
+ if (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) {
+ printk("%sSnapshot Buffer", i ? "," : "");
+ i++;
+ }
+
+ if (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) {
+ printk("%sDiag Trace Buffer", i ? "," : "");
+ i++;
+ }
+
+ if (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) {
+ printk("%sTask Set Full", i ? "," : "");
+ i++;
+ }
+
+ iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
+ if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) {
+ printk("%sNCQ", i ? "," : "");
+ i++;
+ }
+
+ printk(")\n");
+}
+
+/**
+ * _base_static_config_pages - static start of day config pages
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_static_config_pages(struct MPT2SAS_ADAPTER *ioc)
+{
+ Mpi2ConfigReply_t mpi_reply;
+ u32 iounit_pg1_flags;
+
+ mpt2sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0);
+ mpt2sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2);
+ mpt2sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3);
+ mpt2sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8);
+ mpt2sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0);
+ mpt2sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1);
+ _base_display_ioc_capabilities(ioc);
+
+ /*
+ * Enable task_set_full handling in iounit_pg1 when the
+ * facts capabilities indicate that its supported.
+ */
+ iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags);
+ if ((ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING))
+ iounit_pg1_flags &=
+ ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
+ else
+ iounit_pg1_flags |=
+ MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING;
+ ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags);
+ mpt2sas_config_set_iounit_pg1(ioc, &mpi_reply, ioc->iounit_pg1);
+}
+
+/**
+ * _base_release_memory_pools - release memory
+ * @ioc: per adapter object
+ *
+ * Free memory allocated from _base_allocate_memory_pools.
+ *
+ * Return nothing.
+ */
+static void
+_base_release_memory_pools(struct MPT2SAS_ADAPTER *ioc)
+{
+ dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ if (ioc->request) {
+ pci_free_consistent(ioc->pdev, ioc->request_dma_sz,
+ ioc->request, ioc->request_dma);
+ dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "request_pool(0x%p)"
+ ": free\n", ioc->name, ioc->request));
+ ioc->request = NULL;
+ }
+
+ if (ioc->sense) {
+ pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma);
+ if (ioc->sense_dma_pool)
+ pci_pool_destroy(ioc->sense_dma_pool);
+ dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_pool(0x%p)"
+ ": free\n", ioc->name, ioc->sense));
+ ioc->sense = NULL;
+ }
+
+ if (ioc->reply) {
+ pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma);
+ if (ioc->reply_dma_pool)
+ pci_pool_destroy(ioc->reply_dma_pool);
+ dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_pool(0x%p)"
+ ": free\n", ioc->name, ioc->reply));
+ ioc->reply = NULL;
+ }
+
+ if (ioc->reply_free) {
+ pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free,
+ ioc->reply_free_dma);
+ if (ioc->reply_free_dma_pool)
+ pci_pool_destroy(ioc->reply_free_dma_pool);
+ dexitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_pool"
+ "(0x%p): free\n", ioc->name, ioc->reply_free));
+ ioc->reply_free = NULL;
+ }
+
+ if (ioc->reply_post_free) {
+ pci_pool_free(ioc->reply_post_free_dma_pool,
+ ioc->reply_post_free, ioc->reply_post_free_dma);
+ if (ioc->reply_post_free_dma_pool)
+ pci_pool_destroy(ioc->reply_post_free_dma_pool);
+ dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "reply_post_free_pool(0x%p): free\n", ioc->name,
+ ioc->reply_post_free));
+ ioc->reply_post_free = NULL;
+ }
+
+ if (ioc->config_page) {
+ dexitprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "config_page(0x%p): free\n", ioc->name,
+ ioc->config_page));
+ pci_free_consistent(ioc->pdev, ioc->config_page_sz,
+ ioc->config_page, ioc->config_page_dma);
+ }
+
+ kfree(ioc->scsi_lookup);
+}
+
+
+/**
+ * _base_allocate_memory_pools - allocate start of day memory pools
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 success, anything else error
+ */
+static int
+_base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
+{
+ Mpi2IOCFactsReply_t *facts;
+ u32 queue_size, queue_diff;
+ u16 max_sge_elements;
+ u16 num_of_reply_frames;
+ u16 chains_needed_per_io;
+ u32 sz, total_sz;
+ u16 i;
+ u32 retry_sz;
+ u16 max_request_credit;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ retry_sz = 0;
+ facts = &ioc->facts;
+
+ /* command line tunables for max sgl entries */
+ if (max_sgl_entries != -1) {
+ ioc->shost->sg_tablesize = (max_sgl_entries <
+ MPT2SAS_SG_DEPTH) ? max_sgl_entries :
+ MPT2SAS_SG_DEPTH;
+ } else {
+ ioc->shost->sg_tablesize = MPT2SAS_SG_DEPTH;
+ }
+
+ /* command line tunables for max controller queue depth */
+ if (max_queue_depth != -1) {
+ max_request_credit = (max_queue_depth < facts->RequestCredit)
+ ? max_queue_depth : facts->RequestCredit;
+ } else {
+ max_request_credit = (facts->RequestCredit >
+ MPT2SAS_MAX_REQUEST_QUEUE) ? MPT2SAS_MAX_REQUEST_QUEUE :
+ facts->RequestCredit;
+ }
+ ioc->request_depth = max_request_credit;
+
+ /* request frame size */
+ ioc->request_sz = facts->IOCRequestFrameSize * 4;
+
+ /* reply frame size */
+ ioc->reply_sz = facts->ReplyFrameSize * 4;
+
+ retry_allocation:
+ total_sz = 0;
+ /* calculate number of sg elements left over in the 1st frame */
+ max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) -
+ sizeof(Mpi2SGEIOUnion_t)) + ioc->sge_size);
+ ioc->max_sges_in_main_message = max_sge_elements/ioc->sge_size;
+
+ /* now do the same for a chain buffer */
+ max_sge_elements = ioc->request_sz - ioc->sge_size;
+ ioc->max_sges_in_chain_message = max_sge_elements/ioc->sge_size;
+
+ ioc->chain_offset_value_for_main_message =
+ ((sizeof(Mpi2SCSIIORequest_t) - sizeof(Mpi2SGEIOUnion_t)) +
+ (ioc->max_sges_in_chain_message * ioc->sge_size)) / 4;
+
+ /*
+ * MPT2SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE
+ */
+ chains_needed_per_io = ((ioc->shost->sg_tablesize -
+ ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message)
+ + 1;
+ if (chains_needed_per_io > facts->MaxChainDepth) {
+ chains_needed_per_io = facts->MaxChainDepth;
+ ioc->shost->sg_tablesize = min_t(u16,
+ ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message
+ * chains_needed_per_io), ioc->shost->sg_tablesize);
+ }
+ ioc->chains_needed_per_io = chains_needed_per_io;
+
+ /* reply free queue sizing - taking into account for events */
+ num_of_reply_frames = ioc->request_depth + 32;
+
+ /* number of replies frames can't be a multiple of 16 */
+ /* decrease number of reply frames by 1 */
+ if (!(num_of_reply_frames % 16))
+ num_of_reply_frames--;
+
+ /* calculate number of reply free queue entries
+ * (must be multiple of 16)
+ */
+
+ /* (we know reply_free_queue_depth is not a multiple of 16) */
+ queue_size = num_of_reply_frames;
+ queue_size += 16 - (queue_size % 16);
+ ioc->reply_free_queue_depth = queue_size;
+
+ /* reply descriptor post queue sizing */
+ /* this size should be the number of request frames + number of reply
+ * frames
+ */
+
+ queue_size = ioc->request_depth + num_of_reply_frames + 1;
+ /* round up to 16 byte boundary */
+ if (queue_size % 16)
+ queue_size += 16 - (queue_size % 16);
+
+ /* check against IOC maximum reply post queue depth */
+ if (queue_size > facts->MaxReplyDescriptorPostQueueDepth) {
+ queue_diff = queue_size -
+ facts->MaxReplyDescriptorPostQueueDepth;
+
+ /* round queue_diff up to multiple of 16 */
+ if (queue_diff % 16)
+ queue_diff += 16 - (queue_diff % 16);
+
+ /* adjust request_depth, reply_free_queue_depth,
+ * and queue_size
+ */
+ ioc->request_depth -= queue_diff;
+ ioc->reply_free_queue_depth -= queue_diff;
+ queue_size -= queue_diff;
+ }
+ ioc->reply_post_queue_depth = queue_size;
+
+ /* max scsi host queue depth */
+ ioc->shost->can_queue = ioc->request_depth - INTERNAL_CMDS_COUNT;
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host queue: depth"
+ "(%d)\n", ioc->name, ioc->shost->can_queue));
+
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scatter gather: "
+ "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), "
+ "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message,
+ ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize,
+ ioc->chains_needed_per_io));
+
+ /* contiguous pool for request and chains, 16 byte align, one extra "
+ * "frame for smid=0
+ */
+ ioc->chain_depth = ioc->chains_needed_per_io * ioc->request_depth;
+ sz = ((ioc->request_depth + 1 + ioc->chain_depth) * ioc->request_sz);
+
+ ioc->request_dma_sz = sz;
+ ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma);
+ if (!ioc->request) {
+ printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
+ "failed: req_depth(%d), chains_per_io(%d), frame_sz(%d), "
+ "total(%d kB)\n", ioc->name, ioc->request_depth,
+ ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
+ if (ioc->request_depth < MPT2SAS_SAS_QUEUE_DEPTH)
+ goto out;
+ retry_sz += 64;
+ ioc->request_depth = max_request_credit - retry_sz;
+ goto retry_allocation;
+ }
+
+ if (retry_sz)
+ printk(MPT2SAS_ERR_FMT "request pool: pci_alloc_consistent "
+ "succeed: req_depth(%d), chains_per_io(%d), frame_sz(%d), "
+ "total(%d kb)\n", ioc->name, ioc->request_depth,
+ ioc->chains_needed_per_io, ioc->request_sz, sz/1024);
+
+ ioc->chain = ioc->request + ((ioc->request_depth + 1) *
+ ioc->request_sz);
+ ioc->chain_dma = ioc->request_dma + ((ioc->request_depth + 1) *
+ ioc->request_sz);
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool(0x%p): "
+ "depth(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name,
+ ioc->request, ioc->request_depth, ioc->request_sz,
+ ((ioc->request_depth + 1) * ioc->request_sz)/1024));
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "chain pool(0x%p): depth"
+ "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->chain,
+ ioc->chain_depth, ioc->request_sz, ((ioc->chain_depth *
+ ioc->request_sz))/1024));
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request pool: dma(0x%llx)\n",
+ ioc->name, (unsigned long long) ioc->request_dma));
+ total_sz += sz;
+
+ ioc->scsi_lookup = kcalloc(ioc->request_depth,
+ sizeof(struct request_tracker), GFP_KERNEL);
+ if (!ioc->scsi_lookup) {
+ printk(MPT2SAS_ERR_FMT "scsi_lookup: kcalloc failed\n",
+ ioc->name);
+ goto out;
+ }
+
+ /* initialize some bits */
+ for (i = 0; i < ioc->request_depth; i++)
+ ioc->scsi_lookup[i].smid = i + 1;
+
+ /* sense buffers, 4 byte align */
+ sz = ioc->request_depth * SCSI_SENSE_BUFFERSIZE;
+ ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4,
+ 0);
+ if (!ioc->sense_dma_pool) {
+ printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_create failed\n",
+ ioc->name);
+ goto out;
+ }
+ ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL,
+ &ioc->sense_dma);
+ if (!ioc->sense) {
+ printk(MPT2SAS_ERR_FMT "sense pool: pci_pool_alloc failed\n",
+ ioc->name);
+ goto out;
+ }
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "sense pool(0x%p): depth(%d), element_size(%d), pool_size"
+ "(%d kB)\n", ioc->name, ioc->sense, ioc->request_depth,
+ SCSI_SENSE_BUFFERSIZE, sz/1024));
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "sense_dma(0x%llx)\n",
+ ioc->name, (unsigned long long)ioc->sense_dma));
+ total_sz += sz;
+
+ /* reply pool, 4 byte align */
+ sz = ioc->reply_free_queue_depth * ioc->reply_sz;
+ ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4,
+ 0);
+ if (!ioc->reply_dma_pool) {
+ printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_create failed\n",
+ ioc->name);
+ goto out;
+ }
+ ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL,
+ &ioc->reply_dma);
+ if (!ioc->reply) {
+ printk(MPT2SAS_ERR_FMT "reply pool: pci_pool_alloc failed\n",
+ ioc->name);
+ goto out;
+ }
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply pool(0x%p): depth"
+ "(%d), frame_size(%d), pool_size(%d kB)\n", ioc->name, ioc->reply,
+ ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024));
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_dma(0x%llx)\n",
+ ioc->name, (unsigned long long)ioc->reply_dma));
+ total_sz += sz;
+
+ /* reply free queue, 16 byte align */
+ sz = ioc->reply_free_queue_depth * 4;
+ ioc->reply_free_dma_pool = pci_pool_create("reply_free pool",
+ ioc->pdev, sz, 16, 0);
+ if (!ioc->reply_free_dma_pool) {
+ printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_create "
+ "failed\n", ioc->name);
+ goto out;
+ }
+ ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL,
+ &ioc->reply_free_dma);
+ if (!ioc->reply_free) {
+ printk(MPT2SAS_ERR_FMT "reply_free pool: pci_pool_alloc "
+ "failed\n", ioc->name);
+ goto out;
+ }
+ memset(ioc->reply_free, 0, sz);
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free pool(0x%p): "
+ "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name,
+ ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024));
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_free_dma"
+ "(0x%llx)\n", ioc->name, (unsigned long long)ioc->reply_free_dma));
+ total_sz += sz;
+
+ /* reply post queue, 16 byte align */
+ sz = ioc->reply_post_queue_depth * sizeof(Mpi2DefaultReplyDescriptor_t);
+ ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool",
+ ioc->pdev, sz, 16, 0);
+ if (!ioc->reply_post_free_dma_pool) {
+ printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_create "
+ "failed\n", ioc->name);
+ goto out;
+ }
+ ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool ,
+ GFP_KERNEL, &ioc->reply_post_free_dma);
+ if (!ioc->reply_post_free) {
+ printk(MPT2SAS_ERR_FMT "reply_post_free pool: pci_pool_alloc "
+ "failed\n", ioc->name);
+ goto out;
+ }
+ memset(ioc->reply_post_free, 0, sz);
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply post free pool"
+ "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n",
+ ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8,
+ sz/1024));
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "reply_post_free_dma = "
+ "(0x%llx)\n", ioc->name, (unsigned long long)
+ ioc->reply_post_free_dma));
+ total_sz += sz;
+
+ ioc->config_page_sz = 512;
+ ioc->config_page = pci_alloc_consistent(ioc->pdev,
+ ioc->config_page_sz, &ioc->config_page_dma);
+ if (!ioc->config_page) {
+ printk(MPT2SAS_ERR_FMT "config page: pci_pool_alloc "
+ "failed\n", ioc->name);
+ goto out;
+ }
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config page(0x%p): size"
+ "(%d)\n", ioc->name, ioc->config_page, ioc->config_page_sz));
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "config_page_dma"
+ "(0x%llx)\n", ioc->name, (unsigned long long)ioc->config_page_dma));
+ total_sz += ioc->config_page_sz;
+
+ printk(MPT2SAS_INFO_FMT "Allocated physical memory: size(%d kB)\n",
+ ioc->name, total_sz/1024);
+ printk(MPT2SAS_INFO_FMT "Current Controller Queue Depth(%d), "
+ "Max Controller Queue Depth(%d)\n",
+ ioc->name, ioc->shost->can_queue, facts->RequestCredit);
+ printk(MPT2SAS_INFO_FMT "Scatter Gather Elements per IO(%d)\n",
+ ioc->name, ioc->shost->sg_tablesize);
+ return 0;
+
+ out:
+ _base_release_memory_pools(ioc);
+ return -ENOMEM;
+}
+
+
+/**
+ * mpt2sas_base_get_iocstate - Get the current state of a MPT adapter.
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @cooked: Request raw or cooked IOC state
+ *
+ * Returns all IOC Doorbell register bits if cooked==0, else just the
+ * Doorbell bits in MPI_IOC_STATE_MASK.
+ */
+u32
+mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked)
+{
+ u32 s, sc;
+
+ s = readl(&ioc->chip->Doorbell);
+ sc = s & MPI2_IOC_STATE_MASK;
+ return cooked ? sc : s;
+}
+
+/**
+ * _base_wait_on_iocstate - waiting on a particular ioc state
+ * @ioc_state: controller state { READY, OPERATIONAL, or RESET }
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_wait_on_iocstate(struct MPT2SAS_ADAPTER *ioc, u32 ioc_state, int timeout,
+ int sleep_flag)
+{
+ u32 count, cntdn;
+ u32 current_state;
+
+ count = 0;
+ cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+ do {
+ current_state = mpt2sas_base_get_iocstate(ioc, 1);
+ if (current_state == ioc_state)
+ return 0;
+ if (count && current_state == MPI2_IOC_STATE_FAULT)
+ break;
+ if (sleep_flag == CAN_SLEEP)
+ msleep(1);
+ else
+ udelay(500);
+ count++;
+ } while (--cntdn);
+
+ return current_state;
+}
+
+/**
+ * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by
+ * a write to the doorbell)
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell.
+ */
+static int
+_base_wait_for_doorbell_int(struct MPT2SAS_ADAPTER *ioc, int timeout,
+ int sleep_flag)
+{
+ u32 cntdn, count;
+ u32 int_status;
+
+ count = 0;
+ cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+ do {
+ int_status = readl(&ioc->chip->HostInterruptStatus);
+ if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
+ dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "successfull count(%d), timeout(%d)\n", ioc->name,
+ __func__, count, timeout));
+ return 0;
+ }
+ if (sleep_flag == CAN_SLEEP)
+ msleep(1);
+ else
+ udelay(500);
+ count++;
+ } while (--cntdn);
+
+ printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
+ "int_status(%x)!\n", ioc->name, __func__, count, int_status);
+ return -EFAULT;
+}
+
+/**
+ * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell.
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to
+ * doorbell.
+ */
+static int
+_base_wait_for_doorbell_ack(struct MPT2SAS_ADAPTER *ioc, int timeout,
+ int sleep_flag)
+{
+ u32 cntdn, count;
+ u32 int_status;
+ u32 doorbell;
+
+ count = 0;
+ cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+ do {
+ int_status = readl(&ioc->chip->HostInterruptStatus);
+ if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
+ dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "successfull count(%d), timeout(%d)\n", ioc->name,
+ __func__, count, timeout));
+ return 0;
+ } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
+ doorbell = readl(&ioc->chip->Doorbell);
+ if ((doorbell & MPI2_IOC_STATE_MASK) ==
+ MPI2_IOC_STATE_FAULT) {
+ mpt2sas_base_fault_info(ioc , doorbell);
+ return -EFAULT;
+ }
+ } else if (int_status == 0xFFFFFFFF)
+ goto out;
+
+ if (sleep_flag == CAN_SLEEP)
+ msleep(1);
+ else
+ udelay(500);
+ count++;
+ } while (--cntdn);
+
+ out:
+ printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
+ "int_status(%x)!\n", ioc->name, __func__, count, int_status);
+ return -EFAULT;
+}
+
+/**
+ * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use
+ * @ioc: per adapter object
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+_base_wait_for_doorbell_not_used(struct MPT2SAS_ADAPTER *ioc, int timeout,
+ int sleep_flag)
+{
+ u32 cntdn, count;
+ u32 doorbell_reg;
+
+ count = 0;
+ cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout;
+ do {
+ doorbell_reg = readl(&ioc->chip->Doorbell);
+ if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
+ dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "successfull count(%d), timeout(%d)\n", ioc->name,
+ __func__, count, timeout));
+ return 0;
+ }
+ if (sleep_flag == CAN_SLEEP)
+ msleep(1);
+ else
+ udelay(500);
+ count++;
+ } while (--cntdn);
+
+ printk(MPT2SAS_ERR_FMT "%s: failed due to timeout count(%d), "
+ "doorbell_reg(%x)!\n", ioc->name, __func__, count, doorbell_reg);
+ return -EFAULT;
+}
+
+/**
+ * _base_send_ioc_reset - send doorbell reset
+ * @ioc: per adapter object
+ * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_send_ioc_reset(struct MPT2SAS_ADAPTER *ioc, u8 reset_type, int timeout,
+ int sleep_flag)
+{
+ u32 ioc_state;
+ int r = 0;
+
+ if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) {
+ printk(MPT2SAS_ERR_FMT "%s: unknown reset_type\n",
+ ioc->name, __func__);
+ return -EFAULT;
+ }
+
+ if (!(ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY))
+ return -EFAULT;
+
+ printk(MPT2SAS_INFO_FMT "sending message unit reset !!\n", ioc->name);
+
+ writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT,
+ &ioc->chip->Doorbell);
+ if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) {
+ r = -EFAULT;
+ goto out;
+ }
+ ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY,
+ timeout, sleep_flag);
+ if (ioc_state) {
+ printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
+ " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
+ r = -EFAULT;
+ goto out;
+ }
+ out:
+ printk(MPT2SAS_INFO_FMT "message unit reset: %s\n",
+ ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
+ return r;
+}
+
+/**
+ * _base_handshake_req_reply_wait - send request thru doorbell interface
+ * @ioc: per adapter object
+ * @request_bytes: request length
+ * @request: pointer having request payload
+ * @reply_bytes: reply length
+ * @reply: pointer to reply payload
+ * @timeout: timeout in second
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_handshake_req_reply_wait(struct MPT2SAS_ADAPTER *ioc, int request_bytes,
+ u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag)
+{
+ MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply;
+ int i;
+ u8 failed;
+ u16 dummy;
+ u32 *mfp;
+
+ /* make sure doorbell is not in use */
+ if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
+ printk(MPT2SAS_ERR_FMT "doorbell is in use "
+ " (line=%d)\n", ioc->name, __LINE__);
+ return -EFAULT;
+ }
+
+ /* clear pending doorbell interrupts from previous state changes */
+ if (readl(&ioc->chip->HostInterruptStatus) &
+ MPI2_HIS_IOC2SYS_DB_STATUS)
+ writel(0, &ioc->chip->HostInterruptStatus);
+
+ /* send message to ioc */
+ writel(((MPI2_FUNCTION_HANDSHAKE<<MPI2_DOORBELL_FUNCTION_SHIFT) |
+ ((request_bytes/4)<<MPI2_DOORBELL_ADD_DWORDS_SHIFT)),
+ &ioc->chip->Doorbell);
+
+ if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
+ printk(MPT2SAS_ERR_FMT "doorbell handshake "
+ "int failed (line=%d)\n", ioc->name, __LINE__);
+ return -EFAULT;
+ }
+ writel(0, &ioc->chip->HostInterruptStatus);
+
+ if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) {
+ printk(MPT2SAS_ERR_FMT "doorbell handshake "
+ "ack failed (line=%d)\n", ioc->name, __LINE__);
+ return -EFAULT;
+ }
+
+ /* send message 32-bits at a time */
+ for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) {
+ writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell);
+ if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag)))
+ failed = 1;
+ }
+
+ if (failed) {
+ printk(MPT2SAS_ERR_FMT "doorbell handshake "
+ "sending request failed (line=%d)\n", ioc->name, __LINE__);
+ return -EFAULT;
+ }
+
+ /* now wait for the reply */
+ if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) {
+ printk(MPT2SAS_ERR_FMT "doorbell handshake "
+ "int failed (line=%d)\n", ioc->name, __LINE__);
+ return -EFAULT;
+ }
+
+ /* read the first two 16-bits, it gives the total length of the reply */
+ reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+ & MPI2_DOORBELL_DATA_MASK);
+ writel(0, &ioc->chip->HostInterruptStatus);
+ if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
+ printk(MPT2SAS_ERR_FMT "doorbell handshake "
+ "int failed (line=%d)\n", ioc->name, __LINE__);
+ return -EFAULT;
+ }
+ reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+ & MPI2_DOORBELL_DATA_MASK);
+ writel(0, &ioc->chip->HostInterruptStatus);
+
+ for (i = 2; i < default_reply->MsgLength * 2; i++) {
+ if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) {
+ printk(MPT2SAS_ERR_FMT "doorbell "
+ "handshake int failed (line=%d)\n", ioc->name,
+ __LINE__);
+ return -EFAULT;
+ }
+ if (i >= reply_bytes/2) /* overflow case */
+ dummy = readl(&ioc->chip->Doorbell);
+ else
+ reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell)
+ & MPI2_DOORBELL_DATA_MASK);
+ writel(0, &ioc->chip->HostInterruptStatus);
+ }
+
+ _base_wait_for_doorbell_int(ioc, 5, sleep_flag);
+ if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) {
+ dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "doorbell is in use "
+ " (line=%d)\n", ioc->name, __LINE__));
+ }
+ writel(0, &ioc->chip->HostInterruptStatus);
+
+ if (ioc->logging_level & MPT_DEBUG_INIT) {
+ mfp = (u32 *)reply;
+ printk(KERN_DEBUG "\toffset:data\n");
+ for (i = 0; i < reply_bytes/4; i++)
+ printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4,
+ le32_to_cpu(mfp[i]));
+ }
+ return 0;
+}
+
+/**
+ * mpt2sas_base_sas_iounit_control - send sas iounit control to FW
+ * @ioc: per adapter object
+ * @mpi_reply: the reply payload from FW
+ * @mpi_request: the request payload sent to FW
+ *
+ * The SAS IO Unit Control Request message allows the host to perform low-level
+ * operations, such as resets on the PHYs of the IO Unit, also allows the host
+ * to obtain the IOC assigned device handles for a device if it has other
+ * identifying information about the device, in addition allows the host to
+ * remove IOC resources associated with the device.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2SasIoUnitControlReply_t *mpi_reply,
+ Mpi2SasIoUnitControlRequest_t *mpi_request)
+{
+ u16 smid;
+ u32 ioc_state;
+ unsigned long timeleft;
+ u8 issue_reset;
+ int rc;
+ void *request;
+ u16 wait_state_count;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ mutex_lock(&ioc->base_cmds.mutex);
+
+ if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ wait_state_count = 0;
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ if (wait_state_count++ == 10) {
+ printk(MPT2SAS_ERR_FMT
+ "%s: failed due to ioc not operational\n",
+ ioc->name, __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+ ssleep(1);
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ printk(MPT2SAS_INFO_FMT "%s: waiting for "
+ "operational state(count=%d)\n", ioc->name,
+ __func__, wait_state_count);
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ rc = 0;
+ ioc->base_cmds.status = MPT2_CMD_PENDING;
+ request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->base_cmds.smid = smid;
+ memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t));
+ if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
+ mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET)
+ ioc->ioc_link_reset_in_progress = 1;
+ mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
+ msecs_to_jiffies(10000));
+ if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET ||
+ mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) &&
+ ioc->ioc_link_reset_in_progress)
+ ioc->ioc_link_reset_in_progress = 0;
+ if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n",
+ ioc->name, __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2SasIoUnitControlRequest_t)/4);
+ if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+ if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
+ memcpy(mpi_reply, ioc->base_cmds.reply,
+ sizeof(Mpi2SasIoUnitControlReply_t));
+ else
+ memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t));
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+ goto out;
+
+ issue_host_reset:
+ if (issue_reset)
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+ rc = -EFAULT;
+ out:
+ mutex_unlock(&ioc->base_cmds.mutex);
+ return rc;
+}
+
+
+/**
+ * mpt2sas_base_scsi_enclosure_processor - sending request to sep device
+ * @ioc: per adapter object
+ * @mpi_reply: the reply payload from FW
+ * @mpi_request: the request payload sent to FW
+ *
+ * The SCSI Enclosure Processor request message causes the IOC to
+ * communicate with SES devices to control LED status signals.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request)
+{
+ u16 smid;
+ u32 ioc_state;
+ unsigned long timeleft;
+ u8 issue_reset;
+ int rc;
+ void *request;
+ u16 wait_state_count;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ mutex_lock(&ioc->base_cmds.mutex);
+
+ if (ioc->base_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: base_cmd in use\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ wait_state_count = 0;
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ if (wait_state_count++ == 10) {
+ printk(MPT2SAS_ERR_FMT
+ "%s: failed due to ioc not operational\n",
+ ioc->name, __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+ ssleep(1);
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ printk(MPT2SAS_INFO_FMT "%s: waiting for "
+ "operational state(count=%d)\n", ioc->name,
+ __func__, wait_state_count);
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ rc = 0;
+ ioc->base_cmds.status = MPT2_CMD_PENDING;
+ request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->base_cmds.smid = smid;
+ memcpy(request, mpi_request, sizeof(Mpi2SepReply_t));
+ mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
+ msecs_to_jiffies(10000));
+ if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n",
+ ioc->name, __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2SepRequest_t)/4);
+ if (!(ioc->base_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+ if (ioc->base_cmds.status & MPT2_CMD_REPLY_VALID)
+ memcpy(mpi_reply, ioc->base_cmds.reply,
+ sizeof(Mpi2SepReply_t));
+ else
+ memset(mpi_reply, 0, sizeof(Mpi2SepReply_t));
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+ goto out;
+
+ issue_host_reset:
+ if (issue_reset)
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+ rc = -EFAULT;
+ out:
+ mutex_unlock(&ioc->base_cmds.mutex);
+ return rc;
+}
+
+/**
+ * _base_get_port_facts - obtain port facts reply and save in ioc
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_get_port_facts(struct MPT2SAS_ADAPTER *ioc, int port, int sleep_flag)
+{
+ Mpi2PortFactsRequest_t mpi_request;
+ Mpi2PortFactsReply_t mpi_reply, *pfacts;
+ int mpi_reply_sz, mpi_request_sz, r;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ mpi_reply_sz = sizeof(Mpi2PortFactsReply_t);
+ mpi_request_sz = sizeof(Mpi2PortFactsRequest_t);
+ memset(&mpi_request, 0, mpi_request_sz);
+ mpi_request.Function = MPI2_FUNCTION_PORT_FACTS;
+ mpi_request.PortNumber = port;
+ r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
+ (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
+
+ if (r != 0) {
+ printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
+ ioc->name, __func__, r);
+ return r;
+ }
+
+ pfacts = &ioc->pfacts[port];
+ memset(pfacts, 0, sizeof(Mpi2PortFactsReply_t));
+ pfacts->PortNumber = mpi_reply.PortNumber;
+ pfacts->VP_ID = mpi_reply.VP_ID;
+ pfacts->VF_ID = mpi_reply.VF_ID;
+ pfacts->MaxPostedCmdBuffers =
+ le16_to_cpu(mpi_reply.MaxPostedCmdBuffers);
+
+ return 0;
+}
+
+/**
+ * _base_get_ioc_facts - obtain ioc facts reply and save in ioc
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_get_ioc_facts(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
+{
+ Mpi2IOCFactsRequest_t mpi_request;
+ Mpi2IOCFactsReply_t mpi_reply, *facts;
+ int mpi_reply_sz, mpi_request_sz, r;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t);
+ mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t);
+ memset(&mpi_request, 0, mpi_request_sz);
+ mpi_request.Function = MPI2_FUNCTION_IOC_FACTS;
+ r = _base_handshake_req_reply_wait(ioc, mpi_request_sz,
+ (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP);
+
+ if (r != 0) {
+ printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
+ ioc->name, __func__, r);
+ return r;
+ }
+
+ facts = &ioc->facts;
+ memset(facts, 0, sizeof(Mpi2IOCFactsReply_t));
+ facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion);
+ facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion);
+ facts->VP_ID = mpi_reply.VP_ID;
+ facts->VF_ID = mpi_reply.VF_ID;
+ facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions);
+ facts->MaxChainDepth = mpi_reply.MaxChainDepth;
+ facts->WhoInit = mpi_reply.WhoInit;
+ facts->NumberOfPorts = mpi_reply.NumberOfPorts;
+ facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit);
+ facts->MaxReplyDescriptorPostQueueDepth =
+ le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth);
+ facts->ProductID = le16_to_cpu(mpi_reply.ProductID);
+ facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities);
+ if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
+ ioc->ir_firmware = 1;
+ facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word);
+ facts->IOCRequestFrameSize =
+ le16_to_cpu(mpi_reply.IOCRequestFrameSize);
+ facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators);
+ facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets);
+ ioc->shost->max_id = -1;
+ facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders);
+ facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures);
+ facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags);
+ facts->HighPriorityCredit =
+ le16_to_cpu(mpi_reply.HighPriorityCredit);
+ facts->ReplyFrameSize = mpi_reply.ReplyFrameSize;
+ facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle);
+
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "hba queue depth(%d), "
+ "max chains per io(%d)\n", ioc->name, facts->RequestCredit,
+ facts->MaxChainDepth));
+ dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "request frame size(%d), "
+ "reply frame size(%d)\n", ioc->name,
+ facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4));
+ return 0;
+}
+
+/**
+ * _base_send_ioc_init - send ioc_init to firmware
+ * @ioc: per adapter object
+ * @VF_ID: virtual function id
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_send_ioc_init(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
+{
+ Mpi2IOCInitRequest_t mpi_request;
+ Mpi2IOCInitReply_t mpi_reply;
+ int r;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_IOC_INIT;
+ mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER;
+ mpi_request.VF_ID = VF_ID;
+ mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION);
+ mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION);
+
+ /* In MPI Revision I (0xA), the SystemReplyFrameSize(offset 0x18) was
+ * removed and made reserved. For those with older firmware will need
+ * this fix. It was decided that the Reply and Request frame sizes are
+ * the same.
+ */
+ if ((ioc->facts.HeaderVersion >> 8) < 0xA) {
+ mpi_request.Reserved7 = cpu_to_le16(ioc->reply_sz);
+/* mpi_request.SystemReplyFrameSize =
+ * cpu_to_le16(ioc->reply_sz);
+ */
+ }
+
+ mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4);
+ mpi_request.ReplyDescriptorPostQueueDepth =
+ cpu_to_le16(ioc->reply_post_queue_depth);
+ mpi_request.ReplyFreeQueueDepth =
+ cpu_to_le16(ioc->reply_free_queue_depth);
+
+#if BITS_PER_LONG > 32
+ mpi_request.SenseBufferAddressHigh =
+ cpu_to_le32(ioc->sense_dma >> 32);
+ mpi_request.SystemReplyAddressHigh =
+ cpu_to_le32(ioc->reply_dma >> 32);
+ mpi_request.SystemRequestFrameBaseAddress =
+ cpu_to_le64(ioc->request_dma);
+ mpi_request.ReplyFreeQueueAddress =
+ cpu_to_le64(ioc->reply_free_dma);
+ mpi_request.ReplyDescriptorPostQueueAddress =
+ cpu_to_le64(ioc->reply_post_free_dma);
+#else
+ mpi_request.SystemRequestFrameBaseAddress =
+ cpu_to_le32(ioc->request_dma);
+ mpi_request.ReplyFreeQueueAddress =
+ cpu_to_le32(ioc->reply_free_dma);
+ mpi_request.ReplyDescriptorPostQueueAddress =
+ cpu_to_le32(ioc->reply_post_free_dma);
+#endif
+
+ if (ioc->logging_level & MPT_DEBUG_INIT) {
+ u32 *mfp;
+ int i;
+
+ mfp = (u32 *)&mpi_request;
+ printk(KERN_DEBUG "\toffset:data\n");
+ for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++)
+ printk(KERN_DEBUG "\t[0x%02x]:%08x\n", i*4,
+ le32_to_cpu(mfp[i]));
+ }
+
+ r = _base_handshake_req_reply_wait(ioc,
+ sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request,
+ sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10,
+ sleep_flag);
+
+ if (r != 0) {
+ printk(MPT2SAS_ERR_FMT "%s: handshake failed (r=%d)\n",
+ ioc->name, __func__, r);
+ return r;
+ }
+
+ if (mpi_reply.IOCStatus != MPI2_IOCSTATUS_SUCCESS ||
+ mpi_reply.IOCLogInfo) {
+ printk(MPT2SAS_ERR_FMT "%s: failed\n", ioc->name, __func__);
+ r = -EIO;
+ }
+
+ return 0;
+}
+
+/**
+ * _base_send_port_enable - send port_enable(discovery stuff) to firmware
+ * @ioc: per adapter object
+ * @VF_ID: virtual function id
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_send_port_enable(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
+{
+ Mpi2PortEnableRequest_t *mpi_request;
+ u32 ioc_state;
+ unsigned long timeleft;
+ int r = 0;
+ u16 smid;
+
+ printk(MPT2SAS_INFO_FMT "sending port enable !!\n", ioc->name);
+
+ if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
+ printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
+ ioc->name, __func__);
+ return -EAGAIN;
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ return -EAGAIN;
+ }
+
+ ioc->base_cmds.status = MPT2_CMD_PENDING;
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->base_cmds.smid = smid;
+ memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t));
+ mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE;
+ mpi_request->VF_ID = VF_ID;
+
+ mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->base_cmds.done,
+ 300*HZ);
+ if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n",
+ ioc->name, __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2PortEnableRequest_t)/4);
+ if (ioc->base_cmds.status & MPT2_CMD_RESET)
+ r = -EFAULT;
+ else
+ r = -ETIME;
+ goto out;
+ } else
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n",
+ ioc->name, __func__));
+
+ ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_OPERATIONAL,
+ 60, sleep_flag);
+ if (ioc_state) {
+ printk(MPT2SAS_ERR_FMT "%s: failed going to operational state "
+ " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
+ r = -EFAULT;
+ }
+ out:
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+ printk(MPT2SAS_INFO_FMT "port enable: %s\n",
+ ioc->name, ((r == 0) ? "SUCCESS" : "FAILED"));
+ return r;
+}
+
+/**
+ * _base_unmask_events - turn on notification for this event
+ * @ioc: per adapter object
+ * @event: firmware event
+ *
+ * The mask is stored in ioc->event_masks.
+ */
+static void
+_base_unmask_events(struct MPT2SAS_ADAPTER *ioc, u16 event)
+{
+ u32 desired_event;
+
+ if (event >= 128)
+ return;
+
+ desired_event = (1 << (event % 32));
+
+ if (event < 32)
+ ioc->event_masks[0] &= ~desired_event;
+ else if (event < 64)
+ ioc->event_masks[1] &= ~desired_event;
+ else if (event < 96)
+ ioc->event_masks[2] &= ~desired_event;
+ else if (event < 128)
+ ioc->event_masks[3] &= ~desired_event;
+}
+
+/**
+ * _base_event_notification - send event notification
+ * @ioc: per adapter object
+ * @VF_ID: virtual function id
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_event_notification(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, int sleep_flag)
+{
+ Mpi2EventNotificationRequest_t *mpi_request;
+ unsigned long timeleft;
+ u16 smid;
+ int r = 0;
+ int i;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
+ printk(MPT2SAS_ERR_FMT "%s: internal command already in use\n",
+ ioc->name, __func__);
+ return -EAGAIN;
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->base_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ return -EAGAIN;
+ }
+ ioc->base_cmds.status = MPT2_CMD_PENDING;
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->base_cmds.smid = smid;
+ memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t));
+ mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
+ mpi_request->VF_ID = VF_ID;
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ mpi_request->EventMasks[i] =
+ le32_to_cpu(ioc->event_masks[i]);
+ mpt2sas_base_put_smid_default(ioc, smid, VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ);
+ if (!(ioc->base_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n",
+ ioc->name, __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2EventNotificationRequest_t)/4);
+ if (ioc->base_cmds.status & MPT2_CMD_RESET)
+ r = -EFAULT;
+ else
+ r = -ETIME;
+ } else
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: complete\n",
+ ioc->name, __func__));
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+ return r;
+}
+
+/**
+ * mpt2sas_base_validate_event_type - validating event types
+ * @ioc: per adapter object
+ * @event: firmware event
+ *
+ * This will turn on firmware event notification when application
+ * ask for that event. We don't mask events that are already enabled.
+ */
+void
+mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type)
+{
+ int i, j;
+ u32 event_mask, desired_event;
+ u8 send_update_to_fw;
+
+ for (i = 0, send_update_to_fw = 0; i <
+ MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) {
+ event_mask = ~event_type[i];
+ desired_event = 1;
+ for (j = 0; j < 32; j++) {
+ if (!(event_mask & desired_event) &&
+ (ioc->event_masks[i] & desired_event)) {
+ ioc->event_masks[i] &= ~desired_event;
+ send_update_to_fw = 1;
+ }
+ desired_event = (desired_event << 1);
+ }
+ }
+
+ if (!send_update_to_fw)
+ return;
+
+ mutex_lock(&ioc->base_cmds.mutex);
+ _base_event_notification(ioc, 0, CAN_SLEEP);
+ mutex_unlock(&ioc->base_cmds.mutex);
+}
+
+/**
+ * _base_diag_reset - the "big hammer" start of day reset
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_diag_reset(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
+{
+ u32 host_diagnostic;
+ u32 ioc_state;
+ u32 count;
+ u32 hcb_size;
+
+ printk(MPT2SAS_INFO_FMT "sending diag reset !!\n", ioc->name);
+
+ _base_save_msix_table(ioc);
+
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "clear interrupts\n",
+ ioc->name));
+ writel(0, &ioc->chip->HostInterruptStatus);
+
+ count = 0;
+ do {
+ /* Write magic sequence to WriteSequence register
+ * Loop until in diagnostic mode
+ */
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "write magic "
+ "sequence\n", ioc->name));
+ writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
+ writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence);
+ writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence);
+ writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence);
+ writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence);
+ writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence);
+ writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence);
+
+ /* wait 100 msec */
+ if (sleep_flag == CAN_SLEEP)
+ msleep(100);
+ else
+ mdelay(100);
+
+ if (count++ > 20)
+ goto out;
+
+ host_diagnostic = readl(&ioc->chip->HostDiagnostic);
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "wrote magic "
+ "sequence: count(%d), host_diagnostic(0x%08x)\n",
+ ioc->name, count, host_diagnostic));
+
+ } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0);
+
+ hcb_size = readl(&ioc->chip->HCBSize);
+
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "diag reset: issued\n",
+ ioc->name));
+ writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER,
+ &ioc->chip->HostDiagnostic);
+
+ /* don't access any registers for 50 milliseconds */
+ msleep(50);
+
+ /* 300 second max wait */
+ for (count = 0; count < 3000000 ; count++) {
+
+ host_diagnostic = readl(&ioc->chip->HostDiagnostic);
+
+ if (host_diagnostic == 0xFFFFFFFF)
+ goto out;
+ if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER))
+ break;
+
+ /* wait 100 msec */
+ if (sleep_flag == CAN_SLEEP)
+ msleep(1);
+ else
+ mdelay(1);
+ }
+
+ if (host_diagnostic & MPI2_DIAG_HCB_MODE) {
+
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter "
+ "assuming the HCB Address points to good F/W\n",
+ ioc->name));
+ host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK;
+ host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW;
+ writel(host_diagnostic, &ioc->chip->HostDiagnostic);
+
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "re-enable the HCDW\n", ioc->name));
+ writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE,
+ &ioc->chip->HCBSize);
+ }
+
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "restart the adapter\n",
+ ioc->name));
+ writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET,
+ &ioc->chip->HostDiagnostic);
+
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "disable writes to the "
+ "diagnostic register\n", ioc->name));
+ writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence);
+
+ drsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "Wait for FW to go to the "
+ "READY state\n", ioc->name));
+ ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20,
+ sleep_flag);
+ if (ioc_state) {
+ printk(MPT2SAS_ERR_FMT "%s: failed going to ready state "
+ " (ioc_state=0x%x)\n", ioc->name, __func__, ioc_state);
+ goto out;
+ }
+
+ _base_restore_msix_table(ioc);
+ printk(MPT2SAS_INFO_FMT "diag reset: SUCCESS\n", ioc->name);
+ return 0;
+
+ out:
+ printk(MPT2SAS_ERR_FMT "diag reset: FAILED\n", ioc->name);
+ return -EFAULT;
+}
+
+/**
+ * _base_make_ioc_ready - put controller in READY state
+ * @ioc: per adapter object
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ * @type: FORCE_BIG_HAMMER or SOFT_RESET
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_make_ioc_ready(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
+ enum reset_type type)
+{
+ u32 ioc_state;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
+ dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: ioc_state(0x%08x)\n",
+ ioc->name, __func__, ioc_state));
+
+ if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY)
+ return 0;
+
+ if (ioc_state & MPI2_DOORBELL_USED) {
+ dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell "
+ "active!\n", ioc->name));
+ goto issue_diag_reset;
+ }
+
+ if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+ mpt2sas_base_fault_info(ioc, ioc_state &
+ MPI2_DOORBELL_DATA_MASK);
+ goto issue_diag_reset;
+ }
+
+ if (type == FORCE_BIG_HAMMER)
+ goto issue_diag_reset;
+
+ if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL)
+ if (!(_base_send_ioc_reset(ioc,
+ MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP)))
+ return 0;
+
+ issue_diag_reset:
+ return _base_diag_reset(ioc, CAN_SLEEP);
+}
+
+/**
+ * _base_make_ioc_operational - put controller in OPERATIONAL state
+ * @ioc: per adapter object
+ * @VF_ID: virtual function id
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_base_make_ioc_operational(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ int sleep_flag)
+{
+ int r, i;
+ unsigned long flags;
+ u32 reply_address;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ /* initialize the scsi lookup free list */
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ INIT_LIST_HEAD(&ioc->free_list);
+ for (i = 0; i < ioc->request_depth; i++) {
+ ioc->scsi_lookup[i].cb_idx = 0xFF;
+ list_add_tail(&ioc->scsi_lookup[i].tracker_list,
+ &ioc->free_list);
+ }
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+ /* initialize Reply Free Queue */
+ for (i = 0, reply_address = (u32)ioc->reply_dma ;
+ i < ioc->reply_free_queue_depth ; i++, reply_address +=
+ ioc->reply_sz)
+ ioc->reply_free[i] = cpu_to_le32(reply_address);
+
+ /* initialize Reply Post Free Queue */
+ for (i = 0; i < ioc->reply_post_queue_depth; i++)
+ ioc->reply_post_free[i].Words = ~0ULL;
+
+ r = _base_send_ioc_init(ioc, VF_ID, sleep_flag);
+ if (r)
+ return r;
+
+ /* initialize the index's */
+ ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1;
+ ioc->reply_post_host_index = 0;
+ writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex);
+ writel(0, &ioc->chip->ReplyPostHostIndex);
+
+ _base_unmask_interrupts(ioc);
+ r = _base_event_notification(ioc, VF_ID, sleep_flag);
+ if (r)
+ return r;
+
+ if (sleep_flag == CAN_SLEEP)
+ _base_static_config_pages(ioc);
+
+ r = _base_send_port_enable(ioc, VF_ID, sleep_flag);
+ if (r)
+ return r;
+
+ return r;
+}
+
+/**
+ * mpt2sas_base_free_resources - free resources controller resources (io/irq/memap)
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct pci_dev *pdev = ioc->pdev;
+
+ dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ _base_mask_interrupts(ioc);
+ _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
+ if (ioc->pci_irq) {
+ synchronize_irq(pdev->irq);
+ free_irq(ioc->pci_irq, ioc);
+ }
+ _base_disable_msix(ioc);
+ if (ioc->chip_phys)
+ iounmap(ioc->chip);
+ ioc->pci_irq = -1;
+ ioc->chip_phys = 0;
+ pci_release_selected_regions(ioc->pdev, ioc->bars);
+ pci_disable_device(pdev);
+ pci_set_drvdata(pdev, NULL);
+ return;
+}
+
+/**
+ * mpt2sas_base_attach - attach controller instance
+ * @ioc: per adapter object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc)
+{
+ int r, i;
+ unsigned long flags;
+
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ r = mpt2sas_base_map_resources(ioc);
+ if (r)
+ return r;
+
+ r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET);
+ if (r)
+ goto out_free_resources;
+
+ r = _base_get_ioc_facts(ioc, CAN_SLEEP);
+ if (r)
+ goto out_free_resources;
+
+ r = _base_allocate_memory_pools(ioc, CAN_SLEEP);
+ if (r)
+ goto out_free_resources;
+
+ init_waitqueue_head(&ioc->reset_wq);
+
+ /* base internal command bits */
+ mutex_init(&ioc->base_cmds.mutex);
+ init_completion(&ioc->base_cmds.done);
+ ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+ ioc->base_cmds.status = MPT2_CMD_NOT_USED;
+
+ /* transport internal command bits */
+ ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+ ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_init(&ioc->transport_cmds.mutex);
+ init_completion(&ioc->transport_cmds.done);
+
+ /* task management internal command bits */
+ ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_init(&ioc->tm_cmds.mutex);
+ init_completion(&ioc->tm_cmds.done);
+
+ /* config page internal command bits */
+ ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+ ioc->config_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_init(&ioc->config_cmds.mutex);
+ init_completion(&ioc->config_cmds.done);
+
+ /* ctl module internal command bits */
+ ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL);
+ ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_init(&ioc->ctl_cmds.mutex);
+ init_completion(&ioc->ctl_cmds.done);
+
+ for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++)
+ ioc->event_masks[i] = -1;
+
+ /* here we enable the events we care about */
+ _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY);
+ _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE);
+ _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
+ _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
+ _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
+ _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST);
+ _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME);
+ _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK);
+ _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS);
+ _base_unmask_events(ioc, MPI2_EVENT_TASK_SET_FULL);
+ _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED);
+
+ ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts,
+ sizeof(Mpi2PortFactsReply_t), GFP_KERNEL);
+ if (!ioc->pfacts)
+ goto out_free_resources;
+
+ for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) {
+ r = _base_get_port_facts(ioc, i, CAN_SLEEP);
+ if (r)
+ goto out_free_resources;
+ }
+ r = _base_make_ioc_operational(ioc, 0, CAN_SLEEP);
+ if (r)
+ goto out_free_resources;
+
+ /* initialize fault polling */
+ INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work);
+ snprintf(ioc->fault_reset_work_q_name,
+ sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id);
+ ioc->fault_reset_work_q =
+ create_singlethread_workqueue(ioc->fault_reset_work_q_name);
+ if (!ioc->fault_reset_work_q) {
+ printk(MPT2SAS_ERR_FMT "%s: failed (line=%d)\n",
+ ioc->name, __func__, __LINE__);
+ goto out_free_resources;
+ }
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->fault_reset_work_q)
+ queue_delayed_work(ioc->fault_reset_work_q,
+ &ioc->fault_reset_work,
+ msecs_to_jiffies(FAULT_POLLING_INTERVAL));
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ return 0;
+
+ out_free_resources:
+
+ ioc->remove_host = 1;
+ mpt2sas_base_free_resources(ioc);
+ _base_release_memory_pools(ioc);
+ kfree(ioc->tm_cmds.reply);
+ kfree(ioc->transport_cmds.reply);
+ kfree(ioc->config_cmds.reply);
+ kfree(ioc->base_cmds.reply);
+ kfree(ioc->ctl_cmds.reply);
+ kfree(ioc->pfacts);
+ ioc->ctl_cmds.reply = NULL;
+ ioc->base_cmds.reply = NULL;
+ ioc->tm_cmds.reply = NULL;
+ ioc->transport_cmds.reply = NULL;
+ ioc->config_cmds.reply = NULL;
+ ioc->pfacts = NULL;
+ return r;
+}
+
+
+/**
+ * mpt2sas_base_detach - remove controller instance
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc)
+{
+ unsigned long flags;
+ struct workqueue_struct *wq;
+
+ dexitprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ wq = ioc->fault_reset_work_q;
+ ioc->fault_reset_work_q = NULL;
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ if (!cancel_delayed_work(&ioc->fault_reset_work))
+ flush_workqueue(wq);
+ destroy_workqueue(wq);
+
+ mpt2sas_base_free_resources(ioc);
+ _base_release_memory_pools(ioc);
+ kfree(ioc->pfacts);
+ kfree(ioc->ctl_cmds.reply);
+ kfree(ioc->base_cmds.reply);
+ kfree(ioc->tm_cmds.reply);
+ kfree(ioc->transport_cmds.reply);
+ kfree(ioc->config_cmds.reply);
+}
+
+/**
+ * _base_reset_handler - reset callback handler (for base)
+ * @ioc: per adapter object
+ * @reset_phase: phase
+ *
+ * The handler for doing any required cleanup or initialization.
+ *
+ * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
+ * MPT2_IOC_DONE_RESET
+ *
+ * Return nothing.
+ */
+static void
+_base_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
+{
+ switch (reset_phase) {
+ case MPT2_IOC_PRE_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
+ break;
+ case MPT2_IOC_AFTER_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
+ if (ioc->transport_cmds.status & MPT2_CMD_PENDING) {
+ ioc->transport_cmds.status |= MPT2_CMD_RESET;
+ mpt2sas_base_free_smid(ioc, ioc->transport_cmds.smid);
+ complete(&ioc->transport_cmds.done);
+ }
+ if (ioc->base_cmds.status & MPT2_CMD_PENDING) {
+ ioc->base_cmds.status |= MPT2_CMD_RESET;
+ mpt2sas_base_free_smid(ioc, ioc->base_cmds.smid);
+ complete(&ioc->base_cmds.done);
+ }
+ if (ioc->config_cmds.status & MPT2_CMD_PENDING) {
+ ioc->config_cmds.status |= MPT2_CMD_RESET;
+ mpt2sas_base_free_smid(ioc, ioc->config_cmds.smid);
+ complete(&ioc->config_cmds.done);
+ }
+ break;
+ case MPT2_IOC_DONE_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
+ break;
+ }
+ mpt2sas_scsih_reset_handler(ioc, reset_phase);
+ mpt2sas_ctl_reset_handler(ioc, reset_phase);
+}
+
+/**
+ * _wait_for_commands_to_complete - reset controller
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ *
+ * This function waiting(3s) for all pending commands to complete
+ * prior to putting controller in reset.
+ */
+static void
+_wait_for_commands_to_complete(struct MPT2SAS_ADAPTER *ioc, int sleep_flag)
+{
+ u32 ioc_state;
+ unsigned long flags;
+ u16 i;
+
+ ioc->pending_io_count = 0;
+ if (sleep_flag != CAN_SLEEP)
+ return;
+
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
+ if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL)
+ return;
+
+ /* pending command count */
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ for (i = 0; i < ioc->request_depth; i++)
+ if (ioc->scsi_lookup[i].cb_idx != 0xFF)
+ ioc->pending_io_count++;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+ if (!ioc->pending_io_count)
+ return;
+
+ /* wait for pending commands to complete */
+ wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 3 * HZ);
+}
+
+/**
+ * mpt2sas_base_hard_reset_handler - reset controller
+ * @ioc: Pointer to MPT_ADAPTER structure
+ * @sleep_flag: CAN_SLEEP or NO_SLEEP
+ * @type: FORCE_BIG_HAMMER or SOFT_RESET
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
+ enum reset_type type)
+{
+ int r, i;
+ unsigned long flags;
+
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+ __func__));
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->ioc_reset_in_progress) {
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ printk(MPT2SAS_ERR_FMT "%s: busy\n",
+ ioc->name, __func__);
+ return -EBUSY;
+ }
+ ioc->ioc_reset_in_progress = 1;
+ ioc->shost_recovery = 1;
+ if (ioc->shost->shost_state == SHOST_RUNNING) {
+ /* set back to SHOST_RUNNING in mpt2sas_scsih.c */
+ scsi_host_set_state(ioc->shost, SHOST_RECOVERY);
+ printk(MPT2SAS_INFO_FMT "putting controller into "
+ "SHOST_RECOVERY\n", ioc->name);
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ _base_reset_handler(ioc, MPT2_IOC_PRE_RESET);
+ _wait_for_commands_to_complete(ioc, sleep_flag);
+ _base_mask_interrupts(ioc);
+ r = _base_make_ioc_ready(ioc, sleep_flag, type);
+ if (r)
+ goto out;
+ _base_reset_handler(ioc, MPT2_IOC_AFTER_RESET);
+ for (i = 0 ; i < ioc->facts.NumberOfPorts; i++)
+ r = _base_make_ioc_operational(ioc, ioc->pfacts[i].VF_ID,
+ sleep_flag);
+ if (!r)
+ _base_reset_handler(ioc, MPT2_IOC_DONE_RESET);
+ out:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: %s\n",
+ ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED")));
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ ioc->ioc_reset_in_progress = 0;
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ return r;
+}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_base.h b/drivers/scsi/mpt2sas/mpt2sas_base.h
new file mode 100644
index 00000000000..6945ff4d382
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_base.h
@@ -0,0 +1,779 @@
+/*
+ * This is the Fusion MPT base driver providing common API layer interface
+ * for access to MPT (Message Passing Technology) firmware.
+ *
+ * This code is based on drivers/scsi/mpt2sas/mpt2_base.h
+ * Copyright (C) 2007-2008 LSI Corporation
+ * (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifndef MPT2SAS_BASE_H_INCLUDED
+#define MPT2SAS_BASE_H_INCLUDED
+
+#include "mpi/mpi2_type.h"
+#include "mpi/mpi2.h"
+#include "mpi/mpi2_ioc.h"
+#include "mpi/mpi2_cnfg.h"
+#include "mpi/mpi2_init.h"
+#include "mpi/mpi2_raid.h"
+#include "mpi/mpi2_tool.h"
+#include "mpi/mpi2_sas.h"
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/scsi_transport_sas.h>
+#include <scsi/scsi_dbg.h>
+
+#include "mpt2sas_debug.h"
+
+/* driver versioning info */
+#define MPT2SAS_DRIVER_NAME "mpt2sas"
+#define MPT2SAS_AUTHOR "LSI Corporation <DL-MPTFusionLinux@lsi.com>"
+#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
+#define MPT2SAS_DRIVER_VERSION "00.100.11.16"
+#define MPT2SAS_MAJOR_VERSION 00
+#define MPT2SAS_MINOR_VERSION 100
+#define MPT2SAS_BUILD_VERSION 11
+#define MPT2SAS_RELEASE_VERSION 16
+
+/*
+ * Set MPT2SAS_SG_DEPTH value based on user input.
+ */
+#ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE
+#if CONFIG_SCSI_MPT2SAS_MAX_SGE < 16
+#define MPT2SAS_SG_DEPTH 16
+#elif CONFIG_SCSI_MPT2SAS_MAX_SGE > 128
+#define MPT2SAS_SG_DEPTH 128
+#else
+#define MPT2SAS_SG_DEPTH CONFIG_SCSI_MPT2SAS_MAX_SGE
+#endif
+#else
+#define MPT2SAS_SG_DEPTH 128 /* MAX_HW_SEGMENTS */
+#endif
+
+
+/*
+ * Generic Defines
+ */
+#define MPT2SAS_SATA_QUEUE_DEPTH 32
+#define MPT2SAS_SAS_QUEUE_DEPTH 254
+#define MPT2SAS_RAID_QUEUE_DEPTH 128
+
+#define MPT_NAME_LENGTH 32 /* generic length of strings */
+#define MPT_STRING_LENGTH 64
+
+#define MPT_MAX_CALLBACKS 16
+
+#define CAN_SLEEP 1
+#define NO_SLEEP 0
+
+#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */
+
+#define MPI2_HIM_MASK 0xFFFFFFFF /* mask every bit*/
+
+#define MPT2SAS_INVALID_DEVICE_HANDLE 0xFFFF
+
+
+/*
+ * reset phases
+ */
+#define MPT2_IOC_PRE_RESET 1 /* prior to host reset */
+#define MPT2_IOC_AFTER_RESET 2 /* just after host reset */
+#define MPT2_IOC_DONE_RESET 3 /* links re-initialized */
+
+/*
+ * logging format
+ */
+#define MPT2SAS_FMT "%s: "
+#define MPT2SAS_DEBUG_FMT KERN_DEBUG MPT2SAS_FMT
+#define MPT2SAS_INFO_FMT KERN_INFO MPT2SAS_FMT
+#define MPT2SAS_NOTE_FMT KERN_NOTICE MPT2SAS_FMT
+#define MPT2SAS_WARN_FMT KERN_WARNING MPT2SAS_FMT
+#define MPT2SAS_ERR_FMT KERN_ERR MPT2SAS_FMT
+
+/*
+ * per target private data
+ */
+#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01
+#define MPT_TARGET_FLAGS_VOLUME 0x02
+#define MPT_TARGET_FLAGS_DELETED 0x04
+
+/**
+ * struct MPT2SAS_TARGET - starget private hostdata
+ * @starget: starget object
+ * @sas_address: target sas address
+ * @handle: device handle
+ * @num_luns: number luns
+ * @flags: MPT_TARGET_FLAGS_XXX flags
+ * @deleted: target flaged for deletion
+ * @tm_busy: target is busy with TM request.
+ */
+struct MPT2SAS_TARGET {
+ struct scsi_target *starget;
+ u64 sas_address;
+ u16 handle;
+ int num_luns;
+ u32 flags;
+ u8 deleted;
+ u8 tm_busy;
+};
+
+/*
+ * per device private data
+ */
+#define MPT_DEVICE_FLAGS_INIT 0x01
+#define MPT_DEVICE_TLR_ON 0x02
+
+/**
+ * struct MPT2SAS_DEVICE - sdev private hostdata
+ * @sas_target: starget private hostdata
+ * @lun: lun number
+ * @flags: MPT_DEVICE_XXX flags
+ * @configured_lun: lun is configured
+ * @block: device is in SDEV_BLOCK state
+ * @tlr_snoop_check: flag used in determining whether to disable TLR
+ */
+struct MPT2SAS_DEVICE {
+ struct MPT2SAS_TARGET *sas_target;
+ unsigned int lun;
+ u32 flags;
+ u8 configured_lun;
+ u8 block;
+ u8 tlr_snoop_check;
+};
+
+#define MPT2_CMD_NOT_USED 0x8000 /* free */
+#define MPT2_CMD_COMPLETE 0x0001 /* completed */
+#define MPT2_CMD_PENDING 0x0002 /* pending */
+#define MPT2_CMD_REPLY_VALID 0x0004 /* reply is valid */
+#define MPT2_CMD_RESET 0x0008 /* host reset dropped the command */
+
+/**
+ * struct _internal_cmd - internal commands struct
+ * @mutex: mutex
+ * @done: completion
+ * @reply: reply message pointer
+ * @status: MPT2_CMD_XXX status
+ * @smid: system message id
+ */
+struct _internal_cmd {
+ struct mutex mutex;
+ struct completion done;
+ void *reply;
+ u16 status;
+ u16 smid;
+};
+
+/*
+ * SAS Topology Structures
+ */
+
+/**
+ * struct _sas_device - attached device information
+ * @list: sas device list
+ * @starget: starget object
+ * @sas_address: device sas address
+ * @device_name: retrieved from the SAS IDENTIFY frame.
+ * @handle: device handle
+ * @parent_handle: handle to parent device
+ * @enclosure_handle: enclosure handle
+ * @enclosure_logical_id: enclosure logical identifier
+ * @volume_handle: volume handle (valid when hidden raid member)
+ * @volume_wwid: volume unique identifier
+ * @device_info: bitfield provides detailed info about the device
+ * @id: target id
+ * @channel: target channel
+ * @slot: number number
+ * @hidden_raid_component: set to 1 when this is a raid member
+ * @responding: used in _scsih_sas_device_mark_responding
+ */
+struct _sas_device {
+ struct list_head list;
+ struct scsi_target *starget;
+ u64 sas_address;
+ u64 device_name;
+ u16 handle;
+ u16 parent_handle;
+ u16 enclosure_handle;
+ u64 enclosure_logical_id;
+ u16 volume_handle;
+ u64 volume_wwid;
+ u32 device_info;
+ int id;
+ int channel;
+ u16 slot;
+ u8 hidden_raid_component;
+ u8 responding;
+};
+
+/**
+ * struct _raid_device - raid volume link list
+ * @list: sas device list
+ * @starget: starget object
+ * @sdev: scsi device struct (volumes are single lun)
+ * @wwid: unique identifier for the volume
+ * @handle: device handle
+ * @id: target id
+ * @channel: target channel
+ * @volume_type: the raid level
+ * @device_info: bitfield provides detailed info about the hidden components
+ * @num_pds: number of hidden raid components
+ * @responding: used in _scsih_raid_device_mark_responding
+ */
+struct _raid_device {
+ struct list_head list;
+ struct scsi_target *starget;
+ struct scsi_device *sdev;
+ u64 wwid;
+ u16 handle;
+ int id;
+ int channel;
+ u8 volume_type;
+ u32 device_info;
+ u8 num_pds;
+ u8 responding;
+};
+
+/**
+ * struct _boot_device - boot device info
+ * @is_raid: flag to indicate whether this is volume
+ * @device: holds pointer for either struct _sas_device or
+ * struct _raid_device
+ */
+struct _boot_device {
+ u8 is_raid;
+ void *device;
+};
+
+/**
+ * struct _sas_port - wide/narrow sas port information
+ * @port_list: list of ports belonging to expander
+ * @handle: device handle for this port
+ * @sas_address: sas address of this port
+ * @num_phys: number of phys belonging to this port
+ * @remote_identify: attached device identification
+ * @rphy: sas transport rphy object
+ * @port: sas transport wide/narrow port object
+ * @phy_list: _sas_phy list objects belonging to this port
+ */
+struct _sas_port {
+ struct list_head port_list;
+ u16 handle;
+ u64 sas_address;
+ u8 num_phys;
+ struct sas_identify remote_identify;
+ struct sas_rphy *rphy;
+ struct sas_port *port;
+ struct list_head phy_list;
+};
+
+/**
+ * struct _sas_phy - phy information
+ * @port_siblings: list of phys belonging to a port
+ * @identify: phy identification
+ * @remote_identify: attached device identification
+ * @phy: sas transport phy object
+ * @phy_id: unique phy id
+ * @handle: device handle for this phy
+ * @attached_handle: device handle for attached device
+ */
+struct _sas_phy {
+ struct list_head port_siblings;
+ struct sas_identify identify;
+ struct sas_identify remote_identify;
+ struct sas_phy *phy;
+ u8 phy_id;
+ u16 handle;
+ u16 attached_handle;
+};
+
+/**
+ * struct _sas_node - sas_host/expander information
+ * @list: list of expanders
+ * @parent_dev: parent device class
+ * @num_phys: number phys belonging to this sas_host/expander
+ * @sas_address: sas address of this sas_host/expander
+ * @handle: handle for this sas_host/expander
+ * @parent_handle: parent handle
+ * @enclosure_handle: handle for this a member of an enclosure
+ * @device_info: bitwise defining capabilities of this sas_host/expander
+ * @responding: used in _scsih_expander_device_mark_responding
+ * @phy: a list of phys that make up this sas_host/expander
+ * @sas_port_list: list of ports attached to this sas_host/expander
+ */
+struct _sas_node {
+ struct list_head list;
+ struct device *parent_dev;
+ u8 num_phys;
+ u64 sas_address;
+ u16 handle;
+ u16 parent_handle;
+ u16 enclosure_handle;
+ u64 enclosure_logical_id;
+ u8 responding;
+ struct _sas_phy *phy;
+ struct list_head sas_port_list;
+};
+
+/**
+ * enum reset_type - reset state
+ * @FORCE_BIG_HAMMER: issue diagnostic reset
+ * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer
+ */
+enum reset_type {
+ FORCE_BIG_HAMMER,
+ SOFT_RESET,
+};
+
+/**
+ * struct request_tracker - firmware request tracker
+ * @smid: system message id
+ * @scmd: scsi request pointer
+ * @cb_idx: callback index
+ * @chain_list: list of chains associated to this IO
+ * @tracker_list: list of free request (ioc->free_list)
+ */
+struct request_tracker {
+ u16 smid;
+ struct scsi_cmnd *scmd;
+ u8 cb_idx;
+ struct list_head tracker_list;
+};
+
+typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr);
+
+/**
+ * struct MPT2SAS_ADAPTER - per adapter struct
+ * @list: ioc_list
+ * @shost: shost object
+ * @id: unique adapter id
+ * @pci_irq: irq number
+ * @name: generic ioc string
+ * @tmp_string: tmp string used for logging
+ * @pdev: pci pdev object
+ * @chip: memory mapped register space
+ * @chip_phys: physical addrss prior to mapping
+ * @pio_chip: I/O mapped register space
+ * @logging_level: see mpt2sas_debug.h
+ * @ir_firmware: IR firmware present
+ * @bars: bitmask of BAR's that must be configured
+ * @mask_interrupts: ignore interrupt
+ * @fault_reset_work_q_name: fw fault work queue
+ * @fault_reset_work_q: ""
+ * @fault_reset_work: ""
+ * @firmware_event_name: fw event work queue
+ * @firmware_event_thread: ""
+ * @fw_events_off: flag to turn off fw event handling
+ * @fw_event_lock:
+ * @fw_event_list: list of fw events
+ * @aen_event_read_flag: event log was read
+ * @broadcast_aen_busy: broadcast aen waiting to be serviced
+ * @ioc_reset_in_progress: host reset in progress
+ * @ioc_reset_in_progress_lock:
+ * @ioc_link_reset_in_progress: phy/hard reset in progress
+ * @ignore_loginfos: ignore loginfos during task managment
+ * @remove_host: flag for when driver unloads, to avoid sending dev resets
+ * @wait_for_port_enable_to_complete:
+ * @msix_enable: flag indicating msix is enabled
+ * @msix_vector_count: number msix vectors
+ * @msix_table: virt address to the msix table
+ * @msix_table_backup: backup msix table
+ * @scsi_io_cb_idx: shost generated commands
+ * @tm_cb_idx: task management commands
+ * @transport_cb_idx: transport internal commands
+ * @ctl_cb_idx: clt internal commands
+ * @base_cb_idx: base internal commands
+ * @config_cb_idx: base internal commands
+ * @base_cmds:
+ * @transport_cmds:
+ * @tm_cmds:
+ * @ctl_cmds:
+ * @config_cmds:
+ * @base_add_sg_single: handler for either 32/64 bit sgl's
+ * @event_type: bits indicating which events to log
+ * @event_context: unique id for each logged event
+ * @event_log: event log pointer
+ * @event_masks: events that are masked
+ * @facts: static facts data
+ * @pfacts: static port facts data
+ * @manu_pg0: static manufacturing page 0
+ * @bios_pg2: static bios page 2
+ * @bios_pg3: static bios page 3
+ * @ioc_pg8: static ioc page 8
+ * @iounit_pg0: static iounit page 0
+ * @iounit_pg1: static iounit page 1
+ * @sas_hba: sas host object
+ * @sas_expander_list: expander object list
+ * @sas_node_lock:
+ * @sas_device_list: sas device object list
+ * @sas_device_init_list: sas device object list (used only at init time)
+ * @sas_device_lock:
+ * @io_missing_delay: time for IO completed by fw when PDR enabled
+ * @device_missing_delay: time for device missing by fw when PDR enabled
+ * @config_page_sz: config page size
+ * @config_page: reserve memory for config page payload
+ * @config_page_dma:
+ * @sge_size: sg element size for either 32/64 bit
+ * @request_depth: hba request queue depth
+ * @request_sz: per request frame size
+ * @request: pool of request frames
+ * @request_dma:
+ * @request_dma_sz:
+ * @scsi_lookup: firmware request tracker list
+ * @scsi_lookup_lock:
+ * @free_list: free list of request
+ * @chain: pool of chains
+ * @pending_io_count:
+ * @reset_wq:
+ * @chain_dma:
+ * @max_sges_in_main_message: number sg elements in main message
+ * @max_sges_in_chain_message: number sg elements per chain
+ * @chains_needed_per_io: max chains per io
+ * @chain_offset_value_for_main_message: location 1st sg in main
+ * @chain_depth: total chains allocated
+ * @sense: pool of sense
+ * @sense_dma:
+ * @sense_dma_pool:
+ * @reply_depth: hba reply queue depth:
+ * @reply_sz: per reply frame size:
+ * @reply: pool of replys:
+ * @reply_dma:
+ * @reply_dma_pool:
+ * @reply_free_queue_depth: reply free depth
+ * @reply_free: pool for reply free queue (32 bit addr)
+ * @reply_free_dma:
+ * @reply_free_dma_pool:
+ * @reply_free_host_index: tail index in pool to insert free replys
+ * @reply_post_queue_depth: reply post queue depth
+ * @reply_post_free: pool for reply post (64bit descriptor)
+ * @reply_post_free_dma:
+ * @reply_post_free_dma_pool:
+ * @reply_post_host_index: head index in the pool where FW completes IO
+ */
+struct MPT2SAS_ADAPTER {
+ struct list_head list;
+ struct Scsi_Host *shost;
+ u8 id;
+ u32 pci_irq;
+ char name[MPT_NAME_LENGTH];
+ char tmp_string[MPT_STRING_LENGTH];
+ struct pci_dev *pdev;
+ Mpi2SystemInterfaceRegs_t __iomem *chip;
+ unsigned long chip_phys;
+ unsigned long pio_chip;
+ int logging_level;
+ u8 ir_firmware;
+ int bars;
+ u8 mask_interrupts;
+
+ /* fw fault handler */
+ char fault_reset_work_q_name[20];
+ struct workqueue_struct *fault_reset_work_q;
+ struct delayed_work fault_reset_work;
+
+ /* fw event handler */
+ char firmware_event_name[20];
+ struct workqueue_struct *firmware_event_thread;
+ u8 fw_events_off;
+ spinlock_t fw_event_lock;
+ struct list_head fw_event_list;
+
+ /* misc flags */
+ int aen_event_read_flag;
+ u8 broadcast_aen_busy;
+ u8 ioc_reset_in_progress;
+ u8 shost_recovery;
+ spinlock_t ioc_reset_in_progress_lock;
+ u8 ioc_link_reset_in_progress;
+ u8 ignore_loginfos;
+ u8 remove_host;
+ u8 wait_for_port_enable_to_complete;
+
+ u8 msix_enable;
+ u16 msix_vector_count;
+ u32 *msix_table;
+ u32 *msix_table_backup;
+
+ /* internal commands, callback index */
+ u8 scsi_io_cb_idx;
+ u8 tm_cb_idx;
+ u8 transport_cb_idx;
+ u8 ctl_cb_idx;
+ u8 base_cb_idx;
+ u8 config_cb_idx;
+ struct _internal_cmd base_cmds;
+ struct _internal_cmd transport_cmds;
+ struct _internal_cmd tm_cmds;
+ struct _internal_cmd ctl_cmds;
+ struct _internal_cmd config_cmds;
+
+ MPT_ADD_SGE base_add_sg_single;
+
+ /* event log */
+ u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
+ u32 event_context;
+ void *event_log;
+ u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
+
+ /* static config pages */
+ Mpi2IOCFactsReply_t facts;
+ Mpi2PortFactsReply_t *pfacts;
+ Mpi2ManufacturingPage0_t manu_pg0;
+ Mpi2BiosPage2_t bios_pg2;
+ Mpi2BiosPage3_t bios_pg3;
+ Mpi2IOCPage8_t ioc_pg8;
+ Mpi2IOUnitPage0_t iounit_pg0;
+ Mpi2IOUnitPage1_t iounit_pg1;
+
+ struct _boot_device req_boot_device;
+ struct _boot_device req_alt_boot_device;
+ struct _boot_device current_boot_device;
+
+ /* sas hba, expander, and device list */
+ struct _sas_node sas_hba;
+ struct list_head sas_expander_list;
+ spinlock_t sas_node_lock;
+ struct list_head sas_device_list;
+ struct list_head sas_device_init_list;
+ spinlock_t sas_device_lock;
+ struct list_head raid_device_list;
+ spinlock_t raid_device_lock;
+ u8 io_missing_delay;
+ u16 device_missing_delay;
+ int sas_id;
+
+ /* config page */
+ u16 config_page_sz;
+ void *config_page;
+ dma_addr_t config_page_dma;
+
+ /* request */
+ u16 sge_size;
+ u16 request_depth;
+ u16 request_sz;
+ u8 *request;
+ dma_addr_t request_dma;
+ u32 request_dma_sz;
+ struct request_tracker *scsi_lookup;
+ spinlock_t scsi_lookup_lock;
+ struct list_head free_list;
+ int pending_io_count;
+ wait_queue_head_t reset_wq;
+
+ /* chain */
+ u8 *chain;
+ dma_addr_t chain_dma;
+ u16 max_sges_in_main_message;
+ u16 max_sges_in_chain_message;
+ u16 chains_needed_per_io;
+ u16 chain_offset_value_for_main_message;
+ u16 chain_depth;
+
+ /* sense */
+ u8 *sense;
+ dma_addr_t sense_dma;
+ struct dma_pool *sense_dma_pool;
+
+ /* reply */
+ u16 reply_sz;
+ u8 *reply;
+ dma_addr_t reply_dma;
+ struct dma_pool *reply_dma_pool;
+
+ /* reply free queue */
+ u16 reply_free_queue_depth;
+ u32 *reply_free;
+ dma_addr_t reply_free_dma;
+ struct dma_pool *reply_free_dma_pool;
+ u32 reply_free_host_index;
+
+ /* reply post queue */
+ u16 reply_post_queue_depth;
+ Mpi2ReplyDescriptorsUnion_t *reply_post_free;
+ dma_addr_t reply_post_free_dma;
+ struct dma_pool *reply_post_free_dma_pool;
+ u32 reply_post_host_index;
+
+ /* diag buffer support */
+ u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT];
+ u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT];
+ dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT];
+ u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT];
+ u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT];
+ u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23];
+ u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT];
+};
+
+typedef void (*MPT_CALLBACK)(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
+ u32 reply);
+
+
+/* base shared API */
+extern struct list_head mpt2sas_ioc_list;
+
+int mpt2sas_base_attach(struct MPT2SAS_ADAPTER *ioc);
+void mpt2sas_base_detach(struct MPT2SAS_ADAPTER *ioc);
+int mpt2sas_base_map_resources(struct MPT2SAS_ADAPTER *ioc);
+void mpt2sas_base_free_resources(struct MPT2SAS_ADAPTER *ioc);
+int mpt2sas_base_hard_reset_handler(struct MPT2SAS_ADAPTER *ioc, int sleep_flag,
+ enum reset_type type);
+
+void *mpt2sas_base_get_msg_frame(struct MPT2SAS_ADAPTER *ioc, u16 smid);
+void *mpt2sas_base_get_sense_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid);
+void mpt2sas_base_build_zero_len_sge(struct MPT2SAS_ADAPTER *ioc, void *paddr);
+dma_addr_t mpt2sas_base_get_msg_frame_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid);
+dma_addr_t mpt2sas_base_get_sense_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid);
+
+u16 mpt2sas_base_get_smid(struct MPT2SAS_ADAPTER *ioc, u8 cb_idx);
+void mpt2sas_base_free_smid(struct MPT2SAS_ADAPTER *ioc, u16 smid);
+void mpt2sas_base_put_smid_scsi_io(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id,
+ u16 handle);
+void mpt2sas_base_put_smid_hi_priority(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id);
+void mpt2sas_base_put_smid_target_assist(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+ u8 vf_id, u16 io_index);
+void mpt2sas_base_put_smid_default(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 vf_id);
+void mpt2sas_base_initialize_callback_handler(void);
+u8 mpt2sas_base_register_callback_handler(MPT_CALLBACK cb_func);
+void mpt2sas_base_release_callback_handler(u8 cb_idx);
+
+void mpt2sas_base_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
+void *mpt2sas_base_get_reply_virt_addr(struct MPT2SAS_ADAPTER *ioc, u32 phys_addr);
+
+u32 mpt2sas_base_get_iocstate(struct MPT2SAS_ADAPTER *ioc, int cooked);
+
+void mpt2sas_base_fault_info(struct MPT2SAS_ADAPTER *ioc , u16 fault_code);
+int mpt2sas_base_sas_iounit_control(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2SasIoUnitControlReply_t *mpi_reply, Mpi2SasIoUnitControlRequest_t
+ *mpi_request);
+int mpt2sas_base_scsi_enclosure_processor(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request);
+void mpt2sas_base_validate_event_type(struct MPT2SAS_ADAPTER *ioc, u32 *event_type);
+
+/* scsih shared API */
+void mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
+ u8 type, u16 smid_task, ulong timeout);
+void mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
+void mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle);
+struct _sas_node *mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc,
+ u16 handle);
+struct _sas_node *mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER
+ *ioc, u64 sas_address);
+struct _sas_device *mpt2sas_scsih_sas_device_find_by_sas_address(
+ struct MPT2SAS_ADAPTER *ioc, u64 sas_address);
+
+void mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply);
+void mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
+
+/* config shared API */
+void mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
+int mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys);
+int mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page);
+int mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2BiosPage2_t *config_page);
+int mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2BiosPage3_t *config_page);
+int mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2IOUnitPage0_t *config_page);
+int mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle);
+int mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle);
+int mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz);
+int mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2IOUnitPage1_t *config_page);
+int mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2IOUnitPage1_t config_page);
+int mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz);
+int mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2IOCPage8_t *config_page);
+int mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle);
+int mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, u16 handle);
+int mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle);
+int mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number);
+int mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number);
+int mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, u32 handle);
+int mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 *num_pds);
+int mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, u32 handle, u16 sz);
+int mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
+ u32 form_specific);
+int mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
+ u16 *volume_handle);
+int mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
+ u64 *wwid);
+
+/* ctl shared API */
+extern struct device_attribute *mpt2sas_host_attrs[];
+extern struct device_attribute *mpt2sas_dev_attrs[];
+void mpt2sas_ctl_init(void);
+void mpt2sas_ctl_exit(void);
+void mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
+void mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase);
+void mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply);
+void mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventNotificationReply_t *mpi_reply);
+
+/* transport shared API */
+void mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply);
+struct _sas_port *mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc,
+ u16 handle, u16 parent_handle);
+void mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
+ u16 parent_handle);
+int mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
+ *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev);
+int mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
+ *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev);
+void mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc, u16 handle,
+ u16 attached_handle, u8 phy_number, u8 link_rate);
+extern struct sas_function_template mpt2sas_transport_functions;
+extern struct scsi_transport_template *mpt2sas_transport_template;
+
+#endif /* MPT2SAS_BASE_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_config.c b/drivers/scsi/mpt2sas/mpt2sas_config.c
new file mode 100644
index 00000000000..58cfb97846f
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_config.c
@@ -0,0 +1,1873 @@
+/*
+ * This module provides common API for accessing firmware configuration pages
+ *
+ * This code is based on drivers/scsi/mpt2sas/mpt2_base.c
+ * Copyright (C) 2007-2008 LSI Corporation
+ * (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include "mpt2sas_base.h"
+
+/* local definitions */
+
+/* Timeout for config page request (in seconds) */
+#define MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT 15
+
+/* Common sgl flags for READING a config page. */
+#define MPT2_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
+ MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
+ | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT)
+
+/* Common sgl flags for WRITING a config page. */
+#define MPT2_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \
+ MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \
+ | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \
+ << MPI2_SGE_FLAGS_SHIFT)
+
+/**
+ * struct config_request - obtain dma memory via routine
+ * @config_page_sz: size
+ * @config_page: virt pointer
+ * @config_page_dma: phys pointer
+ *
+ */
+struct config_request{
+ u16 config_page_sz;
+ void *config_page;
+ dma_addr_t config_page_dma;
+};
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _config_display_some_debug - debug routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @calling_function_name: string pass from calling function
+ * @mpi_reply: reply message frame
+ * Context: none.
+ *
+ * Function for displaying debug info helpfull when debugging issues
+ * in this module.
+ */
+static void
+_config_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+ char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
+{
+ Mpi2ConfigRequest_t *mpi_request;
+ char *desc = NULL;
+
+ if (!(ioc->logging_level & MPT_DEBUG_CONFIG))
+ return;
+
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) {
+ case MPI2_CONFIG_PAGETYPE_IO_UNIT:
+ desc = "io_unit";
+ break;
+ case MPI2_CONFIG_PAGETYPE_IOC:
+ desc = "ioc";
+ break;
+ case MPI2_CONFIG_PAGETYPE_BIOS:
+ desc = "bios";
+ break;
+ case MPI2_CONFIG_PAGETYPE_RAID_VOLUME:
+ desc = "raid_volume";
+ break;
+ case MPI2_CONFIG_PAGETYPE_MANUFACTURING:
+ desc = "manufaucturing";
+ break;
+ case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK:
+ desc = "physdisk";
+ break;
+ case MPI2_CONFIG_PAGETYPE_EXTENDED:
+ switch (mpi_request->ExtPageType) {
+ case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT:
+ desc = "sas_io_unit";
+ break;
+ case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER:
+ desc = "sas_expander";
+ break;
+ case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE:
+ desc = "sas_device";
+ break;
+ case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY:
+ desc = "sas_phy";
+ break;
+ case MPI2_CONFIG_EXTPAGETYPE_LOG:
+ desc = "log";
+ break;
+ case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE:
+ desc = "enclosure";
+ break;
+ case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG:
+ desc = "raid_config";
+ break;
+ case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING:
+ desc = "driver_mappping";
+ break;
+ }
+ break;
+ }
+
+ if (!desc)
+ return;
+
+ printk(MPT2SAS_DEBUG_FMT "%s: %s(%d), action(%d), form(0x%08x), "
+ "smid(%d)\n", ioc->name, calling_function_name, desc,
+ mpi_request->Header.PageNumber, mpi_request->Action,
+ le32_to_cpu(mpi_request->PageAddress), smid);
+
+ if (!mpi_reply)
+ return;
+
+ if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
+ printk(MPT2SAS_DEBUG_FMT
+ "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+ le32_to_cpu(mpi_reply->IOCLogInfo));
+}
+#endif
+
+/**
+ * mpt2sas_config_done - config page completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: none.
+ *
+ * The callback handler when using _config_request.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_config_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+{
+ MPI2DefaultReply_t *mpi_reply;
+
+ if (ioc->config_cmds.status == MPT2_CMD_NOT_USED)
+ return;
+ if (ioc->config_cmds.smid != smid)
+ return;
+ ioc->config_cmds.status |= MPT2_CMD_COMPLETE;
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ if (mpi_reply) {
+ ioc->config_cmds.status |= MPT2_CMD_REPLY_VALID;
+ memcpy(ioc->config_cmds.reply, mpi_reply,
+ mpi_reply->MsgLength*4);
+ }
+ ioc->config_cmds.status &= ~MPT2_CMD_PENDING;
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ _config_display_some_debug(ioc, smid, "config_done", mpi_reply);
+#endif
+ complete(&ioc->config_cmds.done);
+}
+
+/**
+ * _config_request - main routine for sending config page requests
+ * @ioc: per adapter object
+ * @mpi_request: request message frame
+ * @mpi_reply: reply mf payload returned from firmware
+ * @timeout: timeout in seconds
+ * Context: sleep, the calling function needs to acquire the config_cmds.mutex
+ *
+ * A generic API for config page requests to firmware.
+ *
+ * The ioc->config_cmds.status flag should be MPT2_CMD_NOT_USED before calling
+ * this API.
+ *
+ * The callback index is set inside `ioc->config_cb_idx.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_config_request(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigRequest_t
+ *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout)
+{
+ u16 smid;
+ u32 ioc_state;
+ unsigned long timeleft;
+ Mpi2ConfigRequest_t *config_request;
+ int r;
+ u8 retry_count;
+ u8 issue_reset;
+ u16 wait_state_count;
+
+ if (ioc->config_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: config_cmd in use\n",
+ ioc->name, __func__);
+ return -EAGAIN;
+ }
+ retry_count = 0;
+
+ retry_config:
+ wait_state_count = 0;
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ if (wait_state_count++ == MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT) {
+ printk(MPT2SAS_ERR_FMT
+ "%s: failed due to ioc not operational\n",
+ ioc->name, __func__);
+ ioc->config_cmds.status = MPT2_CMD_NOT_USED;
+ return -EFAULT;
+ }
+ ssleep(1);
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ printk(MPT2SAS_INFO_FMT "%s: waiting for "
+ "operational state(count=%d)\n", ioc->name,
+ __func__, wait_state_count);
+ }
+ if (wait_state_count)
+ printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
+ ioc->name, __func__);
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->config_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ ioc->config_cmds.status = MPT2_CMD_NOT_USED;
+ return -EAGAIN;
+ }
+
+ r = 0;
+ memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t));
+ ioc->config_cmds.status = MPT2_CMD_PENDING;
+ config_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->config_cmds.smid = smid;
+ memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t));
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ _config_display_some_debug(ioc, smid, "config_request", NULL);
+#endif
+ mpt2sas_base_put_smid_default(ioc, smid, config_request->VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->config_cmds.done,
+ timeout*HZ);
+ if (!(ioc->config_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n",
+ ioc->name, __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2ConfigRequest_t)/4);
+ if (!(ioc->config_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+ if (ioc->config_cmds.status & MPT2_CMD_REPLY_VALID)
+ memcpy(mpi_reply, ioc->config_cmds.reply,
+ sizeof(Mpi2ConfigReply_t));
+ if (retry_count)
+ printk(MPT2SAS_INFO_FMT "%s: retry completed!!\n",
+ ioc->name, __func__);
+ ioc->config_cmds.status = MPT2_CMD_NOT_USED;
+ return r;
+
+ issue_host_reset:
+ if (issue_reset)
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ ioc->config_cmds.status = MPT2_CMD_NOT_USED;
+ if (!retry_count) {
+ printk(MPT2SAS_INFO_FMT "%s: attempting retry\n",
+ ioc->name, __func__);
+ retry_count++;
+ goto retry_config;
+ }
+ return -EFAULT;
+}
+
+/**
+ * _config_alloc_config_dma_memory - obtain physical memory
+ * @ioc: per adapter object
+ * @mem: struct config_request
+ *
+ * A wrapper for obtaining dma-able memory for config page request.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_config_alloc_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
+ struct config_request *mem)
+{
+ int r = 0;
+
+ mem->config_page = pci_alloc_consistent(ioc->pdev, mem->config_page_sz,
+ &mem->config_page_dma);
+ if (!mem->config_page)
+ r = -ENOMEM;
+ return r;
+}
+
+/**
+ * _config_free_config_dma_memory - wrapper to free the memory
+ * @ioc: per adapter object
+ * @mem: struct config_request
+ *
+ * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static void
+_config_free_config_dma_memory(struct MPT2SAS_ADAPTER *ioc,
+ struct config_request *mem)
+{
+ pci_free_consistent(ioc->pdev, mem->config_page_sz, mem->config_page,
+ mem->config_page_dma);
+}
+
+/**
+ * mpt2sas_config_get_manufacturing_pg0 - obtain manufacturing page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_manufacturing_pg0(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2ManufacturingPage0_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2ManufacturingPage0_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_bios_pg2 - obtain bios page 2
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_bios_pg2(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2BiosPage2_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
+ mpi_request.Header.PageNumber = 2;
+ mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2BiosPage2_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_bios_pg3 - obtain bios page 3
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_bios_pg3(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2BiosPage3_t *config_page)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2BiosPage3_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS;
+ mpi_request.Header.PageNumber = 3;
+ mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2BiosPage3_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_iounit_pg0 - obtain iounit page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_iounit_pg0(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2IOUnitPage0_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2IOUnitPage0_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_iounit_pg1 - obtain iounit page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2IOUnitPage1_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
+ mpi_request.Header.PageNumber = 1;
+ mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2IOUnitPage1_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_set_iounit_pg1 - set iounit page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_set_iounit_pg1(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t config_page)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT;
+ mpi_request.Header.PageNumber = 1;
+ mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+
+ memset(mem.config_page, 0, mem.config_page_sz);
+ memcpy(mem.config_page, &config_page,
+ sizeof(Mpi2IOUnitPage1_t));
+
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_WRITE_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_ioc_pg8 - obtain ioc page 8
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_ioc_pg8(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2IOCPage8_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC;
+ mpi_request.Header.PageNumber = 8;
+ mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2IOCPage8_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_sas_device_pg0 - obtain sas device page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: device handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_sas_device_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasDevicePage0_t *config_page, u32 form, u32 handle)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2SasDevicePage0_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+ mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION;
+ mpi_request.Header.PageNumber = 0;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress = cpu_to_le32(form | handle);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2SasDevicePage0_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_sas_device_pg1 - obtain sas device page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: device handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_sas_device_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasDevicePage1_t *config_page, u32 form, u32 handle)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2SasDevicePage1_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE;
+ mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION;
+ mpi_request.Header.PageNumber = 1;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress = cpu_to_le32(form | handle);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2SasDevicePage1_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_number_hba_phys - obtain number of phys on the host
+ * @ioc: per adapter object
+ * @num_phys: pointer returned with the number of phys
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_number_hba_phys(struct MPT2SAS_ADAPTER *ioc, u8 *num_phys)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+ u16 ioc_status;
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasIOUnitPage0_t config_page;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, &mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply.Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply.ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply.ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, &mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+ memcpy(&config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2SasIOUnitPage0_t)));
+ *num_phys = config_page.NumPhys;
+ }
+ }
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Calling function should call config_get_number_hba_phys prior to
+ * this function, so enough memory is allocated for config_page.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_sas_iounit_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, u16 sz)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sz);
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, sz, mem.config_page_sz));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_sas_iounit_pg1 - obtain sas iounit page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Calling function should call config_get_number_hba_phys prior to
+ * this function, so enough memory is allocated for config_page.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_sas_iounit_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, u16 sz)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sz);
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT;
+ mpi_request.Header.PageNumber = 1;
+ mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, sz, mem.config_page_sz));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_expander_pg0 - obtain expander page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: expander handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_expander_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2ExpanderPage0_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress = cpu_to_le32(form | handle);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2ExpanderPage0_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_expander_pg1 - obtain expander page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @phy_number: phy number
+ * @handle: expander handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_expander_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number,
+ u16 handle)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2ExpanderPage1_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER;
+ mpi_request.Header.PageNumber = 1;
+ mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress =
+ cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM |
+ (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2ExpanderPage1_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_enclosure_pg0 - obtain enclosure page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: expander handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_enclosure_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2SasEnclosurePage0_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress = cpu_to_le32(form | handle);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2SasEnclosurePage0_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_phy_pg0 - obtain phy page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @phy_number: phy number
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_phy_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2SasPhyPage0_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress =
+ cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2SasPhyPage0_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_phy_pg1 - obtain phy page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @phy_number: phy number
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_phy_pg1(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2SasPhyPage1_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY;
+ mpi_request.Header.PageNumber = 1;
+ mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress =
+ cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply->ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply->ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2SasPhyPage1_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_raid_volume_pg1 - obtain raid volume page 1
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: volume handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_raid_volume_pg1(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form,
+ u32 handle)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(config_page, 0, sizeof(Mpi2RaidVolPage1_t));
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+ mpi_request.Header.PageNumber = 1;
+ mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress = cpu_to_le32(form | handle);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2RaidVolPage1_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_number_pds - obtain number of phys disk assigned to volume
+ * @ioc: per adapter object
+ * @handle: volume handle
+ * @num_pds: returns pds count
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_number_pds(struct MPT2SAS_ADAPTER *ioc, u16 handle,
+ u8 *num_pds)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ Mpi2RaidVolPage0_t *config_page;
+ Mpi2ConfigReply_t mpi_reply;
+ int r;
+ struct config_request mem;
+ u16 ioc_status;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ *num_pds = 0;
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, &mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress =
+ cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply.Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply.Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply.Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, &mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+ config_page = mem.config_page;
+ *num_pds = config_page->NumPhysDisks;
+ }
+ }
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_raid_volume_pg0 - obtain raid volume page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_HANDLE or HANDLE
+ * @handle: volume handle
+ * @sz: size of buffer passed in config_page
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_raid_volume_pg0(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form,
+ u32 handle, u16 sz)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ memset(config_page, 0, sz);
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress = cpu_to_le32(form | handle);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, sz, mem.config_page_sz));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_phys_disk_pg0 - obtain phys disk page 0
+ * @ioc: per adapter object
+ * @mpi_reply: reply mf payload returned from firmware
+ * @config_page: contents of the config page
+ * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE
+ * @form_specific: specific to the form
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_phys_disk_pg0(struct MPT2SAS_ADAPTER *ioc, Mpi2ConfigReply_t
+ *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form,
+ u32 form_specific)
+{
+ Mpi2ConfigRequest_t mpi_request;
+ int r;
+ struct config_request mem;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ memset(config_page, 0, sizeof(Mpi2RaidPhysDiskPage0_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK;
+ mpi_request.Header.PageNumber = 0;
+ mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress = cpu_to_le32(form | form_specific);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply->Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply->Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply->Header.PageType;
+ mpi_request.Header.PageLength = mpi_reply->Header.PageLength;
+ mem.config_page_sz = le16_to_cpu(mpi_reply->Header.PageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (!r)
+ memcpy(config_page, mem.config_page,
+ min_t(u16, mem.config_page_sz,
+ sizeof(Mpi2RaidPhysDiskPage0_t)));
+
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_volume_handle - returns volume handle for give hidden raid components
+ * @ioc: per adapter object
+ * @pd_handle: phys disk handle
+ * @volume_handle: volume handle
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_volume_handle(struct MPT2SAS_ADAPTER *ioc, u16 pd_handle,
+ u16 *volume_handle)
+{
+ Mpi2RaidConfigurationPage0_t *config_page;
+ Mpi2ConfigRequest_t mpi_request;
+ Mpi2ConfigReply_t mpi_reply;
+ int r, i;
+ struct config_request mem;
+ u16 ioc_status;
+
+ mutex_lock(&ioc->config_cmds.mutex);
+ *volume_handle = 0;
+ memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_CONFIG;
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER;
+ mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED;
+ mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG;
+ mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION;
+ mpi_request.Header.PageNumber = 0;
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request.PageBufferSGE);
+ r = _config_request(ioc, &mpi_request, &mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ mpi_request.PageAddress =
+ cpu_to_le32(MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG);
+ mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT;
+ mpi_request.Header.PageVersion = mpi_reply.Header.PageVersion;
+ mpi_request.Header.PageNumber = mpi_reply.Header.PageNumber;
+ mpi_request.Header.PageType = mpi_reply.Header.PageType;
+ mpi_request.ExtPageLength = mpi_reply.ExtPageLength;
+ mpi_request.ExtPageType = mpi_reply.ExtPageType;
+ mem.config_page_sz = le16_to_cpu(mpi_reply.ExtPageLength) * 4;
+ if (mem.config_page_sz > ioc->config_page_sz) {
+ r = _config_alloc_config_dma_memory(ioc, &mem);
+ if (r)
+ goto out;
+ } else {
+ mem.config_page_dma = ioc->config_page_dma;
+ mem.config_page = ioc->config_page;
+ }
+ ioc->base_add_sg_single(&mpi_request.PageBufferSGE,
+ MPT2_CONFIG_COMMON_SGLFLAGS | mem.config_page_sz,
+ mem.config_page_dma);
+ r = _config_request(ioc, &mpi_request, &mpi_reply,
+ MPT2_CONFIG_PAGE_DEFAULT_TIMEOUT);
+ if (r)
+ goto out;
+
+ r = -1;
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+ goto done;
+ config_page = mem.config_page;
+ for (i = 0; i < config_page->NumElements; i++) {
+ if ((config_page->ConfigElement[i].ElementFlags &
+ MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE) !=
+ MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT)
+ continue;
+ if (config_page->ConfigElement[i].PhysDiskDevHandle ==
+ pd_handle) {
+ *volume_handle = le16_to_cpu(config_page->
+ ConfigElement[i].VolDevHandle);
+ r = 0;
+ goto done;
+ }
+ }
+
+ done:
+ if (mem.config_page_sz > ioc->config_page_sz)
+ _config_free_config_dma_memory(ioc, &mem);
+
+ out:
+ mutex_unlock(&ioc->config_cmds.mutex);
+ return r;
+}
+
+/**
+ * mpt2sas_config_get_volume_wwid - returns wwid given the volume handle
+ * @ioc: per adapter object
+ * @volume_handle: volume handle
+ * @wwid: volume wwid
+ * Context: sleep.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_config_get_volume_wwid(struct MPT2SAS_ADAPTER *ioc, u16 volume_handle,
+ u64 *wwid)
+{
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2RaidVolPage1_t raid_vol_pg1;
+
+ *wwid = 0;
+ if (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+ &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE,
+ volume_handle))) {
+ *wwid = le64_to_cpu(raid_vol_pg1.WWID);
+ return 0;
+ } else
+ return -1;
+}
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.c b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
new file mode 100644
index 00000000000..2d4f85c9d7a
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.c
@@ -0,0 +1,2516 @@
+/*
+ * Management Module Support for MPT (Message Passing Technology) based
+ * controllers
+ *
+ * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.c
+ * Copyright (C) 2007-2008 LSI Corporation
+ * (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <linux/version.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/delay.h>
+#include <linux/smp_lock.h>
+#include <linux/compat.h>
+#include <linux/poll.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+
+#include "mpt2sas_base.h"
+#include "mpt2sas_ctl.h"
+
+static struct fasync_struct *async_queue;
+static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait);
+
+/**
+ * enum block_state - blocking state
+ * @NON_BLOCKING: non blocking
+ * @BLOCKING: blocking
+ *
+ * These states are for ioctls that need to wait for a response
+ * from firmware, so they probably require sleep.
+ */
+enum block_state {
+ NON_BLOCKING,
+ BLOCKING,
+};
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _ctl_display_some_debug - debug routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @calling_function_name: string pass from calling function
+ * @mpi_reply: reply message frame
+ * Context: none.
+ *
+ * Function for displaying debug info helpfull when debugging issues
+ * in this module.
+ */
+static void
+_ctl_display_some_debug(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+ char *calling_function_name, MPI2DefaultReply_t *mpi_reply)
+{
+ Mpi2ConfigRequest_t *mpi_request;
+ char *desc = NULL;
+
+ if (!(ioc->logging_level & MPT_DEBUG_IOCTL))
+ return;
+
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ switch (mpi_request->Function) {
+ case MPI2_FUNCTION_SCSI_IO_REQUEST:
+ {
+ Mpi2SCSIIORequest_t *scsi_request =
+ (Mpi2SCSIIORequest_t *)mpi_request;
+
+ snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
+ "scsi_io, cmd(0x%02x), cdb_len(%d)",
+ scsi_request->CDB.CDB32[0],
+ le16_to_cpu(scsi_request->IoFlags) & 0xF);
+ desc = ioc->tmp_string;
+ break;
+ }
+ case MPI2_FUNCTION_SCSI_TASK_MGMT:
+ desc = "task_mgmt";
+ break;
+ case MPI2_FUNCTION_IOC_INIT:
+ desc = "ioc_init";
+ break;
+ case MPI2_FUNCTION_IOC_FACTS:
+ desc = "ioc_facts";
+ break;
+ case MPI2_FUNCTION_CONFIG:
+ {
+ Mpi2ConfigRequest_t *config_request =
+ (Mpi2ConfigRequest_t *)mpi_request;
+
+ snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
+ "config, type(0x%02x), ext_type(0x%02x), number(%d)",
+ (config_request->Header.PageType &
+ MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType,
+ config_request->Header.PageNumber);
+ desc = ioc->tmp_string;
+ break;
+ }
+ case MPI2_FUNCTION_PORT_FACTS:
+ desc = "port_facts";
+ break;
+ case MPI2_FUNCTION_PORT_ENABLE:
+ desc = "port_enable";
+ break;
+ case MPI2_FUNCTION_EVENT_NOTIFICATION:
+ desc = "event_notification";
+ break;
+ case MPI2_FUNCTION_FW_DOWNLOAD:
+ desc = "fw_download";
+ break;
+ case MPI2_FUNCTION_FW_UPLOAD:
+ desc = "fw_upload";
+ break;
+ case MPI2_FUNCTION_RAID_ACTION:
+ desc = "raid_action";
+ break;
+ case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
+ {
+ Mpi2SCSIIORequest_t *scsi_request =
+ (Mpi2SCSIIORequest_t *)mpi_request;
+
+ snprintf(ioc->tmp_string, MPT_STRING_LENGTH,
+ "raid_pass, cmd(0x%02x), cdb_len(%d)",
+ scsi_request->CDB.CDB32[0],
+ le16_to_cpu(scsi_request->IoFlags) & 0xF);
+ desc = ioc->tmp_string;
+ break;
+ }
+ case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
+ desc = "sas_iounit_cntl";
+ break;
+ case MPI2_FUNCTION_SATA_PASSTHROUGH:
+ desc = "sata_pass";
+ break;
+ case MPI2_FUNCTION_DIAG_BUFFER_POST:
+ desc = "diag_buffer_post";
+ break;
+ case MPI2_FUNCTION_DIAG_RELEASE:
+ desc = "diag_release";
+ break;
+ case MPI2_FUNCTION_SMP_PASSTHROUGH:
+ desc = "smp_passthrough";
+ break;
+ }
+
+ if (!desc)
+ return;
+
+ printk(MPT2SAS_DEBUG_FMT "%s: %s, smid(%d)\n",
+ ioc->name, calling_function_name, desc, smid);
+
+ if (!mpi_reply)
+ return;
+
+ if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo)
+ printk(MPT2SAS_DEBUG_FMT
+ "\tiocstatus(0x%04x), loginfo(0x%08x)\n",
+ ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+ le32_to_cpu(mpi_reply->IOCLogInfo));
+
+ if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+ mpi_request->Function ==
+ MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
+ Mpi2SCSIIOReply_t *scsi_reply =
+ (Mpi2SCSIIOReply_t *)mpi_reply;
+ if (scsi_reply->SCSIState || scsi_reply->SCSIStatus)
+ printk(MPT2SAS_DEBUG_FMT
+ "\tscsi_state(0x%02x), scsi_status"
+ "(0x%02x)\n", ioc->name,
+ scsi_reply->SCSIState,
+ scsi_reply->SCSIStatus);
+ }
+}
+#endif
+
+/**
+ * mpt2sas_ctl_done - ctl module completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: none.
+ *
+ * The callback handler when using ioc->ctl_cb_idx.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_ctl_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+{
+ MPI2DefaultReply_t *mpi_reply;
+
+ if (ioc->ctl_cmds.status == MPT2_CMD_NOT_USED)
+ return;
+ if (ioc->ctl_cmds.smid != smid)
+ return;
+ ioc->ctl_cmds.status |= MPT2_CMD_COMPLETE;
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ if (mpi_reply) {
+ memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
+ ioc->ctl_cmds.status |= MPT2_CMD_REPLY_VALID;
+ }
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply);
+#endif
+ ioc->ctl_cmds.status &= ~MPT2_CMD_PENDING;
+ complete(&ioc->ctl_cmds.done);
+}
+
+/**
+ * _ctl_check_event_type - determines when an event needs logging
+ * @ioc: per adapter object
+ * @event: firmware event
+ *
+ * The bitmask in ioc->event_type[] indicates which events should be
+ * be saved in the driver event_log. This bitmask is set by application.
+ *
+ * Returns 1 when event should be captured, or zero means no match.
+ */
+static int
+_ctl_check_event_type(struct MPT2SAS_ADAPTER *ioc, u16 event)
+{
+ u16 i;
+ u32 desired_event;
+
+ if (event >= 128 || !event || !ioc->event_log)
+ return 0;
+
+ desired_event = (1 << (event % 32));
+ if (!desired_event)
+ desired_event = 1;
+ i = event / 32;
+ return desired_event & ioc->event_type[i];
+}
+
+/**
+ * mpt2sas_ctl_add_to_event_log - add event
+ * @ioc: per adapter object
+ * @mpi_reply: reply message frame
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_ctl_add_to_event_log(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventNotificationReply_t *mpi_reply)
+{
+ struct MPT2_IOCTL_EVENTS *event_log;
+ u16 event;
+ int i;
+ u32 sz, event_data_sz;
+ u8 send_aen = 0;
+
+ if (!ioc->event_log)
+ return;
+
+ event = le16_to_cpu(mpi_reply->Event);
+
+ if (_ctl_check_event_type(ioc, event)) {
+
+ /* insert entry into circular event_log */
+ i = ioc->event_context % MPT2SAS_CTL_EVENT_LOG_SIZE;
+ event_log = ioc->event_log;
+ event_log[i].event = event;
+ event_log[i].context = ioc->event_context++;
+
+ event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4;
+ sz = min_t(u32, event_data_sz, MPT2_EVENT_DATA_SIZE);
+ memset(event_log[i].data, 0, MPT2_EVENT_DATA_SIZE);
+ memcpy(event_log[i].data, mpi_reply->EventData, sz);
+ send_aen = 1;
+ }
+
+ /* This aen_event_read_flag flag is set until the
+ * application has read the event log.
+ * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify.
+ */
+ if (event == MPI2_EVENT_LOG_ENTRY_ADDED ||
+ (send_aen && !ioc->aen_event_read_flag)) {
+ ioc->aen_event_read_flag = 1;
+ wake_up_interruptible(&ctl_poll_wait);
+ if (async_queue)
+ kill_fasync(&async_queue, SIGIO, POLL_IN);
+ }
+}
+
+/**
+ * mpt2sas_ctl_event_callback - firmware event handler (called at ISR time)
+ * @ioc: per adapter object
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt.
+ *
+ * This function merely adds a new work task into ioc->firmware_event_thread.
+ * The tasks are worked from _firmware_event_work in user context.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_ctl_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
+{
+ Mpi2EventNotificationReply_t *mpi_reply;
+
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ mpt2sas_ctl_add_to_event_log(ioc, mpi_reply);
+}
+
+/**
+ * _ctl_verify_adapter - validates ioc_number passed from application
+ * @ioc: per adapter object
+ * @iocpp: The ioc pointer is returned in this.
+ *
+ * Return (-1) means error, else ioc_number.
+ */
+static int
+_ctl_verify_adapter(int ioc_number, struct MPT2SAS_ADAPTER **iocpp)
+{
+ struct MPT2SAS_ADAPTER *ioc;
+
+ list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
+ if (ioc->id != ioc_number)
+ continue;
+ *iocpp = ioc;
+ return ioc_number;
+ }
+ *iocpp = NULL;
+ return -1;
+}
+
+/**
+ * mpt2sas_ctl_reset_handler - reset callback handler (for ctl)
+ * @ioc: per adapter object
+ * @reset_phase: phase
+ *
+ * The handler for doing any required cleanup or initialization.
+ *
+ * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
+ * MPT2_IOC_DONE_RESET
+ */
+void
+mpt2sas_ctl_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
+{
+ switch (reset_phase) {
+ case MPT2_IOC_PRE_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
+ break;
+ case MPT2_IOC_AFTER_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
+ if (ioc->ctl_cmds.status & MPT2_CMD_PENDING) {
+ ioc->ctl_cmds.status |= MPT2_CMD_RESET;
+ mpt2sas_base_free_smid(ioc, ioc->ctl_cmds.smid);
+ complete(&ioc->ctl_cmds.done);
+ }
+ break;
+ case MPT2_IOC_DONE_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
+ break;
+ }
+}
+
+/**
+ * _ctl_fasync -
+ * @fd -
+ * @filep -
+ * @mode -
+ *
+ * Called when application request fasyn callback handler.
+ */
+static int
+_ctl_fasync(int fd, struct file *filep, int mode)
+{
+ return fasync_helper(fd, filep, mode, &async_queue);
+}
+
+/**
+ * _ctl_release -
+ * @inode -
+ * @filep -
+ *
+ * Called when application releases the fasyn callback handler.
+ */
+static int
+_ctl_release(struct inode *inode, struct file *filep)
+{
+ return fasync_helper(-1, filep, 0, &async_queue);
+}
+
+/**
+ * _ctl_poll -
+ * @file -
+ * @wait -
+ *
+ */
+static unsigned int
+_ctl_poll(struct file *filep, poll_table *wait)
+{
+ struct MPT2SAS_ADAPTER *ioc;
+
+ poll_wait(filep, &ctl_poll_wait, wait);
+
+ list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
+ if (ioc->aen_event_read_flag)
+ return POLLIN | POLLRDNORM;
+ }
+ return 0;
+}
+
+/**
+ * _ctl_do_task_abort - assign an active smid to the abort_task
+ * @ioc: per adapter object
+ * @karg - (struct mpt2_ioctl_command)
+ * @tm_request - pointer to mf from user space
+ *
+ * Returns 0 when an smid if found, else fail.
+ * during failure, the reply frame is filled.
+ */
+static int
+_ctl_do_task_abort(struct MPT2SAS_ADAPTER *ioc, struct mpt2_ioctl_command *karg,
+ Mpi2SCSITaskManagementRequest_t *tm_request)
+{
+ u8 found = 0;
+ u16 i;
+ u16 handle;
+ struct scsi_cmnd *scmd;
+ struct MPT2SAS_DEVICE *priv_data;
+ unsigned long flags;
+ Mpi2SCSITaskManagementReply_t *tm_reply;
+ u32 sz;
+ u32 lun;
+
+ lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN);
+
+ handle = le16_to_cpu(tm_request->DevHandle);
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ for (i = ioc->request_depth; i && !found; i--) {
+ scmd = ioc->scsi_lookup[i - 1].scmd;
+ if (scmd == NULL || scmd->device == NULL ||
+ scmd->device->hostdata == NULL)
+ continue;
+ if (lun != scmd->device->lun)
+ continue;
+ priv_data = scmd->device->hostdata;
+ if (priv_data->sas_target == NULL)
+ continue;
+ if (priv_data->sas_target->handle != handle)
+ continue;
+ tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid);
+ found = 1;
+ }
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+
+ if (!found) {
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ABORT_TASK: "
+ "DevHandle(0x%04x), lun(%d), no active mid!!\n", ioc->name,
+ tm_request->DevHandle, lun));
+ tm_reply = ioc->ctl_cmds.reply;
+ tm_reply->DevHandle = tm_request->DevHandle;
+ tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+ tm_reply->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK;
+ tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4;
+ tm_reply->VP_ID = tm_request->VP_ID;
+ tm_reply->VF_ID = tm_request->VF_ID;
+ sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz);
+ if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply,
+ sz))
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ return 1;
+ }
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ABORT_TASK: "
+ "DevHandle(0x%04x), lun(%d), smid(%d)\n", ioc->name,
+ tm_request->DevHandle, lun, tm_request->TaskMID));
+ return 0;
+}
+
+/**
+ * _ctl_do_mpt_command - main handler for MPT2COMMAND opcode
+ * @ioc: per adapter object
+ * @karg - (struct mpt2_ioctl_command)
+ * @mf - pointer to mf in user space
+ * @state - NON_BLOCKING or BLOCKING
+ */
+static long
+_ctl_do_mpt_command(struct MPT2SAS_ADAPTER *ioc,
+ struct mpt2_ioctl_command karg, void __user *mf, enum block_state state)
+{
+ MPI2RequestHeader_t *mpi_request;
+ MPI2DefaultReply_t *mpi_reply;
+ u32 ioc_state;
+ u16 ioc_status;
+ u16 smid;
+ unsigned long timeout, timeleft;
+ u8 issue_reset;
+ u32 sz;
+ void *psge;
+ void *priv_sense = NULL;
+ void *data_out = NULL;
+ dma_addr_t data_out_dma;
+ size_t data_out_sz = 0;
+ void *data_in = NULL;
+ dma_addr_t data_in_dma;
+ size_t data_in_sz = 0;
+ u32 sgl_flags;
+ long ret;
+ u16 wait_state_count;
+
+ issue_reset = 0;
+
+ if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
+ return -EAGAIN;
+ else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+ return -ERESTARTSYS;
+
+ if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
+ ioc->name, __func__);
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ wait_state_count = 0;
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ if (wait_state_count++ == 10) {
+ printk(MPT2SAS_ERR_FMT
+ "%s: failed due to ioc not operational\n",
+ ioc->name, __func__);
+ ret = -EFAULT;
+ goto out;
+ }
+ ssleep(1);
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ printk(MPT2SAS_INFO_FMT "%s: waiting for "
+ "operational state(count=%d)\n", ioc->name,
+ __func__, wait_state_count);
+ }
+ if (wait_state_count)
+ printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
+ ioc->name, __func__);
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ ret = 0;
+ ioc->ctl_cmds.status = MPT2_CMD_PENDING;
+ memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->ctl_cmds.smid = smid;
+ data_out_sz = karg.data_out_size;
+ data_in_sz = karg.data_in_size;
+
+ /* copy in request message frame from user */
+ if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
+ __func__);
+ ret = -EFAULT;
+ mpt2sas_base_free_smid(ioc, smid);
+ goto out;
+ }
+
+ if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+ mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) {
+ if (!mpi_request->FunctionDependent1 ||
+ mpi_request->FunctionDependent1 >
+ cpu_to_le16(ioc->facts.MaxDevHandle)) {
+ ret = -EINVAL;
+ mpt2sas_base_free_smid(ioc, smid);
+ goto out;
+ }
+ }
+
+ /* obtain dma-able memory for data transfer */
+ if (data_out_sz) /* WRITE */ {
+ data_out = pci_alloc_consistent(ioc->pdev, data_out_sz,
+ &data_out_dma);
+ if (!data_out) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ ret = -ENOMEM;
+ mpt2sas_base_free_smid(ioc, smid);
+ goto out;
+ }
+ if (copy_from_user(data_out, karg.data_out_buf_ptr,
+ data_out_sz)) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ ret = -EFAULT;
+ mpt2sas_base_free_smid(ioc, smid);
+ goto out;
+ }
+ }
+
+ if (data_in_sz) /* READ */ {
+ data_in = pci_alloc_consistent(ioc->pdev, data_in_sz,
+ &data_in_dma);
+ if (!data_in) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ ret = -ENOMEM;
+ mpt2sas_base_free_smid(ioc, smid);
+ goto out;
+ }
+ }
+
+ /* add scatter gather elements */
+ psge = (void *)mpi_request + (karg.data_sge_offset*4);
+
+ if (!data_out_sz && !data_in_sz) {
+ mpt2sas_base_build_zero_len_sge(ioc, psge);
+ } else if (data_out_sz && data_in_sz) {
+ /* WRITE sgel first */
+ sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+ ioc->base_add_sg_single(psge, sgl_flags |
+ data_out_sz, data_out_dma);
+
+ /* incr sgel */
+ psge += ioc->sge_size;
+
+ /* READ sgel last */
+ sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+ MPI2_SGE_FLAGS_END_OF_LIST);
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+ ioc->base_add_sg_single(psge, sgl_flags |
+ data_in_sz, data_in_dma);
+ } else if (data_out_sz) /* WRITE */ {
+ sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+ MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC);
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+ ioc->base_add_sg_single(psge, sgl_flags |
+ data_out_sz, data_out_dma);
+ } else if (data_in_sz) /* READ */ {
+ sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+ MPI2_SGE_FLAGS_END_OF_LIST);
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+ ioc->base_add_sg_single(psge, sgl_flags |
+ data_in_sz, data_in_dma);
+ }
+
+ /* send command to firmware */
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ _ctl_display_some_debug(ioc, smid, "ctl_request", NULL);
+#endif
+
+ switch (mpi_request->Function) {
+ case MPI2_FUNCTION_SCSI_IO_REQUEST:
+ case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH:
+ {
+ Mpi2SCSIIORequest_t *scsiio_request =
+ (Mpi2SCSIIORequest_t *)mpi_request;
+ scsiio_request->SenseBufferLowAddress =
+ (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid);
+ priv_sense = mpt2sas_base_get_sense_buffer(ioc, smid);
+ memset(priv_sense, 0, SCSI_SENSE_BUFFERSIZE);
+ mpt2sas_base_put_smid_scsi_io(ioc, smid, 0,
+ le16_to_cpu(mpi_request->FunctionDependent1));
+ break;
+ }
+ case MPI2_FUNCTION_SCSI_TASK_MGMT:
+ {
+ Mpi2SCSITaskManagementRequest_t *tm_request =
+ (Mpi2SCSITaskManagementRequest_t *)mpi_request;
+
+ if (tm_request->TaskType ==
+ MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) {
+ if (_ctl_do_task_abort(ioc, &karg, tm_request))
+ goto out;
+ }
+
+ mutex_lock(&ioc->tm_cmds.mutex);
+ mpt2sas_scsih_set_tm_flag(ioc, le16_to_cpu(
+ tm_request->DevHandle));
+ mpt2sas_base_put_smid_hi_priority(ioc, smid,
+ mpi_request->VF_ID);
+ break;
+ }
+ case MPI2_FUNCTION_SMP_PASSTHROUGH:
+ {
+ Mpi2SmpPassthroughRequest_t *smp_request =
+ (Mpi2SmpPassthroughRequest_t *)mpi_request;
+ u8 *data;
+
+ /* ioc determines which port to use */
+ smp_request->PhysicalPort = 0xFF;
+ if (smp_request->PassthroughFlags &
+ MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE)
+ data = (u8 *)&smp_request->SGL;
+ else
+ data = data_out;
+
+ if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) {
+ ioc->ioc_link_reset_in_progress = 1;
+ ioc->ignore_loginfos = 1;
+ }
+ mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+ break;
+ }
+ case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL:
+ {
+ Mpi2SasIoUnitControlRequest_t *sasiounit_request =
+ (Mpi2SasIoUnitControlRequest_t *)mpi_request;
+
+ if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET
+ || sasiounit_request->Operation ==
+ MPI2_SAS_OP_PHY_LINK_RESET) {
+ ioc->ioc_link_reset_in_progress = 1;
+ ioc->ignore_loginfos = 1;
+ }
+ mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+ break;
+ }
+ default:
+ mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+ break;
+ }
+
+ if (karg.timeout < MPT2_IOCTL_DEFAULT_TIMEOUT)
+ timeout = MPT2_IOCTL_DEFAULT_TIMEOUT;
+ else
+ timeout = karg.timeout;
+ timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
+ timeout*HZ);
+ if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) {
+ Mpi2SCSITaskManagementRequest_t *tm_request =
+ (Mpi2SCSITaskManagementRequest_t *)mpi_request;
+ mutex_unlock(&ioc->tm_cmds.mutex);
+ mpt2sas_scsih_clear_tm_flag(ioc, le16_to_cpu(
+ tm_request->DevHandle));
+ } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH ||
+ mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) &&
+ ioc->ioc_link_reset_in_progress) {
+ ioc->ioc_link_reset_in_progress = 0;
+ ioc->ignore_loginfos = 0;
+ }
+ if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
+ __func__);
+ _debug_dump_mf(mpi_request, karg.data_sge_offset);
+ if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+
+ mpi_reply = ioc->ctl_cmds.reply;
+ ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT &&
+ (ioc->logging_level & MPT_DEBUG_TM)) {
+ Mpi2SCSITaskManagementReply_t *tm_reply =
+ (Mpi2SCSITaskManagementReply_t *)mpi_reply;
+
+ printk(MPT2SAS_DEBUG_FMT "TASK_MGMT: "
+ "IOCStatus(0x%04x), IOCLogInfo(0x%08x), "
+ "TerminationCount(0x%08x)\n", ioc->name,
+ tm_reply->IOCStatus, tm_reply->IOCLogInfo,
+ tm_reply->TerminationCount);
+ }
+#endif
+ /* copy out xdata to user */
+ if (data_in_sz) {
+ if (copy_to_user(karg.data_in_buf_ptr, data_in,
+ data_in_sz)) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ ret = -ENODATA;
+ goto out;
+ }
+ }
+
+ /* copy out reply message frame to user */
+ if (karg.max_reply_bytes) {
+ sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz);
+ if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply,
+ sz)) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ ret = -ENODATA;
+ goto out;
+ }
+ }
+
+ /* copy out sense to user */
+ if (karg.max_sense_bytes && (mpi_request->Function ==
+ MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function ==
+ MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+ sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE);
+ if (copy_to_user(karg.sense_data_ptr, priv_sense, sz)) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ ret = -ENODATA;
+ goto out;
+ }
+ }
+
+ issue_host_reset:
+ if (issue_reset) {
+ if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST ||
+ mpi_request->Function ==
+ MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) {
+ printk(MPT2SAS_INFO_FMT "issue target reset: handle "
+ "= (0x%04x)\n", ioc->name,
+ mpi_request->FunctionDependent1);
+ mutex_lock(&ioc->tm_cmds.mutex);
+ mpt2sas_scsih_issue_tm(ioc,
+ mpi_request->FunctionDependent1, 0,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10);
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->tm_cmds.mutex);
+ } else
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ }
+
+ out:
+
+ /* free memory associated with sg buffers */
+ if (data_in)
+ pci_free_consistent(ioc->pdev, data_in_sz, data_in,
+ data_in_dma);
+
+ if (data_out)
+ pci_free_consistent(ioc->pdev, data_out_sz, data_out,
+ data_out_dma);
+
+ ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->ctl_cmds.mutex);
+ return ret;
+}
+
+/**
+ * _ctl_getiocinfo - main handler for MPT2IOCINFO opcode
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_getiocinfo(void __user *arg)
+{
+ struct mpt2_ioctl_iocinfo karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ u8 revision;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+ __func__));
+
+ memset(&karg, 0 , sizeof(karg));
+ karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2;
+ if (ioc->pfacts)
+ karg.port_number = ioc->pfacts[0].PortNumber;
+ pci_read_config_byte(ioc->pdev, PCI_CLASS_REVISION, &revision);
+ karg.hw_rev = revision;
+ karg.pci_id = ioc->pdev->device;
+ karg.subsystem_device = ioc->pdev->subsystem_device;
+ karg.subsystem_vendor = ioc->pdev->subsystem_vendor;
+ karg.pci_information.u.bits.bus = ioc->pdev->bus->number;
+ karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn);
+ karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn);
+ karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus);
+ karg.firmware_version = ioc->facts.FWVersion.Word;
+ strncpy(karg.driver_version, MPT2SAS_DRIVER_VERSION,
+ MPT2_IOCTL_VERSION_LENGTH);
+ karg.driver_version[MPT2_IOCTL_VERSION_LENGTH - 1] = '\0';
+ karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
+
+ if (copy_to_user(arg, &karg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+/**
+ * _ctl_eventquery - main handler for MPT2EVENTQUERY opcode
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_eventquery(void __user *arg)
+{
+ struct mpt2_ioctl_eventquery karg;
+ struct MPT2SAS_ADAPTER *ioc;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+ __func__));
+
+ karg.event_entries = MPT2SAS_CTL_EVENT_LOG_SIZE;
+ memcpy(karg.event_types, ioc->event_type,
+ MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
+
+ if (copy_to_user(arg, &karg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+/**
+ * _ctl_eventenable - main handler for MPT2EVENTENABLE opcode
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_eventenable(void __user *arg)
+{
+ struct mpt2_ioctl_eventenable karg;
+ struct MPT2SAS_ADAPTER *ioc;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+ __func__));
+
+ if (ioc->event_log)
+ return 0;
+ memcpy(ioc->event_type, karg.event_types,
+ MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32));
+ mpt2sas_base_validate_event_type(ioc, ioc->event_type);
+
+ /* initialize event_log */
+ ioc->event_context = 0;
+ ioc->aen_event_read_flag = 0;
+ ioc->event_log = kcalloc(MPT2SAS_CTL_EVENT_LOG_SIZE,
+ sizeof(struct MPT2_IOCTL_EVENTS), GFP_KERNEL);
+ if (!ioc->event_log) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/**
+ * _ctl_eventreport - main handler for MPT2EVENTREPORT opcode
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_eventreport(void __user *arg)
+{
+ struct mpt2_ioctl_eventreport karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ u32 number_bytes, max_events, max;
+ struct mpt2_ioctl_eventreport __user *uarg = arg;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+ __func__));
+
+ number_bytes = karg.hdr.max_data_size -
+ sizeof(struct mpt2_ioctl_header);
+ max_events = number_bytes/sizeof(struct MPT2_IOCTL_EVENTS);
+ max = min_t(u32, MPT2SAS_CTL_EVENT_LOG_SIZE, max_events);
+
+ /* If fewer than 1 event is requested, there must have
+ * been some type of error.
+ */
+ if (!max || !ioc->event_log)
+ return -ENODATA;
+
+ number_bytes = max * sizeof(struct MPT2_IOCTL_EVENTS);
+ if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+
+ /* reset flag so SIGIO can restart */
+ ioc->aen_event_read_flag = 0;
+ return 0;
+}
+
+/**
+ * _ctl_do_reset - main handler for MPT2HARDRESET opcode
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_do_reset(void __user *arg)
+{
+ struct mpt2_ioctl_diag_reset karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ int retval;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+ __func__));
+
+ retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ printk(MPT2SAS_INFO_FMT "host reset: %s\n",
+ ioc->name, ((!retval) ? "SUCCESS" : "FAILED"));
+ return 0;
+}
+
+/**
+ * _ctl_btdh_search_sas_device - searching for sas device
+ * @ioc: per adapter object
+ * @btdh: btdh ioctl payload
+ */
+static int
+_ctl_btdh_search_sas_device(struct MPT2SAS_ADAPTER *ioc,
+ struct mpt2_ioctl_btdh_mapping *btdh)
+{
+ struct _sas_device *sas_device;
+ unsigned long flags;
+ int rc = 0;
+
+ if (list_empty(&ioc->sas_device_list))
+ return rc;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+ if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
+ btdh->handle == sas_device->handle) {
+ btdh->bus = sas_device->channel;
+ btdh->id = sas_device->id;
+ rc = 1;
+ goto out;
+ } else if (btdh->bus == sas_device->channel && btdh->id ==
+ sas_device->id && btdh->handle == 0xFFFF) {
+ btdh->handle = sas_device->handle;
+ rc = 1;
+ goto out;
+ }
+ }
+ out:
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ return rc;
+}
+
+/**
+ * _ctl_btdh_search_raid_device - searching for raid device
+ * @ioc: per adapter object
+ * @btdh: btdh ioctl payload
+ */
+static int
+_ctl_btdh_search_raid_device(struct MPT2SAS_ADAPTER *ioc,
+ struct mpt2_ioctl_btdh_mapping *btdh)
+{
+ struct _raid_device *raid_device;
+ unsigned long flags;
+ int rc = 0;
+
+ if (list_empty(&ioc->raid_device_list))
+ return rc;
+
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+ if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF &&
+ btdh->handle == raid_device->handle) {
+ btdh->bus = raid_device->channel;
+ btdh->id = raid_device->id;
+ rc = 1;
+ goto out;
+ } else if (btdh->bus == raid_device->channel && btdh->id ==
+ raid_device->id && btdh->handle == 0xFFFF) {
+ btdh->handle = raid_device->handle;
+ rc = 1;
+ goto out;
+ }
+ }
+ out:
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ return rc;
+}
+
+/**
+ * _ctl_btdh_mapping - main handler for MPT2BTDHMAPPING opcode
+ * @arg - user space buffer containing ioctl content
+ */
+static long
+_ctl_btdh_mapping(void __user *arg)
+{
+ struct mpt2_ioctl_btdh_mapping karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ int rc;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ rc = _ctl_btdh_search_sas_device(ioc, &karg);
+ if (!rc)
+ _ctl_btdh_search_raid_device(ioc, &karg);
+
+ if (copy_to_user(arg, &karg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+/**
+ * _ctl_diag_capability - return diag buffer capability
+ * @ioc: per adapter object
+ * @buffer_type: specifies either TRACE or SNAPSHOT
+ *
+ * returns 1 when diag buffer support is enabled in firmware
+ */
+static u8
+_ctl_diag_capability(struct MPT2SAS_ADAPTER *ioc, u8 buffer_type)
+{
+ u8 rc = 0;
+
+ switch (buffer_type) {
+ case MPI2_DIAG_BUF_TYPE_TRACE:
+ if (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER)
+ rc = 1;
+ break;
+ case MPI2_DIAG_BUF_TYPE_SNAPSHOT:
+ if (ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER)
+ rc = 1;
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * _ctl_diag_register - application register with driver
+ * @arg - user space buffer containing ioctl content
+ * @state - NON_BLOCKING or BLOCKING
+ *
+ * This will allow the driver to setup any required buffers that will be
+ * needed by firmware to communicate with the driver.
+ */
+static long
+_ctl_diag_register(void __user *arg, enum block_state state)
+{
+ struct mpt2_diag_register karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ int rc, i;
+ void *request_data = NULL;
+ dma_addr_t request_data_dma;
+ u32 request_data_sz = 0;
+ Mpi2DiagBufferPostRequest_t *mpi_request;
+ Mpi2DiagBufferPostReply_t *mpi_reply;
+ u8 buffer_type;
+ unsigned long timeleft;
+ u16 smid;
+ u16 ioc_status;
+ u8 issue_reset = 0;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ buffer_type = karg.buffer_type;
+ if (!_ctl_diag_capability(ioc, buffer_type)) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -EPERM;
+ }
+
+ if (ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED) {
+ printk(MPT2SAS_ERR_FMT "%s: already has a registered "
+ "buffer for buffer_type(0x%02x)\n", ioc->name, __func__,
+ buffer_type);
+ return -EINVAL;
+ }
+
+ if (karg.requested_buffer_size % 4) {
+ printk(MPT2SAS_ERR_FMT "%s: the requested_buffer_size "
+ "is not 4 byte aligned\n", ioc->name, __func__);
+ return -EINVAL;
+ }
+
+ if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
+ return -EAGAIN;
+ else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+ return -ERESTARTSYS;
+
+ if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ rc = 0;
+ ioc->ctl_cmds.status = MPT2_CMD_PENDING;
+ memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->ctl_cmds.smid = smid;
+
+ request_data = ioc->diag_buffer[buffer_type];
+ request_data_sz = karg.requested_buffer_size;
+ ioc->unique_id[buffer_type] = karg.unique_id;
+ ioc->diag_buffer_status[buffer_type] = 0;
+ memcpy(ioc->product_specific[buffer_type], karg.product_specific,
+ MPT2_PRODUCT_SPECIFIC_DWORDS);
+ ioc->diagnostic_flags[buffer_type] = karg.diagnostic_flags;
+
+ if (request_data) {
+ request_data_dma = ioc->diag_buffer_dma[buffer_type];
+ if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) {
+ pci_free_consistent(ioc->pdev,
+ ioc->diag_buffer_sz[buffer_type],
+ request_data, request_data_dma);
+ request_data = NULL;
+ }
+ }
+
+ if (request_data == NULL) {
+ ioc->diag_buffer_sz[buffer_type] = 0;
+ ioc->diag_buffer_dma[buffer_type] = 0;
+ request_data = pci_alloc_consistent(
+ ioc->pdev, request_data_sz, &request_data_dma);
+ if (request_data == NULL) {
+ printk(MPT2SAS_ERR_FMT "%s: failed allocating memory"
+ " for diag buffers, requested size(%d)\n",
+ ioc->name, __func__, request_data_sz);
+ mpt2sas_base_free_smid(ioc, smid);
+ return -ENOMEM;
+ }
+ ioc->diag_buffer[buffer_type] = request_data;
+ ioc->diag_buffer_sz[buffer_type] = request_data_sz;
+ ioc->diag_buffer_dma[buffer_type] = request_data_dma;
+ }
+
+ mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
+ mpi_request->BufferType = karg.buffer_type;
+ mpi_request->Flags = cpu_to_le32(karg.diagnostic_flags);
+ mpi_request->BufferAddress = cpu_to_le64(request_data_dma);
+ mpi_request->BufferLength = cpu_to_le32(request_data_sz);
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(0x%p), "
+ "dma(0x%llx), sz(%d)\n", ioc->name, __func__, request_data,
+ (unsigned long long)request_data_dma, mpi_request->BufferLength));
+
+ for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
+ mpi_request->ProductSpecific[i] =
+ cpu_to_le32(ioc->product_specific[buffer_type][i]);
+
+ mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
+ MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
+
+ if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
+ __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2DiagBufferPostRequest_t)/4);
+ if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+
+ /* process the completed Reply Message Frame */
+ if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
+ ioc->name, __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+
+ mpi_reply = ioc->ctl_cmds.reply;
+ ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+ if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+ ioc->diag_buffer_status[buffer_type] |=
+ MPT2_DIAG_BUFFER_IS_REGISTERED;
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
+ ioc->name, __func__));
+ } else {
+ printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
+ "log_info(0x%08x)\n", ioc->name, __func__,
+ ioc_status, mpi_reply->IOCLogInfo);
+ rc = -EFAULT;
+ }
+
+ issue_host_reset:
+ if (issue_reset)
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+
+ out:
+
+ if (rc && request_data)
+ pci_free_consistent(ioc->pdev, request_data_sz,
+ request_data, request_data_dma);
+
+ ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->ctl_cmds.mutex);
+ return rc;
+}
+
+/**
+ * _ctl_diag_unregister - application unregister with driver
+ * @arg - user space buffer containing ioctl content
+ *
+ * This will allow the driver to cleanup any memory allocated for diag
+ * messages and to free up any resources.
+ */
+static long
+_ctl_diag_unregister(void __user *arg)
+{
+ struct mpt2_diag_unregister karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ void *request_data;
+ dma_addr_t request_data_dma;
+ u32 request_data_sz;
+ u8 buffer_type;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ buffer_type = karg.unique_id & 0x000000ff;
+ if (!_ctl_diag_capability(ioc, buffer_type)) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -EPERM;
+ }
+
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
+ "registered\n", ioc->name, __func__, buffer_type);
+ return -EINVAL;
+ }
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) has not been "
+ "released\n", ioc->name, __func__, buffer_type);
+ return -EINVAL;
+ }
+
+ if (karg.unique_id != ioc->unique_id[buffer_type]) {
+ printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
+ "registered\n", ioc->name, __func__, karg.unique_id);
+ return -EINVAL;
+ }
+
+ request_data = ioc->diag_buffer[buffer_type];
+ if (!request_data) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -ENOMEM;
+ }
+
+ request_data_sz = ioc->diag_buffer_sz[buffer_type];
+ request_data_dma = ioc->diag_buffer_dma[buffer_type];
+ pci_free_consistent(ioc->pdev, request_data_sz,
+ request_data, request_data_dma);
+ ioc->diag_buffer[buffer_type] = NULL;
+ ioc->diag_buffer_status[buffer_type] = 0;
+ return 0;
+}
+
+/**
+ * _ctl_diag_query - query relevant info associated with diag buffers
+ * @arg - user space buffer containing ioctl content
+ *
+ * The application will send only buffer_type and unique_id. Driver will
+ * inspect unique_id first, if valid, fill in all the info. If unique_id is
+ * 0x00, the driver will return info specified by Buffer Type.
+ */
+static long
+_ctl_diag_query(void __user *arg)
+{
+ struct mpt2_diag_query karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ void *request_data;
+ int i;
+ u8 buffer_type;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ karg.application_flags = 0;
+ buffer_type = karg.buffer_type;
+
+ if (!_ctl_diag_capability(ioc, buffer_type)) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -EPERM;
+ }
+
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
+ "registered\n", ioc->name, __func__, buffer_type);
+ return -EINVAL;
+ }
+
+ if (karg.unique_id & 0xffffff00) {
+ if (karg.unique_id != ioc->unique_id[buffer_type]) {
+ printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
+ "registered\n", ioc->name, __func__,
+ karg.unique_id);
+ return -EINVAL;
+ }
+ }
+
+ request_data = ioc->diag_buffer[buffer_type];
+ if (!request_data) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -ENOMEM;
+ }
+
+ if (ioc->diag_buffer_status[buffer_type] & MPT2_DIAG_BUFFER_IS_RELEASED)
+ karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
+ MPT2_APP_FLAGS_BUFFER_VALID);
+ else
+ karg.application_flags = (MPT2_APP_FLAGS_APP_OWNED |
+ MPT2_APP_FLAGS_BUFFER_VALID |
+ MPT2_APP_FLAGS_FW_BUFFER_ACCESS);
+
+ for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
+ karg.product_specific[i] =
+ ioc->product_specific[buffer_type][i];
+
+ karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type];
+ karg.driver_added_buffer_size = 0;
+ karg.unique_id = ioc->unique_id[buffer_type];
+ karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type];
+
+ if (copy_to_user(arg, &karg, sizeof(struct mpt2_diag_query))) {
+ printk(MPT2SAS_ERR_FMT "%s: unable to write mpt2_diag_query "
+ "data @ %p\n", ioc->name, __func__, arg);
+ return -EFAULT;
+ }
+ return 0;
+}
+
+/**
+ * _ctl_diag_release - request to send Diag Release Message to firmware
+ * @arg - user space buffer containing ioctl content
+ * @state - NON_BLOCKING or BLOCKING
+ *
+ * This allows ownership of the specified buffer to returned to the driver,
+ * allowing an application to read the buffer without fear that firmware is
+ * overwritting information in the buffer.
+ */
+static long
+_ctl_diag_release(void __user *arg, enum block_state state)
+{
+ struct mpt2_diag_release karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ void *request_data;
+ int rc;
+ Mpi2DiagReleaseRequest_t *mpi_request;
+ Mpi2DiagReleaseReply_t *mpi_reply;
+ u8 buffer_type;
+ unsigned long timeleft;
+ u16 smid;
+ u16 ioc_status;
+ u8 issue_reset = 0;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ buffer_type = karg.unique_id & 0x000000ff;
+ if (!_ctl_diag_capability(ioc, buffer_type)) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -EPERM;
+ }
+
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_REGISTERED) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) is not "
+ "registered\n", ioc->name, __func__, buffer_type);
+ return -EINVAL;
+ }
+
+ if (karg.unique_id != ioc->unique_id[buffer_type]) {
+ printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
+ "registered\n", ioc->name, __func__, karg.unique_id);
+ return -EINVAL;
+ }
+
+ if (ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_RELEASED) {
+ printk(MPT2SAS_ERR_FMT "%s: buffer_type(0x%02x) "
+ "is already released\n", ioc->name, __func__,
+ buffer_type);
+ return 0;
+ }
+
+ request_data = ioc->diag_buffer[buffer_type];
+
+ if (!request_data) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have memory allocated for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -ENOMEM;
+ }
+
+ if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
+ return -EAGAIN;
+ else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+ return -ERESTARTSYS;
+
+ if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ rc = 0;
+ ioc->ctl_cmds.status = MPT2_CMD_PENDING;
+ memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->ctl_cmds.smid = smid;
+
+ mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE;
+ mpi_request->BufferType = buffer_type;
+
+ mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
+ MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
+
+ if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
+ __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2DiagReleaseRequest_t)/4);
+ if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+
+ /* process the completed Reply Message Frame */
+ if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
+ ioc->name, __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+
+ mpi_reply = ioc->ctl_cmds.reply;
+ ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+ if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+ ioc->diag_buffer_status[buffer_type] |=
+ MPT2_DIAG_BUFFER_IS_RELEASED;
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
+ ioc->name, __func__));
+ } else {
+ printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
+ "log_info(0x%08x)\n", ioc->name, __func__,
+ ioc_status, mpi_reply->IOCLogInfo);
+ rc = -EFAULT;
+ }
+
+ issue_host_reset:
+ if (issue_reset)
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+
+ out:
+
+ ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->ctl_cmds.mutex);
+ return rc;
+}
+
+/**
+ * _ctl_diag_read_buffer - request for copy of the diag buffer
+ * @arg - user space buffer containing ioctl content
+ * @state - NON_BLOCKING or BLOCKING
+ */
+static long
+_ctl_diag_read_buffer(void __user *arg, enum block_state state)
+{
+ struct mpt2_diag_read_buffer karg;
+ struct mpt2_diag_read_buffer __user *uarg = arg;
+ struct MPT2SAS_ADAPTER *ioc;
+ void *request_data, *diag_data;
+ Mpi2DiagBufferPostRequest_t *mpi_request;
+ Mpi2DiagBufferPostReply_t *mpi_reply;
+ int rc, i;
+ u8 buffer_type;
+ unsigned long timeleft;
+ u16 smid;
+ u16 ioc_status;
+ u8 issue_reset = 0;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s\n", ioc->name,
+ __func__));
+
+ buffer_type = karg.unique_id & 0x000000ff;
+ if (!_ctl_diag_capability(ioc, buffer_type)) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have capability for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -EPERM;
+ }
+
+ if (karg.unique_id != ioc->unique_id[buffer_type]) {
+ printk(MPT2SAS_ERR_FMT "%s: unique_id(0x%08x) is not "
+ "registered\n", ioc->name, __func__, karg.unique_id);
+ return -EINVAL;
+ }
+
+ request_data = ioc->diag_buffer[buffer_type];
+ if (!request_data) {
+ printk(MPT2SAS_ERR_FMT "%s: doesn't have buffer for "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type);
+ return -ENOMEM;
+ }
+
+ if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
+ printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
+ "or bytes_to_read are not 4 byte aligned\n", ioc->name,
+ __func__);
+ return -EINVAL;
+ }
+
+ diag_data = (void *)(request_data + karg.starting_offset);
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: diag_buffer(%p), "
+ "offset(%d), sz(%d)\n", ioc->name, __func__,
+ diag_data, karg.starting_offset, karg.bytes_to_read));
+
+ if (copy_to_user((void __user *)uarg->diagnostic_data,
+ diag_data, karg.bytes_to_read)) {
+ printk(MPT2SAS_ERR_FMT "%s: Unable to write "
+ "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
+ __func__, diag_data);
+ return -EFAULT;
+ }
+
+ if ((karg.flags & MPT2_FLAGS_REREGISTER) == 0)
+ return 0;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: Reregister "
+ "buffer_type(0x%02x)\n", ioc->name, __func__, buffer_type));
+ if ((ioc->diag_buffer_status[buffer_type] &
+ MPT2_DIAG_BUFFER_IS_RELEASED) == 0) {
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "buffer_type(0x%02x) is still registered\n", ioc->name,
+ __func__, buffer_type));
+ return 0;
+ }
+ /* Get a free request frame and save the message context.
+ */
+ if (state == NON_BLOCKING && !mutex_trylock(&ioc->ctl_cmds.mutex))
+ return -EAGAIN;
+ else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex))
+ return -ERESTARTSYS;
+
+ if (ioc->ctl_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: ctl_cmd in use\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->ctl_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ rc = 0;
+ ioc->ctl_cmds.status = MPT2_CMD_PENDING;
+ memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz);
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->ctl_cmds.smid = smid;
+
+ mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST;
+ mpi_request->BufferType = buffer_type;
+ mpi_request->BufferLength =
+ cpu_to_le32(ioc->diag_buffer_sz[buffer_type]);
+ mpi_request->BufferAddress =
+ cpu_to_le64(ioc->diag_buffer_dma[buffer_type]);
+ for (i = 0; i < MPT2_PRODUCT_SPECIFIC_DWORDS; i++)
+ mpi_request->ProductSpecific[i] =
+ cpu_to_le32(ioc->product_specific[buffer_type][i]);
+
+ mpt2sas_base_put_smid_default(ioc, smid, mpi_request->VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done,
+ MPT2_IOCTL_DEFAULT_TIMEOUT*HZ);
+
+ if (!(ioc->ctl_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n", ioc->name,
+ __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2DiagBufferPostRequest_t)/4);
+ if (!(ioc->ctl_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+
+ /* process the completed Reply Message Frame */
+ if ((ioc->ctl_cmds.status & MPT2_CMD_REPLY_VALID) == 0) {
+ printk(MPT2SAS_ERR_FMT "%s: no reply message\n",
+ ioc->name, __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+
+ mpi_reply = ioc->ctl_cmds.reply;
+ ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK;
+
+ if (ioc_status == MPI2_IOCSTATUS_SUCCESS) {
+ ioc->diag_buffer_status[buffer_type] |=
+ MPT2_DIAG_BUFFER_IS_REGISTERED;
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: success\n",
+ ioc->name, __func__));
+ } else {
+ printk(MPT2SAS_DEBUG_FMT "%s: ioc_status(0x%04x) "
+ "log_info(0x%08x)\n", ioc->name, __func__,
+ ioc_status, mpi_reply->IOCLogInfo);
+ rc = -EFAULT;
+ }
+
+ issue_host_reset:
+ if (issue_reset)
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+
+ out:
+
+ ioc->ctl_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->ctl_cmds.mutex);
+ return rc;
+}
+
+/**
+ * _ctl_ioctl_main - main ioctl entry point
+ * @file - (struct file)
+ * @cmd - ioctl opcode
+ * @arg -
+ */
+static long
+_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg)
+{
+ enum block_state state;
+ long ret = -EINVAL;
+ unsigned long flags;
+
+ state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING :
+ BLOCKING;
+
+ switch (cmd) {
+ case MPT2IOCINFO:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_iocinfo))
+ ret = _ctl_getiocinfo(arg);
+ break;
+ case MPT2COMMAND:
+ {
+ struct mpt2_ioctl_command karg;
+ struct mpt2_ioctl_command __user *uarg;
+ struct MPT2SAS_ADAPTER *ioc;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
+ !ioc)
+ return -ENODEV;
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->shost_recovery) {
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
+ flags);
+ return -EAGAIN;
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_command)) {
+ uarg = arg;
+ ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
+ }
+ break;
+ }
+ case MPT2EVENTQUERY:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventquery))
+ ret = _ctl_eventquery(arg);
+ break;
+ case MPT2EVENTENABLE:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_eventenable))
+ ret = _ctl_eventenable(arg);
+ break;
+ case MPT2EVENTREPORT:
+ ret = _ctl_eventreport(arg);
+ break;
+ case MPT2HARDRESET:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_diag_reset))
+ ret = _ctl_do_reset(arg);
+ break;
+ case MPT2BTDHMAPPING:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_ioctl_btdh_mapping))
+ ret = _ctl_btdh_mapping(arg);
+ break;
+ case MPT2DIAGREGISTER:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_register))
+ ret = _ctl_diag_register(arg, state);
+ break;
+ case MPT2DIAGUNREGISTER:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_unregister))
+ ret = _ctl_diag_unregister(arg);
+ break;
+ case MPT2DIAGQUERY:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_query))
+ ret = _ctl_diag_query(arg);
+ break;
+ case MPT2DIAGRELEASE:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_release))
+ ret = _ctl_diag_release(arg, state);
+ break;
+ case MPT2DIAGREADBUFFER:
+ if (_IOC_SIZE(cmd) == sizeof(struct mpt2_diag_read_buffer))
+ ret = _ctl_diag_read_buffer(arg, state);
+ break;
+ default:
+ {
+ struct mpt2_ioctl_command karg;
+ struct MPT2SAS_ADAPTER *ioc;
+
+ if (copy_from_user(&karg, arg, sizeof(karg))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+
+ if (_ctl_verify_adapter(karg.hdr.ioc_number, &ioc) == -1 ||
+ !ioc)
+ return -ENODEV;
+
+ dctlprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd));
+ break;
+ }
+ }
+ return ret;
+}
+
+/**
+ * _ctl_ioctl - main ioctl entry point (unlocked)
+ * @file - (struct file)
+ * @cmd - ioctl opcode
+ * @arg -
+ */
+static long
+_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ long ret;
+ lock_kernel();
+ ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
+ unlock_kernel();
+ return ret;
+}
+
+#ifdef CONFIG_COMPAT
+/**
+ * _ctl_compat_mpt_command - convert 32bit pointers to 64bit.
+ * @file - (struct file)
+ * @cmd - ioctl opcode
+ * @arg - (struct mpt2_ioctl_command32)
+ *
+ * MPT2COMMAND32 - Handle 32bit applications running on 64bit os.
+ */
+static long
+_ctl_compat_mpt_command(struct file *file, unsigned cmd, unsigned long arg)
+{
+ struct mpt2_ioctl_command32 karg32;
+ struct mpt2_ioctl_command32 __user *uarg;
+ struct mpt2_ioctl_command karg;
+ struct MPT2SAS_ADAPTER *ioc;
+ enum block_state state;
+ unsigned long flags;
+
+ if (_IOC_SIZE(cmd) != sizeof(struct mpt2_ioctl_command32))
+ return -EINVAL;
+
+ uarg = (struct mpt2_ioctl_command32 __user *) arg;
+
+ if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n",
+ __FILE__, __LINE__, __func__);
+ return -EFAULT;
+ }
+ if (_ctl_verify_adapter(karg32.hdr.ioc_number, &ioc) == -1 || !ioc)
+ return -ENODEV;
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->shost_recovery) {
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock,
+ flags);
+ return -EAGAIN;
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ memset(&karg, 0, sizeof(struct mpt2_ioctl_command));
+ karg.hdr.ioc_number = karg32.hdr.ioc_number;
+ karg.hdr.port_number = karg32.hdr.port_number;
+ karg.hdr.max_data_size = karg32.hdr.max_data_size;
+ karg.timeout = karg32.timeout;
+ karg.max_reply_bytes = karg32.max_reply_bytes;
+ karg.data_in_size = karg32.data_in_size;
+ karg.data_out_size = karg32.data_out_size;
+ karg.max_sense_bytes = karg32.max_sense_bytes;
+ karg.data_sge_offset = karg32.data_sge_offset;
+ memcpy(&karg.reply_frame_buf_ptr, &karg32.reply_frame_buf_ptr,
+ sizeof(uint32_t));
+ memcpy(&karg.data_in_buf_ptr, &karg32.data_in_buf_ptr,
+ sizeof(uint32_t));
+ memcpy(&karg.data_out_buf_ptr, &karg32.data_out_buf_ptr,
+ sizeof(uint32_t));
+ memcpy(&karg.sense_data_ptr, &karg32.sense_data_ptr,
+ sizeof(uint32_t));
+ state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING;
+ return _ctl_do_mpt_command(ioc, karg, &uarg->mf, state);
+}
+
+/**
+ * _ctl_ioctl_compat - main ioctl entry point (compat)
+ * @file -
+ * @cmd -
+ * @arg -
+ *
+ * This routine handles 32 bit applications in 64bit os.
+ */
+static long
+_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg)
+{
+ long ret;
+ lock_kernel();
+ if (cmd == MPT2COMMAND32)
+ ret = _ctl_compat_mpt_command(file, cmd, arg);
+ else
+ ret = _ctl_ioctl_main(file, cmd, (void __user *)arg);
+ unlock_kernel();
+ return ret;
+}
+#endif
+
+/* scsi host attributes */
+
+/**
+ * _ctl_version_fw_show - firmware version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
+ (ioc->facts.FWVersion.Word & 0xFF000000) >> 24,
+ (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16,
+ (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8,
+ ioc->facts.FWVersion.Word & 0x000000FF);
+}
+static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL);
+
+/**
+ * _ctl_version_bios_show - bios version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion);
+
+ return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n",
+ (version & 0xFF000000) >> 24,
+ (version & 0x00FF0000) >> 16,
+ (version & 0x0000FF00) >> 8,
+ version & 0x000000FF);
+}
+static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL);
+
+/**
+ * _ctl_version_mpi_show - MPI (message passing interface) version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%03x.%02x\n",
+ ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8);
+}
+static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL);
+
+/**
+ * _ctl_version_product_show - product name
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_product_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName);
+}
+static DEVICE_ATTR(version_product, S_IRUGO,
+ _ctl_version_product_show, NULL);
+
+/**
+ * _ctl_version_nvdata_persistent_show - ndvata persistent version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_nvdata_persistent_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%02xh\n",
+ le16_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word));
+}
+static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO,
+ _ctl_version_nvdata_persistent_show, NULL);
+
+/**
+ * _ctl_version_nvdata_default_show - nvdata default version
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_version_nvdata_default_show(struct device *cdev,
+ struct device_attribute *attr, char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%02xh\n",
+ le16_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word));
+}
+static DEVICE_ATTR(version_nvdata_default, S_IRUGO,
+ _ctl_version_nvdata_default_show, NULL);
+
+/**
+ * _ctl_board_name_show - board name
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_board_name_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName);
+}
+static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL);
+
+/**
+ * _ctl_board_assembly_show - board assembly name
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly);
+}
+static DEVICE_ATTR(board_assembly, S_IRUGO,
+ _ctl_board_assembly_show, NULL);
+
+/**
+ * _ctl_board_tracer_show - board tracer number
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber);
+}
+static DEVICE_ATTR(board_tracer, S_IRUGO,
+ _ctl_board_tracer_show, NULL);
+
+/**
+ * _ctl_io_delay_show - io missing delay
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is for firmware implemention for deboucing device
+ * removal events.
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay);
+}
+static DEVICE_ATTR(io_delay, S_IRUGO,
+ _ctl_io_delay_show, NULL);
+
+/**
+ * _ctl_device_delay_show - device missing delay
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is for firmware implemention for deboucing device
+ * removal events.
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay);
+}
+static DEVICE_ATTR(device_delay, S_IRUGO,
+ _ctl_device_delay_show, NULL);
+
+/**
+ * _ctl_fw_queue_depth_show - global credits
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is firmware queue depth limit
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit);
+}
+static DEVICE_ATTR(fw_queue_depth, S_IRUGO,
+ _ctl_fw_queue_depth_show, NULL);
+
+/**
+ * _ctl_sas_address_show - sas address
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is the controller sas address
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
+ (unsigned long long)ioc->sas_hba.sas_address);
+}
+static DEVICE_ATTR(host_sas_address, S_IRUGO,
+ _ctl_host_sas_address_show, NULL);
+
+/**
+ * _ctl_logging_level_show - logging level
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * A sysfs 'read/write' shost attribute.
+ */
+static ssize_t
+_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr,
+ char *buf)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+
+ return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level);
+}
+static ssize_t
+_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct Scsi_Host *shost = class_to_shost(cdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ int val = 0;
+
+ if (sscanf(buf, "%x", &val) != 1)
+ return -EINVAL;
+
+ ioc->logging_level = val;
+ printk(MPT2SAS_INFO_FMT "logging_level=%08xh\n", ioc->name,
+ ioc->logging_level);
+ return strlen(buf);
+}
+static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR,
+ _ctl_logging_level_show, _ctl_logging_level_store);
+
+struct device_attribute *mpt2sas_host_attrs[] = {
+ &dev_attr_version_fw,
+ &dev_attr_version_bios,
+ &dev_attr_version_mpi,
+ &dev_attr_version_product,
+ &dev_attr_version_nvdata_persistent,
+ &dev_attr_version_nvdata_default,
+ &dev_attr_board_name,
+ &dev_attr_board_assembly,
+ &dev_attr_board_tracer,
+ &dev_attr_io_delay,
+ &dev_attr_device_delay,
+ &dev_attr_logging_level,
+ &dev_attr_fw_queue_depth,
+ &dev_attr_host_sas_address,
+ NULL,
+};
+
+/* device attributes */
+
+/**
+ * _ctl_device_sas_address_show - sas address
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is the sas address for the target
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
+
+ return snprintf(buf, PAGE_SIZE, "0x%016llx\n",
+ (unsigned long long)sas_device_priv_data->sas_target->sas_address);
+}
+static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL);
+
+/**
+ * _ctl_device_handle_show - device handle
+ * @cdev - pointer to embedded class device
+ * @buf - the buffer returned
+ *
+ * This is the firmware assigned device handle
+ *
+ * A sysfs 'read-only' shost attribute.
+ */
+static ssize_t
+_ctl_device_handle_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct scsi_device *sdev = to_scsi_device(dev);
+ struct MPT2SAS_DEVICE *sas_device_priv_data = sdev->hostdata;
+
+ return snprintf(buf, PAGE_SIZE, "0x%04x\n",
+ sas_device_priv_data->sas_target->handle);
+}
+static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL);
+
+struct device_attribute *mpt2sas_dev_attrs[] = {
+ &dev_attr_sas_address,
+ &dev_attr_sas_device_handle,
+ NULL,
+};
+
+static const struct file_operations ctl_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = _ctl_ioctl,
+ .release = _ctl_release,
+ .poll = _ctl_poll,
+ .fasync = _ctl_fasync,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = _ctl_ioctl_compat,
+#endif
+};
+
+static struct miscdevice ctl_dev = {
+ .minor = MPT2SAS_MINOR,
+ .name = MPT2SAS_DEV_NAME,
+ .fops = &ctl_fops,
+};
+
+/**
+ * mpt2sas_ctl_init - main entry point for ctl.
+ *
+ */
+void
+mpt2sas_ctl_init(void)
+{
+ async_queue = NULL;
+ if (misc_register(&ctl_dev) < 0)
+ printk(KERN_ERR "%s can't register misc device [minor=%d]\n",
+ MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR);
+
+ init_waitqueue_head(&ctl_poll_wait);
+}
+
+/**
+ * mpt2sas_ctl_exit - exit point for ctl
+ *
+ */
+void
+mpt2sas_ctl_exit(void)
+{
+ struct MPT2SAS_ADAPTER *ioc;
+ int i;
+
+ list_for_each_entry(ioc, &mpt2sas_ioc_list, list) {
+
+ /* free memory associated to diag buffers */
+ for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) {
+ if (!ioc->diag_buffer[i])
+ continue;
+ pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i],
+ ioc->diag_buffer[i], ioc->diag_buffer_dma[i]);
+ ioc->diag_buffer[i] = NULL;
+ ioc->diag_buffer_status[i] = 0;
+ }
+
+ kfree(ioc->event_log);
+ }
+ misc_deregister(&ctl_dev);
+}
+
diff --git a/drivers/scsi/mpt2sas/mpt2sas_ctl.h b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
new file mode 100644
index 00000000000..dbb6c0cf888
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_ctl.h
@@ -0,0 +1,416 @@
+/*
+ * Management Module Support for MPT (Message Passing Technology) based
+ * controllers
+ *
+ * This code is based on drivers/scsi/mpt2sas/mpt2_ctl.h
+ * Copyright (C) 2007-2008 LSI Corporation
+ * (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifndef MPT2SAS_CTL_H_INCLUDED
+#define MPT2SAS_CTL_H_INCLUDED
+
+#ifdef __KERNEL__
+#include <linux/miscdevice.h>
+#endif
+
+#define MPT2SAS_DEV_NAME "mpt2ctl"
+#define MPT2_MAGIC_NUMBER 'm'
+#define MPT2_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */
+
+/**
+ * IOCTL opcodes
+ */
+#define MPT2IOCINFO _IOWR(MPT2_MAGIC_NUMBER, 17, \
+ struct mpt2_ioctl_iocinfo)
+#define MPT2COMMAND _IOWR(MPT2_MAGIC_NUMBER, 20, \
+ struct mpt2_ioctl_command)
+#ifdef CONFIG_COMPAT
+#define MPT2COMMAND32 _IOWR(MPT2_MAGIC_NUMBER, 20, \
+ struct mpt2_ioctl_command32)
+#endif
+#define MPT2EVENTQUERY _IOWR(MPT2_MAGIC_NUMBER, 21, \
+ struct mpt2_ioctl_eventquery)
+#define MPT2EVENTENABLE _IOWR(MPT2_MAGIC_NUMBER, 22, \
+ struct mpt2_ioctl_eventenable)
+#define MPT2EVENTREPORT _IOWR(MPT2_MAGIC_NUMBER, 23, \
+ struct mpt2_ioctl_eventreport)
+#define MPT2HARDRESET _IOWR(MPT2_MAGIC_NUMBER, 24, \
+ struct mpt2_ioctl_diag_reset)
+#define MPT2BTDHMAPPING _IOWR(MPT2_MAGIC_NUMBER, 31, \
+ struct mpt2_ioctl_btdh_mapping)
+
+/* diag buffer support */
+#define MPT2DIAGREGISTER _IOWR(MPT2_MAGIC_NUMBER, 26, \
+ struct mpt2_diag_register)
+#define MPT2DIAGRELEASE _IOWR(MPT2_MAGIC_NUMBER, 27, \
+ struct mpt2_diag_release)
+#define MPT2DIAGUNREGISTER _IOWR(MPT2_MAGIC_NUMBER, 28, \
+ struct mpt2_diag_unregister)
+#define MPT2DIAGQUERY _IOWR(MPT2_MAGIC_NUMBER, 29, \
+ struct mpt2_diag_query)
+#define MPT2DIAGREADBUFFER _IOWR(MPT2_MAGIC_NUMBER, 30, \
+ struct mpt2_diag_read_buffer)
+
+/**
+ * struct mpt2_ioctl_header - main header structure
+ * @ioc_number - IOC unit number
+ * @port_number - IOC port number
+ * @max_data_size - maximum number bytes to transfer on read
+ */
+struct mpt2_ioctl_header {
+ uint32_t ioc_number;
+ uint32_t port_number;
+ uint32_t max_data_size;
+};
+
+/**
+ * struct mpt2_ioctl_diag_reset - diagnostic reset
+ * @hdr - generic header
+ */
+struct mpt2_ioctl_diag_reset {
+ struct mpt2_ioctl_header hdr;
+};
+
+
+/**
+ * struct mpt2_ioctl_pci_info - pci device info
+ * @device - pci device id
+ * @function - pci function id
+ * @bus - pci bus id
+ * @segment_id - pci segment id
+ */
+struct mpt2_ioctl_pci_info {
+ union {
+ struct {
+ uint32_t device:5;
+ uint32_t function:3;
+ uint32_t bus:24;
+ } bits;
+ uint32_t word;
+ } u;
+ uint32_t segment_id;
+};
+
+
+#define MPT2_IOCTL_INTERFACE_SCSI (0x00)
+#define MPT2_IOCTL_INTERFACE_FC (0x01)
+#define MPT2_IOCTL_INTERFACE_FC_IP (0x02)
+#define MPT2_IOCTL_INTERFACE_SAS (0x03)
+#define MPT2_IOCTL_INTERFACE_SAS2 (0x04)
+#define MPT2_IOCTL_VERSION_LENGTH (32)
+
+/**
+ * struct mpt2_ioctl_iocinfo - generic controller info
+ * @hdr - generic header
+ * @adapter_type - type of adapter (spi, fc, sas)
+ * @port_number - port number
+ * @pci_id - PCI Id
+ * @hw_rev - hardware revision
+ * @sub_system_device - PCI subsystem Device ID
+ * @sub_system_vendor - PCI subsystem Vendor ID
+ * @rsvd0 - reserved
+ * @firmware_version - firmware version
+ * @bios_version - BIOS version
+ * @driver_version - driver version - 32 ASCII characters
+ * @rsvd1 - reserved
+ * @scsi_id - scsi id of adapter 0
+ * @rsvd2 - reserved
+ * @pci_information - pci info (2nd revision)
+ */
+struct mpt2_ioctl_iocinfo {
+ struct mpt2_ioctl_header hdr;
+ uint32_t adapter_type;
+ uint32_t port_number;
+ uint32_t pci_id;
+ uint32_t hw_rev;
+ uint32_t subsystem_device;
+ uint32_t subsystem_vendor;
+ uint32_t rsvd0;
+ uint32_t firmware_version;
+ uint32_t bios_version;
+ uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH];
+ uint8_t rsvd1;
+ uint8_t scsi_id;
+ uint16_t rsvd2;
+ struct mpt2_ioctl_pci_info pci_information;
+};
+
+
+/* number of event log entries */
+#define MPT2SAS_CTL_EVENT_LOG_SIZE (50)
+
+/**
+ * struct mpt2_ioctl_eventquery - query event count and type
+ * @hdr - generic header
+ * @event_entries - number of events returned by get_event_report
+ * @rsvd - reserved
+ * @event_types - type of events currently being captured
+ */
+struct mpt2_ioctl_eventquery {
+ struct mpt2_ioctl_header hdr;
+ uint16_t event_entries;
+ uint16_t rsvd;
+ uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS];
+};
+
+/**
+ * struct mpt2_ioctl_eventenable - enable/disable event capturing
+ * @hdr - generic header
+ * @event_types - toggle off/on type of events to be captured
+ */
+struct mpt2_ioctl_eventenable {
+ struct mpt2_ioctl_header hdr;
+ uint32_t event_types[4];
+};
+
+#define MPT2_EVENT_DATA_SIZE (192)
+/**
+ * struct MPT2_IOCTL_EVENTS -
+ * @event - the event that was reported
+ * @context - unique value for each event assigned by driver
+ * @data - event data returned in fw reply message
+ */
+struct MPT2_IOCTL_EVENTS {
+ uint32_t event;
+ uint32_t context;
+ uint8_t data[MPT2_EVENT_DATA_SIZE];
+};
+
+/**
+ * struct mpt2_ioctl_eventreport - returing event log
+ * @hdr - generic header
+ * @event_data - (see struct MPT2_IOCTL_EVENTS)
+ */
+struct mpt2_ioctl_eventreport {
+ struct mpt2_ioctl_header hdr;
+ struct MPT2_IOCTL_EVENTS event_data[1];
+};
+
+/**
+ * struct mpt2_ioctl_command - generic mpt firmware passthru ioclt
+ * @hdr - generic header
+ * @timeout - command timeout in seconds. (if zero then use driver default
+ * value).
+ * @reply_frame_buf_ptr - reply location
+ * @data_in_buf_ptr - destination for read
+ * @data_out_buf_ptr - data source for write
+ * @sense_data_ptr - sense data location
+ * @max_reply_bytes - maximum number of reply bytes to be sent to app.
+ * @data_in_size - number bytes for data transfer in (read)
+ * @data_out_size - number bytes for data transfer out (write)
+ * @max_sense_bytes - maximum number of bytes for auto sense buffers
+ * @data_sge_offset - offset in words from the start of the request message to
+ * the first SGL
+ * @mf[1];
+ */
+struct mpt2_ioctl_command {
+ struct mpt2_ioctl_header hdr;
+ uint32_t timeout;
+ void __user *reply_frame_buf_ptr;
+ void __user *data_in_buf_ptr;
+ void __user *data_out_buf_ptr;
+ void __user *sense_data_ptr;
+ uint32_t max_reply_bytes;
+ uint32_t data_in_size;
+ uint32_t data_out_size;
+ uint32_t max_sense_bytes;
+ uint32_t data_sge_offset;
+ uint8_t mf[1];
+};
+
+#ifdef CONFIG_COMPAT
+struct mpt2_ioctl_command32 {
+ struct mpt2_ioctl_header hdr;
+ uint32_t timeout;
+ uint32_t reply_frame_buf_ptr;
+ uint32_t data_in_buf_ptr;
+ uint32_t data_out_buf_ptr;
+ uint32_t sense_data_ptr;
+ uint32_t max_reply_bytes;
+ uint32_t data_in_size;
+ uint32_t data_out_size;
+ uint32_t max_sense_bytes;
+ uint32_t data_sge_offset;
+ uint8_t mf[1];
+};
+#endif
+
+/**
+ * struct mpt2_ioctl_btdh_mapping - mapping info
+ * @hdr - generic header
+ * @id - target device identification number
+ * @bus - SCSI bus number that the target device exists on
+ * @handle - device handle for the target device
+ * @rsvd - reserved
+ *
+ * To obtain a bus/id the application sets
+ * handle to valid handle, and bus/id to 0xFFFF.
+ *
+ * To obtain the device handle the application sets
+ * bus/id valid value, and the handle to 0xFFFF.
+ */
+struct mpt2_ioctl_btdh_mapping {
+ struct mpt2_ioctl_header hdr;
+ uint32_t id;
+ uint32_t bus;
+ uint16_t handle;
+ uint16_t rsvd;
+};
+
+
+/* status bits for ioc->diag_buffer_status */
+#define MPT2_DIAG_BUFFER_IS_REGISTERED (0x01)
+#define MPT2_DIAG_BUFFER_IS_RELEASED (0x02)
+
+/* application flags for mpt2_diag_register, mpt2_diag_query */
+#define MPT2_APP_FLAGS_APP_OWNED (0x0001)
+#define MPT2_APP_FLAGS_BUFFER_VALID (0x0002)
+#define MPT2_APP_FLAGS_FW_BUFFER_ACCESS (0x0004)
+
+/* flags for mpt2_diag_read_buffer */
+#define MPT2_FLAGS_REREGISTER (0x0001)
+
+#define MPT2_PRODUCT_SPECIFIC_DWORDS 23
+
+/**
+ * struct mpt2_diag_register - application register with driver
+ * @hdr - generic header
+ * @reserved -
+ * @buffer_type - specifies either TRACE or SNAPSHOT
+ * @application_flags - misc flags
+ * @diagnostic_flags - specifies flags affecting command processing
+ * @product_specific - product specific information
+ * @requested_buffer_size - buffers size in bytes
+ * @unique_id - tag specified by application that is used to signal ownership
+ * of the buffer.
+ *
+ * This will allow the driver to setup any required buffers that will be
+ * needed by firmware to communicate with the driver.
+ */
+struct mpt2_diag_register {
+ struct mpt2_ioctl_header hdr;
+ uint8_t reserved;
+ uint8_t buffer_type;
+ uint16_t application_flags;
+ uint32_t diagnostic_flags;
+ uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS];
+ uint32_t requested_buffer_size;
+ uint32_t unique_id;
+};
+
+/**
+ * struct mpt2_diag_unregister - application unregister with driver
+ * @hdr - generic header
+ * @unique_id - tag uniquely identifies the buffer to be unregistered
+ *
+ * This will allow the driver to cleanup any memory allocated for diag
+ * messages and to free up any resources.
+ */
+struct mpt2_diag_unregister {
+ struct mpt2_ioctl_header hdr;
+ uint32_t unique_id;
+};
+
+/**
+ * struct mpt2_diag_query - query relevant info associated with diag buffers
+ * @hdr - generic header
+ * @reserved -
+ * @buffer_type - specifies either TRACE or SNAPSHOT
+ * @application_flags - misc flags
+ * @diagnostic_flags - specifies flags affecting command processing
+ * @product_specific - product specific information
+ * @total_buffer_size - diag buffer size in bytes
+ * @driver_added_buffer_size - size of extra space appended to end of buffer
+ * @unique_id - unique id associated with this buffer.
+ *
+ * The application will send only buffer_type and unique_id. Driver will
+ * inspect unique_id first, if valid, fill in all the info. If unique_id is
+ * 0x00, the driver will return info specified by Buffer Type.
+ */
+struct mpt2_diag_query {
+ struct mpt2_ioctl_header hdr;
+ uint8_t reserved;
+ uint8_t buffer_type;
+ uint16_t application_flags;
+ uint32_t diagnostic_flags;
+ uint32_t product_specific[MPT2_PRODUCT_SPECIFIC_DWORDS];
+ uint32_t total_buffer_size;
+ uint32_t driver_added_buffer_size;
+ uint32_t unique_id;
+};
+
+/**
+ * struct mpt2_diag_release - request to send Diag Release Message to firmware
+ * @hdr - generic header
+ * @unique_id - tag uniquely identifies the buffer to be released
+ *
+ * This allows ownership of the specified buffer to returned to the driver,
+ * allowing an application to read the buffer without fear that firmware is
+ * overwritting information in the buffer.
+ */
+struct mpt2_diag_release {
+ struct mpt2_ioctl_header hdr;
+ uint32_t unique_id;
+};
+
+/**
+ * struct mpt2_diag_read_buffer - request for copy of the diag buffer
+ * @hdr - generic header
+ * @status -
+ * @reserved -
+ * @flags - misc flags
+ * @starting_offset - starting offset within drivers buffer where to start
+ * reading data at into the specified application buffer
+ * @bytes_to_read - number of bytes to copy from the drivers buffer into the
+ * application buffer starting at starting_offset.
+ * @unique_id - unique id associated with this buffer.
+ * @diagnostic_data - data payload
+ */
+struct mpt2_diag_read_buffer {
+ struct mpt2_ioctl_header hdr;
+ uint8_t status;
+ uint8_t reserved;
+ uint16_t flags;
+ uint32_t starting_offset;
+ uint32_t bytes_to_read;
+ uint32_t unique_id;
+ uint32_t diagnostic_data[1];
+};
+
+#endif /* MPT2SAS_CTL_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_debug.h b/drivers/scsi/mpt2sas/mpt2sas_debug.h
new file mode 100644
index 00000000000..ad325096e84
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_debug.h
@@ -0,0 +1,181 @@
+/*
+ * Logging Support for MPT (Message Passing Technology) based controllers
+ *
+ * This code is based on drivers/scsi/mpt2sas/mpt2_debug.c
+ * Copyright (C) 2007-2008 LSI Corporation
+ * (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#ifndef MPT2SAS_DEBUG_H_INCLUDED
+#define MPT2SAS_DEBUG_H_INCLUDED
+
+#define MPT_DEBUG 0x00000001
+#define MPT_DEBUG_MSG_FRAME 0x00000002
+#define MPT_DEBUG_SG 0x00000004
+#define MPT_DEBUG_EVENTS 0x00000008
+#define MPT_DEBUG_EVENT_WORK_TASK 0x00000010
+#define MPT_DEBUG_INIT 0x00000020
+#define MPT_DEBUG_EXIT 0x00000040
+#define MPT_DEBUG_FAIL 0x00000080
+#define MPT_DEBUG_TM 0x00000100
+#define MPT_DEBUG_REPLY 0x00000200
+#define MPT_DEBUG_HANDSHAKE 0x00000400
+#define MPT_DEBUG_CONFIG 0x00000800
+#define MPT_DEBUG_DL 0x00001000
+#define MPT_DEBUG_RESET 0x00002000
+#define MPT_DEBUG_SCSI 0x00004000
+#define MPT_DEBUG_IOCTL 0x00008000
+#define MPT_DEBUG_CSMISAS 0x00010000
+#define MPT_DEBUG_SAS 0x00020000
+#define MPT_DEBUG_TRANSPORT 0x00040000
+#define MPT_DEBUG_TASK_SET_FULL 0x00080000
+
+#define MPT_DEBUG_TARGET_MODE 0x00100000
+
+
+/*
+ * CONFIG_SCSI_MPT2SAS_LOGGING - enabled in Kconfig
+ */
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \
+{ \
+ if (IOC->logging_level & BITS) \
+ CMD; \
+}
+#else
+#define MPT_CHECK_LOGGING(IOC, CMD, BITS)
+#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */
+
+
+/*
+ * debug macros
+ */
+
+#define dprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG)
+
+#define dsgprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG)
+
+#define devtprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS)
+
+#define dewtprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK)
+
+#define dinitprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT)
+
+#define dexitprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT)
+
+#define dfailprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL)
+
+#define dtmprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM)
+
+#define dreplyprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY)
+
+#define dhsprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE)
+
+#define dcprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG)
+
+#define ddlprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL)
+
+#define drsprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET)
+
+#define dsprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI)
+
+#define dctlprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL)
+
+#define dcsmisasprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CSMISAS)
+
+#define dsasprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS)
+
+#define dsastransport(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE)
+
+#define dmfprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME)
+
+#define dtsfprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL)
+
+#define dtransportprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT)
+
+#define dTMprintk(IOC, CMD) \
+ MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TARGET_MODE)
+
+/* inline functions for dumping debug data*/
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _debug_dump_mf - print message frame contents
+ * @mpi_request: pointer to message frame
+ * @sz: number of dwords
+ */
+static inline void
+_debug_dump_mf(void *mpi_request, int sz)
+{
+ int i;
+ u32 *mfp = (u32 *)mpi_request;
+
+ printk(KERN_INFO "mf:\n\t");
+ for (i = 0; i < sz; i++) {
+ if (i && ((i % 8) == 0))
+ printk("\n\t");
+ printk("%08x ", le32_to_cpu(mfp[i]));
+ }
+ printk("\n");
+}
+#else
+#define _debug_dump_mf(mpi_request, sz)
+#endif /* CONFIG_SCSI_MPT2SAS_LOGGING */
+
+#endif /* MPT2SAS_DEBUG_H_INCLUDED */
diff --git a/drivers/scsi/mpt2sas/mpt2sas_scsih.c b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
new file mode 100644
index 00000000000..0c463c483c0
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_scsih.c
@@ -0,0 +1,5687 @@
+/*
+ * Scsi Host Layer for MPT (Message Passing Technology) based controllers
+ *
+ * This code is based on drivers/scsi/mpt2sas/mpt2_scsih.c
+ * Copyright (C) 2007-2008 LSI Corporation
+ * (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/blkdev.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include "mpt2sas_base.h"
+
+MODULE_AUTHOR(MPT2SAS_AUTHOR);
+MODULE_DESCRIPTION(MPT2SAS_DESCRIPTION);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(MPT2SAS_DRIVER_VERSION);
+
+#define RAID_CHANNEL 1
+
+/* forward proto's */
+static void _scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_node *sas_expander);
+static void _firmware_event_work(struct work_struct *work);
+
+/* global parameters */
+LIST_HEAD(mpt2sas_ioc_list);
+
+/* local parameters */
+static u8 scsi_io_cb_idx = -1;
+static u8 tm_cb_idx = -1;
+static u8 ctl_cb_idx = -1;
+static u8 base_cb_idx = -1;
+static u8 transport_cb_idx = -1;
+static u8 config_cb_idx = -1;
+static int mpt_ids;
+
+/* command line options */
+static u32 logging_level;
+MODULE_PARM_DESC(logging_level, " bits for enabling additional logging info "
+ "(default=0)");
+
+/* scsi-mid layer global parmeter is max_report_luns, which is 511 */
+#define MPT2SAS_MAX_LUN (16895)
+static int max_lun = MPT2SAS_MAX_LUN;
+module_param(max_lun, int, 0);
+MODULE_PARM_DESC(max_lun, " max lun, default=16895 ");
+
+/**
+ * struct sense_info - common structure for obtaining sense keys
+ * @skey: sense key
+ * @asc: additional sense code
+ * @ascq: additional sense code qualifier
+ */
+struct sense_info {
+ u8 skey;
+ u8 asc;
+ u8 ascq;
+};
+
+
+#define MPT2SAS_RESCAN_AFTER_HOST_RESET (0xFFFF)
+/**
+ * struct fw_event_work - firmware event struct
+ * @list: link list framework
+ * @work: work object (ioc->fault_reset_work_q)
+ * @ioc: per adapter object
+ * @VF_ID: virtual function id
+ * @host_reset_handling: handling events during host reset
+ * @ignore: flag meaning this event has been marked to ignore
+ * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h
+ * @event_data: reply event data payload follows
+ *
+ * This object stored on ioc->fw_event_list.
+ */
+struct fw_event_work {
+ struct list_head list;
+ struct delayed_work work;
+ struct MPT2SAS_ADAPTER *ioc;
+ u8 VF_ID;
+ u8 host_reset_handling;
+ u8 ignore;
+ u16 event;
+ void *event_data;
+};
+
+/**
+ * struct _scsi_io_transfer - scsi io transfer
+ * @handle: sas device handle (assigned by firmware)
+ * @is_raid: flag set for hidden raid components
+ * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE,
+ * @data_length: data transfer length
+ * @data_dma: dma pointer to data
+ * @sense: sense data
+ * @lun: lun number
+ * @cdb_length: cdb length
+ * @cdb: cdb contents
+ * @valid_reply: flag set for reply message
+ * @timeout: timeout for this command
+ * @sense_length: sense length
+ * @ioc_status: ioc status
+ * @scsi_state: scsi state
+ * @scsi_status: scsi staus
+ * @log_info: log information
+ * @transfer_length: data length transfer when there is a reply message
+ *
+ * Used for sending internal scsi commands to devices within this module.
+ * Refer to _scsi_send_scsi_io().
+ */
+struct _scsi_io_transfer {
+ u16 handle;
+ u8 is_raid;
+ enum dma_data_direction dir;
+ u32 data_length;
+ dma_addr_t data_dma;
+ u8 sense[SCSI_SENSE_BUFFERSIZE];
+ u32 lun;
+ u8 cdb_length;
+ u8 cdb[32];
+ u8 timeout;
+ u8 valid_reply;
+ /* the following bits are only valid when 'valid_reply = 1' */
+ u32 sense_length;
+ u16 ioc_status;
+ u8 scsi_state;
+ u8 scsi_status;
+ u32 log_info;
+ u32 transfer_length;
+};
+
+/*
+ * The pci device ids are defined in mpi/mpi2_cnfg.h.
+ */
+static struct pci_device_id scsih_pci_table[] = {
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Falcon ~ 2008*/
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008,
+ PCI_ANY_ID, PCI_ANY_ID },
+ /* Liberator ~ 2108 */
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1,
+ PCI_ANY_ID, PCI_ANY_ID },
+ { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2,
+ PCI_ANY_ID, PCI_ANY_ID },
+ {0} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(pci, scsih_pci_table);
+
+/**
+ * scsih_set_debug_level - global setting of ioc->logging_level.
+ *
+ * Note: The logging levels are defined in mpt2sas_debug.h.
+ */
+static int
+scsih_set_debug_level(const char *val, struct kernel_param *kp)
+{
+ int ret = param_set_int(val, kp);
+ struct MPT2SAS_ADAPTER *ioc;
+
+ if (ret)
+ return ret;
+
+ printk(KERN_INFO "setting logging_level(0x%08x)\n", logging_level);
+ list_for_each_entry(ioc, &mpt2sas_ioc_list, list)
+ ioc->logging_level = logging_level;
+ return 0;
+}
+module_param_call(logging_level, scsih_set_debug_level, param_get_int,
+ &logging_level, 0644);
+
+/**
+ * _scsih_srch_boot_sas_address - search based on sas_address
+ * @sas_address: sas address
+ * @boot_device: boot device object from bios page 2
+ *
+ * Returns 1 when there's a match, 0 means no match.
+ */
+static inline int
+_scsih_srch_boot_sas_address(u64 sas_address,
+ Mpi2BootDeviceSasWwid_t *boot_device)
+{
+ return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0;
+}
+
+/**
+ * _scsih_srch_boot_device_name - search based on device name
+ * @device_name: device name specified in INDENTIFY fram
+ * @boot_device: boot device object from bios page 2
+ *
+ * Returns 1 when there's a match, 0 means no match.
+ */
+static inline int
+_scsih_srch_boot_device_name(u64 device_name,
+ Mpi2BootDeviceDeviceName_t *boot_device)
+{
+ return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0;
+}
+
+/**
+ * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot
+ * @enclosure_logical_id: enclosure logical id
+ * @slot_number: slot number
+ * @boot_device: boot device object from bios page 2
+ *
+ * Returns 1 when there's a match, 0 means no match.
+ */
+static inline int
+_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number,
+ Mpi2BootDeviceEnclosureSlot_t *boot_device)
+{
+ return (enclosure_logical_id == le64_to_cpu(boot_device->
+ EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device->
+ SlotNumber)) ? 1 : 0;
+}
+
+/**
+ * _scsih_is_boot_device - search for matching boot device.
+ * @sas_address: sas address
+ * @device_name: device name specified in INDENTIFY fram
+ * @enclosure_logical_id: enclosure logical id
+ * @slot_number: slot number
+ * @form: specifies boot device form
+ * @boot_device: boot device object from bios page 2
+ *
+ * Returns 1 when there's a match, 0 means no match.
+ */
+static int
+_scsih_is_boot_device(u64 sas_address, u64 device_name,
+ u64 enclosure_logical_id, u16 slot, u8 form,
+ Mpi2BiosPage2BootDevice_t *boot_device)
+{
+ int rc = 0;
+
+ switch (form) {
+ case MPI2_BIOSPAGE2_FORM_SAS_WWID:
+ if (!sas_address)
+ break;
+ rc = _scsih_srch_boot_sas_address(
+ sas_address, &boot_device->SasWwid);
+ break;
+ case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT:
+ if (!enclosure_logical_id)
+ break;
+ rc = _scsih_srch_boot_encl_slot(
+ enclosure_logical_id,
+ slot, &boot_device->EnclosureSlot);
+ break;
+ case MPI2_BIOSPAGE2_FORM_DEVICE_NAME:
+ if (!device_name)
+ break;
+ rc = _scsih_srch_boot_device_name(
+ device_name, &boot_device->DeviceName);
+ break;
+ case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED:
+ break;
+ }
+
+ return rc;
+}
+
+/**
+ * _scsih_determine_boot_device - determine boot device.
+ * @ioc: per adapter object
+ * @device: either sas_device or raid_device object
+ * @is_raid: [flag] 1 = raid object, 0 = sas object
+ *
+ * Determines whether this device should be first reported device to
+ * to scsi-ml or sas transport, this purpose is for persistant boot device.
+ * There are primary, alternate, and current entries in bios page 2. The order
+ * priority is primary, alternate, then current. This routine saves
+ * the corresponding device object and is_raid flag in the ioc object.
+ * The saved data to be used later in _scsih_probe_boot_devices().
+ */
+static void
+_scsih_determine_boot_device(struct MPT2SAS_ADAPTER *ioc,
+ void *device, u8 is_raid)
+{
+ struct _sas_device *sas_device;
+ struct _raid_device *raid_device;
+ u64 sas_address;
+ u64 device_name;
+ u64 enclosure_logical_id;
+ u16 slot;
+
+ /* only process this function when driver loads */
+ if (!ioc->wait_for_port_enable_to_complete)
+ return;
+
+ if (!is_raid) {
+ sas_device = device;
+ sas_address = sas_device->sas_address;
+ device_name = sas_device->device_name;
+ enclosure_logical_id = sas_device->enclosure_logical_id;
+ slot = sas_device->slot;
+ } else {
+ raid_device = device;
+ sas_address = raid_device->wwid;
+ device_name = 0;
+ enclosure_logical_id = 0;
+ slot = 0;
+ }
+
+ if (!ioc->req_boot_device.device) {
+ if (_scsih_is_boot_device(sas_address, device_name,
+ enclosure_logical_id, slot,
+ (ioc->bios_pg2.ReqBootDeviceForm &
+ MPI2_BIOSPAGE2_FORM_MASK),
+ &ioc->bios_pg2.RequestedBootDevice)) {
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "%s: req_boot_device(0x%016llx)\n",
+ ioc->name, __func__,
+ (unsigned long long)sas_address));
+ ioc->req_boot_device.device = device;
+ ioc->req_boot_device.is_raid = is_raid;
+ }
+ }
+
+ if (!ioc->req_alt_boot_device.device) {
+ if (_scsih_is_boot_device(sas_address, device_name,
+ enclosure_logical_id, slot,
+ (ioc->bios_pg2.ReqAltBootDeviceForm &
+ MPI2_BIOSPAGE2_FORM_MASK),
+ &ioc->bios_pg2.RequestedAltBootDevice)) {
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "%s: req_alt_boot_device(0x%016llx)\n",
+ ioc->name, __func__,
+ (unsigned long long)sas_address));
+ ioc->req_alt_boot_device.device = device;
+ ioc->req_alt_boot_device.is_raid = is_raid;
+ }
+ }
+
+ if (!ioc->current_boot_device.device) {
+ if (_scsih_is_boot_device(sas_address, device_name,
+ enclosure_logical_id, slot,
+ (ioc->bios_pg2.CurrentBootDeviceForm &
+ MPI2_BIOSPAGE2_FORM_MASK),
+ &ioc->bios_pg2.CurrentBootDevice)) {
+ dinitprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "%s: current_boot_device(0x%016llx)\n",
+ ioc->name, __func__,
+ (unsigned long long)sas_address));
+ ioc->current_boot_device.device = device;
+ ioc->current_boot_device.is_raid = is_raid;
+ }
+ }
+}
+
+/**
+ * mpt2sas_scsih_sas_device_find_by_sas_address - sas device search
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for sas_device based on sas_address, then return sas_device
+ * object.
+ */
+struct _sas_device *
+mpt2sas_scsih_sas_device_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
+ u64 sas_address)
+{
+ struct _sas_device *sas_device, *r;
+
+ r = NULL;
+ /* check the sas_device_init_list */
+ list_for_each_entry(sas_device, &ioc->sas_device_init_list,
+ list) {
+ if (sas_device->sas_address != sas_address)
+ continue;
+ r = sas_device;
+ goto out;
+ }
+
+ /* then check the sas_device_list */
+ list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+ if (sas_device->sas_address != sas_address)
+ continue;
+ r = sas_device;
+ goto out;
+ }
+ out:
+ return r;
+}
+
+/**
+ * _scsih_sas_device_find_by_handle - sas device search
+ * @ioc: per adapter object
+ * @handle: sas device handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for sas_device based on sas_address, then return sas_device
+ * object.
+ */
+static struct _sas_device *
+_scsih_sas_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _sas_device *sas_device, *r;
+
+ r = NULL;
+ if (ioc->wait_for_port_enable_to_complete) {
+ list_for_each_entry(sas_device, &ioc->sas_device_init_list,
+ list) {
+ if (sas_device->handle != handle)
+ continue;
+ r = sas_device;
+ goto out;
+ }
+ } else {
+ list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+ if (sas_device->handle != handle)
+ continue;
+ r = sas_device;
+ goto out;
+ }
+ }
+
+ out:
+ return r;
+}
+
+/**
+ * _scsih_sas_device_remove - remove sas_device from list.
+ * @ioc: per adapter object
+ * @sas_device: the sas_device object
+ * Context: This function will acquire ioc->sas_device_lock.
+ *
+ * Removing object and freeing associated memory from the ioc->sas_device_list.
+ */
+static void
+_scsih_sas_device_remove(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_device *sas_device)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ list_del(&sas_device->list);
+ memset(sas_device, 0, sizeof(struct _sas_device));
+ kfree(sas_device);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+}
+
+/**
+ * _scsih_sas_device_add - insert sas_device to the list.
+ * @ioc: per adapter object
+ * @sas_device: the sas_device object
+ * Context: This function will acquire ioc->sas_device_lock.
+ *
+ * Adding new object to the ioc->sas_device_list.
+ */
+static void
+_scsih_sas_device_add(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_device *sas_device)
+{
+ unsigned long flags;
+ u16 handle, parent_handle;
+ u64 sas_address;
+
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle"
+ "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
+ sas_device->handle, (unsigned long long)sas_device->sas_address));
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ list_add_tail(&sas_device->list, &ioc->sas_device_list);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ handle = sas_device->handle;
+ parent_handle = sas_device->parent_handle;
+ sas_address = sas_device->sas_address;
+ if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) {
+ _scsih_sas_device_remove(ioc, sas_device);
+ } else if (!sas_device->starget) {
+ mpt2sas_transport_port_remove(ioc, sas_address, parent_handle);
+ _scsih_sas_device_remove(ioc, sas_device);
+ }
+}
+
+/**
+ * _scsih_sas_device_init_add - insert sas_device to the list.
+ * @ioc: per adapter object
+ * @sas_device: the sas_device object
+ * Context: This function will acquire ioc->sas_device_lock.
+ *
+ * Adding new object at driver load time to the ioc->sas_device_init_list.
+ */
+static void
+_scsih_sas_device_init_add(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_device *sas_device)
+{
+ unsigned long flags;
+
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle"
+ "(0x%04x), sas_addr(0x%016llx)\n", ioc->name, __func__,
+ sas_device->handle, (unsigned long long)sas_device->sas_address));
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ list_add_tail(&sas_device->list, &ioc->sas_device_init_list);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ _scsih_determine_boot_device(ioc, sas_device, 0);
+}
+
+/**
+ * mpt2sas_scsih_expander_find_by_handle - expander device search
+ * @ioc: per adapter object
+ * @handle: expander handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->sas_device_lock
+ *
+ * This searches for expander device based on handle, then returns the
+ * sas_node object.
+ */
+struct _sas_node *
+mpt2sas_scsih_expander_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _sas_node *sas_expander, *r;
+
+ r = NULL;
+ list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
+ if (sas_expander->handle != handle)
+ continue;
+ r = sas_expander;
+ goto out;
+ }
+ out:
+ return r;
+}
+
+/**
+ * _scsih_raid_device_find_by_id - raid device search
+ * @ioc: per adapter object
+ * @id: sas device target id
+ * @channel: sas device channel
+ * Context: Calling function should acquire ioc->raid_device_lock
+ *
+ * This searches for raid_device based on target id, then return raid_device
+ * object.
+ */
+static struct _raid_device *
+_scsih_raid_device_find_by_id(struct MPT2SAS_ADAPTER *ioc, int id, int channel)
+{
+ struct _raid_device *raid_device, *r;
+
+ r = NULL;
+ list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+ if (raid_device->id == id && raid_device->channel == channel) {
+ r = raid_device;
+ goto out;
+ }
+ }
+
+ out:
+ return r;
+}
+
+/**
+ * _scsih_raid_device_find_by_handle - raid device search
+ * @ioc: per adapter object
+ * @handle: sas device handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->raid_device_lock
+ *
+ * This searches for raid_device based on handle, then return raid_device
+ * object.
+ */
+static struct _raid_device *
+_scsih_raid_device_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _raid_device *raid_device, *r;
+
+ r = NULL;
+ list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+ if (raid_device->handle != handle)
+ continue;
+ r = raid_device;
+ goto out;
+ }
+
+ out:
+ return r;
+}
+
+/**
+ * _scsih_raid_device_find_by_wwid - raid device search
+ * @ioc: per adapter object
+ * @handle: sas device handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->raid_device_lock
+ *
+ * This searches for raid_device based on wwid, then return raid_device
+ * object.
+ */
+static struct _raid_device *
+_scsih_raid_device_find_by_wwid(struct MPT2SAS_ADAPTER *ioc, u64 wwid)
+{
+ struct _raid_device *raid_device, *r;
+
+ r = NULL;
+ list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+ if (raid_device->wwid != wwid)
+ continue;
+ r = raid_device;
+ goto out;
+ }
+
+ out:
+ return r;
+}
+
+/**
+ * _scsih_raid_device_add - add raid_device object
+ * @ioc: per adapter object
+ * @raid_device: raid_device object
+ *
+ * This is added to the raid_device_list link list.
+ */
+static void
+_scsih_raid_device_add(struct MPT2SAS_ADAPTER *ioc,
+ struct _raid_device *raid_device)
+{
+ unsigned long flags;
+
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle"
+ "(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__,
+ raid_device->handle, (unsigned long long)raid_device->wwid));
+
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ list_add_tail(&raid_device->list, &ioc->raid_device_list);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+}
+
+/**
+ * _scsih_raid_device_remove - delete raid_device object
+ * @ioc: per adapter object
+ * @raid_device: raid_device object
+ *
+ * This is removed from the raid_device_list link list.
+ */
+static void
+_scsih_raid_device_remove(struct MPT2SAS_ADAPTER *ioc,
+ struct _raid_device *raid_device)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ list_del(&raid_device->list);
+ memset(raid_device, 0, sizeof(struct _raid_device));
+ kfree(raid_device);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+}
+
+/**
+ * mpt2sas_scsih_expander_find_by_sas_address - expander device search
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * Context: Calling function should acquire ioc->sas_node_lock.
+ *
+ * This searches for expander device based on sas_address, then returns the
+ * sas_node object.
+ */
+struct _sas_node *
+mpt2sas_scsih_expander_find_by_sas_address(struct MPT2SAS_ADAPTER *ioc,
+ u64 sas_address)
+{
+ struct _sas_node *sas_expander, *r;
+
+ r = NULL;
+ list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
+ if (sas_expander->sas_address != sas_address)
+ continue;
+ r = sas_expander;
+ goto out;
+ }
+ out:
+ return r;
+}
+
+/**
+ * _scsih_expander_node_add - insert expander device to the list.
+ * @ioc: per adapter object
+ * @sas_expander: the sas_device object
+ * Context: This function will acquire ioc->sas_node_lock.
+ *
+ * Adding new object to the ioc->sas_expander_list.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_expander_node_add(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_node *sas_expander)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ list_add_tail(&sas_expander->list, &ioc->sas_expander_list);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+}
+
+/**
+ * _scsih_is_end_device - determines if device is an end device
+ * @device_info: bitfield providing information about the device.
+ * Context: none
+ *
+ * Returns 1 if end device.
+ */
+static int
+_scsih_is_end_device(u32 device_info)
+{
+ if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE &&
+ ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) |
+ (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) |
+ (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)))
+ return 1;
+ else
+ return 0;
+}
+
+/**
+ * _scsih_scsi_lookup_get - returns scmd entry
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * Returns the smid stored scmd pointer.
+ */
+static struct scsi_cmnd *
+_scsih_scsi_lookup_get(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ unsigned long flags;
+ struct scsi_cmnd *scmd;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ scmd = ioc->scsi_lookup[smid - 1].scmd;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ return scmd;
+}
+
+/**
+ * mptscsih_getclear_scsi_lookup - returns scmd entry
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * Returns the smid stored scmd pointer, as well as clearing the scmd pointer.
+ */
+static struct scsi_cmnd *
+_scsih_scsi_lookup_getclear(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ unsigned long flags;
+ struct scsi_cmnd *scmd;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ scmd = ioc->scsi_lookup[smid - 1].scmd;
+ ioc->scsi_lookup[smid - 1].scmd = NULL;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ return scmd;
+}
+
+/**
+ * _scsih_scsi_lookup_set - updates scmd entry in lookup
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @scmd: pointer to scsi command object
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * This will save scmd pointer in the scsi_lookup array.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_scsi_lookup_set(struct MPT2SAS_ADAPTER *ioc, u16 smid,
+ struct scsi_cmnd *scmd)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ ioc->scsi_lookup[smid - 1].scmd = scmd;
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+}
+
+/**
+ * _scsih_scsi_lookup_find_by_scmd - scmd lookup
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @scmd: pointer to scsi command object
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * This will search for a scmd pointer in the scsi_lookup array,
+ * returning the revelent smid. A returned value of zero means invalid.
+ */
+static u16
+_scsih_scsi_lookup_find_by_scmd(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd
+ *scmd)
+{
+ u16 smid;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ smid = 0;
+ for (i = 0; i < ioc->request_depth; i++) {
+ if (ioc->scsi_lookup[i].scmd == scmd) {
+ smid = i + 1;
+ goto out;
+ }
+ }
+ out:
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ return smid;
+}
+
+/**
+ * _scsih_scsi_lookup_find_by_target - search for matching channel:id
+ * @ioc: per adapter object
+ * @id: target id
+ * @channel: channel
+ * Context: This function will acquire ioc->scsi_lookup_lock.
+ *
+ * This will search for a matching channel:id in the scsi_lookup array,
+ * returning 1 if found.
+ */
+static u8
+_scsih_scsi_lookup_find_by_target(struct MPT2SAS_ADAPTER *ioc, int id,
+ int channel)
+{
+ u8 found;
+ unsigned long flags;
+ int i;
+
+ spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
+ found = 0;
+ for (i = 0 ; i < ioc->request_depth; i++) {
+ if (ioc->scsi_lookup[i].scmd &&
+ (ioc->scsi_lookup[i].scmd->device->id == id &&
+ ioc->scsi_lookup[i].scmd->device->channel == channel)) {
+ found = 1;
+ goto out;
+ }
+ }
+ out:
+ spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
+ return found;
+}
+
+/**
+ * _scsih_get_chain_buffer_dma - obtain block of chains (dma address)
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns phys pointer to chain buffer.
+ */
+static dma_addr_t
+_scsih_get_chain_buffer_dma(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ return ioc->chain_dma + ((smid - 1) * (ioc->request_sz *
+ ioc->chains_needed_per_io));
+}
+
+/**
+ * _scsih_get_chain_buffer - obtain block of chains assigned to a mf request
+ * @ioc: per adapter object
+ * @smid: system request message index
+ *
+ * Returns virt pointer to chain buffer.
+ */
+static void *
+_scsih_get_chain_buffer(struct MPT2SAS_ADAPTER *ioc, u16 smid)
+{
+ return (void *)(ioc->chain + ((smid - 1) * (ioc->request_sz *
+ ioc->chains_needed_per_io)));
+}
+
+/**
+ * _scsih_build_scatter_gather - main sg creation routine
+ * @ioc: per adapter object
+ * @scmd: scsi command
+ * @smid: system request message index
+ * Context: none.
+ *
+ * The main routine that builds scatter gather table from a given
+ * scsi request sent via the .queuecommand main handler.
+ *
+ * Returns 0 success, anything else error
+ */
+static int
+_scsih_build_scatter_gather(struct MPT2SAS_ADAPTER *ioc,
+ struct scsi_cmnd *scmd, u16 smid)
+{
+ Mpi2SCSIIORequest_t *mpi_request;
+ dma_addr_t chain_dma;
+ struct scatterlist *sg_scmd;
+ void *sg_local, *chain;
+ u32 chain_offset;
+ u32 chain_length;
+ u32 chain_flags;
+ u32 sges_left;
+ u32 sges_in_segment;
+ u32 sgl_flags;
+ u32 sgl_flags_last_element;
+ u32 sgl_flags_end_buffer;
+
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+
+ /* init scatter gather flags */
+ sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT;
+ if (scmd->sc_data_direction == DMA_TO_DEVICE)
+ sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC;
+ sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT)
+ << MPI2_SGE_FLAGS_SHIFT;
+ sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT |
+ MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST)
+ << MPI2_SGE_FLAGS_SHIFT;
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+
+ sg_scmd = scsi_sglist(scmd);
+ sges_left = scsi_dma_map(scmd);
+ if (!sges_left) {
+ sdev_printk(KERN_ERR, scmd->device, "pci_map_sg"
+ " failed: request for %d bytes!\n", scsi_bufflen(scmd));
+ return -ENOMEM;
+ }
+
+ sg_local = &mpi_request->SGL;
+ sges_in_segment = ioc->max_sges_in_main_message;
+ if (sges_left <= sges_in_segment)
+ goto fill_in_last_segment;
+
+ mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) +
+ (sges_in_segment * ioc->sge_size))/4;
+
+ /* fill in main message segment when there is a chain following */
+ while (sges_in_segment) {
+ if (sges_in_segment == 1)
+ ioc->base_add_sg_single(sg_local,
+ sgl_flags_last_element | sg_dma_len(sg_scmd),
+ sg_dma_address(sg_scmd));
+ else
+ ioc->base_add_sg_single(sg_local, sgl_flags |
+ sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+ sg_scmd = sg_next(sg_scmd);
+ sg_local += ioc->sge_size;
+ sges_left--;
+ sges_in_segment--;
+ }
+
+ /* initializing the chain flags and pointers */
+ chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT;
+ chain = _scsih_get_chain_buffer(ioc, smid);
+ chain_dma = _scsih_get_chain_buffer_dma(ioc, smid);
+ do {
+ sges_in_segment = (sges_left <=
+ ioc->max_sges_in_chain_message) ? sges_left :
+ ioc->max_sges_in_chain_message;
+ chain_offset = (sges_left == sges_in_segment) ?
+ 0 : (sges_in_segment * ioc->sge_size)/4;
+ chain_length = sges_in_segment * ioc->sge_size;
+ if (chain_offset) {
+ chain_offset = chain_offset <<
+ MPI2_SGE_CHAIN_OFFSET_SHIFT;
+ chain_length += ioc->sge_size;
+ }
+ ioc->base_add_sg_single(sg_local, chain_flags | chain_offset |
+ chain_length, chain_dma);
+ sg_local = chain;
+ if (!chain_offset)
+ goto fill_in_last_segment;
+
+ /* fill in chain segments */
+ while (sges_in_segment) {
+ if (sges_in_segment == 1)
+ ioc->base_add_sg_single(sg_local,
+ sgl_flags_last_element |
+ sg_dma_len(sg_scmd),
+ sg_dma_address(sg_scmd));
+ else
+ ioc->base_add_sg_single(sg_local, sgl_flags |
+ sg_dma_len(sg_scmd),
+ sg_dma_address(sg_scmd));
+ sg_scmd = sg_next(sg_scmd);
+ sg_local += ioc->sge_size;
+ sges_left--;
+ sges_in_segment--;
+ }
+
+ chain_dma += ioc->request_sz;
+ chain += ioc->request_sz;
+ } while (1);
+
+
+ fill_in_last_segment:
+
+ /* fill the last segment */
+ while (sges_left) {
+ if (sges_left == 1)
+ ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer |
+ sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+ else
+ ioc->base_add_sg_single(sg_local, sgl_flags |
+ sg_dma_len(sg_scmd), sg_dma_address(sg_scmd));
+ sg_scmd = sg_next(sg_scmd);
+ sg_local += ioc->sge_size;
+ sges_left--;
+ }
+
+ return 0;
+}
+
+/**
+ * scsih_change_queue_depth - setting device queue depth
+ * @sdev: scsi device struct
+ * @qdepth: requested queue depth
+ *
+ * Returns queue depth.
+ */
+static int
+scsih_change_queue_depth(struct scsi_device *sdev, int qdepth)
+{
+ struct Scsi_Host *shost = sdev->host;
+ int max_depth;
+ int tag_type;
+
+ max_depth = shost->can_queue;
+ if (!sdev->tagged_supported)
+ max_depth = 1;
+ if (qdepth > max_depth)
+ qdepth = max_depth;
+ tag_type = (qdepth == 1) ? 0 : MSG_SIMPLE_TAG;
+ scsi_adjust_queue_depth(sdev, tag_type, qdepth);
+
+ if (sdev->inquiry_len > 7)
+ sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), "
+ "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n",
+ sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags,
+ sdev->ordered_tags, sdev->scsi_level,
+ (sdev->inquiry[7] & 2) >> 1);
+
+ return sdev->queue_depth;
+}
+
+/**
+ * scsih_change_queue_depth - changing device queue tag type
+ * @sdev: scsi device struct
+ * @tag_type: requested tag type
+ *
+ * Returns queue tag type.
+ */
+static int
+scsih_change_queue_type(struct scsi_device *sdev, int tag_type)
+{
+ if (sdev->tagged_supported) {
+ scsi_set_tag_type(sdev, tag_type);
+ if (tag_type)
+ scsi_activate_tcq(sdev, sdev->queue_depth);
+ else
+ scsi_deactivate_tcq(sdev, sdev->queue_depth);
+ } else
+ tag_type = 0;
+
+ return tag_type;
+}
+
+/**
+ * scsih_target_alloc - target add routine
+ * @starget: scsi target struct
+ *
+ * Returns 0 if ok. Any other return is assumed to be an error and
+ * the device is ignored.
+ */
+static int
+scsih_target_alloc(struct scsi_target *starget)
+{
+ struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct _sas_device *sas_device;
+ struct _raid_device *raid_device;
+ unsigned long flags;
+ struct sas_rphy *rphy;
+
+ sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL);
+ if (!sas_target_priv_data)
+ return -ENOMEM;
+
+ starget->hostdata = sas_target_priv_data;
+ sas_target_priv_data->starget = starget;
+ sas_target_priv_data->handle = MPT2SAS_INVALID_DEVICE_HANDLE;
+
+ /* RAID volumes */
+ if (starget->channel == RAID_CHANNEL) {
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
+ starget->channel);
+ if (raid_device) {
+ sas_target_priv_data->handle = raid_device->handle;
+ sas_target_priv_data->sas_address = raid_device->wwid;
+ sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME;
+ raid_device->starget = starget;
+ }
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ return 0;
+ }
+
+ /* sas/sata devices */
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ rphy = dev_to_rphy(starget->dev.parent);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ rphy->identify.sas_address);
+
+ if (sas_device) {
+ sas_target_priv_data->handle = sas_device->handle;
+ sas_target_priv_data->sas_address = sas_device->sas_address;
+ sas_device->starget = starget;
+ sas_device->id = starget->id;
+ sas_device->channel = starget->channel;
+ if (sas_device->hidden_raid_component)
+ sas_target_priv_data->flags |=
+ MPT_TARGET_FLAGS_RAID_COMPONENT;
+ }
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ return 0;
+}
+
+/**
+ * scsih_target_destroy - target destroy routine
+ * @starget: scsi target struct
+ *
+ * Returns nothing.
+ */
+static void
+scsih_target_destroy(struct scsi_target *starget)
+{
+ struct Scsi_Host *shost = dev_to_shost(&starget->dev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct _sas_device *sas_device;
+ struct _raid_device *raid_device;
+ unsigned long flags;
+ struct sas_rphy *rphy;
+
+ sas_target_priv_data = starget->hostdata;
+ if (!sas_target_priv_data)
+ return;
+
+ if (starget->channel == RAID_CHANNEL) {
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = _scsih_raid_device_find_by_id(ioc, starget->id,
+ starget->channel);
+ if (raid_device) {
+ raid_device->starget = NULL;
+ raid_device->sdev = NULL;
+ }
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ goto out;
+ }
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ rphy = dev_to_rphy(starget->dev.parent);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ rphy->identify.sas_address);
+ if (sas_device)
+ sas_device->starget = NULL;
+
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ out:
+ kfree(sas_target_priv_data);
+ starget->hostdata = NULL;
+}
+
+/**
+ * scsih_slave_alloc - device add routine
+ * @sdev: scsi device struct
+ *
+ * Returns 0 if ok. Any other return is assumed to be an error and
+ * the device is ignored.
+ */
+static int
+scsih_slave_alloc(struct scsi_device *sdev)
+{
+ struct Scsi_Host *shost;
+ struct MPT2SAS_ADAPTER *ioc;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_target *starget;
+ struct _raid_device *raid_device;
+ struct _sas_device *sas_device;
+ unsigned long flags;
+
+ sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL);
+ if (!sas_device_priv_data)
+ return -ENOMEM;
+
+ sas_device_priv_data->lun = sdev->lun;
+ sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT;
+
+ starget = scsi_target(sdev);
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->num_luns++;
+ sas_device_priv_data->sas_target = sas_target_priv_data;
+ sdev->hostdata = sas_device_priv_data;
+ if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT))
+ sdev->no_uld_attach = 1;
+
+ shost = dev_to_shost(&starget->dev);
+ ioc = shost_priv(shost);
+ if (starget->channel == RAID_CHANNEL) {
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = _scsih_raid_device_find_by_id(ioc,
+ starget->id, starget->channel);
+ if (raid_device)
+ raid_device->sdev = sdev; /* raid is single lun */
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ } else {
+ /* set TLR bit for SSP devices */
+ if (!(ioc->facts.IOCCapabilities &
+ MPI2_IOCFACTS_CAPABILITY_TLR))
+ goto out;
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device_priv_data->sas_target->sas_address);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (sas_device && sas_device->device_info &
+ MPI2_SAS_DEVICE_INFO_SSP_TARGET)
+ sas_device_priv_data->flags |= MPT_DEVICE_TLR_ON;
+ }
+
+ out:
+ return 0;
+}
+
+/**
+ * scsih_slave_destroy - device destroy routine
+ * @sdev: scsi device struct
+ *
+ * Returns nothing.
+ */
+static void
+scsih_slave_destroy(struct scsi_device *sdev)
+{
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct scsi_target *starget;
+
+ if (!sdev->hostdata)
+ return;
+
+ starget = scsi_target(sdev);
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->num_luns--;
+ kfree(sdev->hostdata);
+ sdev->hostdata = NULL;
+}
+
+/**
+ * scsih_display_sata_capabilities - sata capabilities
+ * @ioc: per adapter object
+ * @sas_device: the sas_device object
+ * @sdev: scsi device struct
+ */
+static void
+scsih_display_sata_capabilities(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_device *sas_device, struct scsi_device *sdev)
+{
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ u32 ioc_status;
+ u16 flags;
+ u32 device_info;
+
+ if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+ MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, sas_device->handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ flags = le16_to_cpu(sas_device_pg0.Flags);
+ device_info = le16_to_cpu(sas_device_pg0.DeviceInfo);
+
+ sdev_printk(KERN_INFO, sdev,
+ "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), "
+ "sw_preserve(%s)\n",
+ (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n",
+ (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n",
+ (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" :
+ "n",
+ (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n",
+ (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n",
+ (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n");
+}
+
+/**
+ * _scsih_get_volume_capabilities - volume capabilities
+ * @ioc: per adapter object
+ * @sas_device: the raid_device object
+ */
+static void
+_scsih_get_volume_capabilities(struct MPT2SAS_ADAPTER *ioc,
+ struct _raid_device *raid_device)
+{
+ Mpi2RaidVolPage0_t *vol_pg0;
+ Mpi2RaidPhysDiskPage0_t pd_pg0;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ Mpi2ConfigReply_t mpi_reply;
+ u16 sz;
+ u8 num_pds;
+
+ if ((mpt2sas_config_get_number_pds(ioc, raid_device->handle,
+ &num_pds)) || !num_pds) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ raid_device->num_pds = num_pds;
+ sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds *
+ sizeof(Mpi2RaidVol0PhysDisk_t));
+ vol_pg0 = kzalloc(sz, GFP_KERNEL);
+ if (!vol_pg0) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ if ((mpt2sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0,
+ MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ kfree(vol_pg0);
+ return;
+ }
+
+ raid_device->volume_type = vol_pg0->VolumeType;
+
+ /* figure out what the underlying devices are by
+ * obtaining the device_info bits for the 1st device
+ */
+ if (!(mpt2sas_config_get_phys_disk_pg0(ioc, &mpi_reply,
+ &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM,
+ vol_pg0->PhysDisk[0].PhysDiskNum))) {
+ if (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+ &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE,
+ le16_to_cpu(pd_pg0.DevHandle)))) {
+ raid_device->device_info =
+ le32_to_cpu(sas_device_pg0.DeviceInfo);
+ }
+ }
+
+ kfree(vol_pg0);
+}
+
+/**
+ * scsih_slave_configure - device configure routine.
+ * @sdev: scsi device struct
+ *
+ * Returns 0 if ok. Any other return is assumed to be an error and
+ * the device is ignored.
+ */
+static int
+scsih_slave_configure(struct scsi_device *sdev)
+{
+ struct Scsi_Host *shost = sdev->host;
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct _sas_device *sas_device;
+ struct _raid_device *raid_device;
+ unsigned long flags;
+ int qdepth;
+ u8 ssp_target = 0;
+ char *ds = "";
+ char *r_level = "";
+
+ qdepth = 1;
+ sas_device_priv_data = sdev->hostdata;
+ sas_device_priv_data->configured_lun = 1;
+ sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT;
+ sas_target_priv_data = sas_device_priv_data->sas_target;
+
+ /* raid volume handling */
+ if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) {
+
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = _scsih_raid_device_find_by_handle(ioc,
+ sas_target_priv_data->handle);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ if (!raid_device) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return 0;
+ }
+
+ _scsih_get_volume_capabilities(ioc, raid_device);
+
+ /* RAID Queue Depth Support
+ * IS volume = underlying qdepth of drive type, either
+ * MPT2SAS_SAS_QUEUE_DEPTH or MPT2SAS_SATA_QUEUE_DEPTH
+ * IM/IME/R10 = 128 (MPT2SAS_RAID_QUEUE_DEPTH)
+ */
+ if (raid_device->device_info &
+ MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
+ qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
+ ds = "SSP";
+ } else {
+ qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
+ if (raid_device->device_info &
+ MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "SATA";
+ else
+ ds = "STP";
+ }
+
+ switch (raid_device->volume_type) {
+ case MPI2_RAID_VOL_TYPE_RAID0:
+ r_level = "RAID0";
+ break;
+ case MPI2_RAID_VOL_TYPE_RAID1E:
+ qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
+ r_level = "RAID1E";
+ break;
+ case MPI2_RAID_VOL_TYPE_RAID1:
+ qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
+ r_level = "RAID1";
+ break;
+ case MPI2_RAID_VOL_TYPE_RAID10:
+ qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
+ r_level = "RAID10";
+ break;
+ case MPI2_RAID_VOL_TYPE_UNKNOWN:
+ default:
+ qdepth = MPT2SAS_RAID_QUEUE_DEPTH;
+ r_level = "RAIDX";
+ break;
+ }
+
+ sdev_printk(KERN_INFO, sdev, "%s: "
+ "handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n",
+ r_level, raid_device->handle,
+ (unsigned long long)raid_device->wwid,
+ raid_device->num_pds, ds);
+ scsih_change_queue_depth(sdev, qdepth);
+ return 0;
+ }
+
+ /* non-raid handling */
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_device_priv_data->sas_target->sas_address);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (sas_device) {
+ if (sas_target_priv_data->flags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT) {
+ mpt2sas_config_get_volume_handle(ioc,
+ sas_device->handle, &sas_device->volume_handle);
+ mpt2sas_config_get_volume_wwid(ioc,
+ sas_device->volume_handle,
+ &sas_device->volume_wwid);
+ }
+ if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) {
+ qdepth = MPT2SAS_SAS_QUEUE_DEPTH;
+ ssp_target = 1;
+ ds = "SSP";
+ } else {
+ qdepth = MPT2SAS_SATA_QUEUE_DEPTH;
+ if (sas_device->device_info &
+ MPI2_SAS_DEVICE_INFO_STP_TARGET)
+ ds = "STP";
+ else if (sas_device->device_info &
+ MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+ ds = "SATA";
+ }
+
+ sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), "
+ "sas_addr(0x%016llx), device_name(0x%016llx)\n",
+ ds, sas_device->handle,
+ (unsigned long long)sas_device->sas_address,
+ (unsigned long long)sas_device->device_name);
+ sdev_printk(KERN_INFO, sdev, "%s: "
+ "enclosure_logical_id(0x%016llx), slot(%d)\n", ds,
+ (unsigned long long) sas_device->enclosure_logical_id,
+ sas_device->slot);
+
+ if (!ssp_target)
+ scsih_display_sata_capabilities(ioc, sas_device, sdev);
+ }
+
+ scsih_change_queue_depth(sdev, qdepth);
+
+ if (ssp_target)
+ sas_read_port_mode_page(sdev);
+ return 0;
+}
+
+/**
+ * scsih_bios_param - fetch head, sector, cylinder info for a disk
+ * @sdev: scsi device struct
+ * @bdev: pointer to block device context
+ * @capacity: device size (in 512 byte sectors)
+ * @params: three element array to place output:
+ * params[0] number of heads (max 255)
+ * params[1] number of sectors (max 63)
+ * params[2] number of cylinders
+ *
+ * Return nothing.
+ */
+static int
+scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev,
+ sector_t capacity, int params[])
+{
+ int heads;
+ int sectors;
+ sector_t cylinders;
+ ulong dummy;
+
+ heads = 64;
+ sectors = 32;
+
+ dummy = heads * sectors;
+ cylinders = capacity;
+ sector_div(cylinders, dummy);
+
+ /*
+ * Handle extended translation size for logical drives
+ * > 1Gb
+ */
+ if ((ulong)capacity >= 0x200000) {
+ heads = 255;
+ sectors = 63;
+ dummy = heads * sectors;
+ cylinders = capacity;
+ sector_div(cylinders, dummy);
+ }
+
+ /* return result */
+ params[0] = heads;
+ params[1] = sectors;
+ params[2] = cylinders;
+
+ return 0;
+}
+
+/**
+ * _scsih_response_code - translation of device response code
+ * @ioc: per adapter object
+ * @response_code: response code returned by the device
+ *
+ * Return nothing.
+ */
+static void
+_scsih_response_code(struct MPT2SAS_ADAPTER *ioc, u8 response_code)
+{
+ char *desc;
+
+ switch (response_code) {
+ case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE:
+ desc = "task management request completed";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME:
+ desc = "invalid frame";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED:
+ desc = "task management request not supported";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_TM_FAILED:
+ desc = "task management request failed";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED:
+ desc = "task management request succeeded";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN:
+ desc = "invalid lun";
+ break;
+ case 0xA:
+ desc = "overlapped tag attempted";
+ break;
+ case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC:
+ desc = "task queued, however not sent to target";
+ break;
+ default:
+ desc = "unknown";
+ break;
+ }
+ printk(MPT2SAS_WARN_FMT "response_code(0x%01x): %s\n",
+ ioc->name, response_code, desc);
+}
+
+/**
+ * scsih_tm_done - tm completion routine
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: none.
+ *
+ * The callback handler when using scsih_issue_tm.
+ *
+ * Return nothing.
+ */
+static void
+scsih_tm_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+{
+ MPI2DefaultReply_t *mpi_reply;
+
+ if (ioc->tm_cmds.status == MPT2_CMD_NOT_USED)
+ return;
+ if (ioc->tm_cmds.smid != smid)
+ return;
+ ioc->tm_cmds.status |= MPT2_CMD_COMPLETE;
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ if (mpi_reply) {
+ memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4);
+ ioc->tm_cmds.status |= MPT2_CMD_REPLY_VALID;
+ }
+ ioc->tm_cmds.status &= ~MPT2_CMD_PENDING;
+ complete(&ioc->tm_cmds.done);
+}
+
+/**
+ * mpt2sas_scsih_set_tm_flag - set per target tm_busy
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During taskmangement request, we need to freeze the device queue.
+ */
+void
+mpt2sas_scsih_set_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+ u8 skip = 0;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ if (skip)
+ continue;
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (sas_device_priv_data->sas_target->handle == handle) {
+ sas_device_priv_data->sas_target->tm_busy = 1;
+ skip = 1;
+ ioc->ignore_loginfos = 1;
+ }
+ }
+}
+
+/**
+ * mpt2sas_scsih_clear_tm_flag - clear per target tm_busy
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During taskmangement request, we need to freeze the device queue.
+ */
+void
+mpt2sas_scsih_clear_tm_flag(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+ u8 skip = 0;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ if (skip)
+ continue;
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (sas_device_priv_data->sas_target->handle == handle) {
+ sas_device_priv_data->sas_target->tm_busy = 0;
+ skip = 1;
+ ioc->ignore_loginfos = 0;
+ }
+ }
+}
+
+/**
+ * mpt2sas_scsih_issue_tm - main routine for sending tm requests
+ * @ioc: per adapter struct
+ * @device_handle: device handle
+ * @lun: lun number
+ * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h)
+ * @smid_task: smid assigned to the task
+ * @timeout: timeout in seconds
+ * Context: The calling function needs to acquire the tm_cmds.mutex
+ *
+ * A generic API for sending task management requests to firmware.
+ *
+ * The ioc->tm_cmds.status flag should be MPT2_CMD_NOT_USED before calling
+ * this API.
+ *
+ * The callback index is set inside `ioc->tm_cb_idx`.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_scsih_issue_tm(struct MPT2SAS_ADAPTER *ioc, u16 handle, uint lun,
+ u8 type, u16 smid_task, ulong timeout)
+{
+ Mpi2SCSITaskManagementRequest_t *mpi_request;
+ Mpi2SCSITaskManagementReply_t *mpi_reply;
+ u16 smid = 0;
+ u32 ioc_state;
+ unsigned long timeleft;
+ u8 VF_ID = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->tm_cmds.status != MPT2_CMD_NOT_USED ||
+ ioc->shost_recovery) {
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+ __func__, ioc->name);
+ return;
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 0);
+ if (ioc_state & MPI2_DOORBELL_USED) {
+ dhsprintk(ioc, printk(MPT2SAS_DEBUG_FMT "unexpected doorbell "
+ "active!\n", ioc->name));
+ goto issue_host_reset;
+ }
+
+ if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) {
+ mpt2sas_base_fault_info(ioc, ioc_state &
+ MPI2_DOORBELL_DATA_MASK);
+ goto issue_host_reset;
+ }
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->tm_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ return;
+ }
+
+ dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "sending tm: handle(0x%04x),"
+ " task_type(0x%02x), smid(%d)\n", ioc->name, handle, type, smid));
+ ioc->tm_cmds.status = MPT2_CMD_PENDING;
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->tm_cmds.smid = smid;
+ memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t));
+ mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT;
+ mpi_request->DevHandle = cpu_to_le16(handle);
+ mpi_request->TaskType = type;
+ mpi_request->TaskMID = cpu_to_le16(smid_task);
+ int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN);
+ mpt2sas_scsih_set_tm_flag(ioc, handle);
+ mpt2sas_base_put_smid_hi_priority(ioc, smid, VF_ID);
+ timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ);
+ mpt2sas_scsih_clear_tm_flag(ioc, handle);
+ if (!(ioc->tm_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n",
+ ioc->name, __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2SCSITaskManagementRequest_t)/4);
+ if (!(ioc->tm_cmds.status & MPT2_CMD_RESET))
+ goto issue_host_reset;
+ }
+
+ if (ioc->tm_cmds.status & MPT2_CMD_REPLY_VALID) {
+ mpi_reply = ioc->tm_cmds.reply;
+ dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "complete tm: "
+ "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n",
+ ioc->name, le16_to_cpu(mpi_reply->IOCStatus),
+ le32_to_cpu(mpi_reply->IOCLogInfo),
+ le32_to_cpu(mpi_reply->TerminationCount)));
+ if (ioc->logging_level & MPT_DEBUG_TM)
+ _scsih_response_code(ioc, mpi_reply->ResponseCode);
+ }
+ return;
+ issue_host_reset:
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, FORCE_BIG_HAMMER);
+}
+
+/**
+ * scsih_abort - eh threads main abort routine
+ * @sdev: scsi device struct
+ *
+ * Returns SUCCESS if command aborted else FAILED
+ */
+static int
+scsih_abort(struct scsi_cmnd *scmd)
+{
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ u16 smid;
+ u16 handle;
+ int r;
+ struct scsi_cmnd *scmd_lookup;
+
+ printk(MPT2SAS_INFO_FMT "attempting task abort! scmd(%p)\n",
+ ioc->name, scmd);
+ scsi_print_command(scmd);
+
+ sas_device_priv_data = scmd->device->hostdata;
+ if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
+ printk(MPT2SAS_INFO_FMT "device been deleted! scmd(%p)\n",
+ ioc->name, scmd);
+ scmd->result = DID_NO_CONNECT << 16;
+ scmd->scsi_done(scmd);
+ r = SUCCESS;
+ goto out;
+ }
+
+ /* search for the command */
+ smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd);
+ if (!smid) {
+ scmd->result = DID_RESET << 16;
+ r = SUCCESS;
+ goto out;
+ }
+
+ /* for hidden raid components and volumes this is not supported */
+ if (sas_device_priv_data->sas_target->flags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT ||
+ sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) {
+ scmd->result = DID_RESET << 16;
+ r = FAILED;
+ goto out;
+ }
+
+ mutex_lock(&ioc->tm_cmds.mutex);
+ handle = sas_device_priv_data->sas_target->handle;
+ mpt2sas_scsih_issue_tm(ioc, handle, sas_device_priv_data->lun,
+ MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30);
+
+ /* sanity check - see whether command actually completed */
+ scmd_lookup = _scsih_scsi_lookup_get(ioc, smid);
+ if (scmd_lookup && (scmd_lookup->serial_number == scmd->serial_number))
+ r = FAILED;
+ else
+ r = SUCCESS;
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->tm_cmds.mutex);
+
+ out:
+ printk(MPT2SAS_INFO_FMT "task abort: %s scmd(%p)\n",
+ ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+ return r;
+}
+
+
+/**
+ * scsih_dev_reset - eh threads main device reset routine
+ * @sdev: scsi device struct
+ *
+ * Returns SUCCESS if command aborted else FAILED
+ */
+static int
+scsih_dev_reset(struct scsi_cmnd *scmd)
+{
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct _sas_device *sas_device;
+ unsigned long flags;
+ u16 handle;
+ int r;
+
+ printk(MPT2SAS_INFO_FMT "attempting target reset! scmd(%p)\n",
+ ioc->name, scmd);
+ scsi_print_command(scmd);
+
+ sas_device_priv_data = scmd->device->hostdata;
+ if (!sas_device_priv_data || !sas_device_priv_data->sas_target) {
+ printk(MPT2SAS_INFO_FMT "device been deleted! scmd(%p)\n",
+ ioc->name, scmd);
+ scmd->result = DID_NO_CONNECT << 16;
+ scmd->scsi_done(scmd);
+ r = SUCCESS;
+ goto out;
+ }
+
+ /* for hidden raid components obtain the volume_handle */
+ handle = 0;
+ if (sas_device_priv_data->sas_target->flags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT) {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc,
+ sas_device_priv_data->sas_target->handle);
+ if (sas_device)
+ handle = sas_device->volume_handle;
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ } else
+ handle = sas_device_priv_data->sas_target->handle;
+
+ if (!handle) {
+ scmd->result = DID_RESET << 16;
+ r = FAILED;
+ goto out;
+ }
+
+ mutex_lock(&ioc->tm_cmds.mutex);
+ mpt2sas_scsih_issue_tm(ioc, handle, 0,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30);
+
+ /*
+ * sanity check see whether all commands to this target been
+ * completed
+ */
+ if (_scsih_scsi_lookup_find_by_target(ioc, scmd->device->id,
+ scmd->device->channel))
+ r = FAILED;
+ else
+ r = SUCCESS;
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->tm_cmds.mutex);
+
+ out:
+ printk(MPT2SAS_INFO_FMT "target reset: %s scmd(%p)\n",
+ ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+ return r;
+}
+
+/**
+ * scsih_abort - eh threads main host reset routine
+ * @sdev: scsi device struct
+ *
+ * Returns SUCCESS if command aborted else FAILED
+ */
+static int
+scsih_host_reset(struct scsi_cmnd *scmd)
+{
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+ int r, retval;
+
+ printk(MPT2SAS_INFO_FMT "attempting host reset! scmd(%p)\n",
+ ioc->name, scmd);
+ scsi_print_command(scmd);
+
+ retval = mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ r = (retval < 0) ? FAILED : SUCCESS;
+ printk(MPT2SAS_INFO_FMT "host reset: %s scmd(%p)\n",
+ ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd);
+
+ return r;
+}
+
+/**
+ * _scsih_fw_event_add - insert and queue up fw_event
+ * @ioc: per adapter object
+ * @fw_event: object describing the event
+ * Context: This function will acquire ioc->fw_event_lock.
+ *
+ * This adds the firmware event object into link list, then queues it up to
+ * be processed from user context.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_fw_event_add(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work *fw_event)
+{
+ unsigned long flags;
+
+ if (ioc->firmware_event_thread == NULL)
+ return;
+
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ list_add_tail(&fw_event->list, &ioc->fw_event_list);
+ INIT_DELAYED_WORK(&fw_event->work, _firmware_event_work);
+ queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, 1);
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+/**
+ * _scsih_fw_event_free - delete fw_event
+ * @ioc: per adapter object
+ * @fw_event: object describing the event
+ * Context: This function will acquire ioc->fw_event_lock.
+ *
+ * This removes firmware event object from link list, frees associated memory.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_fw_event_free(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
+ *fw_event)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ list_del(&fw_event->list);
+ kfree(fw_event->event_data);
+ kfree(fw_event);
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+/**
+ * _scsih_fw_event_add - requeue an event
+ * @ioc: per adapter object
+ * @fw_event: object describing the event
+ * Context: This function will acquire ioc->fw_event_lock.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_fw_event_requeue(struct MPT2SAS_ADAPTER *ioc, struct fw_event_work
+ *fw_event, unsigned long delay)
+{
+ unsigned long flags;
+ if (ioc->firmware_event_thread == NULL)
+ return;
+
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ queue_delayed_work(ioc->firmware_event_thread, &fw_event->work, delay);
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+/**
+ * _scsih_fw_event_off - turn flag off preventing event handling
+ * @ioc: per adapter object
+ *
+ * Used to prevent handling of firmware events during adapter reset
+ * driver unload.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_fw_event_off(struct MPT2SAS_ADAPTER *ioc)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ ioc->fw_events_off = 1;
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+
+}
+
+/**
+ * _scsih_fw_event_on - turn flag on allowing firmware event handling
+ * @ioc: per adapter object
+ *
+ * Returns nothing.
+ */
+static void
+_scsih_fw_event_on(struct MPT2SAS_ADAPTER *ioc)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ ioc->fw_events_off = 0;
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+/**
+ * _scsih_ublock_io_device - set the device state to SDEV_RUNNING
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_ublock_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (!sas_device_priv_data->block)
+ continue;
+ if (sas_device_priv_data->sas_target->handle == handle) {
+ dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
+ MPT2SAS_INFO_FMT "SDEV_RUNNING: "
+ "handle(0x%04x)\n", ioc->name, handle));
+ sas_device_priv_data->block = 0;
+ scsi_device_set_state(sdev, SDEV_RUNNING);
+ }
+ }
+}
+
+/**
+ * _scsih_block_io_device - set the device state to SDEV_BLOCK
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * During device pull we need to appropiately set the sdev state.
+ */
+static void
+_scsih_block_io_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct scsi_device *sdev;
+
+ shost_for_each_device(sdev, ioc->shost) {
+ sas_device_priv_data = sdev->hostdata;
+ if (!sas_device_priv_data)
+ continue;
+ if (sas_device_priv_data->block)
+ continue;
+ if (sas_device_priv_data->sas_target->handle == handle) {
+ dewtprintk(ioc, sdev_printk(KERN_INFO, sdev,
+ MPT2SAS_INFO_FMT "SDEV_BLOCK: "
+ "handle(0x%04x)\n", ioc->name, handle));
+ sas_device_priv_data->block = 1;
+ scsi_device_set_state(sdev, SDEV_BLOCK);
+ }
+ }
+}
+
+/**
+ * _scsih_block_io_to_children_attached_to_ex
+ * @ioc: per adapter object
+ * @sas_expander: the sas_device object
+ *
+ * This routine set sdev state to SDEV_BLOCK for all devices
+ * attached to this expander. This function called when expander is
+ * pulled.
+ */
+static void
+_scsih_block_io_to_children_attached_to_ex(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_node *sas_expander)
+{
+ struct _sas_port *mpt2sas_port;
+ struct _sas_device *sas_device;
+ struct _sas_node *expander_sibling;
+ unsigned long flags;
+
+ if (!sas_expander)
+ return;
+
+ list_for_each_entry(mpt2sas_port,
+ &sas_expander->sas_port_list, port_list) {
+ if (mpt2sas_port->remote_identify.device_type ==
+ SAS_END_DEVICE) {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device =
+ mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ mpt2sas_port->remote_identify.sas_address);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!sas_device)
+ continue;
+ _scsih_block_io_device(ioc, sas_device->handle);
+ }
+ }
+
+ list_for_each_entry(mpt2sas_port,
+ &sas_expander->sas_port_list, port_list) {
+
+ if (mpt2sas_port->remote_identify.device_type ==
+ MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+ mpt2sas_port->remote_identify.device_type ==
+ MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ expander_sibling =
+ mpt2sas_scsih_expander_find_by_sas_address(
+ ioc, mpt2sas_port->remote_identify.sas_address);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ _scsih_block_io_to_children_attached_to_ex(ioc,
+ expander_sibling);
+ }
+ }
+}
+
+/**
+ * _scsih_block_io_to_children_attached_directly
+ * @ioc: per adapter object
+ * @event_data: topology change event data
+ *
+ * This routine set sdev state to SDEV_BLOCK for all devices
+ * direct attached during device pull.
+ */
+static void
+_scsih_block_io_to_children_attached_directly(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventDataSasTopologyChangeList_t *event_data)
+{
+ int i;
+ u16 handle;
+ u16 reason_code;
+ u8 phy_number;
+
+ for (i = 0; i < event_data->NumEntries; i++) {
+ handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+ if (!handle)
+ continue;
+ phy_number = event_data->StartPhyNum + i;
+ reason_code = event_data->PHY[i].PhyStatus &
+ MPI2_EVENT_SAS_TOPO_RC_MASK;
+ if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING)
+ _scsih_block_io_device(ioc, handle);
+ }
+}
+
+/**
+ * _scsih_check_topo_delete_events - sanity check on topo events
+ * @ioc: per adapter object
+ * @event_data: the event data payload
+ *
+ * This routine added to better handle cable breaker.
+ *
+ * This handles the case where driver recieves multiple expander
+ * add and delete events in a single shot. When there is a delete event
+ * the routine will void any pending add events waiting in the event queue.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_check_topo_delete_events(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventDataSasTopologyChangeList_t *event_data)
+{
+ struct fw_event_work *fw_event;
+ Mpi2EventDataSasTopologyChangeList_t *local_event_data;
+ u16 expander_handle;
+ struct _sas_node *sas_expander;
+ unsigned long flags;
+
+ expander_handle = le16_to_cpu(event_data->ExpanderDevHandle);
+ if (expander_handle < ioc->sas_hba.num_phys) {
+ _scsih_block_io_to_children_attached_directly(ioc, event_data);
+ return;
+ }
+
+ if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING
+ || event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) {
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
+ expander_handle);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander);
+ } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING)
+ _scsih_block_io_to_children_attached_directly(ioc, event_data);
+
+ if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
+ return;
+
+ /* mark ignore flag for pending events */
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ list_for_each_entry(fw_event, &ioc->fw_event_list, list) {
+ if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST ||
+ fw_event->ignore)
+ continue;
+ local_event_data = fw_event->event_data;
+ if (local_event_data->ExpStatus ==
+ MPI2_EVENT_SAS_TOPO_ES_ADDED ||
+ local_event_data->ExpStatus ==
+ MPI2_EVENT_SAS_TOPO_ES_RESPONDING) {
+ if (le16_to_cpu(local_event_data->ExpanderDevHandle) ==
+ expander_handle) {
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "setting ignoring flag\n", ioc->name));
+ fw_event->ignore = 1;
+ }
+ }
+ }
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+}
+
+/**
+ * _scsih_queue_rescan - queue a topology rescan from user context
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_scsih_queue_rescan(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct fw_event_work *fw_event;
+
+ if (ioc->wait_for_port_enable_to_complete)
+ return;
+ fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+ if (!fw_event)
+ return;
+ fw_event->event = MPT2SAS_RESCAN_AFTER_HOST_RESET;
+ fw_event->ioc = ioc;
+ _scsih_fw_event_add(ioc, fw_event);
+}
+
+/**
+ * _scsih_flush_running_cmds - completing outstanding commands.
+ * @ioc: per adapter object
+ *
+ * The flushing out of all pending scmd commands following host reset,
+ * where all IO is dropped to the floor.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_flush_running_cmds(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct scsi_cmnd *scmd;
+ u16 smid;
+ u16 count = 0;
+
+ for (smid = 1; smid <= ioc->request_depth; smid++) {
+ scmd = _scsih_scsi_lookup_getclear(ioc, smid);
+ if (!scmd)
+ continue;
+ count++;
+ mpt2sas_base_free_smid(ioc, smid);
+ scsi_dma_unmap(scmd);
+ scmd->result = DID_RESET << 16;
+ scmd->scsi_done(scmd);
+ }
+ dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "completing %d cmds\n",
+ ioc->name, count));
+}
+
+/**
+ * mpt2sas_scsih_reset_handler - reset callback handler (for scsih)
+ * @ioc: per adapter object
+ * @reset_phase: phase
+ *
+ * The handler for doing any required cleanup or initialization.
+ *
+ * The reset phase can be MPT2_IOC_PRE_RESET, MPT2_IOC_AFTER_RESET,
+ * MPT2_IOC_DONE_RESET
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_scsih_reset_handler(struct MPT2SAS_ADAPTER *ioc, int reset_phase)
+{
+ switch (reset_phase) {
+ case MPT2_IOC_PRE_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_PRE_RESET\n", ioc->name, __func__));
+ _scsih_fw_event_off(ioc);
+ break;
+ case MPT2_IOC_AFTER_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_AFTER_RESET\n", ioc->name, __func__));
+ if (ioc->tm_cmds.status & MPT2_CMD_PENDING) {
+ ioc->tm_cmds.status |= MPT2_CMD_RESET;
+ mpt2sas_base_free_smid(ioc, ioc->tm_cmds.smid);
+ complete(&ioc->tm_cmds.done);
+ }
+ _scsih_fw_event_on(ioc);
+ _scsih_flush_running_cmds(ioc);
+ break;
+ case MPT2_IOC_DONE_RESET:
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: "
+ "MPT2_IOC_DONE_RESET\n", ioc->name, __func__));
+ _scsih_queue_rescan(ioc);
+ break;
+ }
+}
+
+/**
+ * scsih_qcmd - main scsi request entry point
+ * @scmd: pointer to scsi command object
+ * @done: function pointer to be invoked on completion
+ *
+ * The callback index is set inside `ioc->scsi_io_cb_idx`.
+ *
+ * Returns 0 on success. If there's a failure, return either:
+ * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or
+ * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full
+ */
+static int
+scsih_qcmd(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *))
+{
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(scmd->device->host);
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ Mpi2SCSIIORequest_t *mpi_request;
+ u32 mpi_control;
+ u16 smid;
+ unsigned long flags;
+
+ scmd->scsi_done = done;
+ sas_device_priv_data = scmd->device->hostdata;
+ if (!sas_device_priv_data) {
+ scmd->result = DID_NO_CONNECT << 16;
+ scmd->scsi_done(scmd);
+ return 0;
+ }
+
+ sas_target_priv_data = sas_device_priv_data->sas_target;
+ if (!sas_target_priv_data || sas_target_priv_data->handle ==
+ MPT2SAS_INVALID_DEVICE_HANDLE || sas_target_priv_data->deleted) {
+ scmd->result = DID_NO_CONNECT << 16;
+ scmd->scsi_done(scmd);
+ return 0;
+ }
+
+ /* see if we are busy with task managment stuff */
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (sas_target_priv_data->tm_busy ||
+ ioc->shost_recovery || ioc->ioc_link_reset_in_progress) {
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ return SCSI_MLQUEUE_HOST_BUSY;
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ if (scmd->sc_data_direction == DMA_FROM_DEVICE)
+ mpi_control = MPI2_SCSIIO_CONTROL_READ;
+ else if (scmd->sc_data_direction == DMA_TO_DEVICE)
+ mpi_control = MPI2_SCSIIO_CONTROL_WRITE;
+ else
+ mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER;
+
+ /* set tags */
+ if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) {
+ if (scmd->device->tagged_supported) {
+ if (scmd->device->ordered_tags)
+ mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ;
+ else
+ mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+ } else
+/* MPI Revision I (UNIT = 0xA) - removed MPI2_SCSIIO_CONTROL_UNTAGGED */
+/* mpi_control |= MPI2_SCSIIO_CONTROL_UNTAGGED;
+ */
+ mpi_control |= (0x500);
+
+ } else
+ mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ;
+
+ if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON))
+ mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON;
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->scsi_io_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ goto out;
+ }
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t));
+ mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+ if (sas_device_priv_data->sas_target->flags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT)
+ mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH;
+ else
+ mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST;
+ mpi_request->DevHandle =
+ cpu_to_le16(sas_device_priv_data->sas_target->handle);
+ mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd));
+ mpi_request->Control = cpu_to_le32(mpi_control);
+ mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len);
+ mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR;
+ mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE;
+ mpi_request->SenseBufferLowAddress =
+ (u32)mpt2sas_base_get_sense_buffer_dma(ioc, smid);
+ mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4;
+ mpi_request->SGLFlags = cpu_to_le16(MPI2_SCSIIO_SGLFLAGS_TYPE_MPI +
+ MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR);
+
+ int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *)
+ mpi_request->LUN);
+ memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len);
+
+ if (!mpi_request->DataLength) {
+ mpt2sas_base_build_zero_len_sge(ioc, &mpi_request->SGL);
+ } else {
+ if (_scsih_build_scatter_gather(ioc, scmd, smid)) {
+ mpt2sas_base_free_smid(ioc, smid);
+ goto out;
+ }
+ }
+
+ _scsih_scsi_lookup_set(ioc, smid, scmd);
+ mpt2sas_base_put_smid_scsi_io(ioc, smid, 0,
+ sas_device_priv_data->sas_target->handle);
+ return 0;
+
+ out:
+ return SCSI_MLQUEUE_HOST_BUSY;
+}
+
+/**
+ * _scsih_normalize_sense - normalize descriptor and fixed format sense data
+ * @sense_buffer: sense data returned by target
+ * @data: normalized skey/asc/ascq
+ *
+ * Return nothing.
+ */
+static void
+_scsih_normalize_sense(char *sense_buffer, struct sense_info *data)
+{
+ if ((sense_buffer[0] & 0x7F) >= 0x72) {
+ /* descriptor format */
+ data->skey = sense_buffer[1] & 0x0F;
+ data->asc = sense_buffer[2];
+ data->ascq = sense_buffer[3];
+ } else {
+ /* fixed format */
+ data->skey = sense_buffer[2] & 0x0F;
+ data->asc = sense_buffer[12];
+ data->ascq = sense_buffer[13];
+ }
+}
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request
+ * @ioc: per adapter object
+ * @scmd: pointer to scsi command object
+ * @mpi_reply: reply mf payload returned from firmware
+ *
+ * scsi_status - SCSI Status code returned from target device
+ * scsi_state - state info associated with SCSI_IO determined by ioc
+ * ioc_status - ioc supplied status info
+ *
+ * Return nothing.
+ */
+static void
+_scsih_scsi_ioc_info(struct MPT2SAS_ADAPTER *ioc, struct scsi_cmnd *scmd,
+ Mpi2SCSIIOReply_t *mpi_reply, u16 smid)
+{
+ u32 response_info;
+ u8 *response_bytes;
+ u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ u8 scsi_state = mpi_reply->SCSIState;
+ u8 scsi_status = mpi_reply->SCSIStatus;
+ char *desc_ioc_state = NULL;
+ char *desc_scsi_status = NULL;
+ char *desc_scsi_state = ioc->tmp_string;
+
+ switch (ioc_status) {
+ case MPI2_IOCSTATUS_SUCCESS:
+ desc_ioc_state = "success";
+ break;
+ case MPI2_IOCSTATUS_INVALID_FUNCTION:
+ desc_ioc_state = "invalid function";
+ break;
+ case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+ desc_ioc_state = "scsi recovered error";
+ break;
+ case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
+ desc_ioc_state = "scsi invalid dev handle";
+ break;
+ case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+ desc_ioc_state = "scsi device not there";
+ break;
+ case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
+ desc_ioc_state = "scsi data overrun";
+ break;
+ case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+ desc_ioc_state = "scsi data underrun";
+ break;
+ case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+ desc_ioc_state = "scsi io data error";
+ break;
+ case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+ desc_ioc_state = "scsi protocol error";
+ break;
+ case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+ desc_ioc_state = "scsi task terminated";
+ break;
+ case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
+ desc_ioc_state = "scsi residual mismatch";
+ break;
+ case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
+ desc_ioc_state = "scsi task mgmt failed";
+ break;
+ case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+ desc_ioc_state = "scsi ioc terminated";
+ break;
+ case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+ desc_ioc_state = "scsi ext terminated";
+ break;
+ default:
+ desc_ioc_state = "unknown";
+ break;
+ }
+
+ switch (scsi_status) {
+ case MPI2_SCSI_STATUS_GOOD:
+ desc_scsi_status = "good";
+ break;
+ case MPI2_SCSI_STATUS_CHECK_CONDITION:
+ desc_scsi_status = "check condition";
+ break;
+ case MPI2_SCSI_STATUS_CONDITION_MET:
+ desc_scsi_status = "condition met";
+ break;
+ case MPI2_SCSI_STATUS_BUSY:
+ desc_scsi_status = "busy";
+ break;
+ case MPI2_SCSI_STATUS_INTERMEDIATE:
+ desc_scsi_status = "intermediate";
+ break;
+ case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET:
+ desc_scsi_status = "intermediate condmet";
+ break;
+ case MPI2_SCSI_STATUS_RESERVATION_CONFLICT:
+ desc_scsi_status = "reservation conflict";
+ break;
+ case MPI2_SCSI_STATUS_COMMAND_TERMINATED:
+ desc_scsi_status = "command terminated";
+ break;
+ case MPI2_SCSI_STATUS_TASK_SET_FULL:
+ desc_scsi_status = "task set full";
+ break;
+ case MPI2_SCSI_STATUS_ACA_ACTIVE:
+ desc_scsi_status = "aca active";
+ break;
+ case MPI2_SCSI_STATUS_TASK_ABORTED:
+ desc_scsi_status = "task aborted";
+ break;
+ default:
+ desc_scsi_status = "unknown";
+ break;
+ }
+
+ desc_scsi_state[0] = '\0';
+ if (!scsi_state)
+ desc_scsi_state = " ";
+ if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID)
+ strcat(desc_scsi_state, "response info ");
+ if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
+ strcat(desc_scsi_state, "state terminated ");
+ if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS)
+ strcat(desc_scsi_state, "no status ");
+ if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED)
+ strcat(desc_scsi_state, "autosense failed ");
+ if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)
+ strcat(desc_scsi_state, "autosense valid ");
+
+ scsi_print_command(scmd);
+ printk(MPT2SAS_WARN_FMT "\tdev handle(0x%04x), "
+ "ioc_status(%s)(0x%04x), smid(%d)\n", ioc->name,
+ le16_to_cpu(mpi_reply->DevHandle), desc_ioc_state,
+ ioc_status, smid);
+ printk(MPT2SAS_WARN_FMT "\trequest_len(%d), underflow(%d), "
+ "resid(%d)\n", ioc->name, scsi_bufflen(scmd), scmd->underflow,
+ scsi_get_resid(scmd));
+ printk(MPT2SAS_WARN_FMT "\ttag(%d), transfer_count(%d), "
+ "sc->result(0x%08x)\n", ioc->name, le16_to_cpu(mpi_reply->TaskTag),
+ le32_to_cpu(mpi_reply->TransferCount), scmd->result);
+ printk(MPT2SAS_WARN_FMT "\tscsi_status(%s)(0x%02x), "
+ "scsi_state(%s)(0x%02x)\n", ioc->name, desc_scsi_status,
+ scsi_status, desc_scsi_state, scsi_state);
+
+ if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+ struct sense_info data;
+ _scsih_normalize_sense(scmd->sense_buffer, &data);
+ printk(MPT2SAS_WARN_FMT "\t[sense_key,asc,ascq]: "
+ "[0x%02x,0x%02x,0x%02x]\n", ioc->name, data.skey,
+ data.asc, data.ascq);
+ }
+
+ if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) {
+ response_info = le32_to_cpu(mpi_reply->ResponseInfo);
+ response_bytes = (u8 *)&response_info;
+ _scsih_response_code(ioc, response_bytes[3]);
+ }
+}
+#endif
+
+/**
+ * _scsih_smart_predicted_fault - illuminate Fault LED
+ * @ioc: per adapter object
+ * @handle: device handle
+ *
+ * Return nothing.
+ */
+static void
+_scsih_smart_predicted_fault(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ Mpi2SepReply_t mpi_reply;
+ Mpi2SepRequest_t mpi_request;
+ struct scsi_target *starget;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ Mpi2EventNotificationReply_t *event_reply;
+ Mpi2EventDataSasDeviceStatusChange_t *event_data;
+ struct _sas_device *sas_device;
+ ssize_t sz;
+ unsigned long flags;
+
+ /* only handle non-raid devices */
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (!sas_device) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ return;
+ }
+ starget = sas_device->starget;
+ sas_target_priv_data = starget->hostdata;
+
+ if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) ||
+ ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ return;
+ }
+ starget_printk(KERN_WARNING, starget, "predicted fault\n");
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) {
+ memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR;
+ mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS;
+ mpi_request.SlotStatus =
+ MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT;
+ mpi_request.DevHandle = cpu_to_le16(handle);
+ mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS;
+ if ((mpt2sas_base_scsi_enclosure_processor(ioc, &mpi_reply,
+ &mpi_request)) != 0) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "enclosure_processor: ioc_status (0x%04x), "
+ "loginfo(0x%08x)\n", ioc->name,
+ le16_to_cpu(mpi_reply.IOCStatus),
+ le32_to_cpu(mpi_reply.IOCLogInfo)));
+ return;
+ }
+ }
+
+ /* insert into event log */
+ sz = offsetof(Mpi2EventNotificationReply_t, EventData) +
+ sizeof(Mpi2EventDataSasDeviceStatusChange_t);
+ event_reply = kzalloc(sz, GFP_KERNEL);
+ if (!event_reply) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION;
+ event_reply->Event =
+ cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE);
+ event_reply->MsgLength = sz/4;
+ event_reply->EventDataLength =
+ cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4);
+ event_data = (Mpi2EventDataSasDeviceStatusChange_t *)
+ event_reply->EventData;
+ event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA;
+ event_data->ASC = 0x5D;
+ event_data->DevHandle = cpu_to_le16(handle);
+ event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address);
+ mpt2sas_ctl_add_to_event_log(ioc, event_reply);
+ kfree(event_reply);
+}
+
+/**
+ * scsih_io_done - scsi request callback
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Callback handler when using scsih_qcmd.
+ *
+ * Return nothing.
+ */
+static void
+scsih_io_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID, u32 reply)
+{
+ Mpi2SCSIIORequest_t *mpi_request;
+ Mpi2SCSIIOReply_t *mpi_reply;
+ struct scsi_cmnd *scmd;
+ u16 ioc_status;
+ u32 xfer_cnt;
+ u8 scsi_state;
+ u8 scsi_status;
+ u32 log_info;
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ u32 response_code;
+
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ scmd = _scsih_scsi_lookup_getclear(ioc, smid);
+ if (scmd == NULL)
+ return;
+
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+
+ if (mpi_reply == NULL) {
+ scmd->result = DID_OK << 16;
+ goto out;
+ }
+
+ sas_device_priv_data = scmd->device->hostdata;
+ if (!sas_device_priv_data || !sas_device_priv_data->sas_target ||
+ sas_device_priv_data->sas_target->deleted) {
+ scmd->result = DID_NO_CONNECT << 16;
+ goto out;
+ }
+
+ /* turning off TLR */
+ if (!sas_device_priv_data->tlr_snoop_check) {
+ sas_device_priv_data->tlr_snoop_check++;
+ if (sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) {
+ response_code = (le32_to_cpu(mpi_reply->ResponseInfo)
+ >> 24);
+ if (response_code ==
+ MPI2_SCSITASKMGMT_RSP_INVALID_FRAME)
+ sas_device_priv_data->flags &=
+ ~MPT_DEVICE_TLR_ON;
+ }
+ }
+
+ xfer_cnt = le32_to_cpu(mpi_reply->TransferCount);
+ scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt);
+ ioc_status = le16_to_cpu(mpi_reply->IOCStatus);
+ if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE)
+ log_info = le32_to_cpu(mpi_reply->IOCLogInfo);
+ else
+ log_info = 0;
+ ioc_status &= MPI2_IOCSTATUS_MASK;
+ scsi_state = mpi_reply->SCSIState;
+ scsi_status = mpi_reply->SCSIStatus;
+
+ if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 &&
+ (scsi_status == MPI2_SCSI_STATUS_BUSY ||
+ scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT ||
+ scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) {
+ ioc_status = MPI2_IOCSTATUS_SUCCESS;
+ }
+
+ if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) {
+ struct sense_info data;
+ const void *sense_data = mpt2sas_base_get_sense_buffer(ioc,
+ smid);
+ memcpy(scmd->sense_buffer, sense_data,
+ le32_to_cpu(mpi_reply->SenseCount));
+ _scsih_normalize_sense(scmd->sense_buffer, &data);
+ /* failure prediction threshold exceeded */
+ if (data.asc == 0x5D)
+ _scsih_smart_predicted_fault(ioc,
+ le16_to_cpu(mpi_reply->DevHandle));
+ }
+
+ switch (ioc_status) {
+ case MPI2_IOCSTATUS_BUSY:
+ case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES:
+ scmd->result = SAM_STAT_BUSY;
+ break;
+
+ case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
+ scmd->result = DID_NO_CONNECT << 16;
+ break;
+
+ case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED:
+ if (sas_device_priv_data->block) {
+ scmd->result = (DID_BUS_BUSY << 16);
+ break;
+ }
+
+ case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED:
+ case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED:
+ scmd->result = DID_RESET << 16;
+ break;
+
+ case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH:
+ if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt))
+ scmd->result = DID_SOFT_ERROR << 16;
+ else
+ scmd->result = (DID_OK << 16) | scsi_status;
+ break;
+
+ case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN:
+ scmd->result = (DID_OK << 16) | scsi_status;
+
+ if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID))
+ break;
+
+ if (xfer_cnt < scmd->underflow) {
+ if (scsi_status == SAM_STAT_BUSY)
+ scmd->result = SAM_STAT_BUSY;
+ else
+ scmd->result = DID_SOFT_ERROR << 16;
+ } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
+ MPI2_SCSI_STATE_NO_SCSI_STATUS))
+ scmd->result = DID_SOFT_ERROR << 16;
+ else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
+ scmd->result = DID_RESET << 16;
+ else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) {
+ mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID;
+ mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION;
+ scmd->result = (DRIVER_SENSE << 24) |
+ SAM_STAT_CHECK_CONDITION;
+ scmd->sense_buffer[0] = 0x70;
+ scmd->sense_buffer[2] = ILLEGAL_REQUEST;
+ scmd->sense_buffer[12] = 0x20;
+ scmd->sense_buffer[13] = 0;
+ }
+ break;
+
+ case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN:
+ scsi_set_resid(scmd, 0);
+ case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR:
+ case MPI2_IOCSTATUS_SUCCESS:
+ scmd->result = (DID_OK << 16) | scsi_status;
+ if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED |
+ MPI2_SCSI_STATE_NO_SCSI_STATUS))
+ scmd->result = DID_SOFT_ERROR << 16;
+ else if (scsi_state & MPI2_SCSI_STATE_TERMINATED)
+ scmd->result = DID_RESET << 16;
+ break;
+
+ case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR:
+ case MPI2_IOCSTATUS_INVALID_FUNCTION:
+ case MPI2_IOCSTATUS_INVALID_SGL:
+ case MPI2_IOCSTATUS_INTERNAL_ERROR:
+ case MPI2_IOCSTATUS_INVALID_FIELD:
+ case MPI2_IOCSTATUS_INVALID_STATE:
+ case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR:
+ case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED:
+ default:
+ scmd->result = DID_SOFT_ERROR << 16;
+ break;
+
+ }
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY))
+ _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid);
+#endif
+
+ out:
+ scsi_dma_unmap(scmd);
+ scmd->scsi_done(scmd);
+}
+
+/**
+ * _scsih_link_change - process phy link changes
+ * @ioc: per adapter object
+ * @handle: phy handle
+ * @attached_handle: valid for devices attached to link
+ * @phy_number: phy number
+ * @link_rate: new link rate
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_link_change(struct MPT2SAS_ADAPTER *ioc, u16 handle, u16 attached_handle,
+ u8 phy_number, u8 link_rate)
+{
+ mpt2sas_transport_update_phy_link_change(ioc, handle, attached_handle,
+ phy_number, link_rate);
+}
+
+/**
+ * _scsih_sas_host_refresh - refreshing sas host object contents
+ * @ioc: per adapter object
+ * @update: update link information
+ * Context: user
+ *
+ * During port enable, fw will send topology events for every device. Its
+ * possible that the handles may change from the previous setting, so this
+ * code keeping handles updating if changed.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_host_refresh(struct MPT2SAS_ADAPTER *ioc, u8 update)
+{
+ u16 sz;
+ u16 ioc_status;
+ int i;
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
+
+ dtmprintk(ioc, printk(MPT2SAS_INFO_FMT
+ "updating handles for sas_host(0x%016llx)\n",
+ ioc->name, (unsigned long long)ioc->sas_hba.sas_address));
+
+ sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys
+ * sizeof(Mpi2SasIOUnit0PhyData_t));
+ sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
+ if (!sas_iounit_pg0) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+ if (!(mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
+ sas_iounit_pg0, sz))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS)
+ goto out;
+ for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
+ ioc->sas_hba.phy[i].handle =
+ le16_to_cpu(sas_iounit_pg0->PhyData[i].
+ ControllerDevHandle);
+ if (update)
+ _scsih_link_change(ioc,
+ ioc->sas_hba.phy[i].handle,
+ le16_to_cpu(sas_iounit_pg0->PhyData[i].
+ AttachedDevHandle), i,
+ sas_iounit_pg0->PhyData[i].
+ NegotiatedLinkRate >> 4);
+ }
+ }
+
+ out:
+ kfree(sas_iounit_pg0);
+}
+
+/**
+ * _scsih_sas_host_add - create sas host object
+ * @ioc: per adapter object
+ *
+ * Creating host side data object, stored in ioc->sas_hba
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_host_add(struct MPT2SAS_ADAPTER *ioc)
+{
+ int i;
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL;
+ Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL;
+ Mpi2SasPhyPage0_t phy_pg0;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ Mpi2SasEnclosurePage0_t enclosure_pg0;
+ u16 ioc_status;
+ u16 sz;
+ u16 device_missing_delay;
+
+ mpt2sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys);
+ if (!ioc->sas_hba.num_phys) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ /* sas_iounit page 0 */
+ sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys *
+ sizeof(Mpi2SasIOUnit0PhyData_t));
+ sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL);
+ if (!sas_iounit_pg0) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+ if ((mpt2sas_config_get_sas_iounit_pg0(ioc, &mpi_reply,
+ sas_iounit_pg0, sz))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+
+ /* sas_iounit page 1 */
+ sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys *
+ sizeof(Mpi2SasIOUnit1PhyData_t));
+ sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL);
+ if (!sas_iounit_pg1) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ if ((mpt2sas_config_get_sas_iounit_pg1(ioc, &mpi_reply,
+ sas_iounit_pg1, sz))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+
+ ioc->io_missing_delay =
+ le16_to_cpu(sas_iounit_pg1->IODeviceMissingDelay);
+ device_missing_delay =
+ le16_to_cpu(sas_iounit_pg1->ReportDeviceMissingDelay);
+ if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16)
+ ioc->device_missing_delay = (device_missing_delay &
+ MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16;
+ else
+ ioc->device_missing_delay = device_missing_delay &
+ MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK;
+
+ ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev;
+ ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys,
+ sizeof(struct _sas_phy), GFP_KERNEL);
+ if (!ioc->sas_hba.phy) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ for (i = 0; i < ioc->sas_hba.num_phys ; i++) {
+ if ((mpt2sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0,
+ i))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ ioc->sas_hba.phy[i].handle =
+ le16_to_cpu(sas_iounit_pg0->PhyData[i].ControllerDevHandle);
+ ioc->sas_hba.phy[i].phy_id = i;
+ mpt2sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i],
+ phy_pg0, ioc->sas_hba.parent_dev);
+ }
+ if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+ MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.phy[0].handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out;
+ }
+ ioc->sas_hba.handle = le16_to_cpu(sas_device_pg0.DevHandle);
+ ioc->sas_hba.enclosure_handle =
+ le16_to_cpu(sas_device_pg0.EnclosureHandle);
+ ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+ printk(MPT2SAS_INFO_FMT "host_add: handle(0x%04x), "
+ "sas_addr(0x%016llx), phys(%d)\n", ioc->name, ioc->sas_hba.handle,
+ (unsigned long long) ioc->sas_hba.sas_address,
+ ioc->sas_hba.num_phys) ;
+
+ if (ioc->sas_hba.enclosure_handle) {
+ if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
+ &enclosure_pg0,
+ MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+ ioc->sas_hba.enclosure_handle))) {
+ ioc->sas_hba.enclosure_logical_id =
+ le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
+ }
+ }
+
+ out:
+ kfree(sas_iounit_pg1);
+ kfree(sas_iounit_pg0);
+}
+
+/**
+ * _scsih_expander_add - creating expander object
+ * @ioc: per adapter object
+ * @handle: expander handle
+ *
+ * Creating expander object, stored in ioc->sas_expander_list.
+ *
+ * Return 0 for success, else error.
+ */
+static int
+_scsih_expander_add(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _sas_node *sas_expander;
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2ExpanderPage0_t expander_pg0;
+ Mpi2ExpanderPage1_t expander_pg1;
+ Mpi2SasEnclosurePage0_t enclosure_pg0;
+ u32 ioc_status;
+ u16 parent_handle;
+ __le64 sas_address;
+ int i;
+ unsigned long flags;
+ struct _sas_port *mpt2sas_port;
+ int rc = 0;
+
+ if (!handle)
+ return -1;
+
+ if ((mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
+ MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ /* handle out of order topology events */
+ parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle);
+ if (parent_handle >= ioc->sas_hba.num_phys) {
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc,
+ parent_handle);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ if (!sas_expander) {
+ rc = _scsih_expander_add(ioc, parent_handle);
+ if (rc != 0)
+ return rc;
+ }
+ }
+
+ sas_address = le64_to_cpu(expander_pg0.SASAddress);
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
+ sas_address);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+ if (sas_expander)
+ return 0;
+
+ sas_expander = kzalloc(sizeof(struct _sas_node),
+ GFP_KERNEL);
+ if (!sas_expander) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ sas_expander->handle = handle;
+ sas_expander->num_phys = expander_pg0.NumPhys;
+ sas_expander->parent_handle = parent_handle;
+ sas_expander->enclosure_handle =
+ le16_to_cpu(expander_pg0.EnclosureHandle);
+ sas_expander->sas_address = sas_address;
+
+ printk(MPT2SAS_INFO_FMT "expander_add: handle(0x%04x),"
+ " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name,
+ handle, sas_expander->parent_handle, (unsigned long long)
+ sas_expander->sas_address, sas_expander->num_phys);
+
+ if (!sas_expander->num_phys)
+ goto out_fail;
+ sas_expander->phy = kcalloc(sas_expander->num_phys,
+ sizeof(struct _sas_phy), GFP_KERNEL);
+ if (!sas_expander->phy) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ rc = -1;
+ goto out_fail;
+ }
+
+ INIT_LIST_HEAD(&sas_expander->sas_port_list);
+ mpt2sas_port = mpt2sas_transport_port_add(ioc, handle,
+ sas_expander->parent_handle);
+ if (!mpt2sas_port) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ rc = -1;
+ goto out_fail;
+ }
+ sas_expander->parent_dev = &mpt2sas_port->rphy->dev;
+
+ for (i = 0 ; i < sas_expander->num_phys ; i++) {
+ if ((mpt2sas_config_get_expander_pg1(ioc, &mpi_reply,
+ &expander_pg1, i, handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ continue;
+ }
+ sas_expander->phy[i].handle = handle;
+ sas_expander->phy[i].phy_id = i;
+ mpt2sas_transport_add_expander_phy(ioc, &sas_expander->phy[i],
+ expander_pg1, sas_expander->parent_dev);
+ }
+
+ if (sas_expander->enclosure_handle) {
+ if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply,
+ &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+ sas_expander->enclosure_handle))) {
+ sas_expander->enclosure_logical_id =
+ le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
+ }
+ }
+
+ _scsih_expander_node_add(ioc, sas_expander);
+ return 0;
+
+ out_fail:
+
+ if (sas_expander)
+ kfree(sas_expander->phy);
+ kfree(sas_expander);
+ return rc;
+}
+
+/**
+ * _scsih_expander_remove - removing expander object
+ * @ioc: per adapter object
+ * @handle: expander handle
+ *
+ * Return nothing.
+ */
+static void
+_scsih_expander_remove(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct _sas_node *sas_expander;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_expander = mpt2sas_scsih_expander_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ _scsih_expander_node_remove(ioc, sas_expander);
+}
+
+/**
+ * _scsih_add_device - creating sas device object
+ * @ioc: per adapter object
+ * @handle: sas device handle
+ * @phy_num: phy number end device attached to
+ * @is_pd: is this hidden raid component
+ *
+ * Creating end device object, stored in ioc->sas_device_list.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_scsih_add_device(struct MPT2SAS_ADAPTER *ioc, u16 handle, u8 phy_num, u8 is_pd)
+{
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ Mpi2SasEnclosurePage0_t enclosure_pg0;
+ struct _sas_device *sas_device;
+ u32 ioc_status;
+ __le64 sas_address;
+ u32 device_info;
+ unsigned long flags;
+
+ if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+ MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ /* check if device is present */
+ if (!(le16_to_cpu(sas_device_pg0.Flags) &
+ MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ printk(MPT2SAS_ERR_FMT "Flags = 0x%04x\n",
+ ioc->name, le16_to_cpu(sas_device_pg0.Flags));
+ return -1;
+ }
+
+ /* check if there were any issus with discovery */
+ if (sas_device_pg0.AccessStatus ==
+ MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ printk(MPT2SAS_ERR_FMT "AccessStatus = 0x%02x\n",
+ ioc->name, sas_device_pg0.AccessStatus);
+ return -1;
+ }
+
+ /* check if this is end device */
+ device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
+ if (!(_scsih_is_end_device(device_info))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ sas_address);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ if (sas_device) {
+ _scsih_ublock_io_device(ioc, handle);
+ return 0;
+ }
+
+ sas_device = kzalloc(sizeof(struct _sas_device),
+ GFP_KERNEL);
+ if (!sas_device) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ sas_device->handle = handle;
+ sas_device->parent_handle =
+ le16_to_cpu(sas_device_pg0.ParentDevHandle);
+ sas_device->enclosure_handle =
+ le16_to_cpu(sas_device_pg0.EnclosureHandle);
+ sas_device->slot =
+ le16_to_cpu(sas_device_pg0.Slot);
+ sas_device->device_info = device_info;
+ sas_device->sas_address = sas_address;
+ sas_device->hidden_raid_component = is_pd;
+
+ /* get enclosure_logical_id */
+ if (!(mpt2sas_config_get_enclosure_pg0(ioc, &mpi_reply, &enclosure_pg0,
+ MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE,
+ sas_device->enclosure_handle))) {
+ sas_device->enclosure_logical_id =
+ le64_to_cpu(enclosure_pg0.EnclosureLogicalID);
+ }
+
+ /* get device name */
+ sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName);
+
+ if (ioc->wait_for_port_enable_to_complete)
+ _scsih_sas_device_init_add(ioc, sas_device);
+ else
+ _scsih_sas_device_add(ioc, sas_device);
+
+ return 0;
+}
+
+/**
+ * _scsih_remove_device - removing sas device object
+ * @ioc: per adapter object
+ * @handle: sas device handle
+ *
+ * Return nothing.
+ */
+static void
+_scsih_remove_device(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct _sas_device *sas_device;
+ unsigned long flags;
+ Mpi2SasIoUnitControlReply_t mpi_reply;
+ Mpi2SasIoUnitControlRequest_t mpi_request;
+ u16 device_handle;
+
+ /* lookup sas_device */
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (!sas_device) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ return;
+ }
+
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter: handle"
+ "(0x%04x)\n", ioc->name, __func__, handle));
+
+ if (sas_device->starget && sas_device->starget->hostdata) {
+ sas_target_priv_data = sas_device->starget->hostdata;
+ sas_target_priv_data->deleted = 1;
+ }
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ if (ioc->remove_host)
+ goto out;
+
+ /* Target Reset to flush out all the outstanding IO */
+ device_handle = (sas_device->hidden_raid_component) ?
+ sas_device->volume_handle : handle;
+ if (device_handle) {
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset: "
+ "handle(0x%04x)\n", ioc->name, device_handle));
+ mutex_lock(&ioc->tm_cmds.mutex);
+ mpt2sas_scsih_issue_tm(ioc, device_handle, 0,
+ MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 10);
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->tm_cmds.mutex);
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "issue target reset "
+ "done: handle(0x%04x)\n", ioc->name, device_handle));
+ }
+
+ /* SAS_IO_UNIT_CNTR - send REMOVE_DEVICE */
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: handle"
+ "(0x%04x)\n", ioc->name, handle));
+ memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t));
+ mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
+ mpi_request.Operation = MPI2_SAS_OP_REMOVE_DEVICE;
+ mpi_request.DevHandle = handle;
+ mpi_request.VF_ID = 0;
+ if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply,
+ &mpi_request)) != 0) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ }
+
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "sas_iounit: ioc_status"
+ "(0x%04x), loginfo(0x%08x)\n", ioc->name,
+ le16_to_cpu(mpi_reply.IOCStatus),
+ le32_to_cpu(mpi_reply.IOCLogInfo)));
+
+ out:
+ mpt2sas_transport_port_remove(ioc, sas_device->sas_address,
+ sas_device->parent_handle);
+
+ printk(MPT2SAS_INFO_FMT "removing handle(0x%04x), sas_addr"
+ "(0x%016llx)\n", ioc->name, sas_device->handle,
+ (unsigned long long) sas_device->sas_address);
+ _scsih_sas_device_remove(ioc, sas_device);
+
+ dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: exit: handle"
+ "(0x%04x)\n", ioc->name, __func__, handle));
+}
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _scsih_sas_topology_change_event_debug - debug for topology event
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ */
+static void
+_scsih_sas_topology_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventDataSasTopologyChangeList_t *event_data)
+{
+ int i;
+ u16 handle;
+ u16 reason_code;
+ u8 phy_number;
+ char *status_str = NULL;
+ char link_rate[25];
+
+ switch (event_data->ExpStatus) {
+ case MPI2_EVENT_SAS_TOPO_ES_ADDED:
+ status_str = "add";
+ break;
+ case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING:
+ status_str = "remove";
+ break;
+ case MPI2_EVENT_SAS_TOPO_ES_RESPONDING:
+ status_str = "responding";
+ break;
+ case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING:
+ status_str = "remove delay";
+ break;
+ default:
+ status_str = "unknown status";
+ break;
+ }
+ printk(MPT2SAS_DEBUG_FMT "sas topology change: (%s)\n",
+ ioc->name, status_str);
+ printk(KERN_DEBUG "\thandle(0x%04x), enclosure_handle(0x%04x) "
+ "start_phy(%02d), count(%d)\n",
+ le16_to_cpu(event_data->ExpanderDevHandle),
+ le16_to_cpu(event_data->EnclosureHandle),
+ event_data->StartPhyNum, event_data->NumEntries);
+ for (i = 0; i < event_data->NumEntries; i++) {
+ handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+ if (!handle)
+ continue;
+ phy_number = event_data->StartPhyNum + i;
+ reason_code = event_data->PHY[i].PhyStatus &
+ MPI2_EVENT_SAS_TOPO_RC_MASK;
+ switch (reason_code) {
+ case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
+ snprintf(link_rate, 25, ": add, link(0x%02x)",
+ (event_data->PHY[i].LinkRate >> 4));
+ status_str = link_rate;
+ break;
+ case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
+ status_str = ": remove";
+ break;
+ case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING:
+ status_str = ": remove_delay";
+ break;
+ case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
+ snprintf(link_rate, 25, ": link(0x%02x)",
+ (event_data->PHY[i].LinkRate >> 4));
+ status_str = link_rate;
+ break;
+ case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE:
+ status_str = ": responding";
+ break;
+ default:
+ status_str = ": unknown";
+ break;
+ }
+ printk(KERN_DEBUG "\tphy(%02d), attached_handle(0x%04x)%s\n",
+ phy_number, handle, status_str);
+ }
+}
+#endif
+
+/**
+ * _scsih_sas_topology_change_event - handle topology changes
+ * @ioc: per adapter object
+ * @VF_ID:
+ * @event_data: event data payload
+ * fw_event:
+ * Context: user.
+ *
+ */
+static void
+_scsih_sas_topology_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataSasTopologyChangeList_t *event_data,
+ struct fw_event_work *fw_event)
+{
+ int i;
+ u16 parent_handle, handle;
+ u16 reason_code;
+ u8 phy_number;
+ struct _sas_node *sas_expander;
+ unsigned long flags;
+ u8 link_rate_;
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ _scsih_sas_topology_change_event_debug(ioc, event_data);
+#endif
+
+ if (!ioc->sas_hba.num_phys)
+ _scsih_sas_host_add(ioc);
+ else
+ _scsih_sas_host_refresh(ioc, 0);
+
+ if (fw_event->ignore) {
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring expander "
+ "event\n", ioc->name));
+ return;
+ }
+
+ parent_handle = le16_to_cpu(event_data->ExpanderDevHandle);
+
+ /* handle expander add */
+ if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED)
+ if (_scsih_expander_add(ioc, parent_handle) != 0)
+ return;
+
+ /* handle siblings events */
+ for (i = 0; i < event_data->NumEntries; i++) {
+ if (fw_event->ignore) {
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "ignoring "
+ "expander event\n", ioc->name));
+ return;
+ }
+ if (event_data->PHY[i].PhyStatus &
+ MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT)
+ continue;
+ handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle);
+ if (!handle)
+ continue;
+ phy_number = event_data->StartPhyNum + i;
+ reason_code = event_data->PHY[i].PhyStatus &
+ MPI2_EVENT_SAS_TOPO_RC_MASK;
+ link_rate_ = event_data->PHY[i].LinkRate >> 4;
+ switch (reason_code) {
+ case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED:
+ case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED:
+ if (!parent_handle) {
+ if (phy_number < ioc->sas_hba.num_phys)
+ _scsih_link_change(ioc,
+ ioc->sas_hba.phy[phy_number].handle,
+ handle, phy_number, link_rate_);
+ } else {
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_expander =
+ mpt2sas_scsih_expander_find_by_handle(ioc,
+ parent_handle);
+ spin_unlock_irqrestore(&ioc->sas_node_lock,
+ flags);
+ if (sas_expander) {
+ if (phy_number < sas_expander->num_phys)
+ _scsih_link_change(ioc,
+ sas_expander->
+ phy[phy_number].handle,
+ handle, phy_number,
+ link_rate_);
+ }
+ }
+ if (reason_code == MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED) {
+ if (link_rate_ >= MPI2_SAS_NEG_LINK_RATE_1_5)
+ _scsih_ublock_io_device(ioc, handle);
+ }
+ if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED) {
+ if (link_rate_ < MPI2_SAS_NEG_LINK_RATE_1_5)
+ break;
+ _scsih_add_device(ioc, handle, phy_number, 0);
+ }
+ break;
+ case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING:
+ _scsih_remove_device(ioc, handle);
+ break;
+ }
+ }
+
+ /* handle expander removal */
+ if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING)
+ _scsih_expander_remove(ioc, parent_handle);
+
+}
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _scsih_sas_device_status_change_event_debug - debug for device event
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_device_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventDataSasDeviceStatusChange_t *event_data)
+{
+ char *reason_str = NULL;
+
+ switch (event_data->ReasonCode) {
+ case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA:
+ reason_str = "smart data";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED:
+ reason_str = "unsupported device discovered";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET:
+ reason_str = "internal device reset";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL:
+ reason_str = "internal task abort";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL:
+ reason_str = "internal task abort set";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL:
+ reason_str = "internal clear task set";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL:
+ reason_str = "internal query task";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE:
+ reason_str = "sata init failure";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET:
+ reason_str = "internal device reset complete";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL:
+ reason_str = "internal task abort complete";
+ break;
+ case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION:
+ reason_str = "internal async notification";
+ break;
+ default:
+ reason_str = "unknown reason";
+ break;
+ }
+ printk(MPT2SAS_DEBUG_FMT "device status change: (%s)\n"
+ "\thandle(0x%04x), sas address(0x%016llx)", ioc->name,
+ reason_str, le16_to_cpu(event_data->DevHandle),
+ (unsigned long long)le64_to_cpu(event_data->SASAddress));
+ if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA)
+ printk(MPT2SAS_DEBUG_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name,
+ event_data->ASC, event_data->ASCQ);
+ printk(KERN_INFO "\n");
+}
+#endif
+
+/**
+ * _scsih_sas_device_status_change_event - handle device status change
+ * @ioc: per adapter object
+ * @VF_ID:
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_device_status_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataSasDeviceStatusChange_t *event_data)
+{
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ _scsih_sas_device_status_change_event_debug(ioc, event_data);
+#endif
+}
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure event
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventDataSasEnclDevStatusChange_t *event_data)
+{
+ char *reason_str = NULL;
+
+ switch (event_data->ReasonCode) {
+ case MPI2_EVENT_SAS_ENCL_RC_ADDED:
+ reason_str = "enclosure add";
+ break;
+ case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING:
+ reason_str = "enclosure remove";
+ break;
+ default:
+ reason_str = "unknown reason";
+ break;
+ }
+
+ printk(MPT2SAS_DEBUG_FMT "enclosure status change: (%s)\n"
+ "\thandle(0x%04x), enclosure logical id(0x%016llx)"
+ " number slots(%d)\n", ioc->name, reason_str,
+ le16_to_cpu(event_data->EnclosureHandle),
+ (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID),
+ le16_to_cpu(event_data->StartSlot));
+}
+#endif
+
+/**
+ * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events
+ * @ioc: per adapter object
+ * @VF_ID:
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_enclosure_dev_status_change_event(struct MPT2SAS_ADAPTER *ioc,
+ u8 VF_ID, Mpi2EventDataSasEnclDevStatusChange_t *event_data)
+{
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ _scsih_sas_enclosure_dev_status_change_event_debug(ioc,
+ event_data);
+#endif
+}
+
+/**
+ * _scsih_sas_broadcast_primative_event - handle broadcast events
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_broadcast_primative_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataSasBroadcastPrimitive_t *event_data)
+{
+ struct scsi_cmnd *scmd;
+ u16 smid, handle;
+ u32 lun;
+ struct MPT2SAS_DEVICE *sas_device_priv_data;
+ u32 termination_count;
+ u32 query_count;
+ Mpi2SCSITaskManagementReply_t *mpi_reply;
+
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "broadcast primative: "
+ "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
+ event_data->PortWidth));
+
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: enter\n", ioc->name,
+ __func__));
+
+ mutex_lock(&ioc->tm_cmds.mutex);
+ termination_count = 0;
+ query_count = 0;
+ mpi_reply = ioc->tm_cmds.reply;
+ for (smid = 1; smid <= ioc->request_depth; smid++) {
+ scmd = _scsih_scsi_lookup_get(ioc, smid);
+ if (!scmd)
+ continue;
+ sas_device_priv_data = scmd->device->hostdata;
+ if (!sas_device_priv_data || !sas_device_priv_data->sas_target)
+ continue;
+ /* skip hidden raid components */
+ if (sas_device_priv_data->sas_target->flags &
+ MPT_TARGET_FLAGS_RAID_COMPONENT)
+ continue;
+ /* skip volumes */
+ if (sas_device_priv_data->sas_target->flags &
+ MPT_TARGET_FLAGS_VOLUME)
+ continue;
+
+ handle = sas_device_priv_data->sas_target->handle;
+ lun = sas_device_priv_data->lun;
+ query_count++;
+
+ mpt2sas_scsih_issue_tm(ioc, handle, lun,
+ MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30);
+ termination_count += le32_to_cpu(mpi_reply->TerminationCount);
+
+ if ((mpi_reply->IOCStatus == MPI2_IOCSTATUS_SUCCESS) &&
+ (mpi_reply->ResponseCode ==
+ MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED ||
+ mpi_reply->ResponseCode ==
+ MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC))
+ continue;
+
+ mpt2sas_scsih_issue_tm(ioc, handle, lun,
+ MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET, smid, 30);
+ termination_count += le32_to_cpu(mpi_reply->TerminationCount);
+ }
+ ioc->tm_cmds.status = MPT2_CMD_NOT_USED;
+ ioc->broadcast_aen_busy = 0;
+ mutex_unlock(&ioc->tm_cmds.mutex);
+
+ dtmprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "%s - exit, query_count = %d termination_count = %d\n",
+ ioc->name, __func__, query_count, termination_count));
+}
+
+/**
+ * _scsih_sas_discovery_event - handle discovery events
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_discovery_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataSasDiscovery_t *event_data)
+{
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) {
+ printk(MPT2SAS_DEBUG_FMT "discovery event: (%s)", ioc->name,
+ (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ?
+ "start" : "stop");
+ if (event_data->DiscoveryStatus)
+ printk(MPT2SAS_DEBUG_FMT ", discovery_status(0x%08x)",
+ ioc->name, le32_to_cpu(event_data->DiscoveryStatus));
+ printk("\n");
+ }
+#endif
+
+ if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED &&
+ !ioc->sas_hba.num_phys)
+ _scsih_sas_host_add(ioc);
+}
+
+/**
+ * _scsih_reprobe_lun - reprobing lun
+ * @sdev: scsi device struct
+ * @no_uld_attach: sdev->no_uld_attach flag setting
+ *
+ **/
+static void
+_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach)
+{
+ int rc;
+
+ sdev->no_uld_attach = no_uld_attach ? 1 : 0;
+ sdev_printk(KERN_INFO, sdev, "%s raid component\n",
+ sdev->no_uld_attach ? "hidding" : "exposing");
+ rc = scsi_device_reprobe(sdev);
+}
+
+/**
+ * _scsih_reprobe_target - reprobing target
+ * @starget: scsi target struct
+ * @no_uld_attach: sdev->no_uld_attach flag setting
+ *
+ * Note: no_uld_attach flag determines whether the disk device is attached
+ * to block layer. A value of `1` means to not attach.
+ **/
+static void
+_scsih_reprobe_target(struct scsi_target *starget, int no_uld_attach)
+{
+ struct MPT2SAS_TARGET *sas_target_priv_data = starget->hostdata;
+
+ if (no_uld_attach)
+ sas_target_priv_data->flags |= MPT_TARGET_FLAGS_RAID_COMPONENT;
+ else
+ sas_target_priv_data->flags &= ~MPT_TARGET_FLAGS_RAID_COMPONENT;
+
+ starget_for_each_device(starget, no_uld_attach ? (void *)1 : NULL,
+ _scsih_reprobe_lun);
+}
+/**
+ * _scsih_sas_volume_add - add new volume
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_volume_add(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventIrConfigElement_t *element)
+{
+ struct _raid_device *raid_device;
+ unsigned long flags;
+ u64 wwid;
+ u16 handle = le16_to_cpu(element->VolDevHandle);
+ int rc;
+
+#if 0 /* RAID_HACKS */
+ if (le32_to_cpu(event_data->Flags) &
+ MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
+ return;
+#endif
+
+ mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
+ if (!wwid) {
+ printk(MPT2SAS_ERR_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+
+ if (raid_device)
+ return;
+
+ raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
+ if (!raid_device) {
+ printk(MPT2SAS_ERR_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__);
+ return;
+ }
+
+ raid_device->id = ioc->sas_id++;
+ raid_device->channel = RAID_CHANNEL;
+ raid_device->handle = handle;
+ raid_device->wwid = wwid;
+ _scsih_raid_device_add(ioc, raid_device);
+ if (!ioc->wait_for_port_enable_to_complete) {
+ rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
+ raid_device->id, 0);
+ if (rc)
+ _scsih_raid_device_remove(ioc, raid_device);
+ } else
+ _scsih_determine_boot_device(ioc, raid_device, 1);
+}
+
+/**
+ * _scsih_sas_volume_delete - delete volume
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_volume_delete(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventIrConfigElement_t *element)
+{
+ struct _raid_device *raid_device;
+ u16 handle = le16_to_cpu(element->VolDevHandle);
+ unsigned long flags;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+
+#if 0 /* RAID_HACKS */
+ if (le32_to_cpu(event_data->Flags) &
+ MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG)
+ return;
+#endif
+
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ if (!raid_device)
+ return;
+ if (raid_device->starget) {
+ sas_target_priv_data = raid_device->starget->hostdata;
+ sas_target_priv_data->deleted = 1;
+ scsi_remove_target(&raid_device->starget->dev);
+ }
+ _scsih_raid_device_remove(ioc, raid_device);
+}
+
+/**
+ * _scsih_sas_pd_expose - expose pd component to /dev/sdX
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_pd_expose(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventIrConfigElement_t *element)
+{
+ struct _sas_device *sas_device;
+ unsigned long flags;
+ u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!sas_device)
+ return;
+
+ /* exposing raid component */
+ sas_device->volume_handle = 0;
+ sas_device->volume_wwid = 0;
+ sas_device->hidden_raid_component = 0;
+ _scsih_reprobe_target(sas_device->starget, 0);
+}
+
+/**
+ * _scsih_sas_pd_hide - hide pd component from /dev/sdX
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_pd_hide(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventIrConfigElement_t *element)
+{
+ struct _sas_device *sas_device;
+ unsigned long flags;
+ u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!sas_device)
+ return;
+
+ /* hiding raid component */
+ mpt2sas_config_get_volume_handle(ioc, handle,
+ &sas_device->volume_handle);
+ mpt2sas_config_get_volume_wwid(ioc, sas_device->volume_handle,
+ &sas_device->volume_wwid);
+ sas_device->hidden_raid_component = 1;
+ _scsih_reprobe_target(sas_device->starget, 1);
+}
+
+/**
+ * _scsih_sas_pd_delete - delete pd component
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_pd_delete(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventIrConfigElement_t *element)
+{
+ struct _sas_device *sas_device;
+ unsigned long flags;
+ u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!sas_device)
+ return;
+ _scsih_remove_device(ioc, handle);
+}
+
+/**
+ * _scsih_sas_pd_add - remove pd component
+ * @ioc: per adapter object
+ * @element: IR config element data
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_pd_add(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventIrConfigElement_t *element)
+{
+ struct _sas_device *sas_device;
+ unsigned long flags;
+ u16 handle = le16_to_cpu(element->PhysDiskDevHandle);
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (sas_device)
+ sas_device->hidden_raid_component = 1;
+ else
+ _scsih_add_device(ioc, handle, 0, 1);
+}
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_config_change_event_debug(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventDataIrConfigChangeList_t *event_data)
+{
+ Mpi2EventIrConfigElement_t *element;
+ u8 element_type;
+ int i;
+ char *reason_str = NULL, *element_str = NULL;
+
+ element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+
+ printk(MPT2SAS_DEBUG_FMT "raid config change: (%s), elements(%d)\n",
+ ioc->name, (le32_to_cpu(event_data->Flags) &
+ MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ?
+ "foreign" : "native", event_data->NumElements);
+ for (i = 0; i < event_data->NumElements; i++, element++) {
+ switch (element->ReasonCode) {
+ case MPI2_EVENT_IR_CHANGE_RC_ADDED:
+ reason_str = "add";
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
+ reason_str = "remove";
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE:
+ reason_str = "no change";
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_HIDE:
+ reason_str = "hide";
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
+ reason_str = "unhide";
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
+ reason_str = "volume_created";
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
+ reason_str = "volume_deleted";
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
+ reason_str = "pd_created";
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
+ reason_str = "pd_deleted";
+ break;
+ default:
+ reason_str = "unknown reason";
+ break;
+ }
+ element_type = le16_to_cpu(element->ElementFlags) &
+ MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK;
+ switch (element_type) {
+ case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT:
+ element_str = "volume";
+ break;
+ case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT:
+ element_str = "phys disk";
+ break;
+ case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT:
+ element_str = "hot spare";
+ break;
+ default:
+ element_str = "unknown element";
+ break;
+ }
+ printk(KERN_DEBUG "\t(%s:%s), vol handle(0x%04x), "
+ "pd handle(0x%04x), pd num(0x%02x)\n", element_str,
+ reason_str, le16_to_cpu(element->VolDevHandle),
+ le16_to_cpu(element->PhysDiskDevHandle),
+ element->PhysDiskNum);
+ }
+}
+#endif
+
+/**
+ * _scsih_sas_ir_config_change_event - handle ir configuration change events
+ * @ioc: per adapter object
+ * @VF_ID:
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_config_change_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataIrConfigChangeList_t *event_data)
+{
+ Mpi2EventIrConfigElement_t *element;
+ int i;
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ _scsih_sas_ir_config_change_event_debug(ioc, event_data);
+
+#endif
+
+ element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0];
+ for (i = 0; i < event_data->NumElements; i++, element++) {
+
+ switch (element->ReasonCode) {
+ case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED:
+ case MPI2_EVENT_IR_CHANGE_RC_ADDED:
+ _scsih_sas_volume_add(ioc, element);
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED:
+ case MPI2_EVENT_IR_CHANGE_RC_REMOVED:
+ _scsih_sas_volume_delete(ioc, element);
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED:
+ _scsih_sas_pd_hide(ioc, element);
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED:
+ _scsih_sas_pd_expose(ioc, element);
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_HIDE:
+ _scsih_sas_pd_add(ioc, element);
+ break;
+ case MPI2_EVENT_IR_CHANGE_RC_UNHIDE:
+ _scsih_sas_pd_delete(ioc, element);
+ break;
+ }
+ }
+}
+
+/**
+ * _scsih_sas_ir_volume_event - IR volume event
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_volume_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataIrVolume_t *event_data)
+{
+ u64 wwid;
+ unsigned long flags;
+ struct _raid_device *raid_device;
+ u16 handle;
+ u32 state;
+ int rc;
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+
+ if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED)
+ return;
+
+ handle = le16_to_cpu(event_data->VolDevHandle);
+ state = le32_to_cpu(event_data->NewValue);
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle(0x%04x), "
+ "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
+ le32_to_cpu(event_data->PreviousValue), state));
+
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = _scsih_raid_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+
+ switch (state) {
+ case MPI2_RAID_VOL_STATE_MISSING:
+ case MPI2_RAID_VOL_STATE_FAILED:
+ if (!raid_device)
+ break;
+ if (raid_device->starget) {
+ sas_target_priv_data = raid_device->starget->hostdata;
+ sas_target_priv_data->deleted = 1;
+ scsi_remove_target(&raid_device->starget->dev);
+ }
+ _scsih_raid_device_remove(ioc, raid_device);
+ break;
+
+ case MPI2_RAID_VOL_STATE_ONLINE:
+ case MPI2_RAID_VOL_STATE_DEGRADED:
+ case MPI2_RAID_VOL_STATE_OPTIMAL:
+ if (raid_device)
+ break;
+
+ mpt2sas_config_get_volume_wwid(ioc, handle, &wwid);
+ if (!wwid) {
+ printk(MPT2SAS_ERR_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__);
+ break;
+ }
+
+ raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL);
+ if (!raid_device) {
+ printk(MPT2SAS_ERR_FMT
+ "failure at %s:%d/%s()!\n", ioc->name,
+ __FILE__, __LINE__, __func__);
+ break;
+ }
+
+ raid_device->id = ioc->sas_id++;
+ raid_device->channel = RAID_CHANNEL;
+ raid_device->handle = handle;
+ raid_device->wwid = wwid;
+ _scsih_raid_device_add(ioc, raid_device);
+ rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
+ raid_device->id, 0);
+ if (rc)
+ _scsih_raid_device_remove(ioc, raid_device);
+ break;
+
+ case MPI2_RAID_VOL_STATE_INITIALIZING:
+ default:
+ break;
+ }
+}
+
+/**
+ * _scsih_sas_ir_physical_disk_event - PD event
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_physical_disk_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataIrPhysicalDisk_t *event_data)
+{
+ u16 handle;
+ u32 state;
+ struct _sas_device *sas_device;
+ unsigned long flags;
+
+ if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED)
+ return;
+
+ handle = le16_to_cpu(event_data->PhysDiskDevHandle);
+ state = le32_to_cpu(event_data->NewValue);
+
+ dewtprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s: handle(0x%04x), "
+ "old(0x%08x), new(0x%08x)\n", ioc->name, __func__, handle,
+ le32_to_cpu(event_data->PreviousValue), state));
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ switch (state) {
+#if 0
+ case MPI2_RAID_PD_STATE_OFFLINE:
+ if (sas_device)
+ _scsih_remove_device(ioc, handle);
+ break;
+#endif
+ case MPI2_RAID_PD_STATE_ONLINE:
+ case MPI2_RAID_PD_STATE_DEGRADED:
+ case MPI2_RAID_PD_STATE_REBUILDING:
+ case MPI2_RAID_PD_STATE_OPTIMAL:
+ if (sas_device)
+ sas_device->hidden_raid_component = 1;
+ else
+ _scsih_add_device(ioc, handle, 0, 1);
+ break;
+
+ case MPI2_RAID_PD_STATE_NOT_CONFIGURED:
+ case MPI2_RAID_PD_STATE_NOT_COMPATIBLE:
+ case MPI2_RAID_PD_STATE_HOT_SPARE:
+ default:
+ break;
+ }
+}
+
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+/**
+ * _scsih_sas_ir_operation_status_event_debug - debug for IR op event
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_operation_status_event_debug(struct MPT2SAS_ADAPTER *ioc,
+ Mpi2EventDataIrOperationStatus_t *event_data)
+{
+ char *reason_str = NULL;
+
+ switch (event_data->RAIDOperation) {
+ case MPI2_EVENT_IR_RAIDOP_RESYNC:
+ reason_str = "resync";
+ break;
+ case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION:
+ reason_str = "online capacity expansion";
+ break;
+ case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK:
+ reason_str = "consistency check";
+ break;
+ default:
+ reason_str = "unknown reason";
+ break;
+ }
+
+ printk(MPT2SAS_INFO_FMT "raid operational status: (%s)"
+ "\thandle(0x%04x), percent complete(%d)\n",
+ ioc->name, reason_str,
+ le16_to_cpu(event_data->VolDevHandle),
+ event_data->PercentComplete);
+}
+#endif
+
+/**
+ * _scsih_sas_ir_operation_status_event - handle RAID operation events
+ * @ioc: per adapter object
+ * @VF_ID:
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_sas_ir_operation_status_event(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataIrOperationStatus_t *event_data)
+{
+#ifdef CONFIG_SCSI_MPT2SAS_LOGGING
+ if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK)
+ _scsih_sas_ir_operation_status_event_debug(ioc, event_data);
+#endif
+}
+
+/**
+ * _scsih_task_set_full - handle task set full
+ * @ioc: per adapter object
+ * @event_data: event data payload
+ * Context: user.
+ *
+ * Throttle back qdepth.
+ */
+static void
+_scsih_task_set_full(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID,
+ Mpi2EventDataTaskSetFull_t *event_data)
+{
+ unsigned long flags;
+ struct _sas_device *sas_device;
+ static struct _raid_device *raid_device;
+ struct scsi_device *sdev;
+ int depth;
+ u16 current_depth;
+ u16 handle;
+ int id, channel;
+ u64 sas_address;
+
+ current_depth = le16_to_cpu(event_data->CurrentDepth);
+ handle = le16_to_cpu(event_data->DevHandle);
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = _scsih_sas_device_find_by_handle(ioc, handle);
+ if (!sas_device) {
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ id = sas_device->id;
+ channel = sas_device->channel;
+ sas_address = sas_device->sas_address;
+
+ /* if hidden raid component, then change to volume characteristics */
+ if (sas_device->hidden_raid_component && sas_device->volume_handle) {
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ raid_device = _scsih_raid_device_find_by_handle(
+ ioc, sas_device->volume_handle);
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+ if (raid_device) {
+ id = raid_device->id;
+ channel = raid_device->channel;
+ handle = raid_device->handle;
+ sas_address = raid_device->wwid;
+ }
+ }
+
+ if (ioc->logging_level & MPT_DEBUG_TASK_SET_FULL)
+ starget_printk(KERN_DEBUG, sas_device->starget, "task set "
+ "full: handle(0x%04x), sas_addr(0x%016llx), depth(%d)\n",
+ handle, (unsigned long long)sas_address, current_depth);
+
+ shost_for_each_device(sdev, ioc->shost) {
+ if (sdev->id == id && sdev->channel == channel) {
+ if (current_depth > sdev->queue_depth) {
+ if (ioc->logging_level &
+ MPT_DEBUG_TASK_SET_FULL)
+ sdev_printk(KERN_INFO, sdev, "strange "
+ "observation, the queue depth is"
+ " (%d) meanwhile fw queue depth "
+ "is (%d)\n", sdev->queue_depth,
+ current_depth);
+ continue;
+ }
+ depth = scsi_track_queue_full(sdev,
+ current_depth - 1);
+ if (depth > 0)
+ sdev_printk(KERN_INFO, sdev, "Queue depth "
+ "reduced to (%d)\n", depth);
+ else if (depth < 0)
+ sdev_printk(KERN_INFO, sdev, "Tagged Command "
+ "Queueing is being disabled\n");
+ else if (depth == 0)
+ if (ioc->logging_level &
+ MPT_DEBUG_TASK_SET_FULL)
+ sdev_printk(KERN_INFO, sdev,
+ "Queue depth not changed yet\n");
+ }
+ }
+}
+
+/**
+ * _scsih_mark_responding_sas_device - mark a sas_devices as responding
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * @slot: enclosure slot id
+ * @handle: device handle
+ *
+ * After host reset, find out whether devices are still responding.
+ * Used in _scsi_remove_unresponsive_sas_devices.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_mark_responding_sas_device(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
+ u16 slot, u16 handle)
+{
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct scsi_target *starget;
+ struct _sas_device *sas_device;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ list_for_each_entry(sas_device, &ioc->sas_device_list, list) {
+ if (sas_device->sas_address == sas_address &&
+ sas_device->slot == slot && sas_device->starget) {
+ sas_device->responding = 1;
+ starget_printk(KERN_INFO, sas_device->starget,
+ "handle(0x%04x), sas_addr(0x%016llx), enclosure "
+ "logical id(0x%016llx), slot(%d)\n", handle,
+ (unsigned long long)sas_device->sas_address,
+ (unsigned long long)
+ sas_device->enclosure_logical_id,
+ sas_device->slot);
+ if (sas_device->handle == handle)
+ goto out;
+ printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
+ sas_device->handle);
+ sas_device->handle = handle;
+ starget = sas_device->starget;
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->handle = handle;
+ goto out;
+ }
+ }
+ out:
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+}
+
+/**
+ * _scsih_search_responding_sas_devices -
+ * @ioc: per adapter object
+ *
+ * After host reset, find out whether devices are still responding.
+ * If not remove.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_search_responding_sas_devices(struct MPT2SAS_ADAPTER *ioc)
+{
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ Mpi2ConfigReply_t mpi_reply;
+ u16 ioc_status;
+ __le64 sas_address;
+ u16 handle;
+ u32 device_info;
+ u16 slot;
+
+ printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+
+ if (list_empty(&ioc->sas_device_list))
+ return;
+
+ handle = 0xFFFF;
+ while (!(mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply,
+ &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE,
+ handle))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+ handle = le16_to_cpu(sas_device_pg0.DevHandle);
+ device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
+ if (!(_scsih_is_end_device(device_info)))
+ continue;
+ sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+ slot = le16_to_cpu(sas_device_pg0.Slot);
+ _scsih_mark_responding_sas_device(ioc, sas_address, slot,
+ handle);
+ }
+}
+
+/**
+ * _scsih_mark_responding_raid_device - mark a raid_device as responding
+ * @ioc: per adapter object
+ * @wwid: world wide identifier for raid volume
+ * @handle: device handle
+ *
+ * After host reset, find out whether devices are still responding.
+ * Used in _scsi_remove_unresponsive_raid_devices.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_mark_responding_raid_device(struct MPT2SAS_ADAPTER *ioc, u64 wwid,
+ u16 handle)
+{
+ struct MPT2SAS_TARGET *sas_target_priv_data;
+ struct scsi_target *starget;
+ struct _raid_device *raid_device;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->raid_device_lock, flags);
+ list_for_each_entry(raid_device, &ioc->raid_device_list, list) {
+ if (raid_device->wwid == wwid && raid_device->starget) {
+ raid_device->responding = 1;
+ starget_printk(KERN_INFO, raid_device->starget,
+ "handle(0x%04x), wwid(0x%016llx)\n", handle,
+ (unsigned long long)raid_device->wwid);
+ if (raid_device->handle == handle)
+ goto out;
+ printk(KERN_INFO "\thandle changed from(0x%04x)!!!\n",
+ raid_device->handle);
+ raid_device->handle = handle;
+ starget = raid_device->starget;
+ sas_target_priv_data = starget->hostdata;
+ sas_target_priv_data->handle = handle;
+ goto out;
+ }
+ }
+ out:
+ spin_unlock_irqrestore(&ioc->raid_device_lock, flags);
+}
+
+/**
+ * _scsih_search_responding_raid_devices -
+ * @ioc: per adapter object
+ *
+ * After host reset, find out whether devices are still responding.
+ * If not remove.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_search_responding_raid_devices(struct MPT2SAS_ADAPTER *ioc)
+{
+ Mpi2RaidVolPage1_t volume_pg1;
+ Mpi2ConfigReply_t mpi_reply;
+ u16 ioc_status;
+ u16 handle;
+
+ printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+
+ if (list_empty(&ioc->raid_device_list))
+ return;
+
+ handle = 0xFFFF;
+ while (!(mpt2sas_config_get_raid_volume_pg1(ioc, &mpi_reply,
+ &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) {
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+ handle = le16_to_cpu(volume_pg1.DevHandle);
+ _scsih_mark_responding_raid_device(ioc,
+ le64_to_cpu(volume_pg1.WWID), handle);
+ }
+}
+
+/**
+ * _scsih_mark_responding_expander - mark a expander as responding
+ * @ioc: per adapter object
+ * @sas_address: sas address
+ * @handle:
+ *
+ * After host reset, find out whether devices are still responding.
+ * Used in _scsi_remove_unresponsive_expanders.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_mark_responding_expander(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
+ u16 handle)
+{
+ struct _sas_node *sas_expander;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) {
+ if (sas_expander->sas_address == sas_address) {
+ sas_expander->responding = 1;
+ if (sas_expander->handle != handle) {
+ printk(KERN_INFO "old handle(0x%04x)\n",
+ sas_expander->handle);
+ sas_expander->handle = handle;
+ }
+ goto out;
+ }
+ }
+ out:
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+}
+
+/**
+ * _scsih_search_responding_expanders -
+ * @ioc: per adapter object
+ *
+ * After host reset, find out whether devices are still responding.
+ * If not remove.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_search_responding_expanders(struct MPT2SAS_ADAPTER *ioc)
+{
+ Mpi2ExpanderPage0_t expander_pg0;
+ Mpi2ConfigReply_t mpi_reply;
+ u16 ioc_status;
+ __le64 sas_address;
+ u16 handle;
+
+ printk(MPT2SAS_INFO_FMT "%s\n", ioc->name, __func__);
+
+ if (list_empty(&ioc->sas_expander_list))
+ return;
+
+ handle = 0xFFFF;
+ while (!(mpt2sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0,
+ MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) {
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE)
+ break;
+
+ handle = le16_to_cpu(expander_pg0.DevHandle);
+ sas_address = le64_to_cpu(expander_pg0.SASAddress);
+ printk(KERN_INFO "\texpander present: handle(0x%04x), "
+ "sas_addr(0x%016llx)\n", handle,
+ (unsigned long long)sas_address);
+ _scsih_mark_responding_expander(ioc, sas_address, handle);
+ }
+
+}
+
+/**
+ * _scsih_remove_unresponding_devices - removing unresponding devices
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_scsih_remove_unresponding_devices(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct _sas_device *sas_device, *sas_device_next;
+ struct _sas_node *sas_expander, *sas_expander_next;
+ struct _raid_device *raid_device, *raid_device_next;
+ unsigned long flags;
+
+ _scsih_search_responding_sas_devices(ioc);
+ _scsih_search_responding_raid_devices(ioc);
+ _scsih_search_responding_expanders(ioc);
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ ioc->shost_recovery = 0;
+ if (ioc->shost->shost_state == SHOST_RECOVERY) {
+ printk(MPT2SAS_INFO_FMT "putting controller into "
+ "SHOST_RUNNING\n", ioc->name);
+ scsi_host_set_state(ioc->shost, SHOST_RUNNING);
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ list_for_each_entry_safe(sas_device, sas_device_next,
+ &ioc->sas_device_list, list) {
+ if (sas_device->responding) {
+ sas_device->responding = 0;
+ continue;
+ }
+ if (sas_device->starget)
+ starget_printk(KERN_INFO, sas_device->starget,
+ "removing: handle(0x%04x), sas_addr(0x%016llx), "
+ "enclosure logical id(0x%016llx), slot(%d)\n",
+ sas_device->handle,
+ (unsigned long long)sas_device->sas_address,
+ (unsigned long long)
+ sas_device->enclosure_logical_id,
+ sas_device->slot);
+ _scsih_remove_device(ioc, sas_device->handle);
+ }
+
+ list_for_each_entry_safe(raid_device, raid_device_next,
+ &ioc->raid_device_list, list) {
+ if (raid_device->responding) {
+ raid_device->responding = 0;
+ continue;
+ }
+ if (raid_device->starget) {
+ starget_printk(KERN_INFO, raid_device->starget,
+ "removing: handle(0x%04x), wwid(0x%016llx)\n",
+ raid_device->handle,
+ (unsigned long long)raid_device->wwid);
+ scsi_remove_target(&raid_device->starget->dev);
+ }
+ _scsih_raid_device_remove(ioc, raid_device);
+ }
+
+ list_for_each_entry_safe(sas_expander, sas_expander_next,
+ &ioc->sas_expander_list, list) {
+ if (sas_expander->responding) {
+ sas_expander->responding = 0;
+ continue;
+ }
+ printk("\tremoving expander: handle(0x%04x), "
+ " sas_addr(0x%016llx)\n", sas_expander->handle,
+ (unsigned long long)sas_expander->sas_address);
+ _scsih_expander_remove(ioc, sas_expander->handle);
+ }
+}
+
+/**
+ * _firmware_event_work - delayed task for processing firmware events
+ * @ioc: per adapter object
+ * @work: equal to the fw_event_work object
+ * Context: user.
+ *
+ * Return nothing.
+ */
+static void
+_firmware_event_work(struct work_struct *work)
+{
+ struct fw_event_work *fw_event = container_of(work,
+ struct fw_event_work, work.work);
+ unsigned long flags;
+ struct MPT2SAS_ADAPTER *ioc = fw_event->ioc;
+
+ /* This is invoked by calling _scsih_queue_rescan(). */
+ if (fw_event->event == MPT2SAS_RESCAN_AFTER_HOST_RESET) {
+ _scsih_fw_event_free(ioc, fw_event);
+ _scsih_sas_host_refresh(ioc, 1);
+ _scsih_remove_unresponding_devices(ioc);
+ return;
+ }
+
+ /* the queue is being flushed so ignore this event */
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ if (ioc->fw_events_off || ioc->remove_host) {
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+ _scsih_fw_event_free(ioc, fw_event);
+ return;
+ }
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->shost_recovery) {
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ _scsih_fw_event_requeue(ioc, fw_event, 1000);
+ return;
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ switch (fw_event->event) {
+ case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+ _scsih_sas_topology_change_event(ioc, fw_event->VF_ID,
+ fw_event->event_data, fw_event);
+ break;
+ case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ _scsih_sas_device_status_change_event(ioc, fw_event->VF_ID,
+ fw_event->event_data);
+ break;
+ case MPI2_EVENT_SAS_DISCOVERY:
+ _scsih_sas_discovery_event(ioc, fw_event->VF_ID,
+ fw_event->event_data);
+ break;
+ case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
+ _scsih_sas_broadcast_primative_event(ioc, fw_event->VF_ID,
+ fw_event->event_data);
+ break;
+ case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+ _scsih_sas_enclosure_dev_status_change_event(ioc,
+ fw_event->VF_ID, fw_event->event_data);
+ break;
+ case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
+ _scsih_sas_ir_config_change_event(ioc, fw_event->VF_ID,
+ fw_event->event_data);
+ break;
+ case MPI2_EVENT_IR_VOLUME:
+ _scsih_sas_ir_volume_event(ioc, fw_event->VF_ID,
+ fw_event->event_data);
+ break;
+ case MPI2_EVENT_IR_PHYSICAL_DISK:
+ _scsih_sas_ir_physical_disk_event(ioc, fw_event->VF_ID,
+ fw_event->event_data);
+ break;
+ case MPI2_EVENT_IR_OPERATION_STATUS:
+ _scsih_sas_ir_operation_status_event(ioc, fw_event->VF_ID,
+ fw_event->event_data);
+ break;
+ case MPI2_EVENT_TASK_SET_FULL:
+ _scsih_task_set_full(ioc, fw_event->VF_ID,
+ fw_event->event_data);
+ break;
+ }
+ _scsih_fw_event_free(ioc, fw_event);
+}
+
+/**
+ * mpt2sas_scsih_event_callback - firmware event handler (called at ISR time)
+ * @ioc: per adapter object
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ * Context: interrupt.
+ *
+ * This function merely adds a new work task into ioc->firmware_event_thread.
+ * The tasks are worked from _firmware_event_work in user context.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_scsih_event_callback(struct MPT2SAS_ADAPTER *ioc, u8 VF_ID, u32 reply)
+{
+ struct fw_event_work *fw_event;
+ Mpi2EventNotificationReply_t *mpi_reply;
+ unsigned long flags;
+ u16 event;
+
+ /* events turned off due to host reset or driver unloading */
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ if (ioc->fw_events_off || ioc->remove_host) {
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+ return;
+ }
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ event = le16_to_cpu(mpi_reply->Event);
+
+ switch (event) {
+ /* handle these */
+ case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE:
+ {
+ Mpi2EventDataSasBroadcastPrimitive_t *baen_data =
+ (Mpi2EventDataSasBroadcastPrimitive_t *)
+ mpi_reply->EventData;
+
+ if (baen_data->Primitive !=
+ MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT ||
+ ioc->broadcast_aen_busy)
+ return;
+ ioc->broadcast_aen_busy = 1;
+ break;
+ }
+
+ case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
+ _scsih_check_topo_delete_events(ioc,
+ (Mpi2EventDataSasTopologyChangeList_t *)
+ mpi_reply->EventData);
+ break;
+
+ case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE:
+ case MPI2_EVENT_IR_OPERATION_STATUS:
+ case MPI2_EVENT_SAS_DISCOVERY:
+ case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
+ case MPI2_EVENT_IR_VOLUME:
+ case MPI2_EVENT_IR_PHYSICAL_DISK:
+ case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST:
+ case MPI2_EVENT_TASK_SET_FULL:
+ break;
+
+ default: /* ignore the rest */
+ return;
+ }
+
+ fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC);
+ if (!fw_event) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return;
+ }
+ fw_event->event_data =
+ kzalloc(mpi_reply->EventDataLength*4, GFP_ATOMIC);
+ if (!fw_event->event_data) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ kfree(fw_event);
+ return;
+ }
+
+ memcpy(fw_event->event_data, mpi_reply->EventData,
+ mpi_reply->EventDataLength*4);
+ fw_event->ioc = ioc;
+ fw_event->VF_ID = VF_ID;
+ fw_event->event = event;
+ _scsih_fw_event_add(ioc, fw_event);
+}
+
+/* shost template */
+static struct scsi_host_template scsih_driver_template = {
+ .module = THIS_MODULE,
+ .name = "Fusion MPT SAS Host",
+ .proc_name = MPT2SAS_DRIVER_NAME,
+ .queuecommand = scsih_qcmd,
+ .target_alloc = scsih_target_alloc,
+ .slave_alloc = scsih_slave_alloc,
+ .slave_configure = scsih_slave_configure,
+ .target_destroy = scsih_target_destroy,
+ .slave_destroy = scsih_slave_destroy,
+ .change_queue_depth = scsih_change_queue_depth,
+ .change_queue_type = scsih_change_queue_type,
+ .eh_abort_handler = scsih_abort,
+ .eh_device_reset_handler = scsih_dev_reset,
+ .eh_host_reset_handler = scsih_host_reset,
+ .bios_param = scsih_bios_param,
+ .can_queue = 1,
+ .this_id = -1,
+ .sg_tablesize = MPT2SAS_SG_DEPTH,
+ .max_sectors = 8192,
+ .cmd_per_lun = 7,
+ .use_clustering = ENABLE_CLUSTERING,
+ .shost_attrs = mpt2sas_host_attrs,
+ .sdev_attrs = mpt2sas_dev_attrs,
+};
+
+/**
+ * _scsih_expander_node_remove - removing expander device from list.
+ * @ioc: per adapter object
+ * @sas_expander: the sas_device object
+ * Context: Calling function should acquire ioc->sas_node_lock.
+ *
+ * Removing object and freeing associated memory from the
+ * ioc->sas_expander_list.
+ *
+ * Return nothing.
+ */
+static void
+_scsih_expander_node_remove(struct MPT2SAS_ADAPTER *ioc,
+ struct _sas_node *sas_expander)
+{
+ struct _sas_port *mpt2sas_port;
+ struct _sas_device *sas_device;
+ struct _sas_node *expander_sibling;
+ unsigned long flags;
+
+ if (!sas_expander)
+ return;
+
+ /* remove sibling ports attached to this expander */
+ retry_device_search:
+ list_for_each_entry(mpt2sas_port,
+ &sas_expander->sas_port_list, port_list) {
+ if (mpt2sas_port->remote_identify.device_type ==
+ SAS_END_DEVICE) {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device =
+ mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ mpt2sas_port->remote_identify.sas_address);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!sas_device)
+ continue;
+ _scsih_remove_device(ioc, sas_device->handle);
+ goto retry_device_search;
+ }
+ }
+
+ retry_expander_search:
+ list_for_each_entry(mpt2sas_port,
+ &sas_expander->sas_port_list, port_list) {
+
+ if (mpt2sas_port->remote_identify.device_type ==
+ MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+ mpt2sas_port->remote_identify.device_type ==
+ MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) {
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ expander_sibling =
+ mpt2sas_scsih_expander_find_by_sas_address(
+ ioc, mpt2sas_port->remote_identify.sas_address);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ if (!expander_sibling)
+ continue;
+ _scsih_expander_remove(ioc, expander_sibling->handle);
+ goto retry_expander_search;
+ }
+ }
+
+ mpt2sas_transport_port_remove(ioc, sas_expander->sas_address,
+ sas_expander->parent_handle);
+
+ printk(MPT2SAS_INFO_FMT "expander_remove: handle"
+ "(0x%04x), sas_addr(0x%016llx)\n", ioc->name,
+ sas_expander->handle, (unsigned long long)
+ sas_expander->sas_address);
+
+ list_del(&sas_expander->list);
+ kfree(sas_expander->phy);
+ kfree(sas_expander);
+}
+
+/**
+ * scsih_remove - detach and remove add host
+ * @pdev: PCI device struct
+ *
+ * Return nothing.
+ */
+static void __devexit
+scsih_remove(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ struct _sas_port *mpt2sas_port;
+ struct _sas_device *sas_device;
+ struct _sas_node *expander_sibling;
+ struct workqueue_struct *wq;
+ unsigned long flags;
+
+ ioc->remove_host = 1;
+ _scsih_fw_event_off(ioc);
+
+ spin_lock_irqsave(&ioc->fw_event_lock, flags);
+ wq = ioc->firmware_event_thread;
+ ioc->firmware_event_thread = NULL;
+ spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
+ if (wq)
+ destroy_workqueue(wq);
+
+ /* free ports attached to the sas_host */
+ retry_again:
+ list_for_each_entry(mpt2sas_port,
+ &ioc->sas_hba.sas_port_list, port_list) {
+ if (mpt2sas_port->remote_identify.device_type ==
+ SAS_END_DEVICE) {
+ sas_device =
+ mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ mpt2sas_port->remote_identify.sas_address);
+ if (sas_device) {
+ _scsih_remove_device(ioc, sas_device->handle);
+ goto retry_again;
+ }
+ } else {
+ expander_sibling =
+ mpt2sas_scsih_expander_find_by_sas_address(ioc,
+ mpt2sas_port->remote_identify.sas_address);
+ if (expander_sibling) {
+ _scsih_expander_remove(ioc,
+ expander_sibling->handle);
+ goto retry_again;
+ }
+ }
+ }
+
+ /* free phys attached to the sas_host */
+ if (ioc->sas_hba.num_phys) {
+ kfree(ioc->sas_hba.phy);
+ ioc->sas_hba.phy = NULL;
+ ioc->sas_hba.num_phys = 0;
+ }
+
+ sas_remove_host(shost);
+ mpt2sas_base_detach(ioc);
+ list_del(&ioc->list);
+ scsi_remove_host(shost);
+ scsi_host_put(shost);
+}
+
+/**
+ * _scsih_probe_boot_devices - reports 1st device
+ * @ioc: per adapter object
+ *
+ * If specified in bios page 2, this routine reports the 1st
+ * device scsi-ml or sas transport for persistent boot device
+ * purposes. Please refer to function _scsih_determine_boot_device()
+ */
+static void
+_scsih_probe_boot_devices(struct MPT2SAS_ADAPTER *ioc)
+{
+ u8 is_raid;
+ void *device;
+ struct _sas_device *sas_device;
+ struct _raid_device *raid_device;
+ u16 handle, parent_handle;
+ u64 sas_address;
+ unsigned long flags;
+ int rc;
+
+ device = NULL;
+ if (ioc->req_boot_device.device) {
+ device = ioc->req_boot_device.device;
+ is_raid = ioc->req_boot_device.is_raid;
+ } else if (ioc->req_alt_boot_device.device) {
+ device = ioc->req_alt_boot_device.device;
+ is_raid = ioc->req_alt_boot_device.is_raid;
+ } else if (ioc->current_boot_device.device) {
+ device = ioc->current_boot_device.device;
+ is_raid = ioc->current_boot_device.is_raid;
+ }
+
+ if (!device)
+ return;
+
+ if (is_raid) {
+ raid_device = device;
+ rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
+ raid_device->id, 0);
+ if (rc)
+ _scsih_raid_device_remove(ioc, raid_device);
+ } else {
+ sas_device = device;
+ handle = sas_device->handle;
+ parent_handle = sas_device->parent_handle;
+ sas_address = sas_device->sas_address;
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ list_move_tail(&sas_device->list, &ioc->sas_device_list);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+ if (!mpt2sas_transport_port_add(ioc, sas_device->handle,
+ sas_device->parent_handle)) {
+ _scsih_sas_device_remove(ioc, sas_device);
+ } else if (!sas_device->starget) {
+ mpt2sas_transport_port_remove(ioc, sas_address,
+ parent_handle);
+ _scsih_sas_device_remove(ioc, sas_device);
+ }
+ }
+}
+
+/**
+ * _scsih_probe_raid - reporting raid volumes to scsi-ml
+ * @ioc: per adapter object
+ *
+ * Called during initial loading of the driver.
+ */
+static void
+_scsih_probe_raid(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct _raid_device *raid_device, *raid_next;
+ int rc;
+
+ list_for_each_entry_safe(raid_device, raid_next,
+ &ioc->raid_device_list, list) {
+ if (raid_device->starget)
+ continue;
+ rc = scsi_add_device(ioc->shost, RAID_CHANNEL,
+ raid_device->id, 0);
+ if (rc)
+ _scsih_raid_device_remove(ioc, raid_device);
+ }
+}
+
+/**
+ * _scsih_probe_sas - reporting raid volumes to sas transport
+ * @ioc: per adapter object
+ *
+ * Called during initial loading of the driver.
+ */
+static void
+_scsih_probe_sas(struct MPT2SAS_ADAPTER *ioc)
+{
+ struct _sas_device *sas_device, *next;
+ unsigned long flags;
+ u16 handle, parent_handle;
+ u64 sas_address;
+
+ /* SAS Device List */
+ list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list,
+ list) {
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ list_move_tail(&sas_device->list, &ioc->sas_device_list);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ handle = sas_device->handle;
+ parent_handle = sas_device->parent_handle;
+ sas_address = sas_device->sas_address;
+ if (!mpt2sas_transport_port_add(ioc, handle, parent_handle)) {
+ _scsih_sas_device_remove(ioc, sas_device);
+ } else if (!sas_device->starget) {
+ mpt2sas_transport_port_remove(ioc, sas_address,
+ parent_handle);
+ _scsih_sas_device_remove(ioc, sas_device);
+ }
+ }
+}
+
+/**
+ * _scsih_probe_devices - probing for devices
+ * @ioc: per adapter object
+ *
+ * Called during initial loading of the driver.
+ */
+static void
+_scsih_probe_devices(struct MPT2SAS_ADAPTER *ioc)
+{
+ u16 volume_mapping_flags =
+ le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) &
+ MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE;
+
+ if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR))
+ return; /* return when IOC doesn't support initiator mode */
+
+ _scsih_probe_boot_devices(ioc);
+
+ if (ioc->ir_firmware) {
+ if ((volume_mapping_flags &
+ MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING)) {
+ _scsih_probe_sas(ioc);
+ _scsih_probe_raid(ioc);
+ } else {
+ _scsih_probe_raid(ioc);
+ _scsih_probe_sas(ioc);
+ }
+ } else
+ _scsih_probe_sas(ioc);
+}
+
+/**
+ * scsih_probe - attach and add scsi host
+ * @pdev: PCI device struct
+ * @id: pci device id
+ *
+ * Returns 0 success, anything else error.
+ */
+static int
+scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+ struct MPT2SAS_ADAPTER *ioc;
+ struct Scsi_Host *shost;
+
+ shost = scsi_host_alloc(&scsih_driver_template,
+ sizeof(struct MPT2SAS_ADAPTER));
+ if (!shost)
+ return -ENODEV;
+
+ /* init local params */
+ ioc = shost_priv(shost);
+ memset(ioc, 0, sizeof(struct MPT2SAS_ADAPTER));
+ INIT_LIST_HEAD(&ioc->list);
+ list_add_tail(&ioc->list, &mpt2sas_ioc_list);
+ ioc->shost = shost;
+ ioc->id = mpt_ids++;
+ sprintf(ioc->name, "%s%d", MPT2SAS_DRIVER_NAME, ioc->id);
+ ioc->pdev = pdev;
+ ioc->scsi_io_cb_idx = scsi_io_cb_idx;
+ ioc->tm_cb_idx = tm_cb_idx;
+ ioc->ctl_cb_idx = ctl_cb_idx;
+ ioc->base_cb_idx = base_cb_idx;
+ ioc->transport_cb_idx = transport_cb_idx;
+ ioc->config_cb_idx = config_cb_idx;
+ ioc->logging_level = logging_level;
+ /* misc semaphores and spin locks */
+ spin_lock_init(&ioc->ioc_reset_in_progress_lock);
+ spin_lock_init(&ioc->scsi_lookup_lock);
+ spin_lock_init(&ioc->sas_device_lock);
+ spin_lock_init(&ioc->sas_node_lock);
+ spin_lock_init(&ioc->fw_event_lock);
+ spin_lock_init(&ioc->raid_device_lock);
+
+ INIT_LIST_HEAD(&ioc->sas_device_list);
+ INIT_LIST_HEAD(&ioc->sas_device_init_list);
+ INIT_LIST_HEAD(&ioc->sas_expander_list);
+ INIT_LIST_HEAD(&ioc->fw_event_list);
+ INIT_LIST_HEAD(&ioc->raid_device_list);
+ INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list);
+
+ /* init shost parameters */
+ shost->max_cmd_len = 16;
+ shost->max_lun = max_lun;
+ shost->transportt = mpt2sas_transport_template;
+ shost->unique_id = ioc->id;
+
+ if ((scsi_add_host(shost, &pdev->dev))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ list_del(&ioc->list);
+ goto out_add_shost_fail;
+ }
+
+ /* event thread */
+ snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name),
+ "fw_event%d", ioc->id);
+ ioc->firmware_event_thread = create_singlethread_workqueue(
+ ioc->firmware_event_name);
+ if (!ioc->firmware_event_thread) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out_thread_fail;
+ }
+
+ ioc->wait_for_port_enable_to_complete = 1;
+ if ((mpt2sas_base_attach(ioc))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out_attach_fail;
+ }
+
+ ioc->wait_for_port_enable_to_complete = 0;
+ _scsih_probe_devices(ioc);
+ return 0;
+
+ out_attach_fail:
+ destroy_workqueue(ioc->firmware_event_thread);
+ out_thread_fail:
+ list_del(&ioc->list);
+ scsi_remove_host(shost);
+ out_add_shost_fail:
+ return -ENODEV;
+}
+
+#ifdef CONFIG_PM
+/**
+ * scsih_suspend - power management suspend main entry point
+ * @pdev: PCI device struct
+ * @state: PM state change to (usually PCI_D3)
+ *
+ * Returns 0 success, anything else error.
+ */
+static int
+scsih_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ u32 device_state;
+
+ flush_scheduled_work();
+ scsi_block_requests(shost);
+ device_state = pci_choose_state(pdev, state);
+ printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering "
+ "operating state [D%d]\n", ioc->name, pdev,
+ pci_name(pdev), device_state);
+
+ mpt2sas_base_free_resources(ioc);
+ pci_save_state(pdev);
+ pci_disable_device(pdev);
+ pci_set_power_state(pdev, device_state);
+ return 0;
+}
+
+/**
+ * scsih_resume - power management resume main entry point
+ * @pdev: PCI device struct
+ *
+ * Returns 0 success, anything else error.
+ */
+static int
+scsih_resume(struct pci_dev *pdev)
+{
+ struct Scsi_Host *shost = pci_get_drvdata(pdev);
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ u32 device_state = pdev->current_state;
+ int r;
+
+ printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, previous "
+ "operating state [D%d]\n", ioc->name, pdev,
+ pci_name(pdev), device_state);
+
+ pci_set_power_state(pdev, PCI_D0);
+ pci_enable_wake(pdev, PCI_D0, 0);
+ pci_restore_state(pdev);
+ ioc->pdev = pdev;
+ r = mpt2sas_base_map_resources(ioc);
+ if (r)
+ return r;
+
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET);
+ scsi_unblock_requests(shost);
+ return 0;
+}
+#endif /* CONFIG_PM */
+
+
+static struct pci_driver scsih_driver = {
+ .name = MPT2SAS_DRIVER_NAME,
+ .id_table = scsih_pci_table,
+ .probe = scsih_probe,
+ .remove = __devexit_p(scsih_remove),
+#ifdef CONFIG_PM
+ .suspend = scsih_suspend,
+ .resume = scsih_resume,
+#endif
+};
+
+
+/**
+ * scsih_init - main entry point for this driver.
+ *
+ * Returns 0 success, anything else error.
+ */
+static int __init
+scsih_init(void)
+{
+ int error;
+
+ mpt_ids = 0;
+ printk(KERN_INFO "%s version %s loaded\n", MPT2SAS_DRIVER_NAME,
+ MPT2SAS_DRIVER_VERSION);
+
+ mpt2sas_transport_template =
+ sas_attach_transport(&mpt2sas_transport_functions);
+ if (!mpt2sas_transport_template)
+ return -ENODEV;
+
+ mpt2sas_base_initialize_callback_handler();
+
+ /* queuecommand callback hander */
+ scsi_io_cb_idx = mpt2sas_base_register_callback_handler(scsih_io_done);
+
+ /* task managment callback handler */
+ tm_cb_idx = mpt2sas_base_register_callback_handler(scsih_tm_done);
+
+ /* base internal commands callback handler */
+ base_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_base_done);
+
+ /* transport internal commands callback handler */
+ transport_cb_idx = mpt2sas_base_register_callback_handler(
+ mpt2sas_transport_done);
+
+ /* configuration page API internal commands callback handler */
+ config_cb_idx = mpt2sas_base_register_callback_handler(
+ mpt2sas_config_done);
+
+ /* ctl module callback handler */
+ ctl_cb_idx = mpt2sas_base_register_callback_handler(mpt2sas_ctl_done);
+
+ mpt2sas_ctl_init();
+
+ error = pci_register_driver(&scsih_driver);
+ if (error)
+ sas_release_transport(mpt2sas_transport_template);
+
+ return error;
+}
+
+/**
+ * scsih_exit - exit point for this driver (when it is a module).
+ *
+ * Returns 0 success, anything else error.
+ */
+static void __exit
+scsih_exit(void)
+{
+ printk(KERN_INFO "mpt2sas version %s unloading\n",
+ MPT2SAS_DRIVER_VERSION);
+
+ pci_unregister_driver(&scsih_driver);
+
+ sas_release_transport(mpt2sas_transport_template);
+ mpt2sas_base_release_callback_handler(scsi_io_cb_idx);
+ mpt2sas_base_release_callback_handler(tm_cb_idx);
+ mpt2sas_base_release_callback_handler(base_cb_idx);
+ mpt2sas_base_release_callback_handler(transport_cb_idx);
+ mpt2sas_base_release_callback_handler(config_cb_idx);
+ mpt2sas_base_release_callback_handler(ctl_cb_idx);
+
+ mpt2sas_ctl_exit();
+}
+
+module_init(scsih_init);
+module_exit(scsih_exit);
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c
new file mode 100644
index 00000000000..e03dc0b1e1a
--- /dev/null
+++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c
@@ -0,0 +1,1211 @@
+/*
+ * SAS Transport Layer for MPT (Message Passing Technology) based controllers
+ *
+ * This code is based on drivers/scsi/mpt2sas/mpt2_transport.c
+ * Copyright (C) 2007-2008 LSI Corporation
+ * (mailto:DL-MPTFusionLinux@lsi.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * NO WARRANTY
+ * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR
+ * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT
+ * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT,
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is
+ * solely responsible for determining the appropriateness of using and
+ * distributing the Program and assumes all risks associated with its
+ * exercise of rights under this Agreement, including but not limited to
+ * the risks and costs of program errors, damage to or loss of data,
+ * programs or equipment, and unavailability or interruption of operations.
+
+ * DISCLAIMER OF LIABILITY
+ * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED
+ * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+ * USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_transport_sas.h>
+#include <scsi/scsi_dbg.h>
+
+#include "mpt2sas_base.h"
+/**
+ * _transport_sas_node_find_by_handle - sas node search
+ * @ioc: per adapter object
+ * @handle: expander or hba handle (assigned by firmware)
+ * Context: Calling function should acquire ioc->sas_node_lock.
+ *
+ * Search for either hba phys or expander device based on handle, then returns
+ * the sas_node object.
+ */
+static struct _sas_node *
+_transport_sas_node_find_by_handle(struct MPT2SAS_ADAPTER *ioc, u16 handle)
+{
+ int i;
+
+ for (i = 0; i < ioc->sas_hba.num_phys; i++)
+ if (ioc->sas_hba.phy[i].handle == handle)
+ return &ioc->sas_hba;
+
+ return mpt2sas_scsih_expander_find_by_handle(ioc, handle);
+}
+
+/**
+ * _transport_convert_phy_link_rate -
+ * @link_rate: link rate returned from mpt firmware
+ *
+ * Convert link_rate from mpi fusion into sas_transport form.
+ */
+static enum sas_linkrate
+_transport_convert_phy_link_rate(u8 link_rate)
+{
+ enum sas_linkrate rc;
+
+ switch (link_rate) {
+ case MPI2_SAS_NEG_LINK_RATE_1_5:
+ rc = SAS_LINK_RATE_1_5_GBPS;
+ break;
+ case MPI2_SAS_NEG_LINK_RATE_3_0:
+ rc = SAS_LINK_RATE_3_0_GBPS;
+ break;
+ case MPI2_SAS_NEG_LINK_RATE_6_0:
+ rc = SAS_LINK_RATE_6_0_GBPS;
+ break;
+ case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED:
+ rc = SAS_PHY_DISABLED;
+ break;
+ case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED:
+ rc = SAS_LINK_RATE_FAILED;
+ break;
+ case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR:
+ rc = SAS_SATA_PORT_SELECTOR;
+ break;
+ case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS:
+ rc = SAS_PHY_RESET_IN_PROGRESS;
+ break;
+ default:
+ case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE:
+ case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE:
+ rc = SAS_LINK_RATE_UNKNOWN;
+ break;
+ }
+ return rc;
+}
+
+/**
+ * _transport_set_identify - set identify for phys and end devices
+ * @ioc: per adapter object
+ * @handle: device handle
+ * @identify: sas identify info
+ *
+ * Populates sas identify info.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+_transport_set_identify(struct MPT2SAS_ADAPTER *ioc, u16 handle,
+ struct sas_identify *identify)
+{
+ Mpi2SasDevicePage0_t sas_device_pg0;
+ Mpi2ConfigReply_t mpi_reply;
+ u32 device_info;
+ u32 ioc_status;
+
+ if ((mpt2sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0,
+ MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ ioc_status = le16_to_cpu(mpi_reply.IOCStatus) &
+ MPI2_IOCSTATUS_MASK;
+ if (ioc_status != MPI2_IOCSTATUS_SUCCESS) {
+ printk(MPT2SAS_ERR_FMT "handle(0x%04x), ioc_status(0x%04x)"
+ "\nfailure at %s:%d/%s()!\n", ioc->name, handle, ioc_status,
+ __FILE__, __LINE__, __func__);
+ return -1;
+ }
+
+ memset(identify, 0, sizeof(identify));
+ device_info = le32_to_cpu(sas_device_pg0.DeviceInfo);
+
+ /* sas_address */
+ identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress);
+
+ /* device_type */
+ switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) {
+ case MPI2_SAS_DEVICE_INFO_NO_DEVICE:
+ identify->device_type = SAS_PHY_UNUSED;
+ break;
+ case MPI2_SAS_DEVICE_INFO_END_DEVICE:
+ identify->device_type = SAS_END_DEVICE;
+ break;
+ case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER:
+ identify->device_type = SAS_EDGE_EXPANDER_DEVICE;
+ break;
+ case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER:
+ identify->device_type = SAS_FANOUT_EXPANDER_DEVICE;
+ break;
+ }
+
+ /* initiator_port_protocols */
+ if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR)
+ identify->initiator_port_protocols |= SAS_PROTOCOL_SSP;
+ if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR)
+ identify->initiator_port_protocols |= SAS_PROTOCOL_STP;
+ if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR)
+ identify->initiator_port_protocols |= SAS_PROTOCOL_SMP;
+ if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST)
+ identify->initiator_port_protocols |= SAS_PROTOCOL_SATA;
+
+ /* target_port_protocols */
+ if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET)
+ identify->target_port_protocols |= SAS_PROTOCOL_SSP;
+ if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET)
+ identify->target_port_protocols |= SAS_PROTOCOL_STP;
+ if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET)
+ identify->target_port_protocols |= SAS_PROTOCOL_SMP;
+ if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE)
+ identify->target_port_protocols |= SAS_PROTOCOL_SATA;
+
+ return 0;
+}
+
+/**
+ * mpt2sas_transport_done - internal transport layer callback handler.
+ * @ioc: per adapter object
+ * @smid: system request message index
+ * @VF_ID: virtual function id
+ * @reply: reply message frame(lower 32bit addr)
+ *
+ * Callback handler when sending internal generated transport cmds.
+ * The callback index passed is `ioc->transport_cb_idx`
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_transport_done(struct MPT2SAS_ADAPTER *ioc, u16 smid, u8 VF_ID,
+ u32 reply)
+{
+ MPI2DefaultReply_t *mpi_reply;
+
+ mpi_reply = mpt2sas_base_get_reply_virt_addr(ioc, reply);
+ if (ioc->transport_cmds.status == MPT2_CMD_NOT_USED)
+ return;
+ if (ioc->transport_cmds.smid != smid)
+ return;
+ ioc->transport_cmds.status |= MPT2_CMD_COMPLETE;
+ if (mpi_reply) {
+ memcpy(ioc->transport_cmds.reply, mpi_reply,
+ mpi_reply->MsgLength*4);
+ ioc->transport_cmds.status |= MPT2_CMD_REPLY_VALID;
+ }
+ ioc->transport_cmds.status &= ~MPT2_CMD_PENDING;
+ complete(&ioc->transport_cmds.done);
+}
+
+/* report manufacture request structure */
+struct rep_manu_request{
+ u8 smp_frame_type;
+ u8 function;
+ u8 reserved;
+ u8 request_length;
+};
+
+/* report manufacture reply structure */
+struct rep_manu_reply{
+ u8 smp_frame_type; /* 0x41 */
+ u8 function; /* 0x01 */
+ u8 function_result;
+ u8 response_length;
+ u16 expander_change_count;
+ u8 reserved0[2];
+ u8 sas_format:1;
+ u8 reserved1:7;
+ u8 reserved2[3];
+ u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN];
+ u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN];
+ u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN];
+ u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN];
+ u16 component_id;
+ u8 component_revision_id;
+ u8 reserved3;
+ u8 vendor_specific[8];
+};
+
+/**
+ * transport_expander_report_manufacture - obtain SMP report_manufacture
+ * @ioc: per adapter object
+ * @sas_address: expander sas address
+ * @edev: the sas_expander_device object
+ *
+ * Fills in the sas_expander_device object when SMP port is created.
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+transport_expander_report_manufacture(struct MPT2SAS_ADAPTER *ioc,
+ u64 sas_address, struct sas_expander_device *edev)
+{
+ Mpi2SmpPassthroughRequest_t *mpi_request;
+ Mpi2SmpPassthroughReply_t *mpi_reply;
+ struct rep_manu_reply *manufacture_reply;
+ struct rep_manu_request *manufacture_request;
+ int rc;
+ u16 smid;
+ u32 ioc_state;
+ unsigned long timeleft;
+ void *psge;
+ u32 sgl_flags;
+ u8 issue_reset = 0;
+ unsigned long flags;
+ void *data_out = NULL;
+ dma_addr_t data_out_dma;
+ u32 sz;
+ u64 *sas_address_le;
+ u16 wait_state_count;
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->ioc_reset_in_progress) {
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+ __func__, ioc->name);
+ return -EFAULT;
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ mutex_lock(&ioc->transport_cmds.mutex);
+
+ if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+ ioc->transport_cmds.status = MPT2_CMD_PENDING;
+
+ wait_state_count = 0;
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ if (wait_state_count++ == 10) {
+ printk(MPT2SAS_ERR_FMT
+ "%s: failed due to ioc not operational\n",
+ ioc->name, __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+ ssleep(1);
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ printk(MPT2SAS_INFO_FMT "%s: waiting for "
+ "operational state(count=%d)\n", ioc->name,
+ __func__, wait_state_count);
+ }
+ if (wait_state_count)
+ printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
+ ioc->name, __func__);
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ rc = 0;
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->transport_cmds.smid = smid;
+
+ sz = sizeof(struct rep_manu_request) + sizeof(struct rep_manu_reply);
+ data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma);
+
+ if (!data_out) {
+ printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__,
+ __LINE__, __func__);
+ rc = -ENOMEM;
+ mpt2sas_base_free_smid(ioc, smid);
+ goto out;
+ }
+
+ manufacture_request = data_out;
+ manufacture_request->smp_frame_type = 0x40;
+ manufacture_request->function = 1;
+ manufacture_request->reserved = 0;
+ manufacture_request->request_length = 0;
+
+ memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
+ mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
+ mpi_request->PhysicalPort = 0xFF;
+ sas_address_le = (u64 *)&mpi_request->SASAddress;
+ *sas_address_le = cpu_to_le64(sas_address);
+ mpi_request->RequestDataLength = sizeof(struct rep_manu_request);
+ psge = &mpi_request->SGL;
+
+ /* WRITE sgel first */
+ sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+ ioc->base_add_sg_single(psge, sgl_flags |
+ sizeof(struct rep_manu_request), data_out_dma);
+
+ /* incr sgel */
+ psge += ioc->sge_size;
+
+ /* READ sgel last */
+ sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+ MPI2_SGE_FLAGS_END_OF_LIST);
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+ ioc->base_add_sg_single(psge, sgl_flags |
+ sizeof(struct rep_manu_reply), data_out_dma +
+ sizeof(struct rep_manu_request));
+
+ dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
+ "send to sas_addr(0x%016llx)\n", ioc->name,
+ (unsigned long long)sas_address));
+ mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
+ timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
+ 10*HZ);
+
+ if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s: timeout\n",
+ ioc->name, __func__);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2SmpPassthroughRequest_t)/4);
+ if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+
+ dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "report_manufacture - "
+ "complete\n", ioc->name));
+
+ if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
+ u8 *tmp;
+
+ mpi_reply = ioc->transport_cmds.reply;
+
+ dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "report_manufacture - reply data transfer size(%d)\n",
+ ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength)));
+
+ if (le16_to_cpu(mpi_reply->ResponseDataLength) !=
+ sizeof(struct rep_manu_reply))
+ goto out;
+
+ manufacture_reply = data_out + sizeof(struct rep_manu_request);
+ strncpy(edev->vendor_id, manufacture_reply->vendor_id,
+ SAS_EXPANDER_VENDOR_ID_LEN);
+ strncpy(edev->product_id, manufacture_reply->product_id,
+ SAS_EXPANDER_PRODUCT_ID_LEN);
+ strncpy(edev->product_rev, manufacture_reply->product_rev,
+ SAS_EXPANDER_PRODUCT_REV_LEN);
+ edev->level = manufacture_reply->sas_format;
+ if (manufacture_reply->sas_format) {
+ strncpy(edev->component_vendor_id,
+ manufacture_reply->component_vendor_id,
+ SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN);
+ tmp = (u8 *)&manufacture_reply->component_id;
+ edev->component_id = tmp[0] << 8 | tmp[1];
+ edev->component_revision_id =
+ manufacture_reply->component_revision_id;
+ }
+ } else
+ dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "report_manufacture - no reply\n", ioc->name));
+
+ issue_host_reset:
+ if (issue_reset)
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ out:
+ ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
+ if (data_out)
+ pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma);
+
+ mutex_unlock(&ioc->transport_cmds.mutex);
+ return rc;
+}
+
+/**
+ * mpt2sas_transport_port_add - insert port to the list
+ * @ioc: per adapter object
+ * @handle: handle of attached device
+ * @parent_handle: parent handle(either hba or expander)
+ * Context: This function will acquire ioc->sas_node_lock.
+ *
+ * Adding new port object to the sas_node->sas_port_list.
+ *
+ * Returns mpt2sas_port.
+ */
+struct _sas_port *
+mpt2sas_transport_port_add(struct MPT2SAS_ADAPTER *ioc, u16 handle,
+ u16 parent_handle)
+{
+ struct _sas_phy *mpt2sas_phy, *next;
+ struct _sas_port *mpt2sas_port;
+ unsigned long flags;
+ struct _sas_node *sas_node;
+ struct sas_rphy *rphy;
+ int i;
+ struct sas_port *port;
+
+ if (!parent_handle)
+ return NULL;
+
+ mpt2sas_port = kzalloc(sizeof(struct _sas_port),
+ GFP_KERNEL);
+ if (!mpt2sas_port) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return NULL;
+ }
+
+ INIT_LIST_HEAD(&mpt2sas_port->port_list);
+ INIT_LIST_HEAD(&mpt2sas_port->phy_list);
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+ if (!sas_node) {
+ printk(MPT2SAS_ERR_FMT "%s: Could not find parent(0x%04x)!\n",
+ ioc->name, __func__, parent_handle);
+ goto out_fail;
+ }
+
+ mpt2sas_port->handle = parent_handle;
+ mpt2sas_port->sas_address = sas_node->sas_address;
+ if ((_transport_set_identify(ioc, handle,
+ &mpt2sas_port->remote_identify))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out_fail;
+ }
+
+ if (mpt2sas_port->remote_identify.device_type == SAS_PHY_UNUSED) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out_fail;
+ }
+
+ for (i = 0; i < sas_node->num_phys; i++) {
+ if (sas_node->phy[i].remote_identify.sas_address !=
+ mpt2sas_port->remote_identify.sas_address)
+ continue;
+ list_add_tail(&sas_node->phy[i].port_siblings,
+ &mpt2sas_port->phy_list);
+ mpt2sas_port->num_phys++;
+ }
+
+ if (!mpt2sas_port->num_phys) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out_fail;
+ }
+
+ port = sas_port_alloc_num(sas_node->parent_dev);
+ if ((sas_port_add(port))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ goto out_fail;
+ }
+
+ list_for_each_entry(mpt2sas_phy, &mpt2sas_port->phy_list,
+ port_siblings) {
+ if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+ dev_printk(KERN_INFO, &port->dev, "add: handle(0x%04x)"
+ ", sas_addr(0x%016llx), phy(%d)\n", handle,
+ (unsigned long long)
+ mpt2sas_port->remote_identify.sas_address,
+ mpt2sas_phy->phy_id);
+ sas_port_add_phy(port, mpt2sas_phy->phy);
+ }
+
+ mpt2sas_port->port = port;
+ if (mpt2sas_port->remote_identify.device_type == SAS_END_DEVICE)
+ rphy = sas_end_device_alloc(port);
+ else
+ rphy = sas_expander_alloc(port,
+ mpt2sas_port->remote_identify.device_type);
+
+ rphy->identify = mpt2sas_port->remote_identify;
+ if ((sas_rphy_add(rphy))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ }
+ if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+ dev_printk(KERN_INFO, &rphy->dev, "add: handle(0x%04x), "
+ "sas_addr(0x%016llx)\n", handle,
+ (unsigned long long)
+ mpt2sas_port->remote_identify.sas_address);
+ mpt2sas_port->rphy = rphy;
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ list_add_tail(&mpt2sas_port->port_list, &sas_node->sas_port_list);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+ /* fill in report manufacture */
+ if (mpt2sas_port->remote_identify.device_type ==
+ MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER ||
+ mpt2sas_port->remote_identify.device_type ==
+ MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER)
+ transport_expander_report_manufacture(ioc,
+ mpt2sas_port->remote_identify.sas_address,
+ rphy_to_expander_device(rphy));
+
+ return mpt2sas_port;
+
+ out_fail:
+ list_for_each_entry_safe(mpt2sas_phy, next, &mpt2sas_port->phy_list,
+ port_siblings)
+ list_del(&mpt2sas_phy->port_siblings);
+ kfree(mpt2sas_port);
+ return NULL;
+}
+
+/**
+ * mpt2sas_transport_port_remove - remove port from the list
+ * @ioc: per adapter object
+ * @sas_address: sas address of attached device
+ * @parent_handle: handle to the upstream parent(either hba or expander)
+ * Context: This function will acquire ioc->sas_node_lock.
+ *
+ * Removing object and freeing associated memory from the
+ * ioc->sas_port_list.
+ *
+ * Return nothing.
+ */
+void
+mpt2sas_transport_port_remove(struct MPT2SAS_ADAPTER *ioc, u64 sas_address,
+ u16 parent_handle)
+{
+ int i;
+ unsigned long flags;
+ struct _sas_port *mpt2sas_port, *next;
+ struct _sas_node *sas_node;
+ u8 found = 0;
+ struct _sas_phy *mpt2sas_phy, *next_phy;
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_node = _transport_sas_node_find_by_handle(ioc, parent_handle);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ if (!sas_node)
+ return;
+ list_for_each_entry_safe(mpt2sas_port, next, &sas_node->sas_port_list,
+ port_list) {
+ if (mpt2sas_port->remote_identify.sas_address != sas_address)
+ continue;
+ found = 1;
+ list_del(&mpt2sas_port->port_list);
+ goto out;
+ }
+ out:
+ if (!found)
+ return;
+
+ for (i = 0; i < sas_node->num_phys; i++) {
+ if (sas_node->phy[i].remote_identify.sas_address == sas_address)
+ memset(&sas_node->phy[i].remote_identify, 0 ,
+ sizeof(struct sas_identify));
+ }
+
+ list_for_each_entry_safe(mpt2sas_phy, next_phy,
+ &mpt2sas_port->phy_list, port_siblings) {
+ if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+ dev_printk(KERN_INFO, &mpt2sas_port->port->dev,
+ "remove: parent_handle(0x%04x), "
+ "sas_addr(0x%016llx), phy(%d)\n", parent_handle,
+ (unsigned long long)
+ mpt2sas_port->remote_identify.sas_address,
+ mpt2sas_phy->phy_id);
+ sas_port_delete_phy(mpt2sas_port->port, mpt2sas_phy->phy);
+ list_del(&mpt2sas_phy->port_siblings);
+ }
+ sas_port_delete(mpt2sas_port->port);
+ kfree(mpt2sas_port);
+}
+
+/**
+ * mpt2sas_transport_add_host_phy - report sas_host phy to transport
+ * @ioc: per adapter object
+ * @mpt2sas_phy: mpt2sas per phy object
+ * @phy_pg0: sas phy page 0
+ * @parent_dev: parent device class object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_transport_add_host_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
+ *mpt2sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev)
+{
+ struct sas_phy *phy;
+ int phy_index = mpt2sas_phy->phy_id;
+
+
+ INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
+ phy = sas_phy_alloc(parent_dev, phy_index);
+ if (!phy) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+ if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
+ &mpt2sas_phy->identify))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+ phy->identify = mpt2sas_phy->identify;
+ mpt2sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle);
+ if (mpt2sas_phy->attached_handle)
+ _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
+ &mpt2sas_phy->remote_identify);
+ phy->identify.phy_identifier = mpt2sas_phy->phy_id;
+ phy->negotiated_linkrate = _transport_convert_phy_link_rate(
+ phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
+ phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
+ phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
+ phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
+ phy_pg0.HwLinkRate >> 4);
+ phy->minimum_linkrate = _transport_convert_phy_link_rate(
+ phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
+ phy->maximum_linkrate = _transport_convert_phy_link_rate(
+ phy_pg0.ProgrammedLinkRate >> 4);
+
+ if ((sas_phy_add(phy))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ sas_phy_free(phy);
+ return -1;
+ }
+ if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+ dev_printk(KERN_INFO, &phy->dev,
+ "add: handle(0x%04x), sas_addr(0x%016llx)\n"
+ "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
+ mpt2sas_phy->handle, (unsigned long long)
+ mpt2sas_phy->identify.sas_address,
+ mpt2sas_phy->attached_handle,
+ (unsigned long long)
+ mpt2sas_phy->remote_identify.sas_address);
+ mpt2sas_phy->phy = phy;
+ return 0;
+}
+
+
+/**
+ * mpt2sas_transport_add_expander_phy - report expander phy to transport
+ * @ioc: per adapter object
+ * @mpt2sas_phy: mpt2sas per phy object
+ * @expander_pg1: expander page 1
+ * @parent_dev: parent device class object
+ *
+ * Returns 0 for success, non-zero for failure.
+ */
+int
+mpt2sas_transport_add_expander_phy(struct MPT2SAS_ADAPTER *ioc, struct _sas_phy
+ *mpt2sas_phy, Mpi2ExpanderPage1_t expander_pg1, struct device *parent_dev)
+{
+ struct sas_phy *phy;
+ int phy_index = mpt2sas_phy->phy_id;
+
+ INIT_LIST_HEAD(&mpt2sas_phy->port_siblings);
+ phy = sas_phy_alloc(parent_dev, phy_index);
+ if (!phy) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+ if ((_transport_set_identify(ioc, mpt2sas_phy->handle,
+ &mpt2sas_phy->identify))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -1;
+ }
+ phy->identify = mpt2sas_phy->identify;
+ mpt2sas_phy->attached_handle =
+ le16_to_cpu(expander_pg1.AttachedDevHandle);
+ if (mpt2sas_phy->attached_handle)
+ _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
+ &mpt2sas_phy->remote_identify);
+ phy->identify.phy_identifier = mpt2sas_phy->phy_id;
+ phy->negotiated_linkrate = _transport_convert_phy_link_rate(
+ expander_pg1.NegotiatedLinkRate &
+ MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL);
+ phy->minimum_linkrate_hw = _transport_convert_phy_link_rate(
+ expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK);
+ phy->maximum_linkrate_hw = _transport_convert_phy_link_rate(
+ expander_pg1.HwLinkRate >> 4);
+ phy->minimum_linkrate = _transport_convert_phy_link_rate(
+ expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK);
+ phy->maximum_linkrate = _transport_convert_phy_link_rate(
+ expander_pg1.ProgrammedLinkRate >> 4);
+
+ if ((sas_phy_add(phy))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ sas_phy_free(phy);
+ return -1;
+ }
+ if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+ dev_printk(KERN_INFO, &phy->dev,
+ "add: handle(0x%04x), sas_addr(0x%016llx)\n"
+ "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
+ mpt2sas_phy->handle, (unsigned long long)
+ mpt2sas_phy->identify.sas_address,
+ mpt2sas_phy->attached_handle,
+ (unsigned long long)
+ mpt2sas_phy->remote_identify.sas_address);
+ mpt2sas_phy->phy = phy;
+ return 0;
+}
+
+/**
+ * mpt2sas_transport_update_phy_link_change - refreshing phy link changes and attached devices
+ * @ioc: per adapter object
+ * @handle: handle to sas_host or expander
+ * @attached_handle: attached device handle
+ * @phy_numberv: phy number
+ * @link_rate: new link rate
+ *
+ * Returns nothing.
+ */
+void
+mpt2sas_transport_update_phy_link_change(struct MPT2SAS_ADAPTER *ioc,
+ u16 handle, u16 attached_handle, u8 phy_number, u8 link_rate)
+{
+ unsigned long flags;
+ struct _sas_node *sas_node;
+ struct _sas_phy *mpt2sas_phy;
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_node = _transport_sas_node_find_by_handle(ioc, handle);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+ if (!sas_node)
+ return;
+
+ mpt2sas_phy = &sas_node->phy[phy_number];
+ mpt2sas_phy->attached_handle = attached_handle;
+ if (attached_handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5))
+ _transport_set_identify(ioc, mpt2sas_phy->attached_handle,
+ &mpt2sas_phy->remote_identify);
+ else
+ memset(&mpt2sas_phy->remote_identify, 0 , sizeof(struct
+ sas_identify));
+
+ if (mpt2sas_phy->phy)
+ mpt2sas_phy->phy->negotiated_linkrate =
+ _transport_convert_phy_link_rate(link_rate);
+
+ if ((ioc->logging_level & MPT_DEBUG_TRANSPORT))
+ dev_printk(KERN_INFO, &mpt2sas_phy->phy->dev,
+ "refresh: handle(0x%04x), sas_addr(0x%016llx),\n"
+ "\tlink_rate(0x%02x), phy(%d)\n"
+ "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n",
+ handle, (unsigned long long)
+ mpt2sas_phy->identify.sas_address, link_rate,
+ phy_number, attached_handle,
+ (unsigned long long)
+ mpt2sas_phy->remote_identify.sas_address);
+}
+
+static inline void *
+phy_to_ioc(struct sas_phy *phy)
+{
+ struct Scsi_Host *shost = dev_to_shost(phy->dev.parent);
+ return shost_priv(shost);
+}
+
+static inline void *
+rphy_to_ioc(struct sas_rphy *rphy)
+{
+ struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent);
+ return shost_priv(shost);
+}
+
+/**
+ * transport_get_linkerrors -
+ * @phy: The sas phy object
+ *
+ * Only support sas_host direct attached phys.
+ * Returns 0 for success, non-zero for failure.
+ *
+ */
+static int
+transport_get_linkerrors(struct sas_phy *phy)
+{
+ struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
+ struct _sas_phy *mpt2sas_phy;
+ Mpi2ConfigReply_t mpi_reply;
+ Mpi2SasPhyPage1_t phy_pg1;
+ int i;
+
+ for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
+ !mpt2sas_phy; i++) {
+ if (ioc->sas_hba.phy[i].phy != phy)
+ continue;
+ mpt2sas_phy = &ioc->sas_hba.phy[i];
+ }
+
+ if (!mpt2sas_phy) /* this phy not on sas_host */
+ return -EINVAL;
+
+ if ((mpt2sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1,
+ mpt2sas_phy->phy_id))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -ENXIO;
+ }
+
+ if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
+ printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
+ "(0x%04x), loginfo(0x%08x)\n", ioc->name,
+ mpt2sas_phy->phy_id,
+ le16_to_cpu(mpi_reply.IOCStatus),
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+
+ phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount);
+ phy->running_disparity_error_count =
+ le32_to_cpu(phy_pg1.RunningDisparityErrorCount);
+ phy->loss_of_dword_sync_count =
+ le32_to_cpu(phy_pg1.LossDwordSynchCount);
+ phy->phy_reset_problem_count =
+ le32_to_cpu(phy_pg1.PhyResetProblemCount);
+ return 0;
+}
+
+/**
+ * transport_get_enclosure_identifier -
+ * @phy: The sas phy object
+ *
+ * Obtain the enclosure logical id for an expander.
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier)
+{
+ struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
+ struct _sas_node *sas_expander;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_node_lock, flags);
+ sas_expander = mpt2sas_scsih_expander_find_by_sas_address(ioc,
+ rphy->identify.sas_address);
+ spin_unlock_irqrestore(&ioc->sas_node_lock, flags);
+
+ if (!sas_expander)
+ return -ENXIO;
+
+ *identifier = sas_expander->enclosure_logical_id;
+ return 0;
+}
+
+/**
+ * transport_get_bay_identifier -
+ * @phy: The sas phy object
+ *
+ * Returns the slot id for a device that resides inside an enclosure.
+ */
+static int
+transport_get_bay_identifier(struct sas_rphy *rphy)
+{
+ struct MPT2SAS_ADAPTER *ioc = rphy_to_ioc(rphy);
+ struct _sas_device *sas_device;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ioc->sas_device_lock, flags);
+ sas_device = mpt2sas_scsih_sas_device_find_by_sas_address(ioc,
+ rphy->identify.sas_address);
+ spin_unlock_irqrestore(&ioc->sas_device_lock, flags);
+
+ if (!sas_device)
+ return -ENXIO;
+
+ return sas_device->slot;
+}
+
+/**
+ * transport_phy_reset -
+ * @phy: The sas phy object
+ * @hard_reset:
+ *
+ * Only support sas_host direct attached phys.
+ * Returns 0 for success, non-zero for failure.
+ */
+static int
+transport_phy_reset(struct sas_phy *phy, int hard_reset)
+{
+ struct MPT2SAS_ADAPTER *ioc = phy_to_ioc(phy);
+ struct _sas_phy *mpt2sas_phy;
+ Mpi2SasIoUnitControlReply_t mpi_reply;
+ Mpi2SasIoUnitControlRequest_t mpi_request;
+ int i;
+
+ for (i = 0, mpt2sas_phy = NULL; i < ioc->sas_hba.num_phys &&
+ !mpt2sas_phy; i++) {
+ if (ioc->sas_hba.phy[i].phy != phy)
+ continue;
+ mpt2sas_phy = &ioc->sas_hba.phy[i];
+ }
+
+ if (!mpt2sas_phy) /* this phy not on sas_host */
+ return -EINVAL;
+
+ memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t));
+ mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL;
+ mpi_request.Operation = hard_reset ?
+ MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET;
+ mpi_request.PhyNum = mpt2sas_phy->phy_id;
+
+ if ((mpt2sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) {
+ printk(MPT2SAS_ERR_FMT "failure at %s:%d/%s()!\n",
+ ioc->name, __FILE__, __LINE__, __func__);
+ return -ENXIO;
+ }
+
+ if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo)
+ printk(MPT2SAS_INFO_FMT "phy(%d), ioc_status"
+ "(0x%04x), loginfo(0x%08x)\n", ioc->name,
+ mpt2sas_phy->phy_id,
+ le16_to_cpu(mpi_reply.IOCStatus),
+ le32_to_cpu(mpi_reply.IOCLogInfo));
+
+ return 0;
+}
+
+/**
+ * transport_smp_handler - transport portal for smp passthru
+ * @shost: shost object
+ * @rphy: sas transport rphy object
+ * @req:
+ *
+ * This used primarily for smp_utils.
+ * Example:
+ * smp_rep_general /sys/class/bsg/expander-5:0
+ */
+static int
+transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy,
+ struct request *req)
+{
+ struct MPT2SAS_ADAPTER *ioc = shost_priv(shost);
+ Mpi2SmpPassthroughRequest_t *mpi_request;
+ Mpi2SmpPassthroughReply_t *mpi_reply;
+ int rc;
+ u16 smid;
+ u32 ioc_state;
+ unsigned long timeleft;
+ void *psge;
+ u32 sgl_flags;
+ u8 issue_reset = 0;
+ unsigned long flags;
+ dma_addr_t dma_addr_in = 0;
+ dma_addr_t dma_addr_out = 0;
+ u16 wait_state_count;
+ struct request *rsp = req->next_rq;
+
+ if (!rsp) {
+ printk(MPT2SAS_ERR_FMT "%s: the smp response space is "
+ "missing\n", ioc->name, __func__);
+ return -EINVAL;
+ }
+
+ /* do we need to support multiple segments? */
+ if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) {
+ printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, "
+ "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt,
+ req->data_len, rsp->bio->bi_vcnt, rsp->data_len);
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags);
+ if (ioc->ioc_reset_in_progress) {
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+ printk(MPT2SAS_INFO_FMT "%s: host reset in progress!\n",
+ __func__, ioc->name);
+ return -EFAULT;
+ }
+ spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags);
+
+ rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex);
+ if (rc)
+ return rc;
+
+ if (ioc->transport_cmds.status != MPT2_CMD_NOT_USED) {
+ printk(MPT2SAS_ERR_FMT "%s: transport_cmds in use\n", ioc->name,
+ __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+ ioc->transport_cmds.status = MPT2_CMD_PENDING;
+
+ wait_state_count = 0;
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) {
+ if (wait_state_count++ == 10) {
+ printk(MPT2SAS_ERR_FMT
+ "%s: failed due to ioc not operational\n",
+ ioc->name, __func__);
+ rc = -EFAULT;
+ goto out;
+ }
+ ssleep(1);
+ ioc_state = mpt2sas_base_get_iocstate(ioc, 1);
+ printk(MPT2SAS_INFO_FMT "%s: waiting for "
+ "operational state(count=%d)\n", ioc->name,
+ __func__, wait_state_count);
+ }
+ if (wait_state_count)
+ printk(MPT2SAS_INFO_FMT "%s: ioc is operational\n",
+ ioc->name, __func__);
+
+ smid = mpt2sas_base_get_smid(ioc, ioc->transport_cb_idx);
+ if (!smid) {
+ printk(MPT2SAS_ERR_FMT "%s: failed obtaining a smid\n",
+ ioc->name, __func__);
+ rc = -EAGAIN;
+ goto out;
+ }
+
+ rc = 0;
+ mpi_request = mpt2sas_base_get_msg_frame(ioc, smid);
+ ioc->transport_cmds.smid = smid;
+
+ memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t));
+ mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH;
+ mpi_request->PhysicalPort = 0xFF;
+ *((u64 *)&mpi_request->SASAddress) = (rphy) ?
+ cpu_to_le64(rphy->identify.sas_address) :
+ cpu_to_le64(ioc->sas_hba.sas_address);
+ mpi_request->RequestDataLength = cpu_to_le16(req->data_len - 4);
+ psge = &mpi_request->SGL;
+
+ /* WRITE sgel first */
+ sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC);
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+ dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio),
+ req->data_len, PCI_DMA_BIDIRECTIONAL);
+ if (!dma_addr_out) {
+ mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
+ goto unmap;
+ }
+
+ ioc->base_add_sg_single(psge, sgl_flags | (req->data_len - 4),
+ dma_addr_out);
+
+ /* incr sgel */
+ psge += ioc->sge_size;
+
+ /* READ sgel last */
+ sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT |
+ MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER |
+ MPI2_SGE_FLAGS_END_OF_LIST);
+ sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT;
+ dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio),
+ rsp->data_len, PCI_DMA_BIDIRECTIONAL);
+ if (!dma_addr_in) {
+ mpt2sas_base_free_smid(ioc, le16_to_cpu(smid));
+ goto unmap;
+ }
+
+ ioc->base_add_sg_single(psge, sgl_flags | (rsp->data_len + 4),
+ dma_addr_in);
+
+ dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
+ "sending smp request\n", ioc->name, __func__));
+
+ mpt2sas_base_put_smid_default(ioc, smid, 0 /* VF_ID */);
+ timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done,
+ 10*HZ);
+
+ if (!(ioc->transport_cmds.status & MPT2_CMD_COMPLETE)) {
+ printk(MPT2SAS_ERR_FMT "%s : timeout\n",
+ __func__, ioc->name);
+ _debug_dump_mf(mpi_request,
+ sizeof(Mpi2SmpPassthroughRequest_t)/4);
+ if (!(ioc->transport_cmds.status & MPT2_CMD_RESET))
+ issue_reset = 1;
+ goto issue_host_reset;
+ }
+
+ dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - "
+ "complete\n", ioc->name, __func__));
+
+ if (ioc->transport_cmds.status & MPT2_CMD_REPLY_VALID) {
+
+ mpi_reply = ioc->transport_cmds.reply;
+
+ dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "%s - reply data transfer size(%d)\n",
+ ioc->name, __func__,
+ le16_to_cpu(mpi_reply->ResponseDataLength)));
+
+ memcpy(req->sense, mpi_reply, sizeof(*mpi_reply));
+ req->sense_len = sizeof(*mpi_reply);
+ req->data_len = 0;
+ rsp->data_len -= mpi_reply->ResponseDataLength;
+
+ } else {
+ dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT
+ "%s - no reply\n", ioc->name, __func__));
+ rc = -ENXIO;
+ }
+
+ issue_host_reset:
+ if (issue_reset) {
+ mpt2sas_base_hard_reset_handler(ioc, CAN_SLEEP,
+ FORCE_BIG_HAMMER);
+ rc = -ETIMEDOUT;
+ }
+
+ unmap:
+ if (dma_addr_out)
+ pci_unmap_single(ioc->pdev, dma_addr_out, req->data_len,
+ PCI_DMA_BIDIRECTIONAL);
+ if (dma_addr_in)
+ pci_unmap_single(ioc->pdev, dma_addr_in, rsp->data_len,
+ PCI_DMA_BIDIRECTIONAL);
+
+ out:
+ ioc->transport_cmds.status = MPT2_CMD_NOT_USED;
+ mutex_unlock(&ioc->transport_cmds.mutex);
+ return rc;
+}
+
+struct sas_function_template mpt2sas_transport_functions = {
+ .get_linkerrors = transport_get_linkerrors,
+ .get_enclosure_identifier = transport_get_enclosure_identifier,
+ .get_bay_identifier = transport_get_bay_identifier,
+ .phy_reset = transport_phy_reset,
+ .smp_handler = transport_smp_handler,
+};
+
+struct scsi_transport_template *mpt2sas_transport_template;
diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c
index b264b499d98..b5fbfd6ce87 100644
--- a/drivers/scsi/mvme16x_scsi.c
+++ b/drivers/scsi/mvme16x_scsi.c
@@ -34,7 +34,7 @@ static struct scsi_host_template mvme16x_scsi_driver_template = {
static struct platform_device *mvme16x_scsi_device;
static __devinit int
-mvme16x_probe(struct device *dev)
+mvme16x_probe(struct platform_device *dev)
{
struct Scsi_Host * host = NULL;
struct NCR_700_Host_Parameters *hostdata;
@@ -64,7 +64,8 @@ mvme16x_probe(struct device *dev)
hostdata->ctest7_extra = CTEST7_TT1;
/* and register the chip */
- host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, dev);
+ host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata,
+ &dev->dev);
if (!host) {
printk(KERN_ERR "mvme16x-scsi: No host detected; "
"board configuration problem?\n");
@@ -88,7 +89,7 @@ mvme16x_probe(struct device *dev)
out_be32(0xfff4202c, v);
}
- dev_set_drvdata(dev, host);
+ platform_set_drvdata(dev, host);
scsi_scan_host(host);
return 0;
@@ -102,9 +103,9 @@ mvme16x_probe(struct device *dev)
}
static __devexit int
-mvme16x_device_remove(struct device *dev)
+mvme16x_device_remove(struct platform_device *dev)
{
- struct Scsi_Host *host = dev_get_drvdata(dev);
+ struct Scsi_Host *host = platform_get_drvdata(dev);
struct NCR_700_Host_Parameters *hostdata = shost_priv(host);
/* Disable scsi chip ints */
@@ -123,25 +124,27 @@ mvme16x_device_remove(struct device *dev)
return 0;
}
-static struct device_driver mvme16x_scsi_driver = {
- .name = "mvme16x-scsi",
- .bus = &platform_bus_type,
- .probe = mvme16x_probe,
- .remove = __devexit_p(mvme16x_device_remove),
+static struct platform_driver mvme16x_scsi_driver = {
+ .driver = {
+ .name = "mvme16x-scsi",
+ .owner = THIS_MODULE,
+ },
+ .probe = mvme16x_probe,
+ .remove = __devexit_p(mvme16x_device_remove),
};
static int __init mvme16x_scsi_init(void)
{
int err;
- err = driver_register(&mvme16x_scsi_driver);
+ err = platform_driver_register(&mvme16x_scsi_driver);
if (err)
return err;
mvme16x_scsi_device = platform_device_register_simple("mvme16x-scsi",
-1, NULL, 0);
if (IS_ERR(mvme16x_scsi_device)) {
- driver_unregister(&mvme16x_scsi_driver);
+ platform_driver_unregister(&mvme16x_scsi_driver);
return PTR_ERR(mvme16x_scsi_device);
}
@@ -151,7 +154,7 @@ static int __init mvme16x_scsi_init(void)
static void __exit mvme16x_scsi_exit(void)
{
platform_device_unregister(mvme16x_scsi_device);
- driver_unregister(&mvme16x_scsi_driver);
+ platform_driver_unregister(&mvme16x_scsi_driver);
}
module_init(mvme16x_scsi_init);
diff --git a/drivers/scsi/osd/Kbuild b/drivers/scsi/osd/Kbuild
new file mode 100644
index 00000000000..0e207aa67d1
--- /dev/null
+++ b/drivers/scsi/osd/Kbuild
@@ -0,0 +1,45 @@
+#
+# Kbuild for the OSD modules
+#
+# Copyright (C) 2008 Panasas Inc. All rights reserved.
+#
+# Authors:
+# Boaz Harrosh <bharrosh@panasas.com>
+# Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+
+ifneq ($(OSD_INC),)
+# we are built out-of-tree Kconfigure everything as on
+
+CONFIG_SCSI_OSD_INITIATOR=m
+ccflags-y += -DCONFIG_SCSI_OSD_INITIATOR -DCONFIG_SCSI_OSD_INITIATOR_MODULE
+
+CONFIG_SCSI_OSD_ULD=m
+ccflags-y += -DCONFIG_SCSI_OSD_ULD -DCONFIG_SCSI_OSD_ULD_MODULE
+
+# CONFIG_SCSI_OSD_DPRINT_SENSE =
+# 0 - no print of errors
+# 1 - print errors
+# 2 - errors + warrnings
+ccflags-y += -DCONFIG_SCSI_OSD_DPRINT_SENSE=1
+
+# Uncomment to turn debug on
+# ccflags-y += -DCONFIG_SCSI_OSD_DEBUG
+
+# if we are built out-of-tree and the hosting kernel has OSD headers
+# then "ccflags-y +=" will not pick the out-off-tree headers. Only by doing
+# this it will work. This might break in future kernels
+LINUXINCLUDE := -I$(OSD_INC) $(LINUXINCLUDE)
+
+endif
+
+# libosd.ko - osd-initiator library
+libosd-y := osd_initiator.o
+obj-$(CONFIG_SCSI_OSD_INITIATOR) += libosd.o
+
+# osd.ko - SCSI ULD and char-device
+osd-y := osd_uld.o
+obj-$(CONFIG_SCSI_OSD_ULD) += osd.o
diff --git a/drivers/scsi/osd/Kconfig b/drivers/scsi/osd/Kconfig
new file mode 100644
index 00000000000..861b5cebaea
--- /dev/null
+++ b/drivers/scsi/osd/Kconfig
@@ -0,0 +1,53 @@
+#
+# Kernel configuration file for the OSD scsi protocol
+#
+# Copyright (C) 2008 Panasas Inc. All rights reserved.
+#
+# Authors:
+# Boaz Harrosh <bharrosh@panasas.com>
+# Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public version 2 License as
+# published by the Free Software Foundation
+#
+# FIXME: SCSI_OSD_INITIATOR should select CONFIG (HMAC) SHA1 somehow.
+# How is it done properly?
+#
+
+config SCSI_OSD_INITIATOR
+ tristate "OSD-Initiator library"
+ depends on SCSI
+ help
+ Enable the OSD-Initiator library (libosd.ko).
+ NOTE: You must also select CRYPTO_SHA1 + CRYPTO_HMAC and their
+ dependencies
+
+config SCSI_OSD_ULD
+ tristate "OSD Upper Level driver"
+ depends on SCSI_OSD_INITIATOR
+ help
+ Build a SCSI upper layer driver that exports /dev/osdX devices
+ to user-mode for testing and controlling OSD devices. It is also
+ needed by exofs, for mounting an OSD based file system.
+
+config SCSI_OSD_DPRINT_SENSE
+ int "(0-2) When sense is returned, DEBUG print all sense descriptors"
+ default 1
+ depends on SCSI_OSD_INITIATOR
+ help
+ When a CHECK_CONDITION status is returned from a target, and a
+ sense-buffer is retrieved, turning this on will dump a full
+ sense-decoding message. Setting to 2 will also print recoverable
+ errors that might be regularly returned for some filesystem
+ operations.
+
+config SCSI_OSD_DEBUG
+ bool "Compile All OSD modules with lots of DEBUG prints"
+ default n
+ depends on SCSI_OSD_INITIATOR
+ help
+ OSD Code is populated with lots of OSD_DEBUG(..) printouts to
+ dmesg. Enable this if you found a bug and you want to help us
+ track the problem (see also MAINTAINERS). Setting this will also
+ force SCSI_OSD_DPRINT_SENSE=2.
diff --git a/drivers/scsi/osd/Makefile b/drivers/scsi/osd/Makefile
new file mode 100755
index 00000000000..d905344f83b
--- /dev/null
+++ b/drivers/scsi/osd/Makefile
@@ -0,0 +1,37 @@
+#
+# Makefile for the OSD modules (out of tree)
+#
+# Copyright (C) 2008 Panasas Inc. All rights reserved.
+#
+# Authors:
+# Boaz Harrosh <bharrosh@panasas.com>
+# Benny Halevy <bhalevy@panasas.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2
+#
+# This Makefile is used to call the kernel Makefile in case of an out-of-tree
+# build.
+# $KSRC should point to a Kernel source tree otherwise host's default is
+# used. (eg. /lib/modules/`uname -r`/build)
+
+# include path for out-of-tree Headers
+OSD_INC ?= `pwd`/../../../include
+
+# allow users to override these
+# e.g. to compile for a kernel that you aren't currently running
+KSRC ?= /lib/modules/$(shell uname -r)/build
+KBUILD_OUTPUT ?=
+ARCH ?=
+V ?= 0
+
+# this is the basic Kbuild out-of-tree invocation, with the M= option
+KBUILD_BASE = +$(MAKE) -C $(KSRC) M=`pwd` KBUILD_OUTPUT=$(KBUILD_OUTPUT) ARCH=$(ARCH) V=$(V)
+
+all: libosd
+
+libosd: ;
+ $(KBUILD_BASE) OSD_INC=$(OSD_INC) modules
+
+clean:
+ $(KBUILD_BASE) clean
diff --git a/drivers/scsi/osd/osd_debug.h b/drivers/scsi/osd/osd_debug.h
new file mode 100644
index 00000000000..579e491f11d
--- /dev/null
+++ b/drivers/scsi/osd/osd_debug.h
@@ -0,0 +1,30 @@
+/*
+ * osd_debug.h - Some kprintf macros
+ *
+ * Copyright (C) 2008 Panasas Inc. All rights reserved.
+ *
+ * Authors:
+ * Boaz Harrosh <bharrosh@panasas.com>
+ * Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ */
+#ifndef __OSD_DEBUG_H__
+#define __OSD_DEBUG_H__
+
+#define OSD_ERR(fmt, a...) printk(KERN_ERR "osd: " fmt, ##a)
+#define OSD_INFO(fmt, a...) printk(KERN_NOTICE "osd: " fmt, ##a)
+
+#ifdef CONFIG_SCSI_OSD_DEBUG
+#define OSD_DEBUG(fmt, a...) \
+ printk(KERN_NOTICE "osd @%s:%d: " fmt, __func__, __LINE__, ##a)
+#else
+#define OSD_DEBUG(fmt, a...) do {} while (0)
+#endif
+
+/* u64 has problems with printk this will cast it to unsigned long long */
+#define _LLU(x) (unsigned long long)(x)
+
+#endif /* ndef __OSD_DEBUG_H__ */
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c
new file mode 100644
index 00000000000..2a5f0777148
--- /dev/null
+++ b/drivers/scsi/osd/osd_initiator.c
@@ -0,0 +1,1663 @@
+/*
+ * osd_initiator - Main body of the osd initiator library.
+ *
+ * Note: The file does not contain the advanced security functionality which
+ * is only needed by the security_manager's initiators.
+ *
+ * Copyright (C) 2008 Panasas Inc. All rights reserved.
+ *
+ * Authors:
+ * Boaz Harrosh <bharrosh@panasas.com>
+ * Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Panasas company nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+#include <scsi/osd_attributes.h>
+#include <scsi/osd_sense.h>
+
+#include <scsi/scsi_device.h>
+
+#include "osd_debug.h"
+
+#ifndef __unused
+# define __unused __attribute__((unused))
+#endif
+
+enum { OSD_REQ_RETRIES = 1 };
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd initiator library libosd.ko");
+MODULE_LICENSE("GPL");
+
+static inline void build_test(void)
+{
+ /* structures were not packed */
+ BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
+ BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
+ BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
+}
+
+static const char *_osd_ver_desc(struct osd_request *or)
+{
+ return osd_req_is_ver1(or) ? "OSD1" : "OSD2";
+}
+
+#define ATTR_DEF_RI(id, len) ATTR_DEF(OSD_APAGE_ROOT_INFORMATION, id, len)
+
+static int _osd_print_system_info(struct osd_dev *od, void *caps)
+{
+ struct osd_request *or;
+ struct osd_attr get_attrs[] = {
+ ATTR_DEF_RI(OSD_ATTR_RI_VENDOR_IDENTIFICATION, 8),
+ ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_IDENTIFICATION, 16),
+ ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_MODEL, 32),
+ ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_REVISION_LEVEL, 4),
+ ATTR_DEF_RI(OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER, 64 /*variable*/),
+ ATTR_DEF_RI(OSD_ATTR_RI_OSD_NAME, 64 /*variable*/),
+ ATTR_DEF_RI(OSD_ATTR_RI_TOTAL_CAPACITY, 8),
+ ATTR_DEF_RI(OSD_ATTR_RI_USED_CAPACITY, 8),
+ ATTR_DEF_RI(OSD_ATTR_RI_NUMBER_OF_PARTITIONS, 8),
+ ATTR_DEF_RI(OSD_ATTR_RI_CLOCK, 6),
+ /* IBM-OSD-SIM Has a bug with this one put it last */
+ ATTR_DEF_RI(OSD_ATTR_RI_OSD_SYSTEM_ID, 20),
+ };
+ void *iter = NULL, *pFirst;
+ int nelem = ARRAY_SIZE(get_attrs), a = 0;
+ int ret;
+
+ or = osd_start_request(od, GFP_KERNEL);
+ if (!or)
+ return -ENOMEM;
+
+ /* get attrs */
+ osd_req_get_attributes(or, &osd_root_object);
+ osd_req_add_get_attr_list(or, get_attrs, ARRAY_SIZE(get_attrs));
+
+ ret = osd_finalize_request(or, 0, caps, NULL);
+ if (ret)
+ goto out;
+
+ ret = osd_execute_request(or);
+ if (ret) {
+ OSD_ERR("Failed to detect %s => %d\n", _osd_ver_desc(or), ret);
+ goto out;
+ }
+
+ osd_req_decode_get_attr_list(or, get_attrs, &nelem, &iter);
+
+ OSD_INFO("Detected %s device\n",
+ _osd_ver_desc(or));
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_VENDOR_IDENTIFICATION [%s]\n",
+ (char *)pFirst);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_PRODUCT_IDENTIFICATION [%s]\n",
+ (char *)pFirst);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_PRODUCT_MODEL [%s]\n",
+ (char *)pFirst);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_PRODUCT_REVISION_LEVEL [%u]\n",
+ pFirst ? get_unaligned_be32(pFirst) : ~0U);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_PRODUCT_SERIAL_NUMBER [%s]\n",
+ (char *)pFirst);
+
+ pFirst = get_attrs[a].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_OSD_NAME [%s]\n", (char *)pFirst);
+ a++;
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_TOTAL_CAPACITY [0x%llx]\n",
+ pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_USED_CAPACITY [0x%llx]\n",
+ pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
+
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_NUMBER_OF_PARTITIONS [%llu]\n",
+ pFirst ? _LLU(get_unaligned_be64(pFirst)) : ~0ULL);
+
+ if (a >= nelem)
+ goto out;
+
+ /* FIXME: Where are the time utilities */
+ pFirst = get_attrs[a++].val_ptr;
+ OSD_INFO("OSD_ATTR_RI_CLOCK [0x%02x%02x%02x%02x%02x%02x]\n",
+ ((char *)pFirst)[0], ((char *)pFirst)[1],
+ ((char *)pFirst)[2], ((char *)pFirst)[3],
+ ((char *)pFirst)[4], ((char *)pFirst)[5]);
+
+ if (a < nelem) { /* IBM-OSD-SIM bug, Might not have it */
+ unsigned len = get_attrs[a].len;
+ char sid_dump[32*4 + 2]; /* 2nibbles+space+ASCII */
+
+ hex_dump_to_buffer(get_attrs[a].val_ptr, len, 32, 1,
+ sid_dump, sizeof(sid_dump), true);
+ OSD_INFO("OSD_ATTR_RI_OSD_SYSTEM_ID(%d) [%s]\n", len, sid_dump);
+ a++;
+ }
+out:
+ osd_end_request(or);
+ return ret;
+}
+
+int osd_auto_detect_ver(struct osd_dev *od, void *caps)
+{
+ int ret;
+
+ /* Auto-detect the osd version */
+ ret = _osd_print_system_info(od, caps);
+ if (ret) {
+ osd_dev_set_ver(od, OSD_VER1);
+ OSD_DEBUG("converting to OSD1\n");
+ ret = _osd_print_system_info(od, caps);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(osd_auto_detect_ver);
+
+static unsigned _osd_req_cdb_len(struct osd_request *or)
+{
+ return osd_req_is_ver1(or) ? OSDv1_TOTAL_CDB_LEN : OSD_TOTAL_CDB_LEN;
+}
+
+static unsigned _osd_req_alist_elem_size(struct osd_request *or, unsigned len)
+{
+ return osd_req_is_ver1(or) ?
+ osdv1_attr_list_elem_size(len) :
+ osdv2_attr_list_elem_size(len);
+}
+
+static unsigned _osd_req_alist_size(struct osd_request *or, void *list_head)
+{
+ return osd_req_is_ver1(or) ?
+ osdv1_list_size(list_head) :
+ osdv2_list_size(list_head);
+}
+
+static unsigned _osd_req_sizeof_alist_header(struct osd_request *or)
+{
+ return osd_req_is_ver1(or) ?
+ sizeof(struct osdv1_attributes_list_header) :
+ sizeof(struct osdv2_attributes_list_header);
+}
+
+static void _osd_req_set_alist_type(struct osd_request *or,
+ void *list, int list_type)
+{
+ if (osd_req_is_ver1(or)) {
+ struct osdv1_attributes_list_header *attr_list = list;
+
+ memset(attr_list, 0, sizeof(*attr_list));
+ attr_list->type = list_type;
+ } else {
+ struct osdv2_attributes_list_header *attr_list = list;
+
+ memset(attr_list, 0, sizeof(*attr_list));
+ attr_list->type = list_type;
+ }
+}
+
+static bool _osd_req_is_alist_type(struct osd_request *or,
+ void *list, int list_type)
+{
+ if (!list)
+ return false;
+
+ if (osd_req_is_ver1(or)) {
+ struct osdv1_attributes_list_header *attr_list = list;
+
+ return attr_list->type == list_type;
+ } else {
+ struct osdv2_attributes_list_header *attr_list = list;
+
+ return attr_list->type == list_type;
+ }
+}
+
+/* This is for List-objects not Attributes-Lists */
+static void _osd_req_encode_olist(struct osd_request *or,
+ struct osd_obj_id_list *list)
+{
+ struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+ if (osd_req_is_ver1(or)) {
+ cdbh->v1.list_identifier = list->list_identifier;
+ cdbh->v1.start_address = list->continuation_id;
+ } else {
+ cdbh->v2.list_identifier = list->list_identifier;
+ cdbh->v2.start_address = list->continuation_id;
+ }
+}
+
+static osd_cdb_offset osd_req_encode_offset(struct osd_request *or,
+ u64 offset, unsigned *padding)
+{
+ return __osd_encode_offset(offset, padding,
+ osd_req_is_ver1(or) ?
+ OSDv1_OFFSET_MIN_SHIFT : OSD_OFFSET_MIN_SHIFT,
+ OSD_OFFSET_MAX_SHIFT);
+}
+
+static struct osd_security_parameters *
+_osd_req_sec_params(struct osd_request *or)
+{
+ struct osd_cdb *ocdb = &or->cdb;
+
+ if (osd_req_is_ver1(or))
+ return &ocdb->v1.sec_params;
+ else
+ return &ocdb->v2.sec_params;
+}
+
+void osd_dev_init(struct osd_dev *osdd, struct scsi_device *scsi_device)
+{
+ memset(osdd, 0, sizeof(*osdd));
+ osdd->scsi_device = scsi_device;
+ osdd->def_timeout = BLK_DEFAULT_SG_TIMEOUT;
+#ifdef OSD_VER1_SUPPORT
+ osdd->version = OSD_VER2;
+#endif
+ /* TODO: Allocate pools for osd_request attributes ... */
+}
+EXPORT_SYMBOL(osd_dev_init);
+
+void osd_dev_fini(struct osd_dev *osdd)
+{
+ /* TODO: De-allocate pools */
+
+ osdd->scsi_device = NULL;
+}
+EXPORT_SYMBOL(osd_dev_fini);
+
+static struct osd_request *_osd_request_alloc(gfp_t gfp)
+{
+ struct osd_request *or;
+
+ /* TODO: Use mempool with one saved request */
+ or = kzalloc(sizeof(*or), gfp);
+ return or;
+}
+
+static void _osd_request_free(struct osd_request *or)
+{
+ kfree(or);
+}
+
+struct osd_request *osd_start_request(struct osd_dev *dev, gfp_t gfp)
+{
+ struct osd_request *or;
+
+ or = _osd_request_alloc(gfp);
+ if (!or)
+ return NULL;
+
+ or->osd_dev = dev;
+ or->alloc_flags = gfp;
+ or->timeout = dev->def_timeout;
+ or->retries = OSD_REQ_RETRIES;
+
+ return or;
+}
+EXPORT_SYMBOL(osd_start_request);
+
+static void _osd_free_seg(struct osd_request *or __unused,
+ struct _osd_req_data_segment *seg)
+{
+ if (!seg->buff || !seg->alloc_size)
+ return;
+
+ kfree(seg->buff);
+ seg->buff = NULL;
+ seg->alloc_size = 0;
+}
+
+static void _put_request(struct request *rq , bool is_async)
+{
+ if (is_async) {
+ WARN_ON(rq->bio);
+ __blk_put_request(rq->q, rq);
+ } else {
+ /*
+ * If osd_finalize_request() was called but the request was not
+ * executed through the block layer, then we must release BIOs.
+ * TODO: Keep error code in or->async_error. Need to audit all
+ * code paths.
+ */
+ if (unlikely(rq->bio))
+ blk_end_request(rq, -ENOMEM, blk_rq_bytes(rq));
+ else
+ blk_put_request(rq);
+ }
+}
+
+void osd_end_request(struct osd_request *or)
+{
+ struct request *rq = or->request;
+ /* IMPORTANT: make sure this agrees with osd_execute_request_async */
+ bool is_async = (or->request->end_io_data == or);
+
+ _osd_free_seg(or, &or->set_attr);
+ _osd_free_seg(or, &or->enc_get_attr);
+ _osd_free_seg(or, &or->get_attr);
+
+ if (rq) {
+ if (rq->next_rq) {
+ _put_request(rq->next_rq, is_async);
+ rq->next_rq = NULL;
+ }
+
+ _put_request(rq, is_async);
+ }
+ _osd_request_free(or);
+}
+EXPORT_SYMBOL(osd_end_request);
+
+int osd_execute_request(struct osd_request *or)
+{
+ return blk_execute_rq(or->request->q, NULL, or->request, 0);
+}
+EXPORT_SYMBOL(osd_execute_request);
+
+static void osd_request_async_done(struct request *req, int error)
+{
+ struct osd_request *or = req->end_io_data;
+
+ or->async_error = error;
+
+ if (error)
+ OSD_DEBUG("osd_request_async_done error recieved %d\n", error);
+
+ if (or->async_done)
+ or->async_done(or, or->async_private);
+ else
+ osd_end_request(or);
+}
+
+int osd_execute_request_async(struct osd_request *or,
+ osd_req_done_fn *done, void *private)
+{
+ or->request->end_io_data = or;
+ or->async_private = private;
+ or->async_done = done;
+
+ blk_execute_rq_nowait(or->request->q, NULL, or->request, 0,
+ osd_request_async_done);
+ return 0;
+}
+EXPORT_SYMBOL(osd_execute_request_async);
+
+u8 sg_out_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+u8 sg_in_pad_buffer[1 << OSDv1_OFFSET_MIN_SHIFT];
+
+static int _osd_realloc_seg(struct osd_request *or,
+ struct _osd_req_data_segment *seg, unsigned max_bytes)
+{
+ void *buff;
+
+ if (seg->alloc_size >= max_bytes)
+ return 0;
+
+ buff = krealloc(seg->buff, max_bytes, or->alloc_flags);
+ if (!buff) {
+ OSD_ERR("Failed to Realloc %d-bytes was-%d\n", max_bytes,
+ seg->alloc_size);
+ return -ENOMEM;
+ }
+
+ memset(buff + seg->alloc_size, 0, max_bytes - seg->alloc_size);
+ seg->buff = buff;
+ seg->alloc_size = max_bytes;
+ return 0;
+}
+
+static int _alloc_set_attr_list(struct osd_request *or,
+ const struct osd_attr *oa, unsigned nelem, unsigned add_bytes)
+{
+ unsigned total_bytes = add_bytes;
+
+ for (; nelem; --nelem, ++oa)
+ total_bytes += _osd_req_alist_elem_size(or, oa->len);
+
+ OSD_DEBUG("total_bytes=%d\n", total_bytes);
+ return _osd_realloc_seg(or, &or->set_attr, total_bytes);
+}
+
+static int _alloc_get_attr_desc(struct osd_request *or, unsigned max_bytes)
+{
+ OSD_DEBUG("total_bytes=%d\n", max_bytes);
+ return _osd_realloc_seg(or, &or->enc_get_attr, max_bytes);
+}
+
+static int _alloc_get_attr_list(struct osd_request *or)
+{
+ OSD_DEBUG("total_bytes=%d\n", or->get_attr.total_bytes);
+ return _osd_realloc_seg(or, &or->get_attr, or->get_attr.total_bytes);
+}
+
+/*
+ * Common to all OSD commands
+ */
+
+static void _osdv1_req_encode_common(struct osd_request *or,
+ __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+ struct osdv1_cdb *ocdb = &or->cdb.v1;
+
+ /*
+ * For speed, the commands
+ * OSD_ACT_PERFORM_SCSI_COMMAND , V1 0x8F7E, V2 0x8F7C
+ * OSD_ACT_SCSI_TASK_MANAGEMENT , V1 0x8F7F, V2 0x8F7D
+ * are not supported here. Should pass zero and set after the call
+ */
+ act &= cpu_to_be16(~0x0080); /* V1 action code */
+
+ OSD_DEBUG("OSDv1 execute opcode 0x%x\n", be16_to_cpu(act));
+
+ ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+ ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+ ocdb->h.varlen_cdb.service_action = act;
+
+ ocdb->h.partition = cpu_to_be64(obj->partition);
+ ocdb->h.object = cpu_to_be64(obj->id);
+ ocdb->h.v1.length = cpu_to_be64(len);
+ ocdb->h.v1.start_address = cpu_to_be64(offset);
+}
+
+static void _osdv2_req_encode_common(struct osd_request *or,
+ __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+ struct osdv2_cdb *ocdb = &or->cdb.v2;
+
+ OSD_DEBUG("OSDv2 execute opcode 0x%x\n", be16_to_cpu(act));
+
+ ocdb->h.varlen_cdb.opcode = VARIABLE_LENGTH_CMD;
+ ocdb->h.varlen_cdb.additional_cdb_length = OSD_ADDITIONAL_CDB_LENGTH;
+ ocdb->h.varlen_cdb.service_action = act;
+
+ ocdb->h.partition = cpu_to_be64(obj->partition);
+ ocdb->h.object = cpu_to_be64(obj->id);
+ ocdb->h.v2.length = cpu_to_be64(len);
+ ocdb->h.v2.start_address = cpu_to_be64(offset);
+}
+
+static void _osd_req_encode_common(struct osd_request *or,
+ __be16 act, const struct osd_obj_id *obj, u64 offset, u64 len)
+{
+ if (osd_req_is_ver1(or))
+ _osdv1_req_encode_common(or, act, obj, offset, len);
+ else
+ _osdv2_req_encode_common(or, act, obj, offset, len);
+}
+
+/*
+ * Device commands
+ */
+/*TODO: void osd_req_set_master_seed_xchg(struct osd_request *, ...); */
+/*TODO: void osd_req_set_master_key(struct osd_request *, ...); */
+
+void osd_req_format(struct osd_request *or, u64 tot_capacity)
+{
+ _osd_req_encode_common(or, OSD_ACT_FORMAT_OSD, &osd_root_object, 0,
+ tot_capacity);
+}
+EXPORT_SYMBOL(osd_req_format);
+
+int osd_req_list_dev_partitions(struct osd_request *or,
+ osd_id initial_id, struct osd_obj_id_list *list, unsigned nelem)
+{
+ return osd_req_list_partition_objects(or, 0, initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_dev_partitions);
+
+static void _osd_req_encode_flush(struct osd_request *or,
+ enum osd_options_flush_scope_values op)
+{
+ struct osd_cdb_head *ocdb = osd_cdb_head(&or->cdb);
+
+ ocdb->command_specific_options = op;
+}
+
+void osd_req_flush_obsd(struct osd_request *or,
+ enum osd_options_flush_scope_values op)
+{
+ _osd_req_encode_common(or, OSD_ACT_FLUSH_OSD, &osd_root_object, 0, 0);
+ _osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_obsd);
+
+/*TODO: void osd_req_perform_scsi_command(struct osd_request *,
+ const u8 *cdb, ...); */
+/*TODO: void osd_req_task_management(struct osd_request *, ...); */
+
+/*
+ * Partition commands
+ */
+static void _osd_req_encode_partition(struct osd_request *or,
+ __be16 act, osd_id partition)
+{
+ struct osd_obj_id par = {
+ .partition = partition,
+ .id = 0,
+ };
+
+ _osd_req_encode_common(or, act, &par, 0, 0);
+}
+
+void osd_req_create_partition(struct osd_request *or, osd_id partition)
+{
+ _osd_req_encode_partition(or, OSD_ACT_CREATE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_create_partition);
+
+void osd_req_remove_partition(struct osd_request *or, osd_id partition)
+{
+ _osd_req_encode_partition(or, OSD_ACT_REMOVE_PARTITION, partition);
+}
+EXPORT_SYMBOL(osd_req_remove_partition);
+
+/*TODO: void osd_req_set_partition_key(struct osd_request *,
+ osd_id partition, u8 new_key_id[OSD_CRYPTO_KEYID_SIZE],
+ u8 seed[OSD_CRYPTO_SEED_SIZE]); */
+
+static int _osd_req_list_objects(struct osd_request *or,
+ __be16 action, const struct osd_obj_id *obj, osd_id initial_id,
+ struct osd_obj_id_list *list, unsigned nelem)
+{
+ struct request_queue *q = or->osd_dev->scsi_device->request_queue;
+ u64 len = nelem * sizeof(osd_id) + sizeof(*list);
+ struct bio *bio;
+
+ _osd_req_encode_common(or, action, obj, (u64)initial_id, len);
+
+ if (list->list_identifier)
+ _osd_req_encode_olist(or, list);
+
+ WARN_ON(or->in.bio);
+ bio = bio_map_kern(q, list, len, or->alloc_flags);
+ if (!bio) {
+ OSD_ERR("!!! Failed to allocate list_objects BIO\n");
+ return -ENOMEM;
+ }
+
+ bio->bi_rw &= ~(1 << BIO_RW);
+ or->in.bio = bio;
+ or->in.total_bytes = bio->bi_size;
+ return 0;
+}
+
+int osd_req_list_partition_collections(struct osd_request *or,
+ osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+ unsigned nelem)
+{
+ struct osd_obj_id par = {
+ .partition = partition,
+ .id = 0,
+ };
+
+ return osd_req_list_collection_objects(or, &par, initial_id, list,
+ nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_collections);
+
+int osd_req_list_partition_objects(struct osd_request *or,
+ osd_id partition, osd_id initial_id, struct osd_obj_id_list *list,
+ unsigned nelem)
+{
+ struct osd_obj_id par = {
+ .partition = partition,
+ .id = 0,
+ };
+
+ return _osd_req_list_objects(or, OSD_ACT_LIST, &par, initial_id, list,
+ nelem);
+}
+EXPORT_SYMBOL(osd_req_list_partition_objects);
+
+void osd_req_flush_partition(struct osd_request *or,
+ osd_id partition, enum osd_options_flush_scope_values op)
+{
+ _osd_req_encode_partition(or, OSD_ACT_FLUSH_PARTITION, partition);
+ _osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_partition);
+
+/*
+ * Collection commands
+ */
+/*TODO: void osd_req_create_collection(struct osd_request *,
+ const struct osd_obj_id *); */
+/*TODO: void osd_req_remove_collection(struct osd_request *,
+ const struct osd_obj_id *); */
+
+int osd_req_list_collection_objects(struct osd_request *or,
+ const struct osd_obj_id *obj, osd_id initial_id,
+ struct osd_obj_id_list *list, unsigned nelem)
+{
+ return _osd_req_list_objects(or, OSD_ACT_LIST_COLLECTION, obj,
+ initial_id, list, nelem);
+}
+EXPORT_SYMBOL(osd_req_list_collection_objects);
+
+/*TODO: void query(struct osd_request *, ...); V2 */
+
+void osd_req_flush_collection(struct osd_request *or,
+ const struct osd_obj_id *obj, enum osd_options_flush_scope_values op)
+{
+ _osd_req_encode_common(or, OSD_ACT_FLUSH_PARTITION, obj, 0, 0);
+ _osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_collection);
+
+/*TODO: void get_member_attrs(struct osd_request *, ...); V2 */
+/*TODO: void set_member_attrs(struct osd_request *, ...); V2 */
+
+/*
+ * Object commands
+ */
+void osd_req_create_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+ _osd_req_encode_common(or, OSD_ACT_CREATE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_create_object);
+
+void osd_req_remove_object(struct osd_request *or, struct osd_obj_id *obj)
+{
+ _osd_req_encode_common(or, OSD_ACT_REMOVE, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_remove_object);
+
+
+/*TODO: void osd_req_create_multi(struct osd_request *or,
+ struct osd_obj_id *first, struct osd_obj_id_list *list, unsigned nelem);
+*/
+
+void osd_req_write(struct osd_request *or,
+ const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+ _osd_req_encode_common(or, OSD_ACT_WRITE, obj, offset, bio->bi_size);
+ WARN_ON(or->out.bio || or->out.total_bytes);
+ bio->bi_rw |= (1 << BIO_RW);
+ or->out.bio = bio;
+ or->out.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_write);
+
+/*TODO: void osd_req_append(struct osd_request *,
+ const struct osd_obj_id *, struct bio *data_out); */
+/*TODO: void osd_req_create_write(struct osd_request *,
+ const struct osd_obj_id *, struct bio *data_out, u64 offset); */
+/*TODO: void osd_req_clear(struct osd_request *,
+ const struct osd_obj_id *, u64 offset, u64 len); */
+/*TODO: void osd_req_punch(struct osd_request *,
+ const struct osd_obj_id *, u64 offset, u64 len); V2 */
+
+void osd_req_flush_object(struct osd_request *or,
+ const struct osd_obj_id *obj, enum osd_options_flush_scope_values op,
+ /*V2*/ u64 offset, /*V2*/ u64 len)
+{
+ if (unlikely(osd_req_is_ver1(or) && (offset || len))) {
+ OSD_DEBUG("OSD Ver1 flush on specific range ignored\n");
+ offset = 0;
+ len = 0;
+ }
+
+ _osd_req_encode_common(or, OSD_ACT_FLUSH, obj, offset, len);
+ _osd_req_encode_flush(or, op);
+}
+EXPORT_SYMBOL(osd_req_flush_object);
+
+void osd_req_read(struct osd_request *or,
+ const struct osd_obj_id *obj, struct bio *bio, u64 offset)
+{
+ _osd_req_encode_common(or, OSD_ACT_READ, obj, offset, bio->bi_size);
+ WARN_ON(or->in.bio || or->in.total_bytes);
+ bio->bi_rw &= ~(1 << BIO_RW);
+ or->in.bio = bio;
+ or->in.total_bytes = bio->bi_size;
+}
+EXPORT_SYMBOL(osd_req_read);
+
+void osd_req_get_attributes(struct osd_request *or,
+ const struct osd_obj_id *obj)
+{
+ _osd_req_encode_common(or, OSD_ACT_GET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_get_attributes);
+
+void osd_req_set_attributes(struct osd_request *or,
+ const struct osd_obj_id *obj)
+{
+ _osd_req_encode_common(or, OSD_ACT_SET_ATTRIBUTES, obj, 0, 0);
+}
+EXPORT_SYMBOL(osd_req_set_attributes);
+
+/*
+ * Attributes List-mode
+ */
+
+int osd_req_add_set_attr_list(struct osd_request *or,
+ const struct osd_attr *oa, unsigned nelem)
+{
+ unsigned total_bytes = or->set_attr.total_bytes;
+ void *attr_last;
+ int ret;
+
+ if (or->attributes_mode &&
+ or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+ if (!total_bytes) { /* first-time: allocate and put list header */
+ total_bytes = _osd_req_sizeof_alist_header(or);
+ ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+ if (ret)
+ return ret;
+ _osd_req_set_alist_type(or, or->set_attr.buff,
+ OSD_ATTR_LIST_SET_RETRIEVE);
+ }
+ attr_last = or->set_attr.buff + total_bytes;
+
+ for (; nelem; --nelem) {
+ struct osd_attributes_list_element *attr;
+ unsigned elem_size = _osd_req_alist_elem_size(or, oa->len);
+
+ total_bytes += elem_size;
+ if (unlikely(or->set_attr.alloc_size < total_bytes)) {
+ or->set_attr.total_bytes = total_bytes - elem_size;
+ ret = _alloc_set_attr_list(or, oa, nelem, total_bytes);
+ if (ret)
+ return ret;
+ attr_last =
+ or->set_attr.buff + or->set_attr.total_bytes;
+ }
+
+ attr = attr_last;
+ attr->attr_page = cpu_to_be32(oa->attr_page);
+ attr->attr_id = cpu_to_be32(oa->attr_id);
+ attr->attr_bytes = cpu_to_be16(oa->len);
+ memcpy(attr->attr_val, oa->val_ptr, oa->len);
+
+ attr_last += elem_size;
+ ++oa;
+ }
+
+ or->set_attr.total_bytes = total_bytes;
+ return 0;
+}
+EXPORT_SYMBOL(osd_req_add_set_attr_list);
+
+static int _append_map_kern(struct request *req,
+ void *buff, unsigned len, gfp_t flags)
+{
+ struct bio *bio;
+ int ret;
+
+ bio = bio_map_kern(req->q, buff, len, flags);
+ if (IS_ERR(bio)) {
+ OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len,
+ PTR_ERR(bio));
+ return PTR_ERR(bio);
+ }
+ ret = blk_rq_append_bio(req->q, req, bio);
+ if (ret) {
+ OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret);
+ bio_put(bio);
+ }
+ return ret;
+}
+
+static int _req_append_segment(struct osd_request *or,
+ unsigned padding, struct _osd_req_data_segment *seg,
+ struct _osd_req_data_segment *last_seg, struct _osd_io_info *io)
+{
+ void *pad_buff;
+ int ret;
+
+ if (padding) {
+ /* check if we can just add it to last buffer */
+ if (last_seg &&
+ (padding <= last_seg->alloc_size - last_seg->total_bytes))
+ pad_buff = last_seg->buff + last_seg->total_bytes;
+ else
+ pad_buff = io->pad_buff;
+
+ ret = _append_map_kern(io->req, pad_buff, padding,
+ or->alloc_flags);
+ if (ret)
+ return ret;
+ io->total_bytes += padding;
+ }
+
+ ret = _append_map_kern(io->req, seg->buff, seg->total_bytes,
+ or->alloc_flags);
+ if (ret)
+ return ret;
+
+ io->total_bytes += seg->total_bytes;
+ OSD_DEBUG("padding=%d buff=%p total_bytes=%d\n", padding, seg->buff,
+ seg->total_bytes);
+ return 0;
+}
+
+static int _osd_req_finalize_set_attr_list(struct osd_request *or)
+{
+ struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+ unsigned padding;
+ int ret;
+
+ if (!or->set_attr.total_bytes) {
+ cdbh->attrs_list.set_attr_offset = OSD_OFFSET_UNUSED;
+ return 0;
+ }
+
+ cdbh->attrs_list.set_attr_bytes = cpu_to_be32(or->set_attr.total_bytes);
+ cdbh->attrs_list.set_attr_offset =
+ osd_req_encode_offset(or, or->out.total_bytes, &padding);
+
+ ret = _req_append_segment(or, padding, &or->set_attr,
+ or->out.last_seg, &or->out);
+ if (ret)
+ return ret;
+
+ or->out.last_seg = &or->set_attr;
+ return 0;
+}
+
+int osd_req_add_get_attr_list(struct osd_request *or,
+ const struct osd_attr *oa, unsigned nelem)
+{
+ unsigned total_bytes = or->enc_get_attr.total_bytes;
+ void *attr_last;
+ int ret;
+
+ if (or->attributes_mode &&
+ or->attributes_mode != OSD_CDB_GET_SET_ATTR_LISTS) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+
+ /* first time calc data-in list header size */
+ if (!or->get_attr.total_bytes)
+ or->get_attr.total_bytes = _osd_req_sizeof_alist_header(or);
+
+ /* calc data-out info */
+ if (!total_bytes) { /* first-time: allocate and put list header */
+ unsigned max_bytes;
+
+ total_bytes = _osd_req_sizeof_alist_header(or);
+ max_bytes = total_bytes +
+ nelem * sizeof(struct osd_attributes_list_attrid);
+ ret = _alloc_get_attr_desc(or, max_bytes);
+ if (ret)
+ return ret;
+
+ _osd_req_set_alist_type(or, or->enc_get_attr.buff,
+ OSD_ATTR_LIST_GET);
+ }
+ attr_last = or->enc_get_attr.buff + total_bytes;
+
+ for (; nelem; --nelem) {
+ struct osd_attributes_list_attrid *attrid;
+ const unsigned cur_size = sizeof(*attrid);
+
+ total_bytes += cur_size;
+ if (unlikely(or->enc_get_attr.alloc_size < total_bytes)) {
+ or->enc_get_attr.total_bytes = total_bytes - cur_size;
+ ret = _alloc_get_attr_desc(or,
+ total_bytes + nelem * sizeof(*attrid));
+ if (ret)
+ return ret;
+ attr_last = or->enc_get_attr.buff +
+ or->enc_get_attr.total_bytes;
+ }
+
+ attrid = attr_last;
+ attrid->attr_page = cpu_to_be32(oa->attr_page);
+ attrid->attr_id = cpu_to_be32(oa->attr_id);
+
+ attr_last += cur_size;
+
+ /* calc data-in size */
+ or->get_attr.total_bytes +=
+ _osd_req_alist_elem_size(or, oa->len);
+ ++oa;
+ }
+
+ or->enc_get_attr.total_bytes = total_bytes;
+
+ OSD_DEBUG(
+ "get_attr.total_bytes=%u(%u) enc_get_attr.total_bytes=%u(%Zu)\n",
+ or->get_attr.total_bytes,
+ or->get_attr.total_bytes - _osd_req_sizeof_alist_header(or),
+ or->enc_get_attr.total_bytes,
+ (or->enc_get_attr.total_bytes - _osd_req_sizeof_alist_header(or))
+ / sizeof(struct osd_attributes_list_attrid));
+
+ return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_list);
+
+static int _osd_req_finalize_get_attr_list(struct osd_request *or)
+{
+ struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+ unsigned out_padding;
+ unsigned in_padding;
+ int ret;
+
+ if (!or->enc_get_attr.total_bytes) {
+ cdbh->attrs_list.get_attr_desc_offset = OSD_OFFSET_UNUSED;
+ cdbh->attrs_list.get_attr_offset = OSD_OFFSET_UNUSED;
+ return 0;
+ }
+
+ ret = _alloc_get_attr_list(or);
+ if (ret)
+ return ret;
+
+ /* The out-going buffer info update */
+ OSD_DEBUG("out-going\n");
+ cdbh->attrs_list.get_attr_desc_bytes =
+ cpu_to_be32(or->enc_get_attr.total_bytes);
+
+ cdbh->attrs_list.get_attr_desc_offset =
+ osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+ ret = _req_append_segment(or, out_padding, &or->enc_get_attr,
+ or->out.last_seg, &or->out);
+ if (ret)
+ return ret;
+ or->out.last_seg = &or->enc_get_attr;
+
+ /* The incoming buffer info update */
+ OSD_DEBUG("in-coming\n");
+ cdbh->attrs_list.get_attr_alloc_length =
+ cpu_to_be32(or->get_attr.total_bytes);
+
+ cdbh->attrs_list.get_attr_offset =
+ osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+ ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+ &or->in);
+ if (ret)
+ return ret;
+ or->in.last_seg = &or->get_attr;
+
+ return 0;
+}
+
+int osd_req_decode_get_attr_list(struct osd_request *or,
+ struct osd_attr *oa, int *nelem, void **iterator)
+{
+ unsigned cur_bytes, returned_bytes;
+ int n;
+ const unsigned sizeof_attr_list = _osd_req_sizeof_alist_header(or);
+ void *cur_p;
+
+ if (!_osd_req_is_alist_type(or, or->get_attr.buff,
+ OSD_ATTR_LIST_SET_RETRIEVE)) {
+ oa->attr_page = 0;
+ oa->attr_id = 0;
+ oa->val_ptr = NULL;
+ oa->len = 0;
+ *iterator = NULL;
+ return 0;
+ }
+
+ if (*iterator) {
+ BUG_ON((*iterator < or->get_attr.buff) ||
+ (or->get_attr.buff + or->get_attr.alloc_size < *iterator));
+ cur_p = *iterator;
+ cur_bytes = (*iterator - or->get_attr.buff) - sizeof_attr_list;
+ returned_bytes = or->get_attr.total_bytes;
+ } else { /* first time decode the list header */
+ cur_bytes = sizeof_attr_list;
+ returned_bytes = _osd_req_alist_size(or, or->get_attr.buff) +
+ sizeof_attr_list;
+
+ cur_p = or->get_attr.buff + sizeof_attr_list;
+
+ if (returned_bytes > or->get_attr.alloc_size) {
+ OSD_DEBUG("target report: space was not big enough! "
+ "Allocate=%u Needed=%u\n",
+ or->get_attr.alloc_size,
+ returned_bytes + sizeof_attr_list);
+
+ returned_bytes =
+ or->get_attr.alloc_size - sizeof_attr_list;
+ }
+ or->get_attr.total_bytes = returned_bytes;
+ }
+
+ for (n = 0; (n < *nelem) && (cur_bytes < returned_bytes); ++n) {
+ struct osd_attributes_list_element *attr = cur_p;
+ unsigned inc;
+
+ oa->len = be16_to_cpu(attr->attr_bytes);
+ inc = _osd_req_alist_elem_size(or, oa->len);
+ OSD_DEBUG("oa->len=%d inc=%d cur_bytes=%d\n",
+ oa->len, inc, cur_bytes);
+ cur_bytes += inc;
+ if (cur_bytes > returned_bytes) {
+ OSD_ERR("BAD FOOD from target. list not valid!"
+ "c=%d r=%d n=%d\n",
+ cur_bytes, returned_bytes, n);
+ oa->val_ptr = NULL;
+ break;
+ }
+
+ oa->attr_page = be32_to_cpu(attr->attr_page);
+ oa->attr_id = be32_to_cpu(attr->attr_id);
+ oa->val_ptr = attr->attr_val;
+
+ cur_p += inc;
+ ++oa;
+ }
+
+ *iterator = (returned_bytes - cur_bytes) ? cur_p : NULL;
+ *nelem = n;
+ return returned_bytes - cur_bytes;
+}
+EXPORT_SYMBOL(osd_req_decode_get_attr_list);
+
+/*
+ * Attributes Page-mode
+ */
+
+int osd_req_add_get_attr_page(struct osd_request *or,
+ u32 page_id, void *attar_page, unsigned max_page_len,
+ const struct osd_attr *set_one_attr)
+{
+ struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+
+ if (or->attributes_mode &&
+ or->attributes_mode != OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+ WARN_ON(1);
+ return -EINVAL;
+ }
+ or->attributes_mode = OSD_CDB_GET_ATTR_PAGE_SET_ONE;
+
+ or->get_attr.buff = attar_page;
+ or->get_attr.total_bytes = max_page_len;
+
+ or->set_attr.buff = set_one_attr->val_ptr;
+ or->set_attr.total_bytes = set_one_attr->len;
+
+ cdbh->attrs_page.get_attr_page = cpu_to_be32(page_id);
+ cdbh->attrs_page.get_attr_alloc_length = cpu_to_be32(max_page_len);
+ /* ocdb->attrs_page.get_attr_offset; */
+
+ cdbh->attrs_page.set_attr_page = cpu_to_be32(set_one_attr->attr_page);
+ cdbh->attrs_page.set_attr_id = cpu_to_be32(set_one_attr->attr_id);
+ cdbh->attrs_page.set_attr_length = cpu_to_be32(set_one_attr->len);
+ /* ocdb->attrs_page.set_attr_offset; */
+ return 0;
+}
+EXPORT_SYMBOL(osd_req_add_get_attr_page);
+
+static int _osd_req_finalize_attr_page(struct osd_request *or)
+{
+ struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+ unsigned in_padding, out_padding;
+ int ret;
+
+ /* returned page */
+ cdbh->attrs_page.get_attr_offset =
+ osd_req_encode_offset(or, or->in.total_bytes, &in_padding);
+
+ ret = _req_append_segment(or, in_padding, &or->get_attr, NULL,
+ &or->in);
+ if (ret)
+ return ret;
+
+ /* set one value */
+ cdbh->attrs_page.set_attr_offset =
+ osd_req_encode_offset(or, or->out.total_bytes, &out_padding);
+
+ ret = _req_append_segment(or, out_padding, &or->enc_get_attr, NULL,
+ &or->out);
+ return ret;
+}
+
+static int _osd_req_finalize_data_integrity(struct osd_request *or,
+ bool has_in, bool has_out, const u8 *cap_key)
+{
+ struct osd_security_parameters *sec_parms = _osd_req_sec_params(or);
+ int ret;
+
+ if (!osd_is_sec_alldata(sec_parms))
+ return 0;
+
+ if (has_out) {
+ struct _osd_req_data_segment seg = {
+ .buff = &or->out_data_integ,
+ .total_bytes = sizeof(or->out_data_integ),
+ };
+ unsigned pad;
+
+ or->out_data_integ.data_bytes = cpu_to_be64(
+ or->out.bio ? or->out.bio->bi_size : 0);
+ or->out_data_integ.set_attributes_bytes = cpu_to_be64(
+ or->set_attr.total_bytes);
+ or->out_data_integ.get_attributes_bytes = cpu_to_be64(
+ or->enc_get_attr.total_bytes);
+
+ sec_parms->data_out_integrity_check_offset =
+ osd_req_encode_offset(or, or->out.total_bytes, &pad);
+
+ ret = _req_append_segment(or, pad, &seg, or->out.last_seg,
+ &or->out);
+ if (ret)
+ return ret;
+ or->out.last_seg = NULL;
+
+ /* they are now all chained to request sign them all together */
+ osd_sec_sign_data(&or->out_data_integ, or->out.req->bio,
+ cap_key);
+ }
+
+ if (has_in) {
+ struct _osd_req_data_segment seg = {
+ .buff = &or->in_data_integ,
+ .total_bytes = sizeof(or->in_data_integ),
+ };
+ unsigned pad;
+
+ sec_parms->data_in_integrity_check_offset =
+ osd_req_encode_offset(or, or->in.total_bytes, &pad);
+
+ ret = _req_append_segment(or, pad, &seg, or->in.last_seg,
+ &or->in);
+ if (ret)
+ return ret;
+
+ or->in.last_seg = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * osd_finalize_request and helpers
+ */
+
+static int _init_blk_request(struct osd_request *or,
+ bool has_in, bool has_out)
+{
+ gfp_t flags = or->alloc_flags;
+ struct scsi_device *scsi_device = or->osd_dev->scsi_device;
+ struct request_queue *q = scsi_device->request_queue;
+ struct request *req;
+ int ret = -ENOMEM;
+
+ req = blk_get_request(q, has_out, flags);
+ if (!req)
+ goto out;
+
+ or->request = req;
+ req->cmd_type = REQ_TYPE_BLOCK_PC;
+ req->timeout = or->timeout;
+ req->retries = or->retries;
+ req->sense = or->sense;
+ req->sense_len = 0;
+
+ if (has_out) {
+ or->out.req = req;
+ if (has_in) {
+ /* allocate bidi request */
+ req = blk_get_request(q, READ, flags);
+ if (!req) {
+ OSD_DEBUG("blk_get_request for bidi failed\n");
+ goto out;
+ }
+ req->cmd_type = REQ_TYPE_BLOCK_PC;
+ or->in.req = or->request->next_rq = req;
+ }
+ } else if (has_in)
+ or->in.req = req;
+
+ ret = 0;
+out:
+ OSD_DEBUG("or=%p has_in=%d has_out=%d => %d, %p\n",
+ or, has_in, has_out, ret, or->request);
+ return ret;
+}
+
+int osd_finalize_request(struct osd_request *or,
+ u8 options, const void *cap, const u8 *cap_key)
+{
+ struct osd_cdb_head *cdbh = osd_cdb_head(&or->cdb);
+ bool has_in, has_out;
+ int ret;
+
+ if (options & OSD_REQ_FUA)
+ cdbh->options |= OSD_CDB_FUA;
+
+ if (options & OSD_REQ_DPO)
+ cdbh->options |= OSD_CDB_DPO;
+
+ if (options & OSD_REQ_BYPASS_TIMESTAMPS)
+ cdbh->timestamp_control = OSD_CDB_BYPASS_TIMESTAMPS;
+
+ osd_set_caps(&or->cdb, cap);
+
+ has_in = or->in.bio || or->get_attr.total_bytes;
+ has_out = or->out.bio || or->set_attr.total_bytes ||
+ or->enc_get_attr.total_bytes;
+
+ ret = _init_blk_request(or, has_in, has_out);
+ if (ret) {
+ OSD_DEBUG("_init_blk_request failed\n");
+ return ret;
+ }
+
+ if (or->out.bio) {
+ ret = blk_rq_append_bio(or->request->q, or->out.req,
+ or->out.bio);
+ if (ret) {
+ OSD_DEBUG("blk_rq_append_bio out failed\n");
+ return ret;
+ }
+ OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n",
+ _LLU(or->out.total_bytes), or->out.req->data_len);
+ }
+ if (or->in.bio) {
+ ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio);
+ if (ret) {
+ OSD_DEBUG("blk_rq_append_bio in failed\n");
+ return ret;
+ }
+ OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n",
+ _LLU(or->in.total_bytes), or->in.req->data_len);
+ }
+
+ or->out.pad_buff = sg_out_pad_buffer;
+ or->in.pad_buff = sg_in_pad_buffer;
+
+ if (!or->attributes_mode)
+ or->attributes_mode = OSD_CDB_GET_SET_ATTR_LISTS;
+ cdbh->command_specific_options |= or->attributes_mode;
+ if (or->attributes_mode == OSD_CDB_GET_ATTR_PAGE_SET_ONE) {
+ ret = _osd_req_finalize_attr_page(or);
+ } else {
+ /* TODO: I think that for the GET_ATTR command these 2 should
+ * be reversed to keep them in execution order (for embeded
+ * targets with low memory footprint)
+ */
+ ret = _osd_req_finalize_set_attr_list(or);
+ if (ret) {
+ OSD_DEBUG("_osd_req_finalize_set_attr_list failed\n");
+ return ret;
+ }
+
+ ret = _osd_req_finalize_get_attr_list(or);
+ if (ret) {
+ OSD_DEBUG("_osd_req_finalize_get_attr_list failed\n");
+ return ret;
+ }
+ }
+
+ ret = _osd_req_finalize_data_integrity(or, has_in, has_out, cap_key);
+ if (ret)
+ return ret;
+
+ osd_sec_sign_cdb(&or->cdb, cap_key);
+
+ or->request->cmd = or->cdb.buff;
+ or->request->cmd_len = _osd_req_cdb_len(or);
+
+ return 0;
+}
+EXPORT_SYMBOL(osd_finalize_request);
+
+#define OSD_SENSE_PRINT1(fmt, a...) \
+ do { \
+ if (__cur_sense_need_output) \
+ OSD_ERR(fmt, ##a); \
+ } while (0)
+
+#define OSD_SENSE_PRINT2(fmt, a...) OSD_SENSE_PRINT1(" " fmt, ##a)
+
+int osd_req_decode_sense_full(struct osd_request *or,
+ struct osd_sense_info *osi, bool silent,
+ struct osd_obj_id *bad_obj_list __unused, int max_obj __unused,
+ struct osd_attr *bad_attr_list, int max_attr)
+{
+ int sense_len, original_sense_len;
+ struct osd_sense_info local_osi;
+ struct scsi_sense_descriptor_based *ssdb;
+ void *cur_descriptor;
+#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 0)
+ const bool __cur_sense_need_output = false;
+#else
+ bool __cur_sense_need_output = !silent;
+#endif
+
+ if (!or->request->errors)
+ return 0;
+
+ ssdb = or->request->sense;
+ sense_len = or->request->sense_len;
+ if ((sense_len < (int)sizeof(*ssdb) || !ssdb->sense_key)) {
+ OSD_ERR("Block-layer returned error(0x%x) but "
+ "sense_len(%u) || key(%d) is empty\n",
+ or->request->errors, sense_len, ssdb->sense_key);
+ return -EIO;
+ }
+
+ if ((ssdb->response_code != 0x72) && (ssdb->response_code != 0x73)) {
+ OSD_ERR("Unrecognized scsi sense: rcode=%x length=%d\n",
+ ssdb->response_code, sense_len);
+ return -EIO;
+ }
+
+ osi = osi ? : &local_osi;
+ memset(osi, 0, sizeof(*osi));
+ osi->key = ssdb->sense_key;
+ osi->additional_code = be16_to_cpu(ssdb->additional_sense_code);
+ original_sense_len = ssdb->additional_sense_length + 8;
+
+#if (CONFIG_SCSI_OSD_DPRINT_SENSE == 1)
+ if (__cur_sense_need_output)
+ __cur_sense_need_output = (osi->key > scsi_sk_recovered_error);
+#endif
+ OSD_SENSE_PRINT1("Main Sense information key=0x%x length(%d, %d) "
+ "additional_code=0x%x\n",
+ osi->key, original_sense_len, sense_len,
+ osi->additional_code);
+
+ if (original_sense_len < sense_len)
+ sense_len = original_sense_len;
+
+ cur_descriptor = ssdb->ssd;
+ sense_len -= sizeof(*ssdb);
+ while (sense_len > 0) {
+ struct scsi_sense_descriptor *ssd = cur_descriptor;
+ int cur_len = ssd->additional_length + 2;
+
+ sense_len -= cur_len;
+
+ if (sense_len < 0)
+ break; /* sense was truncated */
+
+ switch (ssd->descriptor_type) {
+ case scsi_sense_information:
+ case scsi_sense_command_specific_information:
+ {
+ struct scsi_sense_command_specific_data_descriptor
+ *sscd = cur_descriptor;
+
+ osi->command_info =
+ get_unaligned_be64(&sscd->information) ;
+ OSD_SENSE_PRINT2(
+ "command_specific_information 0x%llx \n",
+ _LLU(osi->command_info));
+ break;
+ }
+ case scsi_sense_key_specific:
+ {
+ struct scsi_sense_key_specific_data_descriptor
+ *ssks = cur_descriptor;
+
+ osi->sense_info = get_unaligned_be16(&ssks->value);
+ OSD_SENSE_PRINT2(
+ "sense_key_specific_information %u"
+ "sksv_cd_bpv_bp (0x%x)\n",
+ osi->sense_info, ssks->sksv_cd_bpv_bp);
+ break;
+ }
+ case osd_sense_object_identification:
+ { /*FIXME: Keep first not last, Store in array*/
+ struct osd_sense_identification_data_descriptor
+ *osidd = cur_descriptor;
+
+ osi->not_initiated_command_functions =
+ le32_to_cpu(osidd->not_initiated_functions);
+ osi->completed_command_functions =
+ le32_to_cpu(osidd->completed_functions);
+ osi->obj.partition = be64_to_cpu(osidd->partition_id);
+ osi->obj.id = be64_to_cpu(osidd->object_id);
+ OSD_SENSE_PRINT2(
+ "object_identification pid=0x%llx oid=0x%llx\n",
+ _LLU(osi->obj.partition), _LLU(osi->obj.id));
+ OSD_SENSE_PRINT2(
+ "not_initiated_bits(%x) "
+ "completed_command_bits(%x)\n",
+ osi->not_initiated_command_functions,
+ osi->completed_command_functions);
+ break;
+ }
+ case osd_sense_response_integrity_check:
+ {
+ struct osd_sense_response_integrity_check_descriptor
+ *osricd = cur_descriptor;
+ const unsigned len =
+ sizeof(osricd->integrity_check_value);
+ char key_dump[len*4 + 2]; /* 2nibbles+space+ASCII */
+
+ hex_dump_to_buffer(osricd->integrity_check_value, len,
+ 32, 1, key_dump, sizeof(key_dump), true);
+ OSD_SENSE_PRINT2("response_integrity [%s]\n", key_dump);
+ }
+ case osd_sense_attribute_identification:
+ {
+ struct osd_sense_attributes_data_descriptor
+ *osadd = cur_descriptor;
+ int len = min(cur_len, sense_len);
+ int i = 0;
+ struct osd_sense_attr *pattr = osadd->sense_attrs;
+
+ while (len < 0) {
+ u32 attr_page = be32_to_cpu(pattr->attr_page);
+ u32 attr_id = be32_to_cpu(pattr->attr_id);
+
+ if (i++ == 0) {
+ osi->attr.attr_page = attr_page;
+ osi->attr.attr_id = attr_id;
+ }
+
+ if (bad_attr_list && max_attr) {
+ bad_attr_list->attr_page = attr_page;
+ bad_attr_list->attr_id = attr_id;
+ bad_attr_list++;
+ max_attr--;
+ }
+ OSD_SENSE_PRINT2(
+ "osd_sense_attribute_identification"
+ "attr_page=0x%x attr_id=0x%x\n",
+ attr_page, attr_id);
+ }
+ }
+ /*These are not legal for OSD*/
+ case scsi_sense_field_replaceable_unit:
+ OSD_SENSE_PRINT2("scsi_sense_field_replaceable_unit\n");
+ break;
+ case scsi_sense_stream_commands:
+ OSD_SENSE_PRINT2("scsi_sense_stream_commands\n");
+ break;
+ case scsi_sense_block_commands:
+ OSD_SENSE_PRINT2("scsi_sense_block_commands\n");
+ break;
+ case scsi_sense_ata_return:
+ OSD_SENSE_PRINT2("scsi_sense_ata_return\n");
+ break;
+ default:
+ if (ssd->descriptor_type <= scsi_sense_Reserved_last)
+ OSD_SENSE_PRINT2(
+ "scsi_sense Reserved descriptor (0x%x)",
+ ssd->descriptor_type);
+ else
+ OSD_SENSE_PRINT2(
+ "scsi_sense Vendor descriptor (0x%x)",
+ ssd->descriptor_type);
+ }
+
+ cur_descriptor += cur_len;
+ }
+
+ return (osi->key > scsi_sk_recovered_error) ? -EIO : 0;
+}
+EXPORT_SYMBOL(osd_req_decode_sense_full);
+
+/*
+ * Implementation of osd_sec.h API
+ * TODO: Move to a separate osd_sec.c file at a later stage.
+ */
+
+enum { OSD_SEC_CAP_V1_ALL_CAPS =
+ OSD_SEC_CAP_APPEND | OSD_SEC_CAP_OBJ_MGMT | OSD_SEC_CAP_REMOVE |
+ OSD_SEC_CAP_CREATE | OSD_SEC_CAP_SET_ATTR | OSD_SEC_CAP_GET_ATTR |
+ OSD_SEC_CAP_WRITE | OSD_SEC_CAP_READ | OSD_SEC_CAP_POL_SEC |
+ OSD_SEC_CAP_GLOBAL | OSD_SEC_CAP_DEV_MGMT
+};
+
+enum { OSD_SEC_CAP_V2_ALL_CAPS =
+ OSD_SEC_CAP_V1_ALL_CAPS | OSD_SEC_CAP_QUERY | OSD_SEC_CAP_M_OBJECT
+};
+
+void osd_sec_init_nosec_doall_caps(void *caps,
+ const struct osd_obj_id *obj, bool is_collection, const bool is_v1)
+{
+ struct osd_capability *cap = caps;
+ u8 type;
+ u8 descriptor_type;
+
+ if (likely(obj->id)) {
+ if (unlikely(is_collection)) {
+ type = OSD_SEC_OBJ_COLLECTION;
+ descriptor_type = is_v1 ? OSD_SEC_OBJ_DESC_OBJ :
+ OSD_SEC_OBJ_DESC_COL;
+ } else {
+ type = OSD_SEC_OBJ_USER;
+ descriptor_type = OSD_SEC_OBJ_DESC_OBJ;
+ }
+ WARN_ON(!obj->partition);
+ } else {
+ type = obj->partition ? OSD_SEC_OBJ_PARTITION :
+ OSD_SEC_OBJ_ROOT;
+ descriptor_type = OSD_SEC_OBJ_DESC_PAR;
+ }
+
+ memset(cap, 0, sizeof(*cap));
+
+ cap->h.format = OSD_SEC_CAP_FORMAT_VER1;
+ cap->h.integrity_algorithm__key_version = 0; /* MAKE_BYTE(0, 0); */
+ cap->h.security_method = OSD_SEC_NOSEC;
+/* cap->expiration_time;
+ cap->AUDIT[30-10];
+ cap->discriminator[42-30];
+ cap->object_created_time; */
+ cap->h.object_type = type;
+ osd_sec_set_caps(&cap->h, OSD_SEC_CAP_V1_ALL_CAPS);
+ cap->h.object_descriptor_type = descriptor_type;
+ cap->od.obj_desc.policy_access_tag = 0;
+ cap->od.obj_desc.allowed_partition_id = cpu_to_be64(obj->partition);
+ cap->od.obj_desc.allowed_object_id = cpu_to_be64(obj->id);
+}
+EXPORT_SYMBOL(osd_sec_init_nosec_doall_caps);
+
+/* FIXME: Extract version from caps pointer.
+ * Also Pete's target only supports caps from OSDv1 for now
+ */
+void osd_set_caps(struct osd_cdb *cdb, const void *caps)
+{
+ bool is_ver1 = true;
+ /* NOTE: They start at same address */
+ memcpy(&cdb->v1.caps, caps, is_ver1 ? OSDv1_CAP_LEN : OSD_CAP_LEN);
+}
+
+bool osd_is_sec_alldata(struct osd_security_parameters *sec_parms __unused)
+{
+ return false;
+}
+
+void osd_sec_sign_cdb(struct osd_cdb *ocdb __unused, const u8 *cap_key __unused)
+{
+}
+
+void osd_sec_sign_data(void *data_integ __unused,
+ struct bio *bio __unused, const u8 *cap_key __unused)
+{
+}
+
+/*
+ * Declared in osd_protocol.h
+ * 4.12.5 Data-In and Data-Out buffer offsets
+ * byte offset = mantissa * (2^(exponent+8))
+ * Returns the smallest allowed encoded offset that contains given @offset
+ * The actual encoded offset returned is @offset + *@padding.
+ */
+osd_cdb_offset __osd_encode_offset(
+ u64 offset, unsigned *padding, int min_shift, int max_shift)
+{
+ u64 try_offset = -1, mod, align;
+ osd_cdb_offset be32_offset;
+ int shift;
+
+ *padding = 0;
+ if (!offset)
+ return 0;
+
+ for (shift = min_shift; shift < max_shift; ++shift) {
+ try_offset = offset >> shift;
+ if (try_offset < (1 << OSD_OFFSET_MAX_BITS))
+ break;
+ }
+
+ BUG_ON(shift == max_shift);
+
+ align = 1 << shift;
+ mod = offset & (align - 1);
+ if (mod) {
+ *padding = align - mod;
+ try_offset += 1;
+ }
+
+ try_offset |= ((shift - 8) & 0xf) << 28;
+ be32_offset = cpu_to_be32((u32)try_offset);
+
+ OSD_DEBUG("offset=%llu mantissa=%llu exp=%d encoded=%x pad=%d\n",
+ _LLU(offset), _LLU(try_offset & 0x0FFFFFFF), shift,
+ be32_offset, *padding);
+ return be32_offset;
+}
diff --git a/drivers/scsi/osd/osd_uld.c b/drivers/scsi/osd/osd_uld.c
new file mode 100644
index 00000000000..f644c9571ea
--- /dev/null
+++ b/drivers/scsi/osd/osd_uld.c
@@ -0,0 +1,481 @@
+/*
+ * osd_uld.c - OSD Upper Layer Driver
+ *
+ * A Linux driver module that registers as a SCSI ULD and probes
+ * for OSD type SCSI devices.
+ * It's main function is to export osd devices to in-kernel users like
+ * osdfs and pNFS-objects-LD. It also provides one ioctl for running
+ * in Kernel tests.
+ *
+ * Copyright (C) 2008 Panasas Inc. All rights reserved.
+ *
+ * Authors:
+ * Boaz Harrosh <bharrosh@panasas.com>
+ * Benny Halevy <bhalevy@panasas.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Panasas company nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <linux/namei.h>
+#include <linux/cdev.h>
+#include <linux/fs.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/idr.h>
+#include <linux/major.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_driver.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_ioctl.h>
+
+#include <scsi/osd_initiator.h>
+#include <scsi/osd_sec.h>
+
+#include "osd_debug.h"
+
+#ifndef TYPE_OSD
+# define TYPE_OSD 0x11
+#endif
+
+#ifndef SCSI_OSD_MAJOR
+# define SCSI_OSD_MAJOR 260
+#endif
+#define SCSI_OSD_MAX_MINOR 64
+
+static const char osd_name[] = "osd";
+static const char *osd_version_string = "open-osd 0.1.0";
+const char osd_symlink[] = "scsi_osd";
+
+MODULE_AUTHOR("Boaz Harrosh <bharrosh@panasas.com>");
+MODULE_DESCRIPTION("open-osd Upper-Layer-Driver osd.ko");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_CHARDEV_MAJOR(SCSI_OSD_MAJOR);
+MODULE_ALIAS_SCSI_DEVICE(TYPE_OSD);
+
+struct osd_uld_device {
+ int minor;
+ struct kref kref;
+ struct cdev cdev;
+ struct osd_dev od;
+ struct gendisk *disk;
+ struct device *class_member;
+};
+
+static void __uld_get(struct osd_uld_device *oud);
+static void __uld_put(struct osd_uld_device *oud);
+
+/*
+ * Char Device operations
+ */
+
+static int osd_uld_open(struct inode *inode, struct file *file)
+{
+ struct osd_uld_device *oud = container_of(inode->i_cdev,
+ struct osd_uld_device, cdev);
+
+ __uld_get(oud);
+ /* cache osd_uld_device on file handle */
+ file->private_data = oud;
+ OSD_DEBUG("osd_uld_open %p\n", oud);
+ return 0;
+}
+
+static int osd_uld_release(struct inode *inode, struct file *file)
+{
+ struct osd_uld_device *oud = file->private_data;
+
+ OSD_DEBUG("osd_uld_release %p\n", file->private_data);
+ file->private_data = NULL;
+ __uld_put(oud);
+ return 0;
+}
+
+/* FIXME: Only one vector for now */
+unsigned g_test_ioctl;
+do_test_fn *g_do_test;
+
+int osduld_register_test(unsigned ioctl, do_test_fn *do_test)
+{
+ if (g_test_ioctl)
+ return -EINVAL;
+
+ g_test_ioctl = ioctl;
+ g_do_test = do_test;
+ return 0;
+}
+EXPORT_SYMBOL(osduld_register_test);
+
+void osduld_unregister_test(unsigned ioctl)
+{
+ if (ioctl == g_test_ioctl) {
+ g_test_ioctl = 0;
+ g_do_test = NULL;
+ }
+}
+EXPORT_SYMBOL(osduld_unregister_test);
+
+static do_test_fn *_find_ioctl(unsigned cmd)
+{
+ if (g_test_ioctl == cmd)
+ return g_do_test;
+ else
+ return NULL;
+}
+
+static long osd_uld_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ struct osd_uld_device *oud = file->private_data;
+ int ret;
+ do_test_fn *do_test;
+
+ do_test = _find_ioctl(cmd);
+ if (do_test)
+ ret = do_test(&oud->od, cmd, arg);
+ else {
+ OSD_ERR("Unknown ioctl %d: osd_uld_device=%p\n", cmd, oud);
+ ret = -ENOIOCTLCMD;
+ }
+ return ret;
+}
+
+static const struct file_operations osd_fops = {
+ .owner = THIS_MODULE,
+ .open = osd_uld_open,
+ .release = osd_uld_release,
+ .unlocked_ioctl = osd_uld_ioctl,
+};
+
+struct osd_dev *osduld_path_lookup(const char *path)
+{
+ struct nameidata nd;
+ struct inode *inode;
+ struct cdev *cdev;
+ struct osd_uld_device *uninitialized_var(oud);
+ int error;
+
+ if (!path || !*path) {
+ OSD_ERR("Mount with !path || !*path\n");
+ return ERR_PTR(-EINVAL);
+ }
+
+ error = path_lookup(path, LOOKUP_FOLLOW, &nd);
+ if (error) {
+ OSD_ERR("path_lookup of %s faild=>%d\n", path, error);
+ return ERR_PTR(error);
+ }
+
+ inode = nd.path.dentry->d_inode;
+ error = -EINVAL; /* Not the right device e.g osd_uld_device */
+ if (!S_ISCHR(inode->i_mode)) {
+ OSD_DEBUG("!S_ISCHR()\n");
+ goto out;
+ }
+
+ cdev = inode->i_cdev;
+ if (!cdev) {
+ OSD_ERR("Before mounting an OSD Based filesystem\n");
+ OSD_ERR(" user-mode must open+close the %s device\n", path);
+ OSD_ERR(" Example: bash: echo < %s\n", path);
+ goto out;
+ }
+
+ /* The Magic wand. Is it our char-dev */
+ /* TODO: Support sg devices */
+ if (cdev->owner != THIS_MODULE) {
+ OSD_ERR("Error mounting %s - is not an OSD device\n", path);
+ goto out;
+ }
+
+ oud = container_of(cdev, struct osd_uld_device, cdev);
+
+ __uld_get(oud);
+ error = 0;
+
+out:
+ path_put(&nd.path);
+ return error ? ERR_PTR(error) : &oud->od;
+}
+EXPORT_SYMBOL(osduld_path_lookup);
+
+void osduld_put_device(struct osd_dev *od)
+{
+ if (od) {
+ struct osd_uld_device *oud = container_of(od,
+ struct osd_uld_device, od);
+
+ __uld_put(oud);
+ }
+}
+EXPORT_SYMBOL(osduld_put_device);
+
+/*
+ * Scsi Device operations
+ */
+
+static int __detect_osd(struct osd_uld_device *oud)
+{
+ struct scsi_device *scsi_device = oud->od.scsi_device;
+ char caps[OSD_CAP_LEN];
+ int error;
+
+ /* sending a test_unit_ready as first command seems to be needed
+ * by some targets
+ */
+ OSD_DEBUG("start scsi_test_unit_ready %p %p %p\n",
+ oud, scsi_device, scsi_device->request_queue);
+ error = scsi_test_unit_ready(scsi_device, 10*HZ, 5, NULL);
+ if (error)
+ OSD_ERR("warning: scsi_test_unit_ready failed\n");
+
+ osd_sec_init_nosec_doall_caps(caps, &osd_root_object, false, true);
+ if (osd_auto_detect_ver(&oud->od, caps))
+ return -ENODEV;
+
+ return 0;
+}
+
+static struct class *osd_sysfs_class;
+static DEFINE_IDA(osd_minor_ida);
+
+static int osd_probe(struct device *dev)
+{
+ struct scsi_device *scsi_device = to_scsi_device(dev);
+ struct gendisk *disk;
+ struct osd_uld_device *oud;
+ int minor;
+ int error;
+
+ if (scsi_device->type != TYPE_OSD)
+ return -ENODEV;
+
+ do {
+ if (!ida_pre_get(&osd_minor_ida, GFP_KERNEL))
+ return -ENODEV;
+
+ error = ida_get_new(&osd_minor_ida, &minor);
+ } while (error == -EAGAIN);
+
+ if (error)
+ return error;
+ if (minor >= SCSI_OSD_MAX_MINOR) {
+ error = -EBUSY;
+ goto err_retract_minor;
+ }
+
+ error = -ENOMEM;
+ oud = kzalloc(sizeof(*oud), GFP_KERNEL);
+ if (NULL == oud)
+ goto err_retract_minor;
+
+ kref_init(&oud->kref);
+ dev_set_drvdata(dev, oud);
+ oud->minor = minor;
+
+ /* allocate a disk and set it up */
+ /* FIXME: do we need this since sg has already done that */
+ disk = alloc_disk(1);
+ if (!disk) {
+ OSD_ERR("alloc_disk failed\n");
+ goto err_free_osd;
+ }
+ disk->major = SCSI_OSD_MAJOR;
+ disk->first_minor = oud->minor;
+ sprintf(disk->disk_name, "osd%d", oud->minor);
+ oud->disk = disk;
+
+ /* hold one more reference to the scsi_device that will get released
+ * in __release, in case a logout is happening while fs is mounted
+ */
+ scsi_device_get(scsi_device);
+ osd_dev_init(&oud->od, scsi_device);
+
+ /* Detect the OSD Version */
+ error = __detect_osd(oud);
+ if (error) {
+ OSD_ERR("osd detection failed, non-compatible OSD device\n");
+ goto err_put_disk;
+ }
+
+ /* init the char-device for communication with user-mode */
+ cdev_init(&oud->cdev, &osd_fops);
+ oud->cdev.owner = THIS_MODULE;
+ error = cdev_add(&oud->cdev,
+ MKDEV(SCSI_OSD_MAJOR, oud->minor), 1);
+ if (error) {
+ OSD_ERR("cdev_add failed\n");
+ goto err_put_disk;
+ }
+ kobject_get(&oud->cdev.kobj); /* 2nd ref see osd_remove() */
+
+ /* class_member */
+ oud->class_member = device_create(osd_sysfs_class, dev,
+ MKDEV(SCSI_OSD_MAJOR, oud->minor), "%s", disk->disk_name);
+ if (IS_ERR(oud->class_member)) {
+ OSD_ERR("class_device_create failed\n");
+ error = PTR_ERR(oud->class_member);
+ goto err_put_cdev;
+ }
+
+ dev_set_drvdata(oud->class_member, oud);
+
+ OSD_INFO("osd_probe %s\n", disk->disk_name);
+ return 0;
+
+err_put_cdev:
+ cdev_del(&oud->cdev);
+err_put_disk:
+ scsi_device_put(scsi_device);
+ put_disk(disk);
+err_free_osd:
+ dev_set_drvdata(dev, NULL);
+ kfree(oud);
+err_retract_minor:
+ ida_remove(&osd_minor_ida, minor);
+ return error;
+}
+
+static int osd_remove(struct device *dev)
+{
+ struct scsi_device *scsi_device = to_scsi_device(dev);
+ struct osd_uld_device *oud = dev_get_drvdata(dev);
+
+ if (!oud || (oud->od.scsi_device != scsi_device)) {
+ OSD_ERR("Half cooked osd-device %p,%p || %p!=%p",
+ dev, oud, oud ? oud->od.scsi_device : NULL,
+ scsi_device);
+ }
+
+ if (oud->class_member)
+ device_destroy(osd_sysfs_class,
+ MKDEV(SCSI_OSD_MAJOR, oud->minor));
+
+ /* We have 2 references to the cdev. One is released here
+ * and also takes down the /dev/osdX mapping. The second
+ * Will be released in __remove() after all users have released
+ * the osd_uld_device.
+ */
+ if (oud->cdev.owner)
+ cdev_del(&oud->cdev);
+
+ __uld_put(oud);
+ return 0;
+}
+
+static void __remove(struct kref *kref)
+{
+ struct osd_uld_device *oud = container_of(kref,
+ struct osd_uld_device, kref);
+ struct scsi_device *scsi_device = oud->od.scsi_device;
+
+ /* now let delete the char_dev */
+ kobject_put(&oud->cdev.kobj);
+
+ osd_dev_fini(&oud->od);
+ scsi_device_put(scsi_device);
+
+ OSD_INFO("osd_remove %s\n",
+ oud->disk ? oud->disk->disk_name : NULL);
+
+ if (oud->disk)
+ put_disk(oud->disk);
+
+ ida_remove(&osd_minor_ida, oud->minor);
+ kfree(oud);
+}
+
+static void __uld_get(struct osd_uld_device *oud)
+{
+ kref_get(&oud->kref);
+}
+
+static void __uld_put(struct osd_uld_device *oud)
+{
+ kref_put(&oud->kref, __remove);
+}
+
+/*
+ * Global driver and scsi registration
+ */
+
+static struct scsi_driver osd_driver = {
+ .owner = THIS_MODULE,
+ .gendrv = {
+ .name = osd_name,
+ .probe = osd_probe,
+ .remove = osd_remove,
+ }
+};
+
+static int __init osd_uld_init(void)
+{
+ int err;
+
+ osd_sysfs_class = class_create(THIS_MODULE, osd_symlink);
+ if (IS_ERR(osd_sysfs_class)) {
+ OSD_ERR("Unable to register sysfs class => %ld\n",
+ PTR_ERR(osd_sysfs_class));
+ return PTR_ERR(osd_sysfs_class);
+ }
+
+ err = register_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0),
+ SCSI_OSD_MAX_MINOR, osd_name);
+ if (err) {
+ OSD_ERR("Unable to register major %d for osd ULD => %d\n",
+ SCSI_OSD_MAJOR, err);
+ goto err_out;
+ }
+
+ err = scsi_register_driver(&osd_driver.gendrv);
+ if (err) {
+ OSD_ERR("scsi_register_driver failed => %d\n", err);
+ goto err_out_chrdev;
+ }
+
+ OSD_INFO("LOADED %s\n", osd_version_string);
+ return 0;
+
+err_out_chrdev:
+ unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+err_out:
+ class_destroy(osd_sysfs_class);
+ return err;
+}
+
+static void __exit osd_uld_exit(void)
+{
+ scsi_unregister_driver(&osd_driver.gendrv);
+ unregister_chrdev_region(MKDEV(SCSI_OSD_MAJOR, 0), SCSI_OSD_MAX_MINOR);
+ class_destroy(osd_sysfs_class);
+ OSD_INFO("UNLOADED %s\n", osd_version_string);
+}
+
+module_init(osd_uld_init);
+module_exit(osd_uld_exit);
diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c
index 0ea78d9a37d..acb835837ee 100644
--- a/drivers/scsi/osst.c
+++ b/drivers/scsi/osst.c
@@ -280,8 +280,8 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
static int notyetprinted = 1;
printk(KERN_WARNING
- "%s:W: Warning %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
- name, result, suggestion(result), driver_byte(result) & DRIVER_MASK,
+ "%s:W: Warning %x (driver bt 0x%x, host bt 0x%x).\n",
+ name, result, driver_byte(result),
host_byte(result));
if (notyetprinted) {
notyetprinted = 0;
@@ -317,18 +317,25 @@ static int osst_chk_result(struct osst_tape * STp, struct osst_request * SRpnt)
/* Wakeup from interrupt */
-static void osst_sleep_done(void *data, char *sense, int result, int resid)
+static void osst_end_async(struct request *req, int update)
{
- struct osst_request *SRpnt = data;
+ struct osst_request *SRpnt = req->end_io_data;
struct osst_tape *STp = SRpnt->stp;
+ struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
- memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE);
- STp->buffer->cmdstat.midlevel_result = SRpnt->result = result;
+ STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors;
#if DEBUG
STp->write_pending = 0;
#endif
if (SRpnt->waiting)
complete(SRpnt->waiting);
+
+ if (SRpnt->bio) {
+ kfree(mdata->pages);
+ blk_rq_unmap_user(SRpnt->bio);
+ }
+
+ __blk_put_request(req->q, req);
}
/* osst_request memory management */
@@ -342,6 +349,74 @@ static void osst_release_request(struct osst_request *streq)
kfree(streq);
}
+static int osst_execute(struct osst_request *SRpnt, const unsigned char *cmd,
+ int cmd_len, int data_direction, void *buffer, unsigned bufflen,
+ int use_sg, int timeout, int retries)
+{
+ struct request *req;
+ struct page **pages = NULL;
+ struct rq_map_data *mdata = &SRpnt->stp->buffer->map_data;
+
+ int err = 0;
+ int write = (data_direction == DMA_TO_DEVICE);
+
+ req = blk_get_request(SRpnt->stp->device->request_queue, write, GFP_KERNEL);
+ if (!req)
+ return DRIVER_ERROR << 24;
+
+ req->cmd_type = REQ_TYPE_BLOCK_PC;
+ req->cmd_flags |= REQ_QUIET;
+
+ SRpnt->bio = NULL;
+
+ if (use_sg) {
+ struct scatterlist *sg, *sgl = (struct scatterlist *)buffer;
+ int i;
+
+ pages = kzalloc(use_sg * sizeof(struct page *), GFP_KERNEL);
+ if (!pages)
+ goto free_req;
+
+ for_each_sg(sgl, sg, use_sg, i)
+ pages[i] = sg_page(sg);
+
+ mdata->null_mapped = 1;
+
+ mdata->page_order = get_order(sgl[0].length);
+ mdata->nr_entries =
+ DIV_ROUND_UP(bufflen, PAGE_SIZE << mdata->page_order);
+ mdata->offset = 0;
+
+ err = blk_rq_map_user(req->q, req, mdata, NULL, bufflen, GFP_KERNEL);
+ if (err) {
+ kfree(pages);
+ goto free_req;
+ }
+ SRpnt->bio = req->bio;
+ mdata->pages = pages;
+
+ } else if (bufflen) {
+ err = blk_rq_map_kern(req->q, req, buffer, bufflen, GFP_KERNEL);
+ if (err)
+ goto free_req;
+ }
+
+ req->cmd_len = cmd_len;
+ memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
+ memcpy(req->cmd, cmd, req->cmd_len);
+ req->sense = SRpnt->sense;
+ req->sense_len = 0;
+ req->timeout = timeout;
+ req->retries = retries;
+ req->end_io_data = SRpnt;
+
+ blk_execute_rq_nowait(req->q, NULL, req, 1, osst_end_async);
+ return 0;
+free_req:
+ blk_put_request(req);
+ return DRIVER_ERROR << 24;
+}
+
/* Do the scsi command. Waits until command performed if do_wait is true.
Otherwise osst_write_behind_check() is used to check that the command
has finished. */
@@ -403,8 +478,8 @@ static struct osst_request * osst_do_scsi(struct osst_request *SRpnt, struct oss
STp->buffer->cmdstat.have_sense = 0;
STp->buffer->syscall_result = 0;
- if (scsi_execute_async(STp->device, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
- use_sg, timeout, retries, SRpnt, osst_sleep_done, GFP_KERNEL))
+ if (osst_execute(SRpnt, cmd, COMMAND_SIZE(cmd[0]), direction, bp, bytes,
+ use_sg, timeout, retries))
/* could not allocate the buffer or request was too large */
(STp->buffer)->syscall_result = (-EBUSY);
else if (do_wait) {
@@ -5286,11 +5361,6 @@ static int enlarge_buffer(struct osst_buffer *STbuffer, int need_dma)
struct page *page = alloc_pages(priority, (OS_FRAME_SIZE - got <= PAGE_SIZE) ? 0 : order);
STbuffer->sg[segs].offset = 0;
if (page == NULL) {
- if (OS_FRAME_SIZE - got <= (max_segs - segs) * b_size / 2 && order) {
- b_size /= 2; /* Large enough for the rest of the buffers */
- order--;
- continue;
- }
printk(KERN_WARNING "osst :W: Failed to enlarge buffer to %d bytes.\n",
OS_FRAME_SIZE);
#if DEBUG
diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h
index 5aa22740b5d..11d26c57f3f 100644
--- a/drivers/scsi/osst.h
+++ b/drivers/scsi/osst.h
@@ -520,6 +520,7 @@ struct osst_buffer {
int syscall_result;
struct osst_request *last_SRpnt;
struct st_cmdstatus cmdstat;
+ struct rq_map_data map_data;
unsigned char *b_data;
os_aux_t *aux; /* onstream AUX structure at end of each block */
unsigned short use_sg; /* zero or number of s/g segments for this adapter */
@@ -634,6 +635,7 @@ struct osst_request {
int result;
struct osst_tape *stp;
struct completion *waiting;
+ struct bio *bio;
};
/* Values of write_type */
diff --git a/drivers/scsi/ql1040_fw.h b/drivers/scsi/ql1040_fw.h
deleted file mode 100644
index aaf9284a8b7..00000000000
--- a/drivers/scsi/ql1040_fw.h
+++ /dev/null
@@ -1,2130 +0,0 @@
-/**************************************************************************
- * QLOGIC LINUX SOFTWARE
- *
- * Copyright (C) 2004 QLogic Corporation
- * (www.qlogic.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- *************************************************************************/
-
-/************************************************************************
- * *
- * --- ISP1040 Initiator/Target Firmware --- *
- * 32 LUN Support *
- * *
- ************************************************************************
- */
-
-/*
- * Firmware Version 7.65.06 (14:38 Jan 07, 2002)
- */
-
-static unsigned char firmware_version[] = {7,65,6};
-
-#define FW_VERSION_STRING "7.65.06"
-
-static unsigned short risc_code_addr01 = 0x1000 ;
-
-static unsigned short risc_code01[] = {
- 0x0078, 0x103a, 0x0000, 0x4158, 0x0000, 0x2043, 0x4f50, 0x5952,
- 0x4947, 0x4854, 0x2031, 0x3939, 0x3520, 0x514c, 0x4f47, 0x4943,
- 0x2043, 0x4f52, 0x504f, 0x5241, 0x5449, 0x4f4e, 0x2049, 0x5350,
- 0x3130, 0x3230, 0x2049, 0x2f54, 0x2046, 0x6972, 0x6d77, 0x6172,
- 0x6520, 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x372e, 0x3635,
- 0x2020, 0x2043, 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20,
- 0x3030, 0x2050, 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020,
- 0x3031, 0x2024, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x0048,
- 0x1045, 0x0038, 0x104b, 0x0078, 0x1047, 0x0028, 0x104b, 0x20b9,
- 0x1212, 0x0078, 0x104d, 0x20b9, 0x2222, 0x20c1, 0x0008, 0x2071,
- 0x0010, 0x70c3, 0x0004, 0x20c9, 0x78ff, 0x2089, 0x1186, 0x70c7,
- 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0007, 0x3f00,
- 0x70d6, 0x20c1, 0x0008, 0x2019, 0x0000, 0x2009, 0xfeff, 0x2100,
- 0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64, 0x206b, 0x0a0a, 0xaddc,
- 0x3fff, 0x2b54, 0x205b, 0x5050, 0x2114, 0xa286, 0xa5a5, 0x0040,
- 0x10bf, 0xa386, 0x000f, 0x0040, 0x1085, 0x2c6a, 0x2a5a, 0x20c1,
- 0x0000, 0x2019, 0x000f, 0x0078, 0x1065, 0x2c6a, 0x2a5a, 0x20c1,
- 0x0008, 0x2009, 0x7fff, 0x2148, 0x2944, 0x204b, 0x0a0a, 0xa9bc,
- 0x3fff, 0x2734, 0x203b, 0x5050, 0x2114, 0xa286, 0x0a0a, 0x0040,
- 0x10a9, 0x284a, 0x263a, 0x20c1, 0x0004, 0x2009, 0x3fff, 0x2134,
- 0x200b, 0x5050, 0x2114, 0xa286, 0x5050, 0x0040, 0x10aa, 0x0078,
- 0x118e, 0x284a, 0x263a, 0x98c0, 0xa188, 0x1000, 0x212c, 0x200b,
- 0xa5a5, 0x2114, 0xa286, 0xa5a5, 0x0040, 0x10bc, 0x250a, 0xa18a,
- 0x1000, 0x98c1, 0x0078, 0x10c1, 0x250a, 0x0078, 0x10c1, 0x2c6a,
- 0x2a5a, 0x2130, 0xa18a, 0x0040, 0x2128, 0xa1a2, 0x5200, 0x8424,
- 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0xa192, 0x7900, 0x2009,
- 0x0000, 0x2001, 0x0031, 0x1078, 0x1d26, 0x2218, 0x2079, 0x5200,
- 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109,
- 0x00c0, 0x10dc, 0x7ef2, 0x8528, 0x7de6, 0x7cea, 0x7bee, 0x7883,
- 0x0000, 0x2031, 0x0030, 0x78cf, 0x0101, 0x780b, 0x0002, 0x780f,
- 0x0002, 0x784f, 0x0003, 0x2069, 0x5240, 0x2001, 0x04fd, 0x2004,
- 0xa082, 0x0005, 0x0048, 0x1104, 0x0038, 0x1100, 0x0078, 0x1108,
- 0x681b, 0x003c, 0x0078, 0x110a, 0x00a8, 0x1108, 0x681b, 0x003c,
- 0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa, 0x680f, 0x0008,
- 0x6813, 0x0005, 0x6823, 0x0000, 0x6827, 0x0006, 0x6817, 0x0008,
- 0x682b, 0x0000, 0x681f, 0x0019, 0x2069, 0x5480, 0x2011, 0x0020,
- 0x2009, 0x0010, 0x680b, 0x080c, 0x680f, 0x0019, 0x6803, 0xfd00,
- 0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
- 0x8109, 0x00c0, 0x1122, 0x2069, 0x5500, 0x2009, 0x0002, 0x20a9,
- 0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bf0, 0xa386, 0xfeff,
- 0x00c0, 0x1148, 0x6817, 0x0100, 0x681f, 0x0064, 0x0078, 0x114c,
- 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010, 0x0070, 0x1152,
- 0x0078, 0x1139, 0x8109, 0x00c0, 0x1137, 0x1078, 0x22a7, 0x1078,
- 0x493d, 0x1078, 0x19b5, 0x1078, 0x4e33, 0x3200, 0xa085, 0x000d,
- 0x2090, 0x70c3, 0x0000, 0x0090, 0x116c, 0x70c0, 0xa086, 0x0002,
- 0x00c0, 0x116c, 0x1078, 0x1284, 0x1078, 0x1196, 0x78cc, 0xa005,
- 0x00c0, 0x117a, 0x1078, 0x1d4f, 0x0010, 0x1180, 0x0068, 0x1180,
- 0x1078, 0x2186, 0x0010, 0x1180, 0x0068, 0x1180, 0x1078, 0x1ab9,
- 0x00e0, 0x116c, 0x1078, 0x4cba, 0x0078, 0x116c, 0x118e, 0x1190,
- 0x24ac, 0x24ac, 0x49be, 0x49be, 0x24ac, 0x24ac, 0x0078, 0x118e,
- 0x0078, 0x1190, 0x0078, 0x1192, 0x0078, 0x1194, 0x0068, 0x1201,
- 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1201, 0x7814,
- 0xa005, 0x00c0, 0x11a7, 0x0010, 0x1202, 0x0078, 0x1201, 0x2009,
- 0x525b, 0x2104, 0xa005, 0x00c0, 0x1201, 0x2009, 0x5264, 0x200b,
- 0x0000, 0x7914, 0xa186, 0x0042, 0x00c0, 0x11cc, 0x7816, 0x2009,
- 0x5262, 0x2164, 0x200b, 0x0000, 0x6018, 0x70c6, 0x6014, 0x70ca,
- 0x611c, 0xa18c, 0xff00, 0x6020, 0xa084, 0x00ff, 0xa105, 0x70ce,
- 0x1078, 0x199a, 0x0078, 0x11ff, 0x7814, 0xa086, 0x0018, 0x00c0,
- 0x11d3, 0x1078, 0x1678, 0x7817, 0x0000, 0x2009, 0x5262, 0x2104,
- 0xa065, 0x0040, 0x11ef, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17,
- 0x0c7f, 0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6007,
- 0x0103, 0x1078, 0x1976, 0x00c0, 0x11fb, 0x1078, 0x199a, 0x2009,
- 0x5262, 0x200b, 0x0000, 0x2009, 0x525c, 0x2104, 0x200b, 0x0000,
- 0xa005, 0x0040, 0x11ff, 0x2001, 0x4005, 0x0078, 0x1286, 0x0078,
- 0x1284, 0x007c, 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000,
- 0x70cf, 0x0000, 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1252, 0x2038,
- 0x0079, 0x1212, 0x1284, 0x12e5, 0x12a9, 0x12fe, 0x130d, 0x1313,
- 0x12a0, 0x1766, 0x1317, 0x1298, 0x12ad, 0x12af, 0x12b1, 0x12b3,
- 0x176b, 0x1298, 0x1329, 0x1365, 0x1690, 0x1760, 0x12b5, 0x15af,
- 0x15cb, 0x15e7, 0x1612, 0x1568, 0x1576, 0x158a, 0x159e, 0x13e9,
- 0x1298, 0x1397, 0x139d, 0x13a2, 0x13a7, 0x13ad, 0x13b2, 0x13b7,
- 0x13bc, 0x13c1, 0x13c5, 0x13da, 0x13e6, 0x1298, 0x1298, 0x1298,
- 0x1298, 0x13f5, 0x13fe, 0x140d, 0x1451, 0x145b, 0x1462, 0x14a8,
- 0x14b7, 0x14c6, 0x14d8, 0x1548, 0x1558, 0x1298, 0x1298, 0x1298,
- 0x1298, 0x155d, 0xa0bc, 0xffa0, 0x00c0, 0x1298, 0x2038, 0xa084,
- 0x001f, 0x0079, 0x125b, 0x17a4, 0x17a7, 0x17b7, 0x1298, 0x1298,
- 0x1931, 0x194e, 0x1298, 0x1298, 0x1298, 0x1952, 0x195a, 0x1298,
- 0x1298, 0x1298, 0x1298, 0x12db, 0x12f4, 0x131f, 0x135b, 0x1686,
- 0x1782, 0x1796, 0x1298, 0x1847, 0x1960, 0x190d, 0x1917, 0x191b,
- 0x1929, 0x1298, 0x1298, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078,
- 0x1286, 0x73ce, 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068,
- 0x1287, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x00e0,
- 0x128f, 0x00e0, 0x1291, 0x0068, 0x1291, 0x2091, 0x4080, 0x007c,
- 0x70c3, 0x4001, 0x0078, 0x1287, 0x70c3, 0x4006, 0x0078, 0x1287,
- 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078,
- 0x1284, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x1284, 0x0078,
- 0x1284, 0x0078, 0x1284, 0x0078, 0x1284, 0x2091, 0x8000, 0x70c3,
- 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
- 0x0007, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031,
- 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051, 0x0470, 0x2061,
- 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091, 0x5000, 0x2091,
- 0x4080, 0x0078, 0x0455, 0x1078, 0x1bc4, 0x00c0, 0x129c, 0x75d8,
- 0x74dc, 0x75da, 0x74de, 0x0078, 0x12e8, 0x2029, 0x0000, 0x2520,
- 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1afe, 0x0040, 0x1284,
- 0x70c3, 0x4002, 0x0078, 0x1284, 0x1078, 0x1bc4, 0x00c0, 0x129c,
- 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1301, 0x2029, 0x0000,
- 0x2520, 0x71d0, 0x73c8, 0x72cc, 0x70c4, 0x1078, 0x1b5e, 0x0040,
- 0x1284, 0x70c3, 0x4002, 0x0078, 0x1284, 0x71c4, 0x70c8, 0x2114,
- 0x200a, 0x0078, 0x1282, 0x71c4, 0x2114, 0x0078, 0x1282, 0x70c7,
- 0x0007, 0x70cb, 0x0041, 0x70cf, 0x0006, 0x0078, 0x1284, 0x1078,
- 0x1bc4, 0x00c0, 0x129c, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078,
- 0x132c, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0,
- 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x1355, 0xa40a,
- 0x0040, 0x133c, 0x00c8, 0x1346, 0x8001, 0x7892, 0xa084, 0xfc00,
- 0x0040, 0x134a, 0x78cc, 0xa085, 0x0001, 0x78ce, 0x2001, 0x4005,
- 0x0078, 0x1286, 0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x7c96, 0x78cc,
- 0xa084, 0xfffc, 0x78ce, 0x0078, 0x1359, 0x78cc, 0xa085, 0x0001,
- 0x78ce, 0x0078, 0x1284, 0x1078, 0x1bc4, 0x00c0, 0x129c, 0x75d8,
- 0x76dc, 0x75da, 0x76de, 0x0078, 0x1368, 0x2029, 0x0000, 0x2530,
- 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6,
- 0xa005, 0x0040, 0x1391, 0xa40a, 0x0040, 0x1378, 0x00c8, 0x1382,
- 0x8001, 0x78ae, 0xa084, 0xfc00, 0x0040, 0x1386, 0x78cc, 0xa085,
- 0x0100, 0x78ce, 0x2001, 0x4005, 0x0078, 0x1286, 0x7ab6, 0x7bba,
- 0x7dbe, 0x7ec2, 0x7cb2, 0x78cc, 0xa084, 0xfcff, 0x78ce, 0x0078,
- 0x1395, 0x78cc, 0xa085, 0x0100, 0x78ce, 0x0078, 0x1284, 0x2009,
- 0x5261, 0x210c, 0x7aec, 0x0078, 0x1282, 0x2009, 0x5241, 0x210c,
- 0x0078, 0x1283, 0x2009, 0x5242, 0x210c, 0x0078, 0x1283, 0x2061,
- 0x5240, 0x610c, 0x6210, 0x0078, 0x1282, 0x2009, 0x5245, 0x210c,
- 0x0078, 0x1283, 0x2009, 0x5246, 0x210c, 0x0078, 0x1283, 0x2009,
- 0x5248, 0x210c, 0x0078, 0x1283, 0x2009, 0x5249, 0x210c, 0x0078,
- 0x1283, 0x7908, 0x7a0c, 0x0078, 0x1282, 0x71c4, 0x8107, 0xa084,
- 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x5480, 0x6a00, 0x6804,
- 0xa084, 0x0008, 0x0040, 0x13d7, 0x6b08, 0x0078, 0x13d8, 0x6b0c,
- 0x0078, 0x1281, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6b1c,
- 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x1281, 0x794c, 0x0078,
- 0x1283, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6908, 0x6a18,
- 0x6b10, 0x2091, 0x8001, 0x0078, 0x1281, 0x71c4, 0xa182, 0x0010,
- 0x00c8, 0x127c, 0x1078, 0x237f, 0x0078, 0x1281, 0x71c4, 0xa182,
- 0x0010, 0x00c8, 0x127c, 0x2011, 0x5241, 0x2204, 0x007e, 0x2112,
- 0x1078, 0x2338, 0x017f, 0x0078, 0x1283, 0x71c4, 0x2019, 0x0100,
- 0x2304, 0xa082, 0x0006, 0x0048, 0x141b, 0x2011, 0x1449, 0x20a9,
- 0x0008, 0x0078, 0x141f, 0x2011, 0x1441, 0x20a9, 0x0008, 0x2204,
- 0xa106, 0x0040, 0x142a, 0x8210, 0x0070, 0x1428, 0x0078, 0x141f,
- 0x0078, 0x127c, 0x2304, 0xa082, 0x0006, 0x0048, 0x1433, 0xa292,
- 0x1449, 0x0078, 0x1435, 0xa292, 0x1441, 0x027e, 0x2011, 0x5242,
- 0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x2344, 0x017f, 0x0078,
- 0x1283, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032,
- 0x004b, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0004, 0x0001, 0x0002,
- 0x0003, 0x2061, 0x5240, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8,
- 0x6012, 0x0078, 0x1282, 0x2061, 0x5240, 0x6114, 0x70c4, 0x6016,
- 0x0078, 0x1283, 0x2061, 0x5240, 0x71c4, 0x2011, 0x0004, 0x601f,
- 0x0019, 0x2019, 0x1212, 0xa186, 0x0028, 0x0040, 0x1483, 0x2011,
- 0x0005, 0x601f, 0x0019, 0x2019, 0x1212, 0xa186, 0x0032, 0x0040,
- 0x1483, 0x2011, 0x0006, 0x601f, 0x000c, 0x2019, 0x2222, 0xa186,
- 0x003c, 0x00c0, 0x127c, 0x6018, 0x007e, 0x611a, 0x7800, 0xa084,
- 0x0001, 0x00c0, 0x149e, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
- 0x0048, 0x1496, 0x0038, 0x149a, 0x0078, 0x149e, 0x0028, 0x149a,
- 0x0078, 0x149e, 0x2019, 0x2222, 0x0078, 0x14a0, 0x2019, 0x1212,
- 0x23b8, 0x1078, 0x2355, 0x1078, 0x4e33, 0x017f, 0x0078, 0x1283,
- 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x127c, 0x2011, 0x5248, 0x2204,
- 0x2112, 0x007e, 0x1078, 0x2377, 0x017f, 0x0078, 0x1283, 0x71c4,
- 0xa182, 0x0010, 0x00c8, 0x127c, 0x2011, 0x5249, 0x2204, 0x007e,
- 0x2112, 0x1078, 0x2366, 0x017f, 0x0078, 0x1283, 0x71c4, 0x72c8,
- 0xa184, 0xfffd, 0x00c0, 0x127b, 0xa284, 0xfffd, 0x00c0, 0x127b,
- 0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x1282,
- 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
- 0x5480, 0x2019, 0x0000, 0x72c8, 0xd2bc, 0x0040, 0x14e9, 0xa39d,
- 0x0010, 0xd2b4, 0x0040, 0x14ee, 0xa39d, 0x0008, 0x6800, 0x007e,
- 0xa226, 0x0040, 0x1511, 0x6a02, 0xa484, 0x2000, 0x0040, 0x14fa,
- 0xa39d, 0x0010, 0xa484, 0x1000, 0x0040, 0x1500, 0xa39d, 0x0008,
- 0xa484, 0x4000, 0x0040, 0x1511, 0x810f, 0xa284, 0x4000, 0x0040,
- 0x150d, 0x1078, 0x2399, 0x0078, 0x1511, 0x1078, 0x238b, 0x0078,
- 0x1511, 0x72cc, 0x6808, 0xa206, 0x0040, 0x1540, 0xa2a4, 0x00ff,
- 0x2061, 0x5240, 0x6118, 0xa186, 0x0028, 0x0040, 0x1527, 0xa186,
- 0x0032, 0x0040, 0x152d, 0xa186, 0x003c, 0x0040, 0x1533, 0xa482,
- 0x0064, 0x0048, 0x153d, 0x0078, 0x1537, 0xa482, 0x0050, 0x0048,
- 0x153d, 0x0078, 0x1537, 0xa482, 0x0043, 0x0048, 0x153d, 0x71c4,
- 0x71c6, 0x027f, 0x72ca, 0x0078, 0x127d, 0x6a0a, 0xa39d, 0x000a,
- 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078, 0x1281,
- 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a14, 0x6b1c, 0x2091,
- 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078, 0x1281,
- 0x70c4, 0x794c, 0x784e, 0x0078, 0x1283, 0x71c4, 0x72c8, 0x73cc,
- 0xa182, 0x0010, 0x00c8, 0x127c, 0x1078, 0x23a7, 0x0078, 0x1281,
- 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0002,
- 0x6a0a, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x1078,
- 0x19c5, 0x2091, 0x8000, 0x6a08, 0xa294, 0xfff9, 0x6a0a, 0x6804,
- 0xa005, 0x0040, 0x1585, 0x1078, 0x226f, 0x2091, 0x8001, 0x2708,
- 0x0078, 0x1282, 0x77c4, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6a08,
- 0xa295, 0x0004, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1599, 0x1078,
- 0x226f, 0x2091, 0x8001, 0x2708, 0x0078, 0x1282, 0x77c4, 0x2041,
- 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
- 0x19d2, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0078, 0x1282, 0x77c4,
- 0x72c8, 0x73cc, 0x77c6, 0x72ca, 0x73ce, 0x1078, 0x1a52, 0x00c0,
- 0x15c7, 0x6818, 0xa005, 0x0040, 0x15c7, 0x2708, 0x1078, 0x23b7,
- 0x00c0, 0x15c7, 0x7817, 0x0015, 0x2091, 0x8001, 0x007c, 0x2091,
- 0x8001, 0x0078, 0x1284, 0x77c4, 0x77c6, 0x2041, 0x0021, 0x2049,
- 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078, 0x19d2, 0x2061,
- 0x5240, 0x606f, 0x0003, 0x6782, 0x6093, 0x000f, 0x6073, 0x0000,
- 0x7817, 0x0016, 0x1078, 0x226f, 0x2091, 0x8001, 0x007c, 0x77c8,
- 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2061,
- 0x5240, 0x606f, 0x0002, 0x6073, 0x0000, 0x6782, 0x6093, 0x000f,
- 0x7817, 0x0017, 0x1078, 0x226f, 0x2091, 0x8001, 0x2041, 0x0021,
- 0x2049, 0x0004, 0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x19d2,
- 0x70c8, 0x6836, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1606, 0x2091,
- 0x8001, 0x007c, 0x78cc, 0xa084, 0x0003, 0x00c0, 0x1636, 0x2039,
- 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078,
- 0x19c5, 0x2091, 0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001,
- 0x8738, 0xa784, 0x001f, 0x00c0, 0x161f, 0xa7bc, 0xff00, 0x873f,
- 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x161f, 0x2091, 0x8000,
- 0x2069, 0x0100, 0x6830, 0xa084, 0x0040, 0x0040, 0x165f, 0x684b,
- 0x0004, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x164c,
- 0x0070, 0x164c, 0x0078, 0x1643, 0x684b, 0x0009, 0x20a9, 0x0014,
- 0x6848, 0xa084, 0x0001, 0x0040, 0x1659, 0x0070, 0x1659, 0x0078,
- 0x1650, 0x20a9, 0x00fa, 0x0070, 0x165f, 0x0078, 0x165b, 0x2079,
- 0x5200, 0x7817, 0x0018, 0x2061, 0x5240, 0x606f, 0x0001, 0x6073,
- 0x0000, 0x6093, 0x000f, 0x78cc, 0xa085, 0x0002, 0x78ce, 0x6808,
- 0xa084, 0xfffd, 0x680a, 0x681b, 0x0048, 0x2091, 0x8001, 0x007c,
- 0x78cc, 0xa084, 0xfffd, 0x78ce, 0xa084, 0x0001, 0x00c0, 0x1682,
- 0x1078, 0x1a9c, 0x71c4, 0x71c6, 0x794a, 0x007c, 0x1078, 0x1bc4,
- 0x00c0, 0x129c, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1693,
- 0x2029, 0x0000, 0x2520, 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca,
- 0x72ce, 0x2079, 0x5200, 0x2091, 0x8000, 0x1078, 0x1980, 0x2091,
- 0x8001, 0x0040, 0x174a, 0x20a9, 0x0005, 0x20a1, 0x5218, 0x2091,
- 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0020, 0x1078, 0x197b,
- 0x0040, 0x16b6, 0x1078, 0x199a, 0x0078, 0x174a, 0x6004, 0xa084,
- 0xff00, 0x8007, 0x8009, 0x0040, 0x1719, 0x0c7e, 0x2c68, 0x2091,
- 0x8000, 0x1078, 0x1980, 0x2091, 0x8001, 0x0040, 0x16ea, 0x2c00,
- 0x689e, 0x8109, 0x00c0, 0x16be, 0x609f, 0x0000, 0x0c7f, 0x0c7e,
- 0x7218, 0x731c, 0x7420, 0x7524, 0x2c68, 0x689c, 0xa065, 0x0040,
- 0x1718, 0x2009, 0x0020, 0x1078, 0x197b, 0x00c0, 0x1701, 0x6004,
- 0xa084, 0x00ff, 0xa086, 0x0002, 0x00c0, 0x16ea, 0x2d00, 0x6002,
- 0x0078, 0x16d0, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17,
- 0x0c7f, 0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6008,
- 0xa085, 0x0200, 0x600a, 0x1078, 0x1976, 0x1078, 0x199a, 0x0078,
- 0x174a, 0x0c7f, 0x0c7e, 0x609c, 0x2060, 0x1078, 0x1a17, 0x0c7f,
- 0x609f, 0x0000, 0x1078, 0x174e, 0x2009, 0x000c, 0x6007, 0x0103,
- 0x601b, 0x0003, 0x1078, 0x1976, 0x1078, 0x199a, 0x0078, 0x174a,
- 0x0c7f, 0x74c4, 0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x7817,
- 0x0012, 0x0e7e, 0x2071, 0x5240, 0x706f, 0x0005, 0x7073, 0x0000,
- 0x7376, 0x727a, 0x747e, 0x7082, 0x7087, 0x0000, 0x2c00, 0x708a,
- 0x708f, 0x0000, 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0x0060,
- 0x0040, 0x173c, 0x1078, 0x48d3, 0x0e7f, 0x6596, 0x65a6, 0x669a,
- 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x1078, 0x226f, 0x2091,
- 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287, 0x20a9, 0x0005,
- 0x2099, 0x5218, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100,
- 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c,
- 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x1284, 0x71c4, 0x71c6,
- 0x2168, 0x0078, 0x176d, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04,
- 0xa210, 0x8d68, 0x8109, 0x00c0, 0x176f, 0xa285, 0x0000, 0x00c0,
- 0x177d, 0x70c3, 0x4000, 0x0078, 0x177f, 0x70c3, 0x4003, 0x70ca,
- 0x0078, 0x1287, 0x2011, 0x5267, 0x220c, 0x70c4, 0x8003, 0x0048,
- 0x178f, 0x1078, 0x3c51, 0xa184, 0x7fff, 0x0078, 0x1793, 0x1078,
- 0x3c44, 0xa185, 0x8000, 0x2012, 0x0078, 0x1283, 0x71c4, 0x1078,
- 0x3c3b, 0x6100, 0x2001, 0x5267, 0x2004, 0xa084, 0x8000, 0xa10d,
- 0x6204, 0x6308, 0x0078, 0x1281, 0x79e4, 0x0078, 0x1283, 0x71c4,
- 0x71c6, 0x2198, 0x20a1, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x21a0,
- 0x2099, 0x0042, 0x20a9, 0x0004, 0x53a3, 0x0078, 0x1284, 0x70c4,
- 0x2068, 0x2079, 0x5200, 0x2091, 0x8000, 0x1078, 0x1980, 0x2091,
- 0x8001, 0x0040, 0x1843, 0x6007, 0x0001, 0x600b, 0x0000, 0x602b,
- 0x0000, 0x601b, 0x0006, 0x6a10, 0xa28c, 0x000f, 0xa284, 0x00f0,
- 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x6016, 0xa284, 0x0800,
- 0x0040, 0x17de, 0x601b, 0x000a, 0x0078, 0x17e4, 0xa284, 0x1000,
- 0x0040, 0x17e4, 0x601b, 0x000c, 0xa284, 0x0300, 0x0040, 0x17ed,
- 0x602b, 0x0001, 0x8004, 0x8004, 0x8004, 0xa085, 0x0001, 0x601e,
- 0x6023, 0x0000, 0x6027, 0x0000, 0xa284, 0x0400, 0x0040, 0x17fa,
- 0x602b, 0x0000, 0x20a9, 0x0006, 0xac80, 0x000b, 0x20a0, 0xad80,
- 0x0005, 0x2098, 0x53a3, 0xa284, 0x0300, 0x00c0, 0x180f, 0x6046,
- 0x604a, 0x604e, 0x6052, 0x6096, 0x609a, 0x0078, 0x1819, 0x6800,
- 0x6046, 0x6804, 0x604a, 0x6e08, 0x664e, 0x6d0c, 0x6552, 0x6596,
- 0x669a, 0x6014, 0x2091, 0x8000, 0x7817, 0x0042, 0x2c08, 0x2061,
- 0x5240, 0x606f, 0x0005, 0x6073, 0x0000, 0x6077, 0x0000, 0x607b,
- 0x0000, 0x607f, 0x0000, 0x6082, 0x618a, 0xa284, 0x0400, 0x608e,
- 0x2091, 0x8001, 0x0e7e, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007,
- 0x0002, 0x7003, 0x0000, 0x0e7f, 0x2091, 0x8000, 0x1078, 0x226f,
- 0x2091, 0x8001, 0x007c, 0x70c3, 0x4005, 0x0078, 0x1287, 0x0c7e,
- 0x0d7e, 0x0e7e, 0x0f7e, 0x2091, 0x8000, 0x2071, 0x5240, 0x2079,
- 0x0100, 0x2061, 0x0010, 0x70a0, 0xa06d, 0x0040, 0x1903, 0x6a04,
- 0xa294, 0x00ff, 0xa286, 0x0007, 0x0040, 0x1862, 0xa286, 0x000f,
- 0x00c0, 0x1903, 0x691c, 0xa184, 0x00c0, 0x0040, 0x1903, 0xa184,
- 0x0080, 0x00c0, 0x18d3, 0x6824, 0xa084, 0xff00, 0xa085, 0x0019,
- 0x6826, 0x71b0, 0x81ff, 0x0040, 0x1889, 0x0d7e, 0x2069, 0x0020,
- 0x6807, 0x0010, 0x6908, 0x6808, 0xa106, 0x00c0, 0x187a, 0x690c,
- 0x680c, 0xa106, 0x00c0, 0x187f, 0xa184, 0x00ff, 0x00c0, 0x187f,
- 0x0d7f, 0x78b8, 0xa084, 0x801f, 0x00c0, 0x1889, 0x7848, 0xa085,
- 0x000c, 0x784a, 0x71b0, 0x81ff, 0x0040, 0x18ac, 0x70b3, 0x0000,
- 0x0d7e, 0x2069, 0x0020, 0x6807, 0x0018, 0x6804, 0xa084, 0x0008,
- 0x00c0, 0x189d, 0x6807, 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0,
- 0x18a4, 0x6807, 0x0002, 0x0d7f, 0x61c4, 0x62c8, 0x63cc, 0x61c6,
- 0x62ca, 0x63ce, 0x0e7e, 0x2071, 0x5200, 0x7266, 0x736a, 0xae80,
- 0x0019, 0x0e7f, 0x7848, 0xa084, 0x000c, 0x00c0, 0x18ba, 0x1078,
- 0x47e1, 0x78a3, 0x0000, 0x7858, 0xa084, 0xedff, 0x785a, 0x70b4,
- 0xa080, 0x00da, 0x781a, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091,
- 0x8001, 0x0078, 0x1284, 0x6824, 0xa084, 0xff00, 0xa085, 0x0019,
- 0x6826, 0x78b8, 0xa084, 0x801f, 0x00c0, 0x18d9, 0x7848, 0xa085,
- 0x000c, 0x784a, 0x7848, 0xa084, 0x000c, 0x00c0, 0x18e2, 0x71b0,
- 0x81ff, 0x0040, 0x1901, 0x70b3, 0x0000, 0x0d7e, 0x2069, 0x0020,
- 0x6807, 0x0018, 0x6804, 0xa084, 0x0008, 0x00c0, 0x18f2, 0x6807,
- 0x0008, 0x6804, 0xa084, 0x0008, 0x00c0, 0x18f9, 0x6807, 0x0002,
- 0x0d7f, 0x0078, 0x18cb, 0x0f7f, 0x0e7f, 0x0d7f, 0x0c7f, 0x2091,
- 0x8001, 0x2001, 0x4005, 0x0078, 0x1286, 0x7980, 0x71c6, 0x71c4,
- 0xa182, 0x0003, 0x00c8, 0x127c, 0x7982, 0x0078, 0x1284, 0x7980,
- 0x71c6, 0x0078, 0x1284, 0x7974, 0x71c6, 0x71c4, 0x7976, 0x7978,
- 0x71ca, 0x71c8, 0x797a, 0x797c, 0x71ce, 0x71cc, 0x797e, 0x0078,
- 0x1284, 0x7974, 0x71c6, 0x7978, 0x71ca, 0x797c, 0x71ce, 0x0078,
- 0x1284, 0x7900, 0x71c6, 0x71c4, 0x7902, 0x2001, 0x04fd, 0x2004,
- 0xa082, 0x0005, 0x0048, 0x1940, 0x0038, 0x1942, 0x0078, 0x194c,
- 0x00a8, 0x194c, 0xa18c, 0x0001, 0x00c0, 0x194a, 0x20b9, 0x2222,
- 0x0078, 0x194c, 0x20b9, 0x1212, 0x0078, 0x1284, 0x7900, 0x71c6,
- 0x0078, 0x1284, 0x2009, 0x5274, 0x2104, 0x70c6, 0x70c4, 0x200a,
- 0x0078, 0x1284, 0x2009, 0x5274, 0x2104, 0x70c6, 0x0078, 0x1284,
- 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
- 0x5480, 0x6a14, 0xd2b4, 0x0040, 0x1971, 0x2011, 0x0001, 0x0078,
- 0x1973, 0x2011, 0x0000, 0x6b0c, 0x0078, 0x1281, 0xac80, 0x0001,
- 0x1078, 0x1b80, 0x007c, 0xac80, 0x0001, 0x1078, 0x1b20, 0x007c,
- 0x7850, 0xa065, 0x0040, 0x1988, 0x2c04, 0x7852, 0x2063, 0x0000,
- 0x007c, 0x0f7e, 0x2079, 0x5200, 0x7850, 0xa06d, 0x0040, 0x1998,
- 0x2d04, 0x7852, 0x6803, 0x0000, 0x6807, 0x0000, 0x680b, 0x0000,
- 0x0f7f, 0x007c, 0x2091, 0x8000, 0x0f7e, 0x2079, 0x5200, 0x7850,
- 0x2062, 0x2c00, 0xa005, 0x00c0, 0x19a7, 0x1078, 0x248c, 0x7852,
- 0x0f7f, 0x2091, 0x8001, 0x007c, 0x0f7e, 0x2079, 0x5200, 0x7850,
- 0x206a, 0x2d00, 0x7852, 0x0f7f, 0x007c, 0x2011, 0x7900, 0x7a52,
- 0x7bec, 0x8319, 0x0040, 0x19c2, 0xa280, 0x0031, 0x2012, 0x2010,
- 0x0078, 0x19b9, 0x2013, 0x0000, 0x007c, 0xa784, 0x0f00, 0x800b,
- 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8,
- 0x5500, 0x007c, 0x1078, 0x19c5, 0x2900, 0x682a, 0x2a00, 0x682e,
- 0x6808, 0xa084, 0xffef, 0xa80d, 0x690a, 0x2009, 0x5252, 0x210c,
- 0x6804, 0xa005, 0x0040, 0x1a04, 0xa116, 0x00c0, 0x19ef, 0x2060,
- 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x19f2, 0x2009,
- 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1a01, 0x6000, 0x6806,
- 0x1078, 0x1a31, 0x1078, 0x1ccb, 0x6810, 0x8001, 0x6812, 0x00c0,
- 0x19f2, 0x017f, 0x6902, 0x6906, 0x007c, 0xa065, 0x0040, 0x1a16,
- 0x2008, 0x609c, 0xa005, 0x0040, 0x1a13, 0x2062, 0x609f, 0x0000,
- 0xa065, 0x0078, 0x1a09, 0x7850, 0x7952, 0x2062, 0x007c, 0xa065,
- 0x0040, 0x1a30, 0x2008, 0x609c, 0xa005, 0x0040, 0x1a25, 0x2062,
- 0x609f, 0x0000, 0xa065, 0x0078, 0x1a1b, 0x0f7e, 0x2079, 0x5200,
- 0x2091, 0x8000, 0x7850, 0x7952, 0x0f7f, 0x2062, 0x2091, 0x8001,
- 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c, 0xac80,
- 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a, 0x682c,
- 0x6022, 0x007c, 0x0e7e, 0x2071, 0x5240, 0x704c, 0xa08c, 0x0200,
- 0x00c0, 0x1a50, 0xa088, 0x5280, 0x2d0a, 0x8000, 0x704e, 0xa006,
- 0x0e7f, 0x007c, 0x1078, 0x19c5, 0x2091, 0x8000, 0x6804, 0x781e,
- 0xa065, 0x0040, 0x1a9b, 0x0078, 0x1a63, 0x2c00, 0x781e, 0x6000,
- 0xa065, 0x0040, 0x1a9b, 0x600c, 0xa306, 0x00c0, 0x1a5d, 0x6010,
- 0xa206, 0x00c0, 0x1a5d, 0x2c28, 0x2001, 0x5252, 0x2004, 0xac06,
- 0x00c0, 0x1a74, 0x0078, 0x1a99, 0x6804, 0xac06, 0x00c0, 0x1a81,
- 0x6000, 0xa065, 0x6806, 0x00c0, 0x1a8b, 0x6803, 0x0000, 0x0078,
- 0x1a8b, 0x6400, 0x781c, 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0,
- 0x1a8b, 0x2c00, 0x6802, 0x2560, 0x1078, 0x1a31, 0x601b, 0x0005,
- 0x6023, 0x0020, 0x1078, 0x1ccb, 0x6810, 0x8001, 0x1050, 0x248c,
- 0x6812, 0xa085, 0xffff, 0x007c, 0x2039, 0x0000, 0x2041, 0x0021,
- 0x2049, 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x19d2,
- 0x8738, 0xa784, 0x001f, 0x00c0, 0x1aa6, 0xa7bc, 0xff00, 0x873f,
- 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1aa6, 0x2091, 0x8001,
- 0x007c, 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x00c0, 0x1aca,
- 0x2091, 0x8000, 0x78e0, 0x78e3, 0x0000, 0x2091, 0x8001, 0xa005,
- 0x00c0, 0x1acb, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1ad1, 0x1078,
- 0x248c, 0x0079, 0x1ad3, 0x1ae3, 0x1ae6, 0x1aec, 0x1af0, 0x1ae4,
- 0x1af4, 0x1afa, 0x1ae4, 0x1ae4, 0x1c95, 0x1cb9, 0x1cbd, 0x1ae4,
- 0x1ae4, 0x1ae4, 0x1ae4, 0x007c, 0x1078, 0x248c, 0x1078, 0x1a9c,
- 0x2001, 0x8001, 0x0078, 0x1cc3, 0x2001, 0x8003, 0x0078, 0x1cc3,
- 0x2001, 0x8004, 0x0078, 0x1cc3, 0x1078, 0x1a9c, 0x2001, 0x8006,
- 0x0078, 0x1cc3, 0x2001, 0x8007, 0x0078, 0x1cc3, 0x2030, 0x2138,
- 0xa782, 0x0021, 0x0048, 0x1b06, 0x2009, 0x0020, 0x2600, 0x1078,
- 0x1b20, 0x00c0, 0x1b1f, 0xa7ba, 0x0020, 0x0048, 0x1b1e, 0x0040,
- 0x1b1e, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000,
- 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1b00, 0xa006, 0x007c,
- 0x81ff, 0x0040, 0x1b5b, 0x2099, 0x0030, 0x20a0, 0x700c, 0xa084,
- 0x00ff, 0x0040, 0x1b32, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
- 0x00c0, 0x1b2d, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a,
- 0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0001, 0x7002, 0x7007,
- 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x1b4f,
- 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1b41, 0x7008,
- 0x800b, 0x00c8, 0x1b41, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0,
- 0x1b5b, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x2030, 0x2138,
- 0xa782, 0x0021, 0x0048, 0x1b66, 0x2009, 0x0020, 0x2600, 0x1078,
- 0x1b80, 0x00c0, 0x1b7f, 0xa7ba, 0x0020, 0x0048, 0x1b7e, 0x0040,
- 0x1b7e, 0x2708, 0xa6b0, 0x0020, 0xa290, 0x0040, 0xa399, 0x0000,
- 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x0078, 0x1b60, 0xa006, 0x007c,
- 0x81ff, 0x0040, 0x1bc1, 0x2098, 0x20a1, 0x0030, 0x700c, 0xa084,
- 0x00ff, 0x0040, 0x1b92, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004,
- 0x00c0, 0x1b8d, 0x21a8, 0x7017, 0x0000, 0x810b, 0x7112, 0x721a,
- 0x731e, 0x7422, 0x7526, 0x780c, 0xa085, 0x0000, 0x7002, 0x53a6,
- 0x7007, 0x0001, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8,
- 0x1bb0, 0x2009, 0x0022, 0x2104, 0xa084, 0x4000, 0x00c0, 0x1ba2,
- 0x7010, 0xa084, 0xf000, 0x0040, 0x1bb9, 0x7007, 0x0008, 0x0078,
- 0x1bbd, 0x7108, 0x8103, 0x00c8, 0x1ba2, 0x7007, 0x0002, 0xa184,
- 0x01e0, 0x7003, 0x0000, 0x007c, 0x2001, 0x04fd, 0x2004, 0xa082,
- 0x0004, 0x00c8, 0x1bcd, 0x0078, 0x1bd0, 0xa006, 0x0078, 0x1bd2,
- 0xa085, 0x0001, 0x007c, 0x0e7e, 0x2071, 0x5200, 0x2d08, 0x7058,
- 0x6802, 0xa005, 0x00c0, 0x1bdd, 0x715e, 0x715a, 0x0e7f, 0x007c,
- 0x2c08, 0x7858, 0x6002, 0xa005, 0x00c0, 0x1be7, 0x795e, 0x795a,
- 0x007c, 0x2091, 0x8000, 0x6114, 0x1078, 0x2180, 0x6900, 0xa184,
- 0x0100, 0x00c0, 0x2035, 0xa184, 0x0200, 0x00c0, 0x2031, 0x681c,
- 0xa005, 0x00c0, 0x203d, 0x6003, 0x0000, 0x2c08, 0x785c, 0xa065,
- 0x00c0, 0x1c05, 0x795a, 0x0078, 0x1c06, 0x6102, 0x795e, 0x2091,
- 0x8001, 0x1078, 0x228c, 0x007c, 0x0e7e, 0x2071, 0x5200, 0x7058,
- 0xa06d, 0x0040, 0x1c1a, 0x6800, 0x705a, 0xa005, 0x00c0, 0x1c19,
- 0x705e, 0x8dff, 0x0e7f, 0x007c, 0x0d7e, 0x0c7e, 0x0f7e, 0x2079,
- 0x5200, 0xaf80, 0x0016, 0x2060, 0x6000, 0xa005, 0x0040, 0x1c43,
- 0x2068, 0x6814, 0xa306, 0x00c0, 0x1c33, 0x6828, 0xa084, 0x00ff,
- 0xa406, 0x0040, 0x1c36, 0x2d60, 0x0078, 0x1c24, 0x6800, 0xa005,
- 0x6002, 0x00c0, 0x1c42, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1c41,
- 0x2c00, 0x785e, 0x2d00, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c,
- 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5200, 0xaf80, 0x0016, 0x2060,
- 0x6000, 0xa005, 0x0040, 0x1c6b, 0x2068, 0x6814, 0xa084, 0x00ff,
- 0xa306, 0x0040, 0x1c5e, 0x2d60, 0x0078, 0x1c50, 0x6800, 0xa005,
- 0x6002, 0x00c0, 0x1c6a, 0xaf80, 0x0016, 0xac06, 0x0040, 0x1c69,
- 0x2c00, 0x785e, 0x2d00, 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c,
- 0x0d7e, 0x0c7e, 0x0f7e, 0x2079, 0x5200, 0xaf80, 0x0016, 0x2060,
- 0x6000, 0xa06d, 0x0040, 0x1c90, 0x6814, 0xa306, 0x0040, 0x1c83,
- 0x2d60, 0x0078, 0x1c78, 0x6800, 0xa005, 0x6002, 0x00c0, 0x1c8f,
- 0xaf80, 0x0016, 0xac06, 0x0040, 0x1c8e, 0x2c00, 0x785e, 0x2d00,
- 0x0f7f, 0x0c7f, 0x0d7f, 0xa005, 0x007c, 0x2091, 0x8000, 0x2069,
- 0x5240, 0x6800, 0xa086, 0x0000, 0x0040, 0x1ca3, 0x2091, 0x8001,
- 0x78e3, 0x0009, 0x007c, 0x6880, 0xa0bc, 0xff00, 0x2041, 0x0021,
- 0x2049, 0x0004, 0x2051, 0x0010, 0x1078, 0x19d2, 0x8738, 0xa784,
- 0x001f, 0x00c0, 0x1cac, 0x2091, 0x8001, 0x2001, 0x800a, 0x0078,
- 0x1cc3, 0x2001, 0x800c, 0x0078, 0x1cc3, 0x1078, 0x1a9c, 0x2001,
- 0x800d, 0x0078, 0x1cc3, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001,
- 0x2091, 0x4080, 0x007c, 0x6004, 0x2c08, 0x2063, 0x0000, 0x7884,
- 0x8000, 0x7886, 0x7888, 0xa005, 0x798a, 0x0040, 0x1cda, 0x2c02,
- 0x0078, 0x1cdb, 0x798e, 0x007c, 0x6807, 0x0103, 0x0c7e, 0x2061,
- 0x5200, 0x2d08, 0x206b, 0x0000, 0x6084, 0x8000, 0x6086, 0x6088,
- 0xa005, 0x618a, 0x0040, 0x1cef, 0x2d02, 0x0078, 0x1cf0, 0x618e,
- 0x0c7f, 0x007c, 0x1078, 0x1d03, 0x0040, 0x1d02, 0x0c7e, 0x609c,
- 0xa065, 0x0040, 0x1cfd, 0x1078, 0x1a17, 0x0c7f, 0x609f, 0x0000,
- 0x1078, 0x199a, 0x007c, 0x788c, 0xa065, 0x0040, 0x1d15, 0x2091,
- 0x8000, 0x7884, 0x8001, 0x7886, 0x2c04, 0x788e, 0xa005, 0x00c0,
- 0x1d13, 0x788a, 0x8000, 0x2091, 0x8001, 0x007c, 0x20a9, 0x0010,
- 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x1d1f, 0xa200, 0x0070,
- 0x1d23, 0x0078, 0x1d1a, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9,
- 0x0010, 0xa005, 0x0040, 0x1d49, 0xa11a, 0x00c8, 0x1d49, 0x8213,
- 0x818d, 0x0048, 0x1d3a, 0xa11a, 0x00c8, 0x1d3b, 0x0070, 0x1d41,
- 0x0078, 0x1d2f, 0xa11a, 0x2308, 0x8210, 0x0070, 0x1d41, 0x0078,
- 0x1d2f, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f,
- 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x1d45, 0x7994,
- 0x70d0, 0xa106, 0x0040, 0x1dbd, 0x2091, 0x8000, 0x2071, 0x0020,
- 0x7004, 0xa005, 0x00c0, 0x1dbd, 0x7008, 0x7208, 0xa206, 0x00c0,
- 0x1dbd, 0xa286, 0x0008, 0x00c0, 0x1dbd, 0x2071, 0x0010, 0x1078,
- 0x1980, 0x0040, 0x1dbd, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0, 0xa184,
- 0xff00, 0x0040, 0x1d8b, 0x2031, 0x0000, 0x810b, 0x86b5, 0x810b,
- 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b, 0x86b5, 0x810b,
- 0x86b5, 0x2100, 0xa210, 0x2600, 0xa319, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0x0078, 0x1d95, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
- 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x2009, 0x0020, 0x1078,
- 0x197b, 0x2091, 0x8001, 0x0040, 0x1db4, 0x1078, 0x199a, 0x78a8,
- 0x8000, 0x78aa, 0xa086, 0x0002, 0x00c0, 0x1dbd, 0x2091, 0x8000,
- 0x78e3, 0x0002, 0x78ab, 0x0000, 0x78cc, 0xa085, 0x0003, 0x78ce,
- 0x2091, 0x8001, 0x0078, 0x1dbd, 0x78ab, 0x0000, 0x1078, 0x2149,
- 0x6004, 0xa084, 0x000f, 0x0079, 0x1dc2, 0x2071, 0x0010, 0x2091,
- 0x8001, 0x007c, 0x1dd2, 0x1df4, 0x1e1a, 0x1dd2, 0x1e37, 0x1de1,
- 0x1fc9, 0x1fe4, 0x1dd2, 0x1dee, 0x1e14, 0x1e7f, 0x1eee, 0x1f57,
- 0x1f69, 0x1fe0, 0x2039, 0x0400, 0x78dc, 0xa705, 0x78de, 0x6008,
- 0xa705, 0x600a, 0x1078, 0x2064, 0x609c, 0x78da, 0x1078, 0x2131,
- 0x007c, 0x78dc, 0xa084, 0x0100, 0x0040, 0x1de8, 0x0078, 0x1dd2,
- 0x601c, 0xa085, 0x0080, 0x601e, 0x0078, 0x1dfb, 0x1078, 0x1bc4,
- 0x00c0, 0x1dd2, 0x1078, 0x2163, 0x78dc, 0xa084, 0x0100, 0x0040,
- 0x1dfb, 0x0078, 0x1dd2, 0x78df, 0x0000, 0x6004, 0x8007, 0xa084,
- 0x00ff, 0x78d2, 0x8001, 0x609f, 0x0000, 0x0040, 0x1e11, 0x1078,
- 0x2064, 0x0040, 0x1e11, 0x78dc, 0xa085, 0x0100, 0x78de, 0x0078,
- 0x1e13, 0x1078, 0x2088, 0x007c, 0x1078, 0x1bc4, 0x00c0, 0x1dd2,
- 0x1078, 0x215f, 0x78dc, 0xa08c, 0x0e00, 0x00c0, 0x1e23, 0xa084,
- 0x0100, 0x00c0, 0x1e25, 0x0078, 0x1dd2, 0x1078, 0x2064, 0x00c0,
- 0x1e36, 0x6104, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x2021,
- 0xa186, 0x000f, 0x0040, 0x2021, 0x1078, 0x2088, 0x007c, 0x78dc,
- 0xa084, 0x0100, 0x0040, 0x1e3e, 0x0078, 0x1dd2, 0x78df, 0x0000,
- 0x6714, 0x2011, 0x0001, 0x20a9, 0x0001, 0x6018, 0xa084, 0x00ff,
- 0xa005, 0x0040, 0x1e61, 0x2011, 0x0001, 0xa7bc, 0xff00, 0x20a9,
- 0x0020, 0xa08e, 0x0001, 0x0040, 0x1e61, 0x2039, 0x0000, 0x2011,
- 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0040, 0x1e61, 0x0078,
- 0x1e7c, 0x1078, 0x19c5, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f,
- 0x0000, 0x6808, 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091,
- 0x8001, 0x0070, 0x1e75, 0x0078, 0x1e63, 0x8211, 0x0040, 0x1e7c,
- 0x20a9, 0x0100, 0x0078, 0x1e63, 0x1078, 0x199a, 0x007c, 0x2001,
- 0x5267, 0x2004, 0xa084, 0x8000, 0x0040, 0x2049, 0x6114, 0x1078,
- 0x2180, 0x6900, 0xa184, 0x0001, 0x0040, 0x1ea0, 0x6028, 0xa084,
- 0x00ff, 0x00c0, 0x2041, 0x6800, 0xa084, 0x0001, 0x0040, 0x2049,
- 0x6803, 0x0000, 0x680b, 0x0000, 0x6807, 0x0000, 0x0078, 0x2051,
- 0x2011, 0x0001, 0x6020, 0xd0f4, 0x0040, 0x1ea8, 0xa295, 0x0002,
- 0xd0c4, 0x0040, 0x1ead, 0xa295, 0x0008, 0xd0cc, 0x0040, 0x1eb2,
- 0xa295, 0x0400, 0x601c, 0xa084, 0x0002, 0x0040, 0x1eb9, 0xa295,
- 0x0004, 0x602c, 0xa08c, 0x00ff, 0xa182, 0x0002, 0x0048, 0x204d,
- 0xa182, 0x001b, 0x00c8, 0x204d, 0x0040, 0x204d, 0x690e, 0x602c,
- 0x8007, 0xa08c, 0x00ff, 0xa182, 0x0002, 0x0048, 0x204d, 0xa182,
- 0x001b, 0x00c8, 0x204d, 0x0040, 0x204d, 0x6912, 0x6030, 0xa005,
- 0x00c0, 0x1edc, 0x2001, 0x001e, 0x8000, 0x6816, 0x6028, 0xa084,
- 0x00ff, 0x0040, 0x2049, 0x6806, 0x6028, 0x8007, 0xa084, 0x00ff,
- 0x0040, 0x2049, 0x680a, 0x6a02, 0x0078, 0x2051, 0x2001, 0x5240,
- 0x2004, 0xa086, 0x0007, 0x00c0, 0x1f53, 0x2001, 0x5267, 0x2004,
- 0xa084, 0x8000, 0x0040, 0x2049, 0x6114, 0x1078, 0x2180, 0x2001,
- 0x5252, 0x2004, 0x2010, 0x82ff, 0x0040, 0x1f0e, 0xa080, 0x0005,
- 0x2004, 0xa084, 0x00ff, 0xa106, 0x00c0, 0x1f53, 0x2091, 0x8000,
- 0x6a04, 0x6b08, 0x6418, 0xa484, 0x0003, 0x0040, 0x1f2d, 0x6128,
- 0xa18c, 0x00ff, 0x8001, 0x00c0, 0x1f23, 0x2100, 0xa210, 0x0048,
- 0x1f53, 0x0078, 0x1f2d, 0x8001, 0x00c0, 0x1f53, 0x2100, 0xa212,
- 0x0048, 0x1f53, 0x82ff, 0x0040, 0x1f53, 0xa484, 0x000c, 0x0040,
- 0x1f47, 0x6128, 0x810f, 0xa18c, 0x00ff, 0xa082, 0x0004, 0x00c0,
- 0x1f3f, 0x2100, 0xa318, 0x0048, 0x1f53, 0x0078, 0x1f47, 0xa082,
- 0x0004, 0x00c0, 0x1f53, 0x2100, 0xa31a, 0x0048, 0x1f53, 0x6030,
- 0xa005, 0x0040, 0x1f4d, 0x8000, 0x6816, 0x6a06, 0x6b0a, 0x2091,
- 0x8001, 0x0078, 0x2051, 0x2091, 0x8001, 0x0078, 0x204d, 0x6114,
- 0x1078, 0x2180, 0x2091, 0x8000, 0x6b08, 0x8318, 0x0048, 0x1f65,
- 0x6b0a, 0x2091, 0x8001, 0x0078, 0x2060, 0x2091, 0x8001, 0x0078,
- 0x204d, 0x6024, 0x8007, 0xa084, 0x00ff, 0x0040, 0x1f87, 0xa086,
- 0x0080, 0x00c0, 0x1fc7, 0x20a9, 0x0008, 0x2069, 0x7610, 0x2091,
- 0x8000, 0x6800, 0xa084, 0xfcff, 0x6802, 0xade8, 0x0008, 0x0070,
- 0x1f83, 0x0078, 0x1f79, 0x2091, 0x8001, 0x0078, 0x2051, 0x6028,
- 0xa015, 0x0040, 0x1fc7, 0x6114, 0x1078, 0x2180, 0x0c7e, 0x0d7e,
- 0xade8, 0x0007, 0x2091, 0x8000, 0x6800, 0xa00d, 0x0040, 0x1fc3,
- 0xa206, 0x0040, 0x1f9e, 0x2168, 0x0078, 0x1f94, 0x2160, 0x6000,
- 0x6802, 0x2c68, 0x1078, 0x19ac, 0x0d7f, 0x6818, 0xa00d, 0x0040,
- 0x1fbb, 0x2060, 0x6200, 0x6a1a, 0x6a1c, 0x6202, 0x681e, 0x1078,
- 0x1989, 0x2da0, 0x2198, 0x20a9, 0x0031, 0x53a3, 0x2d60, 0x1078,
- 0x1ccb, 0x0078, 0x1fbe, 0x6808, 0x8000, 0x680a, 0x2091, 0x8001,
- 0x0c7f, 0x0078, 0x2060, 0x2091, 0x8001, 0x0d7f, 0x0c7f, 0x0078,
- 0x2049, 0x6114, 0x1078, 0x2180, 0x6800, 0xa084, 0x0001, 0x0040,
- 0x2039, 0x2091, 0x8000, 0x6a04, 0x8210, 0x0048, 0x1fdc, 0x6a06,
- 0x2091, 0x8001, 0x0078, 0x2060, 0x2091, 0x8001, 0x0078, 0x204d,
- 0x1078, 0x1bc4, 0x00c0, 0x1dd2, 0x6114, 0x1078, 0x2180, 0x60be,
- 0x60bb, 0x0000, 0x6900, 0xa184, 0x0008, 0x0040, 0x1ff3, 0x6020,
- 0xa085, 0x0100, 0x6022, 0xa184, 0x0001, 0x0040, 0x2049, 0xa184,
- 0x0100, 0x00c0, 0x2035, 0xa184, 0x0200, 0x00c0, 0x2031, 0x681c,
- 0xa005, 0x00c0, 0x203d, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000f,
- 0x00c0, 0x200c, 0x1078, 0x2163, 0x78df, 0x0000, 0x6004, 0x8007,
- 0xa084, 0x00ff, 0x78d2, 0x8001, 0x609f, 0x0000, 0x0040, 0x2021,
- 0x1078, 0x2064, 0x0040, 0x2021, 0x78dc, 0xa085, 0x0100, 0x78de,
- 0x007c, 0x78d7, 0x0000, 0x78db, 0x0000, 0x6024, 0xa084, 0xff00,
- 0x6026, 0x1078, 0x3aac, 0x0040, 0x1d4f, 0x1078, 0x1be9, 0x0078,
- 0x1d4f, 0x2009, 0x0017, 0x0078, 0x2053, 0x2009, 0x000e, 0x0078,
- 0x2053, 0x2009, 0x0007, 0x0078, 0x2053, 0x2009, 0x0035, 0x0078,
- 0x2053, 0x2009, 0x003e, 0x0078, 0x2053, 0x2009, 0x0004, 0x0078,
- 0x2053, 0x2009, 0x0006, 0x0078, 0x2053, 0x2009, 0x0016, 0x0078,
- 0x2053, 0x2009, 0x0001, 0x6024, 0xa084, 0xff00, 0xa105, 0x6026,
- 0x2091, 0x8000, 0x1078, 0x1ccb, 0x2091, 0x8001, 0x0078, 0x1d4f,
- 0x1078, 0x199a, 0x0078, 0x1d4f, 0x78d4, 0xa06d, 0x00c0, 0x206f,
- 0x2c00, 0x78d6, 0x78da, 0x609f, 0x0000, 0x0078, 0x207b, 0x2c00,
- 0x689e, 0x609f, 0x0000, 0x78d6, 0x2d00, 0x6002, 0x78d8, 0xad06,
- 0x00c0, 0x207b, 0x6002, 0x78d0, 0x8001, 0x78d2, 0x00c0, 0x2087,
- 0x78dc, 0xa084, 0xfeff, 0x78de, 0x78d8, 0x2060, 0xa006, 0x007c,
- 0xa02e, 0x2530, 0x611c, 0x61a2, 0xa184, 0xe1ff, 0x601e, 0xa184,
- 0x0060, 0x0040, 0x2097, 0x0e7e, 0x1078, 0x48d3, 0x0e7f, 0x6596,
- 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714,
- 0x1078, 0x19c5, 0x2091, 0x8000, 0x60a0, 0xa084, 0x8000, 0x00c0,
- 0x20be, 0x6808, 0xa084, 0x0001, 0x0040, 0x20be, 0x2091, 0x8001,
- 0x1078, 0x1a31, 0x2091, 0x8000, 0x1078, 0x1ccb, 0x2091, 0x8001,
- 0x78d7, 0x0000, 0x78db, 0x0000, 0x0078, 0x2130, 0x6024, 0xa096,
- 0x0001, 0x00c0, 0x20c5, 0x8000, 0x6026, 0x6a10, 0x6814, 0x2091,
- 0x8001, 0xa202, 0x0048, 0x20d4, 0x0040, 0x20d4, 0x2039, 0x0200,
- 0x1078, 0x2131, 0x0078, 0x2130, 0x2c08, 0x2091, 0x8000, 0x60a0,
- 0xa084, 0x8000, 0x0040, 0x2101, 0x6800, 0xa065, 0x0040, 0x2106,
- 0x6a04, 0x0e7e, 0x2071, 0x5240, 0x7000, 0xa084, 0x0001, 0x0040,
- 0x20fb, 0x7048, 0xa206, 0x00c0, 0x20fb, 0x6b04, 0x231c, 0x2160,
- 0x6302, 0x2300, 0xa005, 0x00c0, 0x20f6, 0x6902, 0x2260, 0x6102,
- 0x0e7f, 0x0078, 0x210d, 0x2160, 0x6202, 0x6906, 0x0e7f, 0x0078,
- 0x210d, 0x6800, 0xa065, 0x0040, 0x2106, 0x6102, 0x6902, 0x00c0,
- 0x210a, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0x60a0, 0xa084,
- 0x8000, 0x0040, 0x2117, 0x6808, 0xa084, 0xfffc, 0x680a, 0x6810,
- 0x8000, 0x6812, 0x2091, 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040,
- 0x2126, 0xa086, 0x0040, 0x680a, 0x1078, 0x1a42, 0x2091, 0x8000,
- 0x1078, 0x226f, 0x2091, 0x8001, 0x78db, 0x0000, 0x78d7, 0x0000,
- 0x007c, 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x1ccb,
- 0x2091, 0x8001, 0x78d8, 0xa065, 0x0040, 0x2144, 0x609c, 0x78da,
- 0x609f, 0x0000, 0x0078, 0x2134, 0x78d7, 0x0000, 0x78db, 0x0000,
- 0x007c, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8, 0x2150, 0xa006,
- 0x7896, 0x70d2, 0x7804, 0xa005, 0x0040, 0x215e, 0x8001, 0x7806,
- 0x00c0, 0x215e, 0x0068, 0x215e, 0x2091, 0x4080, 0x007c, 0x2039,
- 0x2177, 0x0078, 0x2165, 0x2039, 0x217d, 0x2704, 0xa005, 0x0040,
- 0x2176, 0xac00, 0x2068, 0x6b08, 0x6c0c, 0x6910, 0x6a14, 0x690a,
- 0x6a0e, 0x6b12, 0x6c16, 0x8738, 0x0078, 0x2165, 0x007c, 0x0003,
- 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b, 0x0000,
- 0x0c7e, 0x1078, 0x3c3b, 0x2c68, 0x0c7f, 0x007c, 0x0010, 0x21f7,
- 0x0068, 0x21f7, 0x2029, 0x0000, 0x78cb, 0x0000, 0x788c, 0xa065,
- 0x0040, 0x21f0, 0x2009, 0x5274, 0x2104, 0xa084, 0x0001, 0x0040,
- 0x21be, 0x6004, 0xa086, 0x0103, 0x00c0, 0x21be, 0x6018, 0xa005,
- 0x00c0, 0x21be, 0x6014, 0xa005, 0x00c0, 0x21be, 0x0d7e, 0x2069,
- 0x0000, 0x6818, 0xa084, 0x0001, 0x00c0, 0x21bd, 0x600c, 0x70c6,
- 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091, 0x4080,
- 0x0d7f, 0x1078, 0x1cf2, 0x0078, 0x21f5, 0x0d7f, 0x1078, 0x21f8,
- 0x0040, 0x21f0, 0x6204, 0xa294, 0x00ff, 0xa296, 0x0003, 0x0040,
- 0x21d0, 0x6204, 0xa296, 0x0110, 0x00c0, 0x21de, 0x78cb, 0x0001,
- 0x6204, 0xa294, 0xff00, 0x8217, 0x8211, 0x0040, 0x21de, 0x85ff,
- 0x00c0, 0x21f0, 0x8210, 0xa202, 0x00c8, 0x21f0, 0x057e, 0x1078,
- 0x2207, 0x057f, 0x0040, 0x21eb, 0x78e0, 0xa086, 0x0003, 0x0040,
- 0x21f0, 0x0078, 0x21de, 0x8528, 0x78c8, 0xa005, 0x0040, 0x218e,
- 0x85ff, 0x0040, 0x21f7, 0x2091, 0x4080, 0x78b0, 0x70d6, 0x007c,
- 0x7bac, 0x79b0, 0x70d4, 0xa102, 0x00c0, 0x2201, 0x2300, 0xa005,
- 0x007c, 0x0048, 0x2205, 0xa302, 0x007c, 0x8002, 0x007c, 0x2001,
- 0x04fd, 0x2004, 0xa082, 0x0005, 0x00c8, 0x2221, 0x2091, 0x8000,
- 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2256, 0x7008, 0x7208,
- 0xa206, 0x00c0, 0x2256, 0xa286, 0x0008, 0x00c0, 0x2256, 0x2071,
- 0x0010, 0x1078, 0x225b, 0x2009, 0x0020, 0x6004, 0xa086, 0x0103,
- 0x00c0, 0x2230, 0x6028, 0xa005, 0x00c0, 0x2230, 0x2009, 0x000c,
- 0x1078, 0x1976, 0x0040, 0x2249, 0x78c4, 0x8000, 0x78c6, 0xa086,
- 0x0002, 0x00c0, 0x2256, 0x2091, 0x8000, 0x78e3, 0x0003, 0x78c7,
- 0x0000, 0x78cc, 0xa085, 0x0300, 0x78ce, 0x2091, 0x8001, 0x0078,
- 0x2256, 0x78c7, 0x0000, 0x1078, 0x1cf2, 0x79ac, 0x78b0, 0x8000,
- 0xa10a, 0x00c8, 0x2254, 0xa006, 0x78b2, 0xa006, 0x2071, 0x0010,
- 0x2091, 0x8001, 0x007c, 0x8107, 0x8004, 0x8004, 0x7ab8, 0x7bb4,
- 0x7cc0, 0x7dbc, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0x007c, 0x2009, 0x525b, 0x2091, 0x8000, 0x200a, 0x0f7e,
- 0x0e7e, 0x2071, 0x5240, 0x7000, 0xa086, 0x0000, 0x00c0, 0x2289,
- 0x2009, 0x5212, 0x2104, 0xa005, 0x00c0, 0x2289, 0x2079, 0x0100,
- 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2289, 0x0018, 0x2289, 0x781b,
- 0x004b, 0x0e7f, 0x0f7f, 0x007c, 0x0f7e, 0x0e7e, 0x2071, 0x5240,
- 0x2091, 0x8000, 0x7000, 0xa086, 0x0000, 0x00c0, 0x22a2, 0x2079,
- 0x0100, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x22a2, 0x0018, 0x22a2,
- 0x781b, 0x004d, 0x2091, 0x8001, 0x0e7f, 0x0f7f, 0x007c, 0x127e,
- 0x2091, 0x2300, 0x2071, 0x5240, 0x2079, 0x0100, 0x784b, 0x000f,
- 0x0098, 0x22b5, 0x7838, 0x0078, 0x22ae, 0x20a9, 0x0040, 0x7800,
- 0xa082, 0x0004, 0x0048, 0x22be, 0x20a9, 0x0060, 0x789b, 0x0000,
- 0x78af, 0x0000, 0x78af, 0x0000, 0x0070, 0x22c8, 0x0078, 0x22c0,
- 0x7800, 0xa082, 0x0004, 0x0048, 0x22d7, 0x70b7, 0x0093, 0x2019,
- 0x4ff0, 0x1078, 0x2313, 0x702f, 0x8001, 0x0078, 0x22e3, 0x70b7,
- 0x0000, 0x2019, 0x4e70, 0x1078, 0x2313, 0x2019, 0x4eaf, 0x1078,
- 0x2313, 0x702f, 0x8000, 0x7003, 0x0000, 0x1078, 0x2420, 0x7004,
- 0xa084, 0x000f, 0x017e, 0x2009, 0x04fd, 0x210c, 0xa18a, 0x0005,
- 0x0048, 0x22f8, 0x0038, 0x22fe, 0xa085, 0x6280, 0x0078, 0x2300,
- 0x0028, 0x22fe, 0xa085, 0x6280, 0x0078, 0x2300, 0xa085, 0x62c0,
- 0x017f, 0x7806, 0x780f, 0xb204, 0x7843, 0x00d8, 0x7853, 0x0080,
- 0x780b, 0x0008, 0x7047, 0x0008, 0x7053, 0x527f, 0x704f, 0x0000,
- 0x127f, 0x2000, 0x007c, 0x137e, 0x147e, 0x157e, 0x047e, 0x20a1,
- 0x012b, 0x2304, 0xa005, 0x789a, 0x0040, 0x2333, 0x8318, 0x2324,
- 0x8318, 0x2398, 0x24a8, 0xa484, 0xff00, 0x0040, 0x232b, 0xa482,
- 0x0100, 0x20a9, 0x0100, 0x2020, 0x53a6, 0xa005, 0x00c0, 0x2322,
- 0x3318, 0x0078, 0x2319, 0x047f, 0x157f, 0x147f, 0x137f, 0x007c,
- 0xa18c, 0x000f, 0x2011, 0x0101, 0x2204, 0xa084, 0xfff0, 0xa105,
- 0x2012, 0x1078, 0x2420, 0x007c, 0x2011, 0x0101, 0x20a9, 0x0009,
- 0x810b, 0x0070, 0x234d, 0x0078, 0x2348, 0xa18c, 0x0e00, 0x2204,
- 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2009, 0x0101, 0x20a9,
- 0x0005, 0x8213, 0x0070, 0x235e, 0x0078, 0x2359, 0xa294, 0x00e0,
- 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x007c, 0x2011, 0x0101,
- 0x20a9, 0x000c, 0x810b, 0x0070, 0x236f, 0x0078, 0x236a, 0xa18c,
- 0xf000, 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x007c, 0x2011,
- 0x0102, 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x8103,
- 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac,
- 0x63ac, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e,
- 0x2061, 0x0100, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f,
- 0x007c, 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100,
- 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103,
- 0x8003, 0xa080, 0x0020, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4,
- 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091,
- 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005, 0x0040, 0x23fe, 0x2061,
- 0x7600, 0x1078, 0x2406, 0x0040, 0x23e8, 0x20a9, 0x0000, 0x2061,
- 0x7500, 0x0c7e, 0x1078, 0x2406, 0x0040, 0x23d6, 0x0c7f, 0x8c60,
- 0x0070, 0x23d4, 0x0078, 0x23c9, 0x0078, 0x23fe, 0x007f, 0xa082,
- 0x7500, 0x2071, 0x5240, 0x7086, 0x7182, 0x2001, 0x0004, 0x706e,
- 0x7093, 0x000f, 0x7073, 0x0000, 0x1078, 0x226a, 0x0078, 0x23fa,
- 0x60c0, 0xa005, 0x00c0, 0x23fe, 0x2071, 0x5240, 0x7182, 0x2c00,
- 0x708a, 0x2001, 0x0006, 0x706e, 0x7093, 0x000f, 0x7073, 0x0000,
- 0x1078, 0x226a, 0x2001, 0x0000, 0x0078, 0x2400, 0x2001, 0x0001,
- 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c, 0x2c04, 0xa005,
- 0x0040, 0x241d, 0x2060, 0x600c, 0xa306, 0x00c0, 0x241a, 0x6010,
- 0xa206, 0x00c0, 0x241a, 0x6014, 0xa106, 0x00c0, 0x241a, 0xa006,
- 0x0078, 0x241f, 0x6000, 0x0078, 0x2407, 0xa085, 0x0001, 0x007c,
- 0x2011, 0x5241, 0x220c, 0xa18c, 0x000f, 0x2011, 0x013b, 0x2204,
- 0xa084, 0x0100, 0x0040, 0x2436, 0x2021, 0xff04, 0x2122, 0x810b,
- 0x810b, 0x810b, 0x810b, 0xa18d, 0x0f00, 0x2104, 0x007c, 0x0e7e,
- 0x68e4, 0xa08c, 0x0020, 0x0040, 0x248a, 0xa084, 0x0006, 0x00c0,
- 0x248a, 0x6014, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
- 0xa0f0, 0x5480, 0x7004, 0xa084, 0x000a, 0x00c0, 0x248a, 0x7108,
- 0xa194, 0xff00, 0x0040, 0x248a, 0xa18c, 0x00ff, 0x2001, 0x000c,
- 0xa106, 0x0040, 0x2471, 0x2001, 0x0012, 0xa106, 0x0040, 0x2475,
- 0x2001, 0x0014, 0xa106, 0x0040, 0x2479, 0x2001, 0x0019, 0xa106,
- 0x0040, 0x247d, 0x2001, 0x0032, 0xa106, 0x0040, 0x2481, 0x0078,
- 0x2485, 0x2009, 0x0012, 0x0078, 0x2487, 0x2009, 0x0014, 0x0078,
- 0x2487, 0x2009, 0x0019, 0x0078, 0x2487, 0x2009, 0x0020, 0x0078,
- 0x2487, 0x2009, 0x003f, 0x0078, 0x2487, 0x2011, 0x0000, 0x2100,
- 0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x248c, 0x2091, 0x8000,
- 0x2071, 0x0000, 0x007e, 0x7018, 0xa084, 0x0001, 0x00c0, 0x2493,
- 0x007f, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002,
- 0x70db, 0x0741, 0x70df, 0x0006, 0x2071, 0x0000, 0x701b, 0x0001,
- 0x2091, 0x4080, 0x0078, 0x24aa, 0x107e, 0x007e, 0x127e, 0x2091,
- 0x2300, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x77c2, 0x74c6, 0x76ca,
- 0x75ce, 0xa594, 0x003f, 0xa49c, 0x0003, 0xa484, 0x000f, 0x0079,
- 0x24c1, 0x24d3, 0x24d3, 0x24d3, 0x280d, 0x3a09, 0x24d1, 0x2502,
- 0x250c, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1, 0x24d1,
- 0x24d1, 0x1078, 0x248c, 0x8507, 0xa084, 0x001f, 0x0079, 0x24d8,
- 0x2516, 0x280d, 0x29c7, 0x2ac4, 0x2aec, 0x2d8c, 0x3037, 0x309a,
- 0x30fb, 0x3180, 0x3238, 0x32d6, 0x2502, 0x28e9, 0x300c, 0x24f8,
- 0x3dac, 0x3dcc, 0x3f8f, 0x3f9b, 0x4074, 0x24f8, 0x24f8, 0x4149,
- 0x414d, 0x3daa, 0x24f8, 0x3efa, 0x24f8, 0x3c5e, 0x250c, 0x24f8,
- 0x1078, 0x248c, 0x0018, 0x24b1, 0x127f, 0x2091, 0x8001, 0x007f,
- 0x107f, 0x007c, 0x2019, 0x4f49, 0x1078, 0x2313, 0x702f, 0x0001,
- 0x781b, 0x004f, 0x0078, 0x24fa, 0x2019, 0x4eaf, 0x1078, 0x2313,
- 0x702f, 0x8000, 0x781b, 0x00cd, 0x0078, 0x24fa, 0x7242, 0x2009,
- 0x520f, 0x200b, 0x0000, 0xa584, 0x0001, 0x00c0, 0x3c72, 0x0040,
- 0x2533, 0x1078, 0x248c, 0x7003, 0x0000, 0x704b, 0x0000, 0x7043,
- 0x0000, 0x7037, 0x0000, 0x1078, 0x39e0, 0x0018, 0x24b1, 0x2009,
- 0x520f, 0x200b, 0x0000, 0x7068, 0xa005, 0x00c0, 0x25fe, 0x706c,
- 0xa084, 0x0007, 0x0079, 0x253c, 0x2635, 0x2544, 0x2550, 0x256d,
- 0x258f, 0x25dc, 0x25b5, 0x2544, 0x1078, 0x39c8, 0x2009, 0x0048,
- 0x1078, 0x2ed8, 0x00c0, 0x254e, 0x7003, 0x0004, 0x0078, 0x24fa,
- 0x1078, 0x39c8, 0x00c0, 0x256b, 0x7080, 0x8007, 0x7882, 0x789b,
- 0x0010, 0x78ab, 0x000c, 0x789b, 0x0060, 0x78ab, 0x0001, 0x785b,
- 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0, 0x256b, 0x7003,
- 0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0,
- 0x258d, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f,
- 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab,
- 0x0002, 0x785b, 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0,
- 0x258d, 0x7003, 0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078,
- 0x39c8, 0x00c0, 0x25b3, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010,
- 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0020, 0x7184,
- 0x79aa, 0x78ab, 0x000d, 0x789b, 0x0060, 0x78ab, 0x0004, 0x785b,
- 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0, 0x25b3, 0x7003,
- 0x0004, 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0,
- 0x25da, 0x7180, 0x8107, 0x7882, 0x789b, 0x0010, 0xa18c, 0x001f,
- 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab,
- 0x0002, 0x785b, 0x0004, 0x2009, 0x00dd, 0x1078, 0x2ecc, 0x00c0,
- 0x25da, 0x7088, 0x708b, 0x0000, 0x2068, 0x704a, 0x7003, 0x0002,
- 0x7093, 0x000f, 0x0078, 0x24fa, 0x1078, 0x39c8, 0x00c0, 0x24fa,
- 0x7088, 0x2068, 0x6f14, 0x1078, 0x38bd, 0x2c50, 0x1078, 0x3a7a,
- 0x789b, 0x0010, 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa,
- 0x6e1c, 0x2041, 0x0001, 0x708c, 0xa084, 0x0400, 0x2001, 0x0004,
- 0x0040, 0x25fc, 0x2001, 0x0006, 0x0078, 0x271d, 0x1078, 0x39c8,
- 0x00c0, 0x24fa, 0x789b, 0x0010, 0x7068, 0x2068, 0x6f14, 0x1078,
- 0x38bd, 0x2c50, 0x1078, 0x3a7a, 0x6008, 0xa085, 0x0010, 0x600a,
- 0x6824, 0xa005, 0x0040, 0x261c, 0xa082, 0x0006, 0x0048, 0x261a,
- 0x0078, 0x261c, 0x6827, 0x0005, 0x6b14, 0xa39c, 0x001f, 0xa39d,
- 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040, 0x262a, 0xa684, 0x0001,
- 0x0040, 0x262c, 0xa39c, 0xffbf, 0x7baa, 0x2031, 0x0020, 0x2041,
- 0x0001, 0x2001, 0x0003, 0x0078, 0x271d, 0x0018, 0x24b1, 0x744c,
- 0xa485, 0x0000, 0x0040, 0x264f, 0xa080, 0x5280, 0x2030, 0x7150,
- 0x8108, 0xa12a, 0x0048, 0x2646, 0x2009, 0x5280, 0x2164, 0x6504,
- 0x85ff, 0x00c0, 0x2660, 0x8421, 0x00c0, 0x2640, 0x7152, 0x7003,
- 0x0000, 0x704b, 0x0000, 0x7040, 0xa005, 0x0040, 0x3c72, 0x0078,
- 0x24fa, 0x764c, 0xa6b0, 0x5280, 0x7150, 0x2600, 0x0078, 0x264b,
- 0x7152, 0x2568, 0x2558, 0x754a, 0x2c50, 0x6034, 0xa085, 0x0000,
- 0x00c0, 0x265d, 0x6708, 0x773a, 0xa784, 0x033f, 0x0040, 0x2696,
- 0xa784, 0x0021, 0x00c0, 0x265d, 0xa784, 0x0002, 0x0040, 0x267f,
- 0xa784, 0x0004, 0x0040, 0x265d, 0xa7bc, 0xfffb, 0x670a, 0xa784,
- 0x0008, 0x00c0, 0x265d, 0xa784, 0x0010, 0x00c0, 0x265d, 0xa784,
- 0x0200, 0x00c0, 0x265d, 0xa784, 0x0100, 0x0040, 0x2696, 0x6018,
- 0xa005, 0x00c0, 0x265d, 0xa7bc, 0xfeff, 0x670a, 0x6823, 0x0000,
- 0x6e1c, 0xa684, 0x000e, 0x6118, 0x0040, 0x26a6, 0x601c, 0xa102,
- 0x0048, 0x26a9, 0x0040, 0x26a9, 0x0078, 0x2659, 0x81ff, 0x00c0,
- 0x2659, 0x68c3, 0x0000, 0xa784, 0x0080, 0x00c0, 0x26b1, 0x700c,
- 0x6022, 0xa7bc, 0xff7f, 0x670a, 0x1078, 0x3a7a, 0x0018, 0x24b1,
- 0x789b, 0x0010, 0xa046, 0x1078, 0x39c8, 0x00c0, 0x24fa, 0x6b14,
- 0xa39c, 0x001f, 0xa39d, 0x00c0, 0x7058, 0xa084, 0x8000, 0x0040,
- 0x26cd, 0xa684, 0x0001, 0x0040, 0x26cf, 0xa39c, 0xffbf, 0xa684,
- 0x0010, 0x0040, 0x26d5, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684,
- 0x000e, 0x00c0, 0x26e0, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x271b,
- 0x7158, 0xa18c, 0x0800, 0x0040, 0x34cb, 0x2011, 0x0020, 0xa684,
- 0x0008, 0x00c0, 0x26f1, 0x8210, 0xa684, 0x0002, 0x00c0, 0x26f1,
- 0x8210, 0x7aaa, 0x8840, 0x1078, 0x39e0, 0x6a14, 0x610c, 0x8108,
- 0xa18c, 0x00ff, 0xa1e0, 0x7500, 0x2c64, 0x8cff, 0x0040, 0x2712,
- 0x6014, 0xa206, 0x00c0, 0x26fc, 0x60b8, 0x8001, 0x60ba, 0x00c0,
- 0x26f7, 0x0c7e, 0x2a60, 0x6008, 0xa085, 0x0100, 0x600a, 0x0c7f,
- 0x0078, 0x2635, 0x1078, 0x39c8, 0x00c0, 0x24fa, 0x2a60, 0x610e,
- 0x79aa, 0x8840, 0x7132, 0x2001, 0x0001, 0x007e, 0x715c, 0xa184,
- 0x0018, 0x0040, 0x2738, 0xa184, 0x0010, 0x0040, 0x272b, 0x1078,
- 0x36d0, 0x00c0, 0x275b, 0xa184, 0x0008, 0x0040, 0x2738, 0x69a0,
- 0xa184, 0x0600, 0x00c0, 0x2738, 0x1078, 0x35bb, 0x0078, 0x275b,
- 0x69a0, 0xa184, 0x0800, 0x0040, 0x274f, 0x0c7e, 0x027e, 0x2960,
- 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010, 0x6106,
- 0x027f, 0x0c7f, 0x1078, 0x36d0, 0x00c0, 0x275b, 0x69a0, 0xa184,
- 0x0200, 0x0040, 0x2757, 0x1078, 0x360c, 0x0078, 0x275b, 0xa184,
- 0x0400, 0x00c0, 0x2734, 0x69a0, 0xa184, 0x1000, 0x0040, 0x2766,
- 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x238b, 0x007f, 0x7002,
- 0xa68c, 0x00e0, 0xa684, 0x0060, 0x0040, 0x2774, 0xa086, 0x0060,
- 0x00c0, 0x2774, 0xa18d, 0x4000, 0x88ff, 0x0040, 0x2779, 0xa18d,
- 0x0004, 0x795a, 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b,
- 0x0061, 0x6818, 0xa08d, 0x8000, 0xa084, 0x7fff, 0x691a, 0xa68c,
- 0x0080, 0x0040, 0x2798, 0x7097, 0x0000, 0xa08a, 0x000d, 0x0050,
- 0x2796, 0xa08a, 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a,
- 0x78aa, 0x8008, 0x810c, 0x0040, 0x34d1, 0xa18c, 0x00f8, 0x00c0,
- 0x34d1, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000,
- 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
- 0x157f, 0x6814, 0x8007, 0x7882, 0x6d94, 0x7dd6, 0x7dde, 0x6e98,
- 0x7ed2, 0x7eda, 0x1078, 0x39c8, 0x00c0, 0x27cf, 0x702c, 0x8003,
- 0x0048, 0x27c8, 0x2019, 0x4eaf, 0x1078, 0x2313, 0x702f, 0x8000,
- 0x7830, 0xa084, 0x00c0, 0x00c0, 0x27cf, 0x0098, 0x27d7, 0x6008,
- 0xa084, 0xffef, 0x600a, 0x1078, 0x39e0, 0x0078, 0x2523, 0x7200,
- 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x27e4, 0x781b, 0x004f,
- 0x1078, 0x39e0, 0x0078, 0x27f5, 0x6ab4, 0xa295, 0x2000, 0x7a5a,
- 0x781b, 0x004f, 0x1078, 0x39e0, 0x7200, 0x2500, 0xa605, 0x0040,
- 0x27f5, 0xa284, 0x0007, 0x1079, 0x2803, 0xad80, 0x0009, 0x7036,
- 0xa284, 0x0007, 0xa086, 0x0001, 0x00c0, 0x24fa, 0x6018, 0x8000,
- 0x601a, 0x0078, 0x24fa, 0x280b, 0x4b4b, 0x4b4b, 0x4b3a, 0x4b4b,
- 0x280b, 0x4b3a, 0x280b, 0x1078, 0x248c, 0x1078, 0x39c8, 0x0f7e,
- 0x2079, 0x5200, 0x78cc, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x2831,
- 0x706c, 0xa086, 0x0001, 0x00c0, 0x2820, 0x706e, 0x0078, 0x28c4,
- 0x706c, 0xa086, 0x0005, 0x00c0, 0x282f, 0x7088, 0x2068, 0x681b,
- 0x0004, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822, 0x706f,
- 0x0000, 0x2011, 0x0004, 0x716c, 0xa186, 0x0001, 0x0040, 0x2852,
- 0xa186, 0x0007, 0x00c0, 0x2842, 0x2009, 0x5238, 0x200b, 0x0005,
- 0x0078, 0x2852, 0x2009, 0x5213, 0x2104, 0x2009, 0x5212, 0x200a,
- 0x2009, 0x5238, 0x200b, 0x0001, 0x706f, 0x0000, 0x7073, 0x0001,
- 0x0078, 0x2854, 0x706f, 0x0000, 0x1078, 0x4887, 0x157e, 0x20a9,
- 0x0010, 0x2039, 0x0000, 0x1078, 0x37b0, 0xa7b8, 0x0100, 0x0070,
- 0x2863, 0x0078, 0x285b, 0x157f, 0x7000, 0x0079, 0x2867, 0x2895,
- 0x287c, 0x287c, 0x286f, 0x2895, 0x2895, 0x2895, 0x2895, 0x2021,
- 0x525a, 0x2404, 0xa005, 0x0040, 0x2895, 0xad06, 0x00c0, 0x287c,
- 0x6800, 0x2022, 0x0078, 0x288c, 0x6820, 0xa084, 0x0001, 0x00c0,
- 0x2888, 0x6f14, 0x1078, 0x38bd, 0x1078, 0x34a2, 0x0078, 0x288c,
- 0x7060, 0x2060, 0x6800, 0x6002, 0x6a1a, 0x6817, 0x0000, 0x6820,
- 0xa085, 0x0008, 0x6822, 0x1078, 0x1cdc, 0x2021, 0x7600, 0x1078,
- 0x28d1, 0x2021, 0x525a, 0x1078, 0x28d1, 0x157e, 0x20a9, 0x0000,
- 0x2021, 0x7500, 0x1078, 0x28d1, 0x8420, 0x0070, 0x28a9, 0x0078,
- 0x28a2, 0x2061, 0x5500, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6018,
- 0x6110, 0x81ff, 0x0040, 0x28b8, 0xa102, 0x0050, 0x28b8, 0x6012,
- 0x601b, 0x0000, 0xace0, 0x0010, 0x0070, 0x28c0, 0x0078, 0x28af,
- 0x8421, 0x00c0, 0x28ad, 0x157f, 0x709c, 0xa084, 0x8000, 0x0040,
- 0x28cb, 0x1078, 0x3ace, 0x7003, 0x0000, 0x704b, 0x0000, 0x0078,
- 0x24fa, 0x047e, 0x2404, 0xa005, 0x0040, 0x28e5, 0x2068, 0x6800,
- 0x007e, 0x6a1a, 0x6817, 0x0000, 0x6820, 0xa085, 0x0008, 0x6822,
- 0x1078, 0x1cdc, 0x007f, 0x0078, 0x28d3, 0x047f, 0x2023, 0x0000,
- 0x007c, 0xa282, 0x0003, 0x0050, 0x28ef, 0x1078, 0x248c, 0x2300,
- 0x0079, 0x28f2, 0x28f5, 0x2968, 0x2985, 0xa282, 0x0002, 0x0040,
- 0x28fb, 0x1078, 0x248c, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000,
- 0x0079, 0x2902, 0x290a, 0x290a, 0x290c, 0x2940, 0x34d7, 0x290a,
- 0x2940, 0x290a, 0x1078, 0x248c, 0x7780, 0x1078, 0x37b0, 0x7780,
- 0xa7bc, 0x0f00, 0x1078, 0x38bd, 0x6018, 0xa005, 0x0040, 0x2937,
- 0x2021, 0x7600, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x29a0,
- 0x0040, 0x2937, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7500, 0x047e,
- 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x29a0, 0x047f, 0x0040,
- 0x2936, 0x8420, 0x0070, 0x2936, 0x0078, 0x2927, 0x157f, 0x8738,
- 0xa784, 0x001f, 0x00c0, 0x2912, 0x0078, 0x2523, 0x0078, 0x2523,
- 0x7780, 0x1078, 0x38bd, 0x6018, 0xa005, 0x0040, 0x2966, 0x2021,
- 0x7600, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x29a0, 0x0040,
- 0x2966, 0x157e, 0x20a9, 0x0000, 0x2021, 0x7500, 0x047e, 0x2009,
- 0x0005, 0x2011, 0x0020, 0x1078, 0x29a0, 0x047f, 0x0040, 0x2965,
- 0x8420, 0x0070, 0x2965, 0x0078, 0x2956, 0x157f, 0x0078, 0x2523,
- 0x2200, 0x0079, 0x296b, 0x296e, 0x2970, 0x2970, 0x1078, 0x248c,
- 0x2009, 0x0012, 0x706c, 0xa086, 0x0002, 0x0040, 0x2979, 0x2009,
- 0x000e, 0x6818, 0xa084, 0x8000, 0x0040, 0x297f, 0x691a, 0x706f,
- 0x0000, 0x7073, 0x0001, 0x0078, 0x3956, 0x2200, 0x0079, 0x2988,
- 0x298d, 0x2970, 0x298b, 0x1078, 0x248c, 0x1078, 0x4887, 0x7000,
- 0xa086, 0x0001, 0x00c0, 0x3467, 0x1078, 0x34b8, 0x6008, 0xa084,
- 0xffef, 0x600a, 0x1078, 0x345a, 0x0040, 0x3467, 0x0078, 0x2635,
- 0x2404, 0xa005, 0x0040, 0x29c3, 0x2068, 0x2d04, 0x007e, 0x6814,
- 0xa706, 0x0040, 0x29af, 0x2d20, 0x007f, 0x0078, 0x29a1, 0x007f,
- 0x2022, 0x691a, 0x6817, 0x0000, 0x6820, 0xa205, 0x6822, 0x1078,
- 0x1cdc, 0x6010, 0x8001, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a,
- 0x1078, 0x34b8, 0x007c, 0xa085, 0x0001, 0x0078, 0x29c2, 0x2300,
- 0x0079, 0x29ca, 0x29cf, 0x29cd, 0x2a68, 0x1078, 0x248c, 0x78ec,
- 0xa084, 0x0001, 0x00c0, 0x29e3, 0x7000, 0xa086, 0x0004, 0x00c0,
- 0x29db, 0x0078, 0x2a06, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x0078, 0x3467, 0x78e4, 0xa005, 0x00d0, 0x2a06, 0x0018,
- 0x24fa, 0x2008, 0xa084, 0x0030, 0x00c0, 0x29f2, 0x781b, 0x004f,
- 0x0078, 0x24fa, 0x78ec, 0xa084, 0x0003, 0x0040, 0x29ee, 0x2100,
- 0xa084, 0x0007, 0x0079, 0x29fc, 0x2a3f, 0x2a4a, 0x2a30, 0x2a04,
- 0x39bb, 0x39bb, 0x2a04, 0x2a59, 0x1078, 0x248c, 0x7000, 0xa086,
- 0x0004, 0x00c0, 0x2a20, 0x706c, 0xa086, 0x0002, 0x00c0, 0x2a16,
- 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x28e9, 0x706c, 0xa086,
- 0x0006, 0x0040, 0x2a10, 0x706c, 0xa086, 0x0004, 0x0040, 0x2a10,
- 0x79e4, 0xa184, 0x0030, 0x0040, 0x2a2a, 0x78ec, 0xa084, 0x0003,
- 0x00c0, 0x2a2c, 0x0078, 0x300c, 0x2001, 0x0003, 0x0078, 0x2da0,
- 0x6818, 0xa084, 0x8000, 0x0040, 0x2a37, 0x681b, 0x001d, 0x1078,
- 0x378f, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa, 0x6818,
- 0xa084, 0x8000, 0x0040, 0x2a46, 0x681b, 0x001d, 0x1078, 0x378f,
- 0x0078, 0x3986, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a51, 0x681b,
- 0x001d, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b, 0x00ca, 0x0078,
- 0x24fa, 0x6818, 0xa084, 0x8000, 0x0040, 0x2a60, 0x681b, 0x001d,
- 0x1078, 0x378f, 0x782b, 0x3008, 0x781b, 0x008f, 0x0078, 0x24fa,
- 0xa584, 0x000f, 0x00c0, 0x2a85, 0x7000, 0x0079, 0x2a6f, 0x2523,
- 0x2a79, 0x2a77, 0x3467, 0x3467, 0x3467, 0x3467, 0x2a77, 0x1078,
- 0x248c, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
- 0x345a, 0x0040, 0x3467, 0x0078, 0x2635, 0x78e4, 0xa005, 0x00d0,
- 0x2a06, 0x0018, 0x2a06, 0x2008, 0xa084, 0x0030, 0x00c0, 0x2a94,
- 0x781b, 0x004f, 0x0078, 0x24fa, 0x78ec, 0xa084, 0x0003, 0x0040,
- 0x2a90, 0x2100, 0xa184, 0x0007, 0x0079, 0x2a9e, 0x2ab0, 0x2ab4,
- 0x2aa8, 0x2aa6, 0x39bb, 0x39bb, 0x2aa6, 0x39b1, 0x1078, 0x248c,
- 0x1078, 0x3797, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa,
- 0x1078, 0x3797, 0x0078, 0x3986, 0x1078, 0x3797, 0x782b, 0x3008,
- 0x781b, 0x00ca, 0x0078, 0x24fa, 0x1078, 0x3797, 0x782b, 0x3008,
- 0x781b, 0x008f, 0x0078, 0x24fa, 0x2300, 0x0079, 0x2ac7, 0x2acc,
- 0x2aca, 0x2ace, 0x1078, 0x248c, 0x0078, 0x3180, 0x681b, 0x0008,
- 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0040, 0x3180, 0x78ec,
- 0xa084, 0x0003, 0x0040, 0x3180, 0xa184, 0x0007, 0x0079, 0x2ae0,
- 0x2ae8, 0x2ab4, 0x2a30, 0x3956, 0x39bb, 0x39bb, 0x2ae8, 0x39b1,
- 0x1078, 0x396a, 0x0078, 0x24fa, 0xa282, 0x0005, 0x0050, 0x2af2,
- 0x1078, 0x248c, 0x2300, 0x0079, 0x2af5, 0x2af8, 0x2d4d, 0x2d5b,
- 0x2200, 0x0079, 0x2afb, 0x2b15, 0x2b02, 0x2b15, 0x2b00, 0x2d32,
- 0x1078, 0x248c, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa082,
- 0x0020, 0x0048, 0x376b, 0xa08a, 0x0004, 0x00c8, 0x376b, 0x0079,
- 0x2b11, 0x376b, 0x376b, 0x376b, 0x3719, 0x789b, 0x0018, 0x79a8,
- 0xa184, 0x0080, 0x0040, 0x2b26, 0x0078, 0x376b, 0x7000, 0xa005,
- 0x00c0, 0x2b1c, 0x2011, 0x0004, 0x0078, 0x32e9, 0xa184, 0x00ff,
- 0xa08a, 0x0010, 0x00c8, 0x376b, 0x0079, 0x2b2e, 0x2b40, 0x2b3e,
- 0x2b58, 0x2b5c, 0x2c17, 0x376b, 0x376b, 0x2c19, 0x376b, 0x376b,
- 0x2d2e, 0x2d2e, 0x376b, 0x376b, 0x376b, 0x2d30, 0x1078, 0x248c,
- 0xa684, 0x1000, 0x0040, 0x2b4d, 0x2001, 0x0500, 0x8000, 0x8000,
- 0x783a, 0x781b, 0x008d, 0x0078, 0x24fa, 0x6818, 0xa084, 0x8000,
- 0x0040, 0x2b56, 0x681b, 0x001d, 0x0078, 0x2b44, 0x0078, 0x3956,
- 0x681b, 0x001d, 0x0078, 0x377b, 0x6920, 0x6922, 0xa684, 0x1800,
- 0x00c0, 0x2b9d, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2ba5, 0x6818,
- 0xa086, 0x0008, 0x00c0, 0x2b6e, 0x681b, 0x0000, 0xa684, 0x0400,
- 0x0040, 0x2c13, 0xa684, 0x0080, 0x0040, 0x2b99, 0x7097, 0x0000,
- 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0050, 0x2b99, 0xa08a,
- 0x000c, 0x7196, 0x2001, 0x000c, 0x800c, 0x719a, 0x789b, 0x0061,
- 0x78aa, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000,
- 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f,
- 0x157f, 0x781b, 0x0058, 0x0078, 0x24fa, 0xa684, 0x1000, 0x0040,
- 0x2ba5, 0x781b, 0x0065, 0x0078, 0x24fa, 0xa684, 0x0060, 0x0040,
- 0x2c0f, 0xa684, 0x0800, 0x0040, 0x2c0f, 0xa684, 0x8000, 0x00c0,
- 0x2bb3, 0x0078, 0x2bcb, 0xa6b4, 0x7fff, 0x7e5a, 0x6eb6, 0x7adc,
- 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x2bbe, 0x8000, 0xa084, 0x003f,
- 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94,
- 0x2200, 0xa303, 0x68ae, 0xa684, 0x4000, 0x0040, 0x2bd3, 0xa6b4,
- 0xbfff, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003, 0x00c0, 0x2be0,
- 0x1078, 0x493d, 0x1078, 0x4b3a, 0x781b, 0x0064, 0x0078, 0x24fa,
- 0xa006, 0x1078, 0x4c41, 0x6ab0, 0x69ac, 0x6c98, 0x6b94, 0x2200,
- 0xa105, 0x0040, 0x2bef, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa,
- 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x00c0,
- 0x2c01, 0xa6b5, 0x4000, 0x7e5a, 0x6eb6, 0x781b, 0x0064, 0x0078,
- 0x24fa, 0x781b, 0x0064, 0x2200, 0xa115, 0x00c0, 0x2c0b, 0x1078,
- 0x4b4b, 0x0078, 0x24fa, 0x1078, 0x4b96, 0x0078, 0x24fa, 0x781b,
- 0x0065, 0x0078, 0x24fa, 0x781b, 0x0058, 0x0078, 0x24fa, 0x1078,
- 0x248c, 0x0078, 0x2c7a, 0x6920, 0xa184, 0x0100, 0x0040, 0x2c31,
- 0xa18c, 0xfeff, 0x6922, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084,
- 0xefff, 0x6002, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x0078,
- 0x2c69, 0xa184, 0x0200, 0x0040, 0x2c69, 0xa18c, 0xfdff, 0x6922,
- 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0xdfff, 0x6002, 0x6004,
- 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0008,
- 0x0040, 0x2c69, 0x1078, 0x38b9, 0x1078, 0x35bb, 0x88ff, 0x0040,
- 0x2c69, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004,
- 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2c63, 0x782b, 0x3008, 0x781b,
- 0x0056, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
- 0x24fa, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2c72, 0x781b, 0x0058,
- 0x0078, 0x24fa, 0x781b, 0x0065, 0x0078, 0x24fa, 0x0078, 0x3773,
- 0x0078, 0x3773, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x00c0,
- 0x2c88, 0x6820, 0xa084, 0x0100, 0x0040, 0x2c78, 0x2009, 0x0008,
- 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
- 0x2cbf, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x2cb7,
- 0x0048, 0x2c9c, 0x0078, 0x2cb9, 0xa380, 0x0002, 0xa102, 0x00c8,
- 0x2cb7, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0c7e, 0x7054, 0x2060,
- 0x6000, 0xa084, 0xefef, 0x6002, 0x6004, 0xa084, 0xffe5, 0x6006,
- 0x0c7f, 0x7e58, 0xa6b4, 0xfffb, 0x7e5a, 0x0078, 0x2c6a, 0x0078,
- 0x2c1b, 0x24a8, 0x7aa8, 0x00f0, 0x2cb9, 0x0078, 0x2c8a, 0xa284,
- 0x00f0, 0xa086, 0x0020, 0x00c0, 0x2d1f, 0x8318, 0x8318, 0x2300,
- 0xa102, 0x0040, 0x2ccf, 0x0048, 0x2ccf, 0x0078, 0x2d1c, 0xa286,
- 0x0023, 0x0040, 0x2c78, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
- 0xa684, 0xfff1, 0xa085, 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085,
- 0x0010, 0x600a, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008, 0x2c48,
- 0x0c7f, 0xa184, 0x0010, 0x0040, 0x2cf3, 0x1078, 0x38b9, 0x1078,
- 0x36d0, 0x0078, 0x2d02, 0x0c7e, 0x7054, 0x2060, 0x6004, 0x2008,
- 0x2c48, 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2c69, 0x1078, 0x38b9,
- 0x1078, 0x35bb, 0x88ff, 0x0040, 0x2c69, 0x789b, 0x0060, 0x2800,
- 0x78aa, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2d16,
- 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa, 0x782b, 0x3008,
- 0x781b, 0x0065, 0x0078, 0x24fa, 0x7aa8, 0x0078, 0x2c8a, 0x8318,
- 0x2300, 0xa102, 0x0040, 0x2d28, 0x0048, 0x2d28, 0x0078, 0x2c8a,
- 0xa284, 0x0080, 0x00c0, 0x377b, 0x0078, 0x3773, 0x0078, 0x377b,
- 0x0078, 0x376b, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e,
- 0x0001, 0x0040, 0x2d3d, 0x1078, 0x248c, 0x7aa8, 0xa294, 0x00ff,
- 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x376b, 0x0079,
- 0x2d49, 0x376b, 0x3508, 0x376b, 0x3665, 0xa282, 0x0000, 0x00c0,
- 0x2d53, 0x1078, 0x248c, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
- 0x0065, 0x0078, 0x24fa, 0xa282, 0x0003, 0x00c0, 0x2d61, 0x1078,
- 0x248c, 0xa484, 0x8000, 0x00c0, 0x2d84, 0x706c, 0xa005, 0x0040,
- 0x2d6b, 0x1078, 0x248c, 0x6f14, 0x7782, 0xa7bc, 0x0f00, 0x1078,
- 0x38bd, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f,
- 0x00c0, 0x2d6f, 0x1078, 0x3793, 0x706f, 0x0002, 0x2009, 0x5238,
- 0x200b, 0x0009, 0x0078, 0x2d86, 0x1078, 0x379f, 0x782b, 0x3008,
- 0x781b, 0x0065, 0x0078, 0x24fa, 0xa282, 0x0004, 0x0050, 0x2d92,
- 0x1078, 0x248c, 0x2300, 0x0079, 0x2d95, 0x2d98, 0x2e81, 0x2eb4,
- 0xa286, 0x0003, 0x0040, 0x2d9e, 0x1078, 0x248c, 0x2001, 0x0000,
- 0x007e, 0x68c0, 0xa005, 0x0040, 0x2da7, 0x7003, 0x0003, 0x68a0,
- 0xa084, 0x2000, 0x0040, 0x2db0, 0x6008, 0xa085, 0x0002, 0x600a,
- 0x007f, 0x703e, 0x7000, 0xa084, 0x0007, 0x0079, 0x2db7, 0x2523,
- 0x2dc1, 0x2dc1, 0x2fb6, 0x2ff2, 0x2523, 0x2ff2, 0x2dbf, 0x1078,
- 0x248c, 0xa684, 0x1000, 0x00c0, 0x2dc9, 0x1078, 0x4887, 0x0040,
- 0x2e5b, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x2e11, 0xa186, 0x0008,
- 0x00c0, 0x2de0, 0x1078, 0x34b8, 0x6008, 0xa084, 0xffef, 0x600a,
- 0x1078, 0x345a, 0x0040, 0x2e11, 0x1078, 0x4887, 0x0078, 0x2df8,
- 0xa186, 0x0028, 0x00c0, 0x2e11, 0x1078, 0x4887, 0x6008, 0xa084,
- 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x2df8, 0x8001, 0x601a,
- 0xa005, 0x0040, 0x2df8, 0x8001, 0xa005, 0x0040, 0x2df8, 0x601e,
- 0x6820, 0xa084, 0x0001, 0x0040, 0x2523, 0x6820, 0xa084, 0xfffe,
- 0x6822, 0x7060, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004,
- 0x6802, 0xa005, 0x2d00, 0x00c0, 0x2e0e, 0x6002, 0x6006, 0x0078,
- 0x2523, 0x017e, 0x1078, 0x2ee5, 0x017f, 0xa684, 0xdf00, 0x681e,
- 0x682b, 0x0000, 0x6f14, 0x81ff, 0x0040, 0x2e5b, 0xa186, 0x0002,
- 0x00c0, 0x2e5b, 0xa684, 0x0800, 0x00c0, 0x2e2e, 0xa684, 0x0060,
- 0x0040, 0x2e2e, 0x78d8, 0x7adc, 0x682e, 0x6a32, 0x6820, 0xa084,
- 0x0800, 0x00c0, 0x2e5b, 0x8717, 0xa294, 0x000f, 0x8213, 0x8213,
- 0x8213, 0xa290, 0x5480, 0xa290, 0x0000, 0x221c, 0xa384, 0x0100,
- 0x00c0, 0x2e44, 0x0078, 0x2e4a, 0x8210, 0x2204, 0xa085, 0x0018,
- 0x2012, 0x8211, 0xa384, 0x0400, 0x0040, 0x2e57, 0x68a0, 0xa084,
- 0x0100, 0x00c0, 0x2e57, 0x1078, 0x2f69, 0x0078, 0x2523, 0x6008,
- 0xa085, 0x0002, 0x600a, 0x6916, 0x6818, 0xa084, 0x8000, 0x0040,
- 0x2e63, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x1078, 0x34a9,
- 0x1078, 0x34b8, 0x00c0, 0x2e70, 0x6008, 0xa084, 0xffef, 0x600a,
- 0x6820, 0xa084, 0x0001, 0x00c0, 0x2e79, 0x1078, 0x34a2, 0x0078,
- 0x2e7d, 0x7060, 0x2060, 0x6800, 0x6002, 0x1078, 0x1cdc, 0x0078,
- 0x2523, 0xa282, 0x0004, 0x0048, 0x2e87, 0x1078, 0x248c, 0x2200,
- 0x0079, 0x2e8a, 0x2e85, 0x2e8e, 0x2e9b, 0x2e8e, 0x7000, 0xa086,
- 0x0005, 0x0040, 0x2e97, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
- 0x0065, 0x0078, 0x24fa, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007,
- 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003,
- 0x0040, 0x2eb0, 0xa186, 0x0000, 0x0040, 0x2eb0, 0x0078, 0x376b,
- 0x781b, 0x0065, 0x0078, 0x24fa, 0x6820, 0xa085, 0x0004, 0x6822,
- 0x82ff, 0x00c0, 0x2ebf, 0x1078, 0x378f, 0x0078, 0x2ec6, 0x8211,
- 0x0040, 0x2ec4, 0x1078, 0x248c, 0x1078, 0x379f, 0x782b, 0x3008,
- 0x781b, 0x0065, 0x0078, 0x24fa, 0x702c, 0x8003, 0x0048, 0x2ed6,
- 0x2019, 0x4eaf, 0x1078, 0x2313, 0x702f, 0x8000, 0x1078, 0x39e0,
- 0x7830, 0xa084, 0x00c0, 0x00c0, 0x2ee2, 0x0018, 0x2ee2, 0x791a,
- 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684, 0x0060, 0x00c0,
- 0x2eef, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2f68, 0xa684,
- 0x0800, 0x00c0, 0x2f11, 0x68b4, 0xa084, 0x4800, 0xa635, 0xa684,
- 0x0800, 0x00c0, 0x2f11, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x703c,
- 0xa005, 0x00c0, 0x2f09, 0x2200, 0xa105, 0x0040, 0x2f10, 0x703f,
- 0x0015, 0x7000, 0xa086, 0x0006, 0x0040, 0x2f10, 0x1078, 0x4887,
- 0x007c, 0xa684, 0x0020, 0x0040, 0x2f33, 0xa684, 0x4000, 0x0040,
- 0x2f1f, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x2f09, 0x68b4,
- 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x2f19, 0x703c,
- 0xa005, 0x00c0, 0x2f2d, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x692e,
- 0x6a32, 0x0078, 0x2f09, 0xa684, 0x4000, 0x0040, 0x2f3d, 0x682f,
- 0x0000, 0x6833, 0x0000, 0x0078, 0x2f09, 0x68b4, 0xa084, 0x4800,
- 0xa635, 0xa684, 0x4000, 0x00c0, 0x2f37, 0x703c, 0xa005, 0x00c0,
- 0x2f4b, 0x703f, 0x0015, 0x79d8, 0x7adc, 0x78d0, 0x80fb, 0x00c8,
- 0x2f52, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e,
- 0x6a32, 0x2100, 0xa205, 0x00c0, 0x2f5f, 0x0078, 0x2f09, 0x7000,
- 0xa086, 0x0006, 0x0040, 0x2f68, 0x1078, 0x4c41, 0x0078, 0x2f09,
- 0x007c, 0x6008, 0xa085, 0x0200, 0x600a, 0xa384, 0x0200, 0x0040,
- 0x2f75, 0x6008, 0xa085, 0x0002, 0x600a, 0x681b, 0x0006, 0x688f,
- 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f,
- 0x0003, 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b,
- 0x0020, 0x68b3, 0x0000, 0x68af, 0x0000, 0x7000, 0x0079, 0x2f90,
- 0x2523, 0x2f9a, 0x2fa3, 0x2f98, 0x2f98, 0x2f98, 0x2f98, 0x2f98,
- 0x1078, 0x248c, 0x6820, 0xa084, 0x0001, 0x00c0, 0x2fa3, 0x1078,
- 0x34a2, 0x0078, 0x2fa9, 0x7060, 0x2c50, 0x2060, 0x6800, 0x6002,
- 0x2a60, 0x2021, 0x525a, 0x2404, 0xa005, 0x0040, 0x2fb2, 0x2020,
- 0x0078, 0x2fab, 0x2d22, 0x206b, 0x0000, 0x007c, 0x1078, 0x34a9,
- 0x1078, 0x34b8, 0x6008, 0xa084, 0xfdff, 0x600a, 0x682b, 0x0000,
- 0x789b, 0x000e, 0x6f14, 0x6817, 0x0002, 0x1078, 0x4c89, 0xa684,
- 0x0800, 0x0040, 0x2fcf, 0x691c, 0xa18d, 0x2000, 0x691e, 0x6818,
- 0xa084, 0x8000, 0x0040, 0x2fdf, 0x7868, 0xa08c, 0x00ff, 0x0040,
- 0x2fdd, 0x681b, 0x001e, 0x0078, 0x2fdf, 0x681b, 0x0000, 0x2021,
- 0x525a, 0x2404, 0xad06, 0x0040, 0x2fe6, 0x7460, 0x6800, 0x2022,
- 0x68c3, 0x0000, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x1078, 0x1cdc,
- 0x0078, 0x2523, 0x1078, 0x2ee5, 0x682b, 0x0000, 0x2001, 0x000e,
- 0x6f14, 0x1078, 0x39e6, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xa084,
- 0x8000, 0x0040, 0x3005, 0x703c, 0x681a, 0xa68c, 0xdf00, 0x691e,
- 0x706f, 0x0000, 0x0078, 0x2523, 0x7000, 0xa005, 0x00c0, 0x3012,
- 0x0078, 0x2523, 0xa006, 0x1078, 0x4887, 0x6817, 0x0000, 0x681b,
- 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa085,
- 0x00ff, 0x6822, 0x7000, 0x0079, 0x3025, 0x2523, 0x302f, 0x302f,
- 0x3031, 0x3031, 0x3031, 0x3031, 0x302d, 0x1078, 0x248c, 0x1078,
- 0x34b8, 0x6008, 0xa084, 0xffef, 0x600a, 0x0078, 0x3472, 0x2300,
- 0x0079, 0x303a, 0x303d, 0x303f, 0x3098, 0x1078, 0x248c, 0xa684,
- 0x8000, 0x00c0, 0x307d, 0x7000, 0x0079, 0x3046, 0x2523, 0x3050,
- 0x3050, 0x306c, 0x3050, 0x3079, 0x306c, 0x304e, 0x1078, 0x248c,
- 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0, 0x3068, 0xa6b4, 0xffdf,
- 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a, 0x6eb6, 0x681c, 0xa084,
- 0xffdf, 0x681e, 0x1078, 0x4887, 0x1078, 0x4b4b, 0x0078, 0x3956,
- 0xa684, 0x2000, 0x0040, 0x305a, 0x6818, 0xa084, 0x8000, 0x0040,
- 0x3079, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, 0x3079, 0x681b,
- 0x0007, 0x1078, 0x396a, 0x0078, 0x24fa, 0xa6b4, 0x7fff, 0x7e5a,
- 0x7adc, 0x79d8, 0x78d0, 0x79d2, 0x801b, 0x00c8, 0x3088, 0x8000,
- 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
- 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0065, 0x007c,
- 0x1078, 0x248c, 0x2300, 0x0079, 0x309d, 0x30a0, 0x30a2, 0x30eb,
- 0x1078, 0x248c, 0xa684, 0x8000, 0x00c0, 0x30da, 0x7000, 0x0079,
- 0x30a9, 0x2523, 0x30b3, 0x30b3, 0x30cf, 0x30b3, 0x30d6, 0x30cf,
- 0x30b1, 0x1078, 0x248c, 0xa684, 0x0060, 0xa086, 0x0060, 0x00c0,
- 0x30cb, 0xa6b4, 0xffbf, 0xa6b4, 0xbfff, 0xa6b5, 0x2000, 0x7e5a,
- 0x6eb6, 0x681c, 0xa084, 0xffbf, 0x681e, 0x1078, 0x4887, 0x1078,
- 0x4b4b, 0x0078, 0x3956, 0xa684, 0x2000, 0x0040, 0x30bd, 0x6818,
- 0xa084, 0x8000, 0x0040, 0x30d6, 0x681b, 0x0007, 0x781b, 0x00ca,
- 0x0078, 0x24fa, 0xa6b4, 0x7fff, 0x7e5a, 0x7adc, 0x79d8, 0x6b98,
- 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2,
- 0x781b, 0x0065, 0x007c, 0x6820, 0xa085, 0x0004, 0x6822, 0x1078,
- 0x3921, 0xa6b5, 0x0800, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
- 0x0065, 0x0078, 0x24fa, 0x2300, 0x0079, 0x30fe, 0x3101, 0x3103,
- 0x3105, 0x1078, 0x248c, 0x0078, 0x377b, 0xa684, 0x0400, 0x00c0,
- 0x312e, 0x79e4, 0xa184, 0x0020, 0x0040, 0x3115, 0x78ec, 0xa084,
- 0x0003, 0x0040, 0x3115, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab,
- 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040,
- 0x3126, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x312a, 0x2001, 0x0014,
- 0x0078, 0x2da0, 0xa184, 0x0007, 0x0079, 0x3166, 0x7a90, 0xa294,
- 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0040, 0x3164, 0x789b,
- 0x0010, 0x7ba8, 0xa384, 0x0001, 0x00c0, 0x3155, 0x7ba8, 0x7ba8,
- 0xa386, 0x0001, 0x00c0, 0x3148, 0x2009, 0xfff7, 0x0078, 0x314e,
- 0xa386, 0x0003, 0x00c0, 0x3155, 0x2009, 0xffef, 0x0c7e, 0x7054,
- 0x2060, 0x6004, 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab,
- 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c,
- 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3956, 0x2a3f, 0x2a4a,
- 0x3170, 0x3178, 0x316e, 0x316e, 0x3956, 0x3956, 0x1078, 0x248c,
- 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3960,
- 0x6920, 0xa18c, 0xfdff, 0xa18c, 0xfeff, 0x6922, 0x0078, 0x3956,
- 0x79e4, 0xa184, 0x0030, 0x0040, 0x318a, 0x78ec, 0xa084, 0x0003,
- 0x00c0, 0x31b1, 0x7000, 0xa086, 0x0004, 0x00c0, 0x31a4, 0x706c,
- 0xa086, 0x0002, 0x00c0, 0x319a, 0x2011, 0x0002, 0x2019, 0x0000,
- 0x0078, 0x28e9, 0x706c, 0xa086, 0x0006, 0x0040, 0x3194, 0x706c,
- 0xa086, 0x0004, 0x0040, 0x3194, 0x7000, 0xa086, 0x0000, 0x0040,
- 0x24fa, 0x6818, 0xa085, 0x8000, 0x681a, 0x2001, 0x0014, 0x0078,
- 0x2da0, 0xa184, 0x0007, 0x0079, 0x31b5, 0x3956, 0x3956, 0x31bd,
- 0x3956, 0x39bb, 0x39bb, 0x3956, 0x3956, 0xa684, 0x0080, 0x0040,
- 0x31ec, 0x7194, 0x81ff, 0x0040, 0x31ec, 0xa182, 0x000d, 0x00d0,
- 0x31cd, 0x7097, 0x0000, 0x0078, 0x31d2, 0xa182, 0x000c, 0x7096,
- 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x157e, 0x137e, 0x147e,
- 0x7098, 0x8114, 0xa210, 0x729a, 0xa080, 0x000b, 0xad00, 0x2098,
- 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f,
- 0x137f, 0x157f, 0x0078, 0x3960, 0xa684, 0x0400, 0x00c0, 0x322d,
- 0x6820, 0xa084, 0x0001, 0x0040, 0x3960, 0xa68c, 0x0060, 0xa684,
- 0x0060, 0x0040, 0x3201, 0xa086, 0x0060, 0x00c0, 0x3201, 0xa18d,
- 0x4000, 0xa18c, 0xfffb, 0x795a, 0x69b6, 0x789b, 0x0060, 0x78ab,
- 0x0000, 0x789b, 0x0061, 0x6818, 0xa085, 0x8000, 0x681a, 0x78aa,
- 0x8008, 0x810c, 0x0040, 0x34d1, 0xa18c, 0x00f8, 0x00c0, 0x34d1,
- 0x157e, 0x137e, 0x147e, 0x20a1, 0x012b, 0x789b, 0x0000, 0x8000,
- 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f,
- 0x6814, 0x8007, 0x7882, 0x0078, 0x3960, 0x6818, 0xa084, 0x8000,
- 0x0040, 0x3234, 0x681b, 0x0008, 0x781b, 0x00c0, 0x0078, 0x24fa,
- 0x2300, 0x0079, 0x323b, 0x3240, 0x32d4, 0x323e, 0x1078, 0x248c,
- 0x7000, 0xa084, 0x0007, 0x0079, 0x3245, 0x2523, 0x324f, 0x3284,
- 0x325a, 0x324d, 0x2523, 0x324d, 0x324d, 0x1078, 0x248c, 0x681c,
- 0xa084, 0x2000, 0x0040, 0x3268, 0x6008, 0xa085, 0x0002, 0x600a,
- 0x0078, 0x3268, 0x68c0, 0xa005, 0x00c0, 0x3284, 0x6920, 0xa18d,
- 0x0001, 0x6922, 0x68c3, 0x0001, 0x6800, 0x706a, 0x0078, 0x327e,
- 0x6920, 0xa18d, 0x0001, 0x6922, 0x6800, 0x6006, 0xa005, 0x00c0,
- 0x3272, 0x6002, 0x681c, 0xa084, 0x000e, 0x0040, 0x327e, 0x7014,
- 0x68ba, 0x7130, 0xa188, 0x7500, 0x0078, 0x3280, 0x2009, 0x7600,
- 0x2104, 0x6802, 0x2d0a, 0x7162, 0x6eb6, 0xa684, 0x0060, 0x0040,
- 0x32d2, 0xa684, 0x0800, 0x00c0, 0x3298, 0xa684, 0x7fff, 0x68b6,
- 0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078, 0x4887, 0x0078, 0x32d2,
- 0xa684, 0x0020, 0x0040, 0x32ad, 0x68c0, 0xa005, 0x0040, 0x32a4,
- 0x1078, 0x4c89, 0x0078, 0x32a7, 0xa006, 0x1078, 0x4c41, 0x79d8,
- 0x7adc, 0x69aa, 0x6aa6, 0x0078, 0x32b3, 0x1078, 0x38ca, 0x69aa,
- 0x6aa6, 0x1078, 0x4c41, 0xa684, 0x8000, 0x0040, 0x32d2, 0xa684,
- 0x7fff, 0x68b6, 0x7adc, 0x79d8, 0xa684, 0x0020, 0x00c0, 0x32ca,
- 0x78d0, 0x801b, 0x00c8, 0x32c5, 0x8000, 0xa084, 0x003f, 0xa108,
- 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200,
- 0xa303, 0x68ae, 0x0078, 0x2523, 0x0078, 0x377b, 0x7037, 0x0000,
- 0xa282, 0x0006, 0x0050, 0x32de, 0x1078, 0x248c, 0x7000, 0xa084,
- 0x0007, 0x10c0, 0x3a8c, 0x2300, 0x0079, 0x32e6, 0x32e9, 0x3312,
- 0x3326, 0x2200, 0x0079, 0x32ec, 0x3310, 0x377b, 0x32f2, 0x3310,
- 0x3342, 0x3384, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068, 0x704a,
- 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070, 0x3302,
- 0x0078, 0x32fb, 0x157f, 0xad80, 0x0009, 0x7036, 0x6817, 0x0000,
- 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x0078, 0x376b,
- 0x1078, 0x248c, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068, 0x704a,
- 0xad80, 0x0009, 0x7036, 0x2200, 0x0079, 0x331e, 0x377b, 0x3324,
- 0x3324, 0x3342, 0x3324, 0x377b, 0x1078, 0x248c, 0x7003, 0x0005,
- 0x2001, 0x7710, 0x2068, 0x704a, 0xad80, 0x0009, 0x7036, 0x2200,
- 0x0079, 0x3332, 0x333a, 0x3338, 0x3338, 0x333a, 0x3338, 0x333a,
- 0x1078, 0x248c, 0x1078, 0x379f, 0x782b, 0x3008, 0x781b, 0x0065,
- 0x0078, 0x24fa, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b,
- 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x7600, 0x2d04,
- 0x2d08, 0x7162, 0x2068, 0xa005, 0x0040, 0x335d, 0x6814, 0xa206,
- 0x0040, 0x3379, 0x6800, 0x0078, 0x3350, 0x7003, 0x0005, 0x2001,
- 0x7710, 0x2068, 0x704a, 0x7036, 0x157e, 0x20a9, 0x0031, 0x2003,
- 0x0000, 0x8000, 0x0070, 0x336e, 0x0078, 0x3367, 0x157f, 0xad80,
- 0x0009, 0x7036, 0x6a16, 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827,
- 0x0003, 0x6eb4, 0x7e5a, 0x6820, 0xa084, 0x0c00, 0x0040, 0x33d3,
- 0x1078, 0x3797, 0x0078, 0x33d3, 0x7003, 0x0002, 0x7a80, 0xa294,
- 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x79a8,
- 0x79a8, 0xa18c, 0x00ff, 0xa1e8, 0x7500, 0x2d04, 0x2d08, 0x7162,
- 0x2068, 0xa005, 0x0040, 0x33a3, 0x6814, 0xa206, 0x0040, 0x33be,
- 0x6800, 0x0078, 0x3396, 0x7003, 0x0005, 0x2001, 0x7710, 0x2068,
- 0x704a, 0x157e, 0x20a9, 0x0031, 0x2003, 0x0000, 0x8000, 0x0070,
- 0x33b3, 0x0078, 0x33ac, 0x157f, 0xad80, 0x0009, 0x7036, 0x6a16,
- 0x68b7, 0x0700, 0x6823, 0x0800, 0x6827, 0x0003, 0x6eb4, 0x7e5a,
- 0x6820, 0xa084, 0x0c00, 0x0040, 0x33d3, 0xa084, 0x0800, 0x0040,
- 0x33cd, 0x1078, 0x379b, 0x0078, 0x33d3, 0x1078, 0x3797, 0x708b,
- 0x0000, 0x0078, 0x33d3, 0x027e, 0x8207, 0xa084, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa080, 0x5480, 0x2060, 0x7056, 0x6000, 0x705a,
- 0x6004, 0x705e, 0xa684, 0x0060, 0x0040, 0x342b, 0x6b98, 0x6c94,
- 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x340d, 0x7bd2, 0x7bda, 0x7cd6,
- 0x7cde, 0xa6b4, 0xb7ff, 0x7e5a, 0xa684, 0x0060, 0xa086, 0x0060,
- 0x0040, 0x342b, 0x68c0, 0xa005, 0x0040, 0x3406, 0x7003, 0x0003,
- 0x682b, 0x0000, 0x1078, 0x4b3a, 0x0078, 0x3408, 0x1078, 0x4b4b,
- 0xa6b5, 0x2000, 0x7e5a, 0x0078, 0x342b, 0x68b0, 0xa31a, 0x2100,
- 0xa423, 0x2400, 0xa305, 0x0040, 0x342b, 0x7bd2, 0x7bda, 0x7cd6,
- 0x7cde, 0x68b0, 0xa6b4, 0xbfff, 0x7e5a, 0x007e, 0x68c0, 0xa005,
- 0x007f, 0x0040, 0x3429, 0x7003, 0x0003, 0x1078, 0x4b3a, 0x0078,
- 0x342b, 0x1078, 0x4b96, 0x077f, 0x1078, 0x38bd, 0x2009, 0x0065,
- 0xa684, 0x0004, 0x0040, 0x344c, 0x78e4, 0xa084, 0x0030, 0x0040,
- 0x3444, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3444, 0x782b, 0x3008,
- 0x2009, 0x0065, 0x0078, 0x344c, 0x0f7e, 0x2079, 0x5200, 0x1078,
- 0x4887, 0x0f7f, 0x0040, 0x2523, 0x791a, 0x2d00, 0x704a, 0x8207,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x5480, 0x2048,
- 0x0078, 0x24fa, 0x6020, 0xa005, 0x0040, 0x3466, 0x8001, 0x6022,
- 0x6008, 0xa085, 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006,
- 0x1078, 0x4887, 0x6817, 0x0000, 0x681b, 0x0001, 0x6823, 0x0040,
- 0x681f, 0x0100, 0x7000, 0xa084, 0x0007, 0x0079, 0x3477, 0x2523,
- 0x3481, 0x3481, 0x349e, 0x3489, 0x3487, 0x3489, 0x347f, 0x1078,
- 0x248c, 0x1078, 0x34a9, 0x1078, 0x34a2, 0x1078, 0x1cdc, 0x0078,
- 0x2523, 0x706c, 0x706f, 0x0000, 0x7093, 0x0000, 0x0079, 0x3490,
- 0x349a, 0x349a, 0x3498, 0x3498, 0x3498, 0x349a, 0x3498, 0x349a,
- 0x0079, 0x2902, 0x706f, 0x0000, 0x0078, 0x2523, 0x681b, 0x0000,
- 0x0078, 0x2fb6, 0x6800, 0xa005, 0x00c0, 0x34a7, 0x6002, 0x6006,
- 0x007c, 0x6010, 0xa005, 0x0040, 0x34b2, 0x8001, 0x00d0, 0x34b2,
- 0x1078, 0x248c, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c,
- 0x6018, 0xa005, 0x0040, 0x34be, 0x8001, 0x601a, 0x007c, 0x1078,
- 0x39e0, 0x681b, 0x0018, 0x0078, 0x34f5, 0x1078, 0x39e0, 0x681b,
- 0x0019, 0x0078, 0x34f5, 0x1078, 0x39e0, 0x681b, 0x001a, 0x0078,
- 0x34f5, 0x1078, 0x39e0, 0x681b, 0x0003, 0x0078, 0x34f5, 0x7780,
- 0x1078, 0x38bd, 0x7184, 0xa18c, 0x00ff, 0xa1e8, 0x7500, 0x2d04,
- 0x2d08, 0x2068, 0xa005, 0x00c0, 0x34e7, 0x0078, 0x2523, 0x6814,
- 0x7280, 0xa206, 0x0040, 0x34ef, 0x6800, 0x0078, 0x34e0, 0x6800,
- 0x200a, 0x681b, 0x0005, 0x708b, 0x0000, 0x1078, 0x34a9, 0x6820,
- 0xa084, 0x0001, 0x00c0, 0x34fe, 0x1078, 0x34a2, 0x1078, 0x34b8,
- 0x681f, 0x0000, 0x6823, 0x0020, 0x1078, 0x1cdc, 0x0078, 0x2523,
- 0xa282, 0x0003, 0x00c0, 0x376b, 0x7da8, 0xa5ac, 0x00ff, 0x7ca8,
- 0xa4a4, 0x00ff, 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0100,
- 0x0040, 0x356c, 0xa18c, 0xfeff, 0x6922, 0xa4a4, 0x00ff, 0x0040,
- 0x3556, 0xa482, 0x000c, 0x0048, 0x3529, 0x0040, 0x3529, 0x2021,
- 0x000c, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x3533, 0x1078,
- 0x3627, 0x0078, 0x355f, 0x1078, 0x37e9, 0x0c7e, 0x2960, 0x6004,
- 0xa084, 0xfff5, 0x6006, 0x1078, 0x3652, 0x0c7f, 0x6920, 0xa18d,
- 0x0100, 0x6922, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400,
- 0x00c0, 0x3550, 0x782b, 0x3008, 0x781b, 0x0056, 0x0078, 0x24fa,
- 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa, 0x0c7e, 0x2960,
- 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3652, 0x0c7f, 0x7e58,
- 0xa684, 0x0400, 0x00c0, 0x3568, 0x781b, 0x0058, 0x0078, 0x24fa,
- 0x781b, 0x0065, 0x0078, 0x24fa, 0x0c7e, 0x7054, 0x2060, 0x6100,
- 0xa18c, 0x1000, 0x0040, 0x35ac, 0x6208, 0x8217, 0xa294, 0x00ff,
- 0xa282, 0x000c, 0x0048, 0x3580, 0x0040, 0x3580, 0x2011, 0x000c,
- 0x2400, 0xa202, 0x00c8, 0x3585, 0x2220, 0x6208, 0xa294, 0x00ff,
- 0x7018, 0xa086, 0x0028, 0x00c0, 0x3595, 0xa282, 0x0019, 0x00c8,
- 0x359b, 0x2011, 0x0019, 0x0078, 0x359b, 0xa282, 0x000c, 0x00c8,
- 0x359b, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8, 0x35a0, 0x2228,
- 0x1078, 0x37ed, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x35ac,
- 0x1078, 0x3627, 0x0078, 0x35b0, 0x1078, 0x37e9, 0x1078, 0x3652,
- 0x7858, 0xa085, 0x0004, 0x785a, 0x0c7f, 0x782b, 0x3008, 0x781b,
- 0x0065, 0x0078, 0x24fa, 0x0c7e, 0x2960, 0x6000, 0xd0e4, 0x00c0,
- 0x35d5, 0xd0b4, 0x00c0, 0x35cf, 0x6010, 0xa084, 0x000f, 0x00c0,
- 0x35cf, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x0c7f, 0x007c, 0x2011,
- 0x0032, 0x2019, 0x0000, 0x0078, 0x35fc, 0x68a0, 0xa084, 0x0200,
- 0x00c0, 0x35cf, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028,
- 0x00c0, 0x35ea, 0xa282, 0x0019, 0x00c8, 0x35f0, 0x2011, 0x0019,
- 0x0078, 0x35f0, 0xa282, 0x000c, 0x00c8, 0x35f0, 0x2011, 0x000c,
- 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x35fc,
- 0x0040, 0x35fc, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003,
- 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xa085,
- 0x0100, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0xa18c, 0xfff5,
- 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3617, 0x78ab,
- 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0,
- 0x0005, 0x6820, 0xa085, 0x0100, 0x6822, 0x0c7f, 0x007c, 0x0c7e,
- 0x7154, 0x2160, 0x1078, 0x362e, 0x0c7f, 0x007c, 0x2008, 0xa084,
- 0xfff0, 0xa425, 0x7c86, 0x6018, 0x789a, 0x7cae, 0x6412, 0x78a4,
- 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a,
- 0xa4a4, 0x000f, 0x8427, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa405,
- 0x600e, 0x78ec, 0xd08c, 0x00c0, 0x3651, 0x6004, 0xa084, 0xfff5,
- 0x6006, 0x007c, 0x0c7e, 0x7054, 0x2060, 0x1078, 0x3659, 0x0c7f,
- 0x007c, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6, 0x6012,
- 0x7884, 0xa084, 0xfff0, 0x7886, 0x007c, 0xa282, 0x0002, 0x00c0,
- 0x376b, 0x7aa8, 0x6920, 0xa18d, 0x0080, 0x6922, 0xa184, 0x0200,
- 0x0040, 0x36ae, 0xa18c, 0xfdff, 0x6922, 0xa294, 0x00ff, 0xa282,
- 0x0002, 0x00c8, 0x376b, 0x1078, 0x36f9, 0x1078, 0x3652, 0xa980,
- 0x0001, 0x200c, 0x1078, 0x38b9, 0x1078, 0x35bb, 0x88ff, 0x0040,
- 0x36a1, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xa6b5, 0x0004,
- 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x369b, 0x782b, 0x3008, 0x781b,
- 0x0056, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078,
- 0x24fa, 0x7e58, 0xa684, 0x0400, 0x00c0, 0x36aa, 0x781b, 0x0058,
- 0x0078, 0x24fa, 0x781b, 0x0065, 0x0078, 0x24fa, 0xa282, 0x0002,
- 0x00c8, 0x36b6, 0xa284, 0x0001, 0x0040, 0x36c0, 0x7154, 0xa188,
- 0x0000, 0x210c, 0xa18c, 0x2000, 0x00c0, 0x36c0, 0x2011, 0x0000,
- 0x1078, 0x37db, 0x1078, 0x36f9, 0x1078, 0x3652, 0x7858, 0xa085,
- 0x0004, 0x785a, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa,
- 0x0c7e, 0x027e, 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0,
- 0x36e9, 0xd0bc, 0x00c0, 0x36e7, 0x6014, 0xa084, 0x0040, 0x00c0,
- 0x36e7, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078, 0x36f6, 0x2011,
- 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa,
- 0xa8c0, 0x0004, 0x6820, 0xa085, 0x0200, 0x6822, 0x027f, 0x0c7f,
- 0x007c, 0x0c7e, 0x7054, 0x2060, 0x1078, 0x3700, 0x0c7f, 0x007c,
- 0x82ff, 0x0040, 0x3705, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002,
- 0x789a, 0x78a4, 0xa084, 0xffbf, 0xa205, 0x78a6, 0x788a, 0x6016,
- 0x78ec, 0xd08c, 0x00c0, 0x3718, 0x6004, 0xa084, 0xffef, 0x6006,
- 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x3722, 0x007f,
- 0x0078, 0x3725, 0x007f, 0x0078, 0x3767, 0xa684, 0x0020, 0x0040,
- 0x3767, 0x7888, 0xa084, 0x0040, 0x0040, 0x3767, 0x7bb8, 0xa384,
- 0x003f, 0x831b, 0x00c8, 0x3735, 0x8000, 0xa005, 0x0040, 0x374b,
- 0x831b, 0x00c8, 0x373e, 0x8001, 0x0040, 0x3763, 0xa684, 0x4000,
- 0x0040, 0x374b, 0x78b8, 0x801b, 0x00c8, 0x3747, 0x8000, 0xa084,
- 0x003f, 0x00c0, 0x3763, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc,
- 0x2001, 0x0001, 0xa108, 0x00c8, 0x3757, 0xa291, 0x0000, 0x79d2,
- 0x79da, 0x7ad6, 0x7ade, 0x1078, 0x4c41, 0x781b, 0x0064, 0x1078,
- 0x4ac6, 0x0078, 0x24fa, 0x781b, 0x0064, 0x0078, 0x24fa, 0x781b,
- 0x0065, 0x0078, 0x24fa, 0x1078, 0x37a3, 0x782b, 0x3008, 0x781b,
- 0x0065, 0x0078, 0x24fa, 0x1078, 0x378f, 0x782b, 0x3008, 0x781b,
- 0x0065, 0x0078, 0x24fa, 0x6827, 0x0002, 0x1078, 0x3797, 0x78e4,
- 0xa084, 0x0030, 0x0040, 0x2523, 0x78ec, 0xa084, 0x0003, 0x0040,
- 0x2523, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa, 0x2001,
- 0x0005, 0x0078, 0x37a5, 0x2001, 0x000c, 0x0078, 0x37a5, 0x2001,
- 0x0006, 0x0078, 0x37a5, 0x2001, 0x000d, 0x0078, 0x37a5, 0x2001,
- 0x0009, 0x0078, 0x37a5, 0x2001, 0x0007, 0x789b, 0x0010, 0x78aa,
- 0x789b, 0x0060, 0x78ab, 0x0001, 0xa6b5, 0x0004, 0x7e5a, 0x007c,
- 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0,
- 0x5480, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040,
- 0x37c9, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, 0x0008,
- 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, 0x0040,
- 0x37d9, 0xa184, 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0010,
- 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab,
- 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004,
- 0x007c, 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab,
- 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b,
- 0x0060, 0x78ab, 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff,
- 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0,
- 0x2001, 0x5246, 0x2004, 0xa082, 0x0028, 0x0040, 0x3817, 0x2021,
- 0x38a0, 0x2019, 0x0014, 0x20a9, 0x000c, 0x0078, 0x381d, 0x2021,
- 0x38ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2404,
- 0xa084, 0xfff0, 0xa106, 0x0040, 0x382c, 0x8420, 0x2300, 0xa210,
- 0x0070, 0x382c, 0x0078, 0x381f, 0x157f, 0x007c, 0x157e, 0x2009,
- 0x5246, 0x210c, 0xa182, 0x0032, 0x0048, 0x3842, 0x0040, 0x3846,
- 0x2009, 0x3892, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032,
- 0x0078, 0x3858, 0xa182, 0x0028, 0x0040, 0x3850, 0x2009, 0x38a0,
- 0x2019, 0x0014, 0x20a9, 0x000c, 0x2011, 0x0064, 0x0078, 0x3858,
- 0x2009, 0x38ac, 0x2019, 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064,
- 0x2200, 0xa502, 0x0040, 0x3868, 0x0048, 0x3868, 0x8108, 0x2300,
- 0xa210, 0x0070, 0x3865, 0x0078, 0x3858, 0x157f, 0xa006, 0x007c,
- 0x157f, 0xa582, 0x0064, 0x00c8, 0x3877, 0x7808, 0xa085, 0x0070,
- 0x780a, 0x7044, 0xa085, 0x0070, 0x7046, 0x0078, 0x3877, 0x78ec,
- 0xa084, 0x0300, 0x0040, 0x387f, 0x2104, 0x0078, 0x3890, 0x2104,
- 0xa09e, 0x1102, 0x00c0, 0x3890, 0x2001, 0x04fd, 0x2004, 0xa082,
- 0x0005, 0x0048, 0x388f, 0x2001, 0x1201, 0x0078, 0x3890, 0x2104,
- 0xa005, 0x007c, 0x1102, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
- 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
- 0x3202, 0x4202, 0x5202, 0x6202, 0x7202, 0x6605, 0x7605, 0x7805,
- 0x7a05, 0x7c05, 0x7e05, 0x7f05, 0x2202, 0x3202, 0x4202, 0x5202,
- 0x5404, 0x6404, 0x7404, 0x7604, 0x7804, 0x7a04, 0x7c04, 0x7e04,
- 0x7f04, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00, 0x800b,
- 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e0,
- 0x5500, 0x007c, 0x79d8, 0x7adc, 0x78d0, 0x801b, 0x00c8, 0x38d1,
- 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x007c, 0x0f7e,
- 0x2079, 0x0100, 0x2009, 0x5240, 0x2091, 0x8000, 0x2104, 0x0079,
- 0x38e1, 0x3917, 0x38eb, 0x38eb, 0x38eb, 0x38eb, 0x38eb, 0x38eb,
- 0x391b, 0x1078, 0x248c, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
- 0x00c0, 0x38ed, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
- 0x38f4, 0x68b4, 0xa085, 0x4000, 0x68b6, 0x7858, 0xa085, 0x4000,
- 0x785a, 0x7830, 0xa084, 0x0080, 0x00c0, 0x3917, 0x0018, 0x3917,
- 0x681c, 0xa084, 0x0020, 0x00c0, 0x3915, 0x0e7e, 0x2071, 0x5240,
- 0x1078, 0x396a, 0x0e7f, 0x0078, 0x3917, 0x781b, 0x00ca, 0x2091,
- 0x8001, 0x0f7f, 0x007c, 0x70b3, 0x0000, 0x1078, 0x3b44, 0x0078,
- 0x3917, 0x0c7e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003,
- 0x8003, 0xa0e0, 0x5480, 0x6004, 0xa084, 0x000a, 0x00c0, 0x3954,
- 0x6108, 0xa194, 0xff00, 0x0040, 0x3954, 0xa18c, 0x00ff, 0x2001,
- 0x0019, 0xa106, 0x0040, 0x3943, 0x2001, 0x0032, 0xa106, 0x0040,
- 0x3947, 0x0078, 0x394b, 0x2009, 0x0020, 0x0078, 0x394d, 0x2009,
- 0x003f, 0x0078, 0x394d, 0x2011, 0x0000, 0x2100, 0xa205, 0x600a,
- 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c, 0x781b, 0x0065,
- 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0065, 0x0078, 0x24fa,
- 0x781b, 0x0058, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x0056,
- 0x0078, 0x24fa, 0x2009, 0x5220, 0x210c, 0xa186, 0x0000, 0x0040,
- 0x397e, 0xa186, 0x0001, 0x0040, 0x3981, 0x2009, 0x5238, 0x200b,
- 0x000b, 0x706f, 0x0001, 0x781b, 0x0048, 0x007c, 0x781b, 0x00c4,
- 0x007c, 0x2009, 0x5238, 0x200b, 0x000a, 0x007c, 0x2009, 0x5220,
- 0x210c, 0xa186, 0x0000, 0x0040, 0x39a1, 0xa186, 0x0001, 0x0040,
- 0x399b, 0x2009, 0x5238, 0x200b, 0x000b, 0x706f, 0x0001, 0x781b,
- 0x0048, 0x0078, 0x24fa, 0x2009, 0x5238, 0x200b, 0x000a, 0x0078,
- 0x24fa, 0x782b, 0x3008, 0x781b, 0x00c4, 0x0078, 0x24fa, 0x781b,
- 0x00ca, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b, 0x00ca, 0x0078,
- 0x24fa, 0x781b, 0x008f, 0x0078, 0x24fa, 0x782b, 0x3008, 0x781b,
- 0x008f, 0x0078, 0x24fa, 0x6818, 0xa084, 0x8000, 0x0040, 0x39c2,
- 0x681b, 0x001d, 0x706f, 0x0001, 0x781b, 0x0048, 0x0078, 0x24fa,
- 0x007e, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x39de, 0x7808, 0xa084,
- 0xfffc, 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084,
- 0x0021, 0x0040, 0x39de, 0x7044, 0x780a, 0xa005, 0x007f, 0x007c,
- 0x7044, 0xa085, 0x0002, 0x7046, 0x780a, 0x007c, 0x007e, 0x7830,
- 0xa084, 0x0040, 0x00c0, 0x39e7, 0x0098, 0x39f2, 0x007f, 0x789a,
- 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005,
- 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x3a01, 0x0098,
- 0x39ff, 0x007f, 0x789a, 0x78ac, 0x007e, 0x7044, 0x780a, 0x007f,
- 0x007c, 0x78ec, 0xa084, 0x0002, 0x00c0, 0x4871, 0xa784, 0x007d,
- 0x00c0, 0x3a15, 0x2700, 0x1078, 0x248c, 0xa784, 0x0001, 0x00c0,
- 0x300c, 0xa784, 0x0070, 0x0040, 0x3a25, 0x0c7e, 0x2d60, 0x2f68,
- 0x1078, 0x2437, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
- 0x3a32, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2523,
- 0x0078, 0x3956, 0xa784, 0x0004, 0x0040, 0x3a65, 0x78b8, 0xa084,
- 0x4001, 0x0040, 0x3a65, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
- 0x0040, 0x2523, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
- 0x3a65, 0x78c0, 0xa085, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00ca,
- 0x0078, 0x24fa, 0x784b, 0x0008, 0x6818, 0xa084, 0x8000, 0x0040,
- 0x3a61, 0x681b, 0x0015, 0xa684, 0x4000, 0x0040, 0x3a61, 0x681b,
- 0x0007, 0x1078, 0x396a, 0x0078, 0x24fa, 0x681b, 0x0003, 0x7858,
- 0xa084, 0x3f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000, 0x784b,
- 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x2a06, 0x0018, 0x24fa,
- 0x0078, 0x3773, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
- 0x8003, 0xa080, 0x5480, 0x2060, 0x2048, 0x7056, 0x6000, 0x705a,
- 0x6004, 0x705e, 0x2a60, 0x007c, 0x0079, 0x3a8e, 0x3a96, 0x3a97,
- 0x3a96, 0x3a99, 0x3a96, 0x3a96, 0x3a96, 0x3a9e, 0x007c, 0x1078,
- 0x34b8, 0x1078, 0x4887, 0x7038, 0x600a, 0x007c, 0x70a0, 0xa005,
- 0x0040, 0x3aab, 0x2068, 0x1078, 0x1bd3, 0x1078, 0x47fe, 0x1078,
- 0x4805, 0x70a3, 0x0000, 0x007c, 0x0e7e, 0x2091, 0x8000, 0x2071,
- 0x5240, 0x7000, 0xa086, 0x0007, 0x00c0, 0x3ac2, 0x6110, 0x70bc,
- 0xa106, 0x00c0, 0x3ac2, 0x0e7f, 0x1078, 0x1be0, 0x1078, 0x3ac8,
- 0xa006, 0x007c, 0x2091, 0x8001, 0x0e7f, 0xa085, 0x0001, 0x007c,
- 0x0f7e, 0x0e7e, 0x2071, 0x5240, 0x0078, 0x2297, 0x785b, 0x0000,
- 0x70af, 0x000e, 0x2009, 0x0100, 0x017e, 0x70a0, 0xa06d, 0x0040,
- 0x3add, 0x70a3, 0x0000, 0x0078, 0x3ae3, 0x70b3, 0x0000, 0x1078,
- 0x1c0c, 0x0040, 0x3ae9, 0x70ac, 0x6826, 0x1078, 0x3bc6, 0x0078,
- 0x3add, 0x017f, 0x157e, 0x0c7e, 0x0d7e, 0x20a9, 0x0008, 0x2061,
- 0x7610, 0x6000, 0xa105, 0x6002, 0x601c, 0xa06d, 0x0040, 0x3b01,
- 0x6800, 0x601e, 0x1078, 0x19ac, 0x6008, 0x8000, 0x600a, 0x0078,
- 0x3af4, 0x6018, 0xa06d, 0x0040, 0x3b0b, 0x6800, 0x601a, 0x1078,
- 0x19ac, 0x0078, 0x3b01, 0xace0, 0x0008, 0x0070, 0x3b11, 0x0078,
- 0x3af1, 0x709c, 0xa084, 0x8000, 0x0040, 0x3b18, 0x1078, 0x3c44,
- 0x0d7f, 0x0c7f, 0x157f, 0x007c, 0x127e, 0x2091, 0x2300, 0x6804,
- 0xa084, 0x000f, 0x0079, 0x3b24, 0x3b34, 0x3b34, 0x3b34, 0x3b34,
- 0x3b34, 0x3b34, 0x3b36, 0x3b3c, 0x3b34, 0x3b34, 0x3b34, 0x3b34,
- 0x3b34, 0x3b3e, 0x3b34, 0x3b36, 0x1078, 0x248c, 0x1078, 0x45d3,
- 0x1078, 0x19ac, 0x0078, 0x3b42, 0x6827, 0x000b, 0x1078, 0x45d3,
- 0x1078, 0x3bc6, 0x127f, 0x007c, 0x127e, 0x2091, 0x2300, 0x0098,
- 0x3b60, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x3b60, 0x0d7e, 0x1078,
- 0x4812, 0x2d00, 0x682e, 0x2009, 0x0004, 0x2001, 0x0000, 0x6827,
- 0x0084, 0x1078, 0x47c7, 0x1078, 0x3bc6, 0x0d7f, 0x0078, 0x3b94,
- 0x7948, 0xa185, 0x4000, 0x784a, 0x0098, 0x3b69, 0x794a, 0x0078,
- 0x3b4e, 0x7828, 0xa086, 0x1834, 0x00c0, 0x3b72, 0xa185, 0x0004,
- 0x0078, 0x3b79, 0x7828, 0xa086, 0x1814, 0x00c0, 0x3b66, 0xa185,
- 0x000c, 0x784a, 0x789b, 0x000e, 0x78ab, 0x0002, 0x7858, 0xa084,
- 0x00ff, 0xa085, 0x0400, 0x785a, 0x70b4, 0xa080, 0x0091, 0x781a,
- 0x6827, 0x0284, 0x682c, 0x6836, 0x6830, 0x683a, 0x2009, 0x0004,
- 0x2001, 0x0000, 0x1078, 0x47c7, 0x127f, 0x007c, 0x0d7e, 0x6b14,
- 0x1078, 0x1c70, 0x0040, 0x3ba3, 0x2068, 0x6827, 0x0002, 0x1078,
- 0x3bc6, 0x0078, 0x3b98, 0x0d7f, 0x007c, 0x0d7e, 0x6b14, 0x6c28,
- 0xa4a4, 0x00ff, 0x1078, 0x1c1c, 0x0040, 0x3bb3, 0x2068, 0x6827,
- 0x0002, 0x1078, 0x3bc6, 0x0d7f, 0x007c, 0x0d7e, 0x6b14, 0xa39c,
- 0x00ff, 0x1078, 0x1c48, 0x0040, 0x3bc4, 0x2068, 0x6827, 0x0002,
- 0x1078, 0x3bc6, 0x0078, 0x3bb9, 0x0d7f, 0x007c, 0x0c7e, 0x6914,
- 0x1078, 0x3c3b, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0006, 0x0040,
- 0x3be1, 0xa186, 0x000d, 0x0040, 0x3c00, 0xa186, 0x0017, 0x00c0,
- 0x3bdd, 0x1078, 0x19ac, 0x0078, 0x3bdf, 0x1078, 0x1cde, 0x0c7f,
- 0x007c, 0x6004, 0x8001, 0x0048, 0x3bfe, 0x6006, 0x2009, 0x0000,
- 0xa684, 0x0001, 0x00c0, 0x3bee, 0xa18d, 0x8000, 0xa684, 0x0004,
- 0x0040, 0x3bf4, 0xa18d, 0x0002, 0x691e, 0x6823, 0x0000, 0x7104,
- 0x810f, 0x6818, 0xa105, 0x681a, 0x0078, 0x3bdd, 0x1078, 0x248c,
- 0x6018, 0xa005, 0x00c0, 0x3c0f, 0x6008, 0x8001, 0x0048, 0x3c0f,
- 0x600a, 0x601c, 0x6802, 0x2d00, 0x601e, 0x0078, 0x3c25, 0xac88,
- 0x0006, 0x2104, 0xa005, 0x0040, 0x3c18, 0x2008, 0x0078, 0x3c11,
- 0x6802, 0x2d0a, 0x6008, 0x8001, 0x0048, 0x3bdf, 0x600a, 0x6018,
- 0x2068, 0x6800, 0x601a, 0x0078, 0x3c09, 0x157e, 0x137e, 0x147e,
- 0x0c7e, 0x0d7e, 0x1078, 0x1989, 0x00c0, 0x3c30, 0x1078, 0x248c,
- 0x2da0, 0x137f, 0x20a9, 0x0031, 0x53a3, 0x0c7f, 0x147f, 0x137f,
- 0x157f, 0x0078, 0x3bdd, 0xa184, 0x001f, 0x8003, 0x8003, 0x8003,
- 0xa080, 0x7610, 0x2060, 0x007c, 0x2019, 0x5251, 0x2304, 0xa085,
- 0x0001, 0x201a, 0x2019, 0x0102, 0x2304, 0xa085, 0x0001, 0x201a,
- 0x007c, 0x2019, 0x5251, 0x2304, 0xa084, 0xfffe, 0x201a, 0x2019,
- 0x0102, 0x2304, 0xa084, 0xfffe, 0x201a, 0x007c, 0x7990, 0xa18c,
- 0xfff8, 0x7992, 0x70b4, 0xa080, 0x00d8, 0x781a, 0x0078, 0x24fa,
- 0x70a3, 0x0000, 0x7003, 0x0000, 0x7043, 0x0001, 0x7037, 0x0000,
- 0x0018, 0x24b1, 0x1078, 0x1c0c, 0x0040, 0x3c99, 0x2009, 0x520f,
- 0x200b, 0x0000, 0x68bc, 0x2060, 0x6100, 0xa184, 0x0300, 0x0040,
- 0x3c8d, 0x6827, 0x000e, 0xa084, 0x0200, 0x0040, 0x3c89, 0x6827,
- 0x0017, 0x1078, 0x3bc6, 0x0078, 0x3c68, 0x7000, 0xa086, 0x0007,
- 0x00c0, 0x3d0d, 0x2d00, 0x70a2, 0xad80, 0x000f, 0x7036, 0x0078,
- 0x3ca0, 0x7040, 0xa086, 0x0001, 0x0040, 0x2533, 0x0078, 0x24fa,
- 0x2031, 0x0000, 0x691c, 0xa184, 0x0002, 0x0040, 0x3ca9, 0xa6b5,
- 0x0004, 0xa184, 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080, 0x3da6,
- 0x2004, 0xa635, 0x6820, 0xa084, 0x0400, 0x0040, 0x3cc1, 0x789b,
- 0x0018, 0x78ab, 0x0003, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5,
- 0x5000, 0x6820, 0xa084, 0x8000, 0x0040, 0x3ccf, 0xa6b5, 0x0400,
- 0x789b, 0x000e, 0x6824, 0x8007, 0x78aa, 0x0078, 0x3cef, 0x681c,
- 0xd0fc, 0x00c0, 0x3cdd, 0xa6b5, 0x0800, 0x6820, 0xd0c4, 0x0040,
- 0x3cef, 0xa6b5, 0x4000, 0x0078, 0x3cef, 0x6820, 0xd0c4, 0x0040,
- 0x3ce5, 0xa6b5, 0x4000, 0x0078, 0x3cef, 0x789b, 0x0018, 0x78ab,
- 0x0002, 0x789b, 0x0081, 0x78ab, 0x0001, 0xa6b5, 0x1000, 0xa684,
- 0x0200, 0x0040, 0x3d09, 0x682c, 0x78d2, 0x6830, 0x78d6, 0xa684,
- 0x0100, 0x0040, 0x3d07, 0x682c, 0xa084, 0x0001, 0x0040, 0x3d07,
- 0x7888, 0xa084, 0x0040, 0x0040, 0x3d07, 0xa6b5, 0x8000, 0x1078,
- 0x47f6, 0x7e5a, 0x6eb6, 0x0078, 0x4835, 0x1078, 0x39c8, 0x00c0,
- 0x3da0, 0x702c, 0x8004, 0x0048, 0x3d1b, 0x2019, 0x4f49, 0x1078,
- 0x2313, 0x702f, 0x0001, 0x2041, 0x0001, 0x2031, 0x1000, 0x789b,
- 0x0018, 0x6814, 0xa084, 0x001f, 0xa085, 0x0080, 0x78aa, 0x691c,
- 0xa184, 0x0002, 0x0040, 0x3d34, 0xa6b5, 0x0004, 0x78ab, 0x0020,
- 0x6828, 0x78aa, 0xa8c0, 0x0002, 0x681c, 0xd0f4, 0x0040, 0x3d3d,
- 0x2c50, 0x1078, 0x3a7a, 0x1078, 0x4702, 0x6820, 0xa084, 0x8000,
- 0x0040, 0x3d4b, 0xa6b5, 0x0400, 0x789b, 0x000e, 0x6824, 0x8007,
- 0x78aa, 0x0078, 0x3d52, 0x681c, 0xa084, 0x8000, 0x00c0, 0x3d52,
- 0xa6b5, 0x0800, 0x6820, 0xa084, 0x0100, 0x0040, 0x3d59, 0xa6b5,
- 0x4000, 0x681c, 0xa084, 0x00c0, 0x8003, 0x8003, 0x8007, 0xa080,
- 0x3da6, 0x2004, 0xa635, 0xa684, 0x0100, 0x0040, 0x3d73, 0x682c,
- 0xa084, 0x0001, 0x0040, 0x3d73, 0x7888, 0xa084, 0x0040, 0x0040,
- 0x3d73, 0xa6b5, 0x8000, 0x789b, 0x007e, 0x7eae, 0x6eb6, 0x6814,
- 0x8007, 0x78aa, 0x7882, 0x2810, 0x7aaa, 0x7830, 0xa084, 0x00c0,
- 0x00c0, 0x3da0, 0x0018, 0x3da0, 0x70b4, 0xa080, 0x00dd, 0x781a,
- 0x1078, 0x39e0, 0xa684, 0x0200, 0x0040, 0x3d94, 0x682c, 0x78d2,
- 0x6830, 0x78d6, 0x1078, 0x47f6, 0x2d00, 0x70a2, 0x704a, 0x6810,
- 0x70be, 0x7003, 0x0007, 0xad80, 0x000f, 0x7036, 0x0078, 0x24fa,
- 0x1078, 0x1bd3, 0x1078, 0x39e0, 0x0078, 0x24fa, 0x0000, 0x0300,
- 0x0200, 0x0000, 0x1078, 0x248c, 0x2300, 0x0079, 0x3daf, 0x3db2,
- 0x3db2, 0x3db4, 0x1078, 0x248c, 0x1078, 0x4805, 0x6924, 0xa184,
- 0x00ff, 0xa086, 0x000a, 0x0040, 0x3dc6, 0xa184, 0xff00, 0xa085,
- 0x000a, 0x6826, 0x1078, 0x1bd3, 0x0078, 0x3c68, 0x2001, 0x000a,
- 0x1078, 0x4797, 0x0078, 0x3c68, 0xa282, 0x0005, 0x0050, 0x3dd2,
- 0x1078, 0x248c, 0x7000, 0xa084, 0x0007, 0x10c0, 0x3a8c, 0x1078,
- 0x1989, 0x00c0, 0x3df4, 0x2069, 0xffff, 0xa684, 0x0004, 0x0040,
- 0x3de5, 0x2001, 0x2800, 0x0078, 0x3de7, 0x2001, 0x0800, 0x71b4,
- 0xa188, 0x0091, 0x789b, 0x000e, 0x8007, 0x78aa, 0x2031, 0x0400,
- 0x7e5a, 0x791a, 0x0078, 0x24fa, 0x6807, 0x0106, 0x680b, 0x0000,
- 0x689f, 0x0000, 0x6827, 0x0000, 0xa386, 0x0002, 0x00c0, 0x3e15,
- 0xa286, 0x0002, 0x00c0, 0x3e15, 0x78a0, 0xa005, 0x00c0, 0x3e15,
- 0xa484, 0x8000, 0x00c0, 0x3e15, 0x78e4, 0xa084, 0x0008, 0x0040,
- 0x3e15, 0xa6b5, 0x0008, 0x2019, 0x0000, 0x1078, 0x4217, 0x2d00,
- 0x70a2, 0x704a, 0x7003, 0x0007, 0x7037, 0x0000, 0x6824, 0xa084,
- 0x0080, 0x0040, 0x3e27, 0x1078, 0x42cd, 0x0078, 0x24fa, 0x2300,
- 0x0079, 0x3e2a, 0x3e2d, 0x3eae, 0x3ec7, 0x2200, 0x0079, 0x3e30,
- 0x3e35, 0x3e45, 0x3e6b, 0x3e77, 0x3e9a, 0x2029, 0x0001, 0xa026,
- 0x2011, 0x0000, 0x1078, 0x43f3, 0x0079, 0x3e3e, 0x3e43, 0x24fa,
- 0x3c68, 0x3e43, 0x3e43, 0x1078, 0x248c, 0x7990, 0xa18c, 0x0007,
- 0x00c0, 0x3e4c, 0x2009, 0x0008, 0x2011, 0x0001, 0xa684, 0x0004,
- 0x0040, 0x3e54, 0x2011, 0x0003, 0x2220, 0xa12a, 0x2011, 0x0001,
- 0x1078, 0x43f3, 0x0079, 0x3e5c, 0x3e61, 0x24fa, 0x3c68, 0x3e69,
- 0x3e63, 0x0078, 0x483b, 0x70ab, 0x3e67, 0x0078, 0x24fa, 0x0078,
- 0x3e61, 0x1078, 0x248c, 0xa684, 0x0010, 0x0040, 0x3e75, 0x1078,
- 0x429c, 0x0040, 0x3e75, 0x0078, 0x24fa, 0x0078, 0x430d, 0x6000,
- 0xa084, 0x0002, 0x0040, 0x3e94, 0x70b4, 0xa080, 0x00cd, 0x781a,
- 0x0d7e, 0x1078, 0x4812, 0x2d00, 0x682e, 0x6827, 0x0000, 0x1078,
- 0x3bc6, 0x0d7f, 0x1078, 0x19ac, 0x7003, 0x0000, 0x7037, 0x0000,
- 0x704b, 0x0000, 0x0078, 0x3c68, 0xa684, 0x0004, 0x00c0, 0x3e9a,
- 0x0078, 0x483b, 0x6000, 0xa084, 0x0004, 0x00c0, 0x3eac, 0x6000,
- 0xa084, 0x0001, 0x0040, 0x3eac, 0x70ab, 0x3eac, 0x2001, 0x0007,
- 0x1078, 0x478f, 0x0078, 0x4841, 0x0078, 0x483b, 0x2200, 0x0079,
- 0x3eb1, 0x3eb6, 0x3eb8, 0x3eb6, 0x3eb6, 0x3eb6, 0x1078, 0x248c,
- 0x70a7, 0x3ebc, 0x0078, 0x4847, 0x78e4, 0xa084, 0x0008, 0x00c0,
- 0x3eb8, 0x1078, 0x4781, 0x70ab, 0x3ec5, 0x0078, 0x483b, 0x2200,
- 0x0079, 0x3eca, 0x3ecf, 0x3ed1, 0x3ed1, 0x3ecf, 0x3ecf, 0x1078,
- 0x248c, 0x78e4, 0xa084, 0x0008, 0x0040, 0x3ee6, 0x70a7, 0x3eda,
- 0x0078, 0x4847, 0x2011, 0x0004, 0x1078, 0x43ed, 0x0079, 0x3ee0,
- 0x3ee6, 0x24fa, 0x3c68, 0x3ee6, 0x3ef0, 0x3ef4, 0x70ab, 0x3eee,
- 0x2001, 0x0003, 0x1078, 0x478f, 0x0078, 0x4841, 0x0078, 0x483b,
- 0x70ab, 0x3ee6, 0x0078, 0x24fa, 0x70ab, 0x3ef8, 0x0078, 0x24fa,
- 0x0078, 0x3eee, 0xa282, 0x0003, 0x0050, 0x3f00, 0x1078, 0x248c,
- 0xa386, 0x0002, 0x00c0, 0x3f19, 0xa286, 0x0002, 0x00c0, 0x3f1f,
- 0x78a0, 0xa005, 0x00c0, 0x3f1f, 0xa484, 0x8000, 0x00c0, 0x3f1f,
- 0x78e4, 0xa084, 0x0008, 0x0040, 0x3f19, 0xa6b5, 0x0008, 0x2019,
- 0x0000, 0xa684, 0x0008, 0x0040, 0x3f1f, 0x1078, 0x4279, 0x6810,
- 0x70be, 0x7003, 0x0007, 0x2300, 0x0079, 0x3f26, 0x3f29, 0x3f56,
- 0x3f5e, 0x2200, 0x0079, 0x3f2c, 0x3f31, 0x3f2f, 0x3f4a, 0x1078,
- 0x248c, 0x7990, 0xa1ac, 0x0007, 0xa026, 0x2011, 0x0001, 0x1078,
- 0x43f3, 0x0079, 0x3f3b, 0x3f40, 0x24fa, 0x3c68, 0x3f48, 0x3f42,
- 0x0078, 0x483b, 0x70ab, 0x3f46, 0x0078, 0x24fa, 0x0078, 0x3f40,
- 0x1078, 0x248c, 0xa684, 0x0010, 0x0040, 0x3f54, 0x1078, 0x429c,
- 0x0040, 0x3f54, 0x0078, 0x24fa, 0x0078, 0x430d, 0x2200, 0x0079,
- 0x3f59, 0x3f5c, 0x3f5c, 0x3f5c, 0x1078, 0x248c, 0x2200, 0x0079,
- 0x3f61, 0x3f64, 0x3f66, 0x3f66, 0x1078, 0x248c, 0x78e4, 0xa084,
- 0x0008, 0x0040, 0x3f7b, 0x70a7, 0x3f6f, 0x0078, 0x4847, 0x2011,
- 0x0004, 0x1078, 0x43ed, 0x0079, 0x3f75, 0x3f7b, 0x24fa, 0x3c68,
- 0x3f7b, 0x3f85, 0x3f89, 0x70ab, 0x3f83, 0x2001, 0x0003, 0x1078,
- 0x478f, 0x0078, 0x4841, 0x0078, 0x483b, 0x70ab, 0x3f7b, 0x0078,
- 0x24fa, 0x70ab, 0x3f8d, 0x0078, 0x24fa, 0x0078, 0x3f83, 0x2300,
- 0x0079, 0x3f92, 0x3f97, 0x3f99, 0x3f95, 0x1078, 0x248c, 0x70a4,
- 0x007a, 0x70a4, 0x007a, 0xa282, 0x0002, 0x0050, 0x3fa1, 0x1078,
- 0x248c, 0xa684, 0x0200, 0x0040, 0x3fab, 0x1078, 0x47fe, 0x1078,
- 0x43d5, 0x1078, 0x4805, 0x2300, 0x0079, 0x3fae, 0x3fb1, 0x3fd9,
- 0x403f, 0xad86, 0xffff, 0x0040, 0x3c68, 0xa286, 0x0001, 0x0040,
- 0x3fbb, 0x1078, 0x248c, 0xa684, 0x0200, 0x0040, 0x3fc3, 0x1078,
- 0x47fe, 0x1078, 0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x78b8,
- 0xa084, 0xc001, 0x0040, 0x3fd5, 0x7848, 0xa085, 0x0008, 0x784a,
- 0x7848, 0xa084, 0x0008, 0x00c0, 0x3fd0, 0x7003, 0x0000, 0x0078,
- 0x3c68, 0x2200, 0x0079, 0x3fdc, 0x3fde, 0x400f, 0x70a7, 0x3fe2,
- 0x0078, 0x4847, 0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x3fe8,
- 0x3fef, 0x24fa, 0x3c68, 0x3ff7, 0x3fff, 0x4005, 0x4007, 0xa6b4,
- 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4,
- 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab,
- 0x4003, 0x0078, 0x24fa, 0x0078, 0x3fef, 0x1078, 0x248c, 0x70ab,
- 0x400b, 0x0078, 0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x70a7,
- 0x4013, 0x0078, 0x4847, 0x2011, 0x0012, 0x1078, 0x43ed, 0x0079,
- 0x4019, 0x401f, 0x24fa, 0x3c68, 0x402b, 0x4033, 0x4039, 0xa6b4,
- 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a, 0x70b4, 0xa080, 0x00aa,
- 0x781a, 0x0078, 0x24fa, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6,
- 0x7e5a, 0x0078, 0x4835, 0x70ab, 0x4037, 0x0078, 0x24fa, 0x0078,
- 0x401f, 0x70ab, 0x403d, 0x0078, 0x24fa, 0x0078, 0x402b, 0xa286,
- 0x0001, 0x0040, 0x4045, 0x1078, 0x248c, 0x70a7, 0x4049, 0x0078,
- 0x4847, 0x2011, 0x0015, 0x1078, 0x43ed, 0x0079, 0x404f, 0x4054,
- 0x24fa, 0x3c68, 0x4062, 0x406e, 0xa6b4, 0x00ff, 0xa6b5, 0x0400,
- 0x6eb6, 0x7e5a, 0x783b, 0x1301, 0x70b4, 0xa080, 0x00b5, 0x781a,
- 0x0078, 0x24fa, 0xa6b4, 0x00ff, 0xa6b5, 0x0400, 0x6eb6, 0x7e5a,
- 0x70b4, 0xa080, 0x00aa, 0x781a, 0x0078, 0x24fa, 0x70ab, 0x4072,
- 0x0078, 0x24fa, 0x0078, 0x4054, 0xa282, 0x0003, 0x0050, 0x407a,
- 0x1078, 0x248c, 0x2300, 0x0079, 0x407d, 0x4080, 0x40b7, 0x4114,
- 0xa286, 0x0001, 0x0040, 0x4086, 0x1078, 0x248c, 0x6804, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x00c0, 0x4093, 0x1078, 0x3bc6, 0x7003,
- 0x0000, 0x0078, 0x3c68, 0x683b, 0x0000, 0x6837, 0x0000, 0xa684,
- 0x0200, 0x0040, 0x40a1, 0x1078, 0x47fe, 0x1078, 0x43d5, 0x1078,
- 0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x78b8, 0xa084, 0xc001,
- 0x0040, 0x40b3, 0x7848, 0xa085, 0x0008, 0x784a, 0x7848, 0xa084,
- 0x0008, 0x00c0, 0x40ae, 0x7003, 0x0000, 0x0078, 0x3c68, 0x2200,
- 0x0079, 0x40ba, 0x40bc, 0x40ef, 0x70a7, 0x40c0, 0x0078, 0x4847,
- 0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x40c6, 0x40cd, 0x24fa,
- 0x3c68, 0x40d5, 0x40dd, 0x40e3, 0x40e5, 0xa6b4, 0x00ff, 0xa6b5,
- 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4, 0x00ff, 0xa6b5,
- 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab, 0x40e1, 0x0078,
- 0x24fa, 0x0078, 0x40cd, 0x1078, 0x248c, 0x70ab, 0x40eb, 0x1078,
- 0x4805, 0x0078, 0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x70a7,
- 0x40f3, 0x0078, 0x4847, 0x2011, 0x0005, 0x1078, 0x43ed, 0x0079,
- 0x40f9, 0x40fe, 0x24fa, 0x3c68, 0x4106, 0x410e, 0xa6b4, 0x00ff,
- 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4, 0x00ff,
- 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0x70ab, 0x4112,
- 0x0078, 0x24fa, 0x0078, 0x40fe, 0xa286, 0x0001, 0x0040, 0x411a,
- 0x1078, 0x248c, 0x70a7, 0x411e, 0x0078, 0x4847, 0x2011, 0x0006,
- 0x1078, 0x43ed, 0x0079, 0x4124, 0x4129, 0x24fa, 0x3c68, 0x412f,
- 0x4139, 0xa6b5, 0x0800, 0x6eb6, 0x7e5a, 0x0078, 0x4835, 0xa6b4,
- 0x00ff, 0xa6b5, 0x0800, 0x6eb6, 0xa6b5, 0x4000, 0x7e5a, 0x0078,
- 0x4835, 0x70ab, 0x413d, 0x0078, 0x24fa, 0x0078, 0x4129, 0x2300,
- 0x0079, 0x4142, 0x4147, 0x4145, 0x4145, 0x1078, 0x248c, 0x1078,
- 0x248c, 0x2300, 0x71a8, 0xa005, 0x017a, 0x6810, 0x70be, 0xa282,
- 0x0003, 0x0050, 0x4155, 0x1078, 0x248c, 0x2300, 0x0079, 0x4158,
- 0x415b, 0x4169, 0x418b, 0xa684, 0x0200, 0x0040, 0x4163, 0x1078,
- 0x47fe, 0x1078, 0x4805, 0x2001, 0x0001, 0x1078, 0x4797, 0x0078,
- 0x24fa, 0xa296, 0x0002, 0x0040, 0x4172, 0x82ff, 0x0040, 0x4172,
- 0x1078, 0x248c, 0x70a7, 0x4176, 0x0078, 0x4847, 0x2011, 0x0018,
- 0x1078, 0x43ed, 0x0079, 0x417c, 0x4181, 0x24fa, 0x3c68, 0x4183,
- 0x4185, 0x0078, 0x4835, 0x0078, 0x4835, 0x70ab, 0x4189, 0x0078,
- 0x24fa, 0x0078, 0x4181, 0x2200, 0x0079, 0x418e, 0x4190, 0x41a9,
- 0x70a7, 0x4194, 0x0078, 0x4847, 0x2011, 0x0017, 0x1078, 0x43ed,
- 0x0079, 0x419a, 0x419f, 0x24fa, 0x3c68, 0x41a1, 0x41a3, 0x0078,
- 0x4835, 0x0078, 0x4835, 0x70ab, 0x41a7, 0x0078, 0x24fa, 0x0078,
- 0x419f, 0xa484, 0x8000, 0x00c0, 0x4205, 0xa684, 0x0100, 0x0040,
- 0x41b5, 0x1078, 0x47fe, 0x1078, 0x43d5, 0x78d8, 0x78d2, 0x78dc,
- 0x78d6, 0xa6b4, 0xefff, 0x7e5a, 0x70a7, 0x41c0, 0x0078, 0x4847,
- 0x2011, 0x000d, 0x1078, 0x43ed, 0x0079, 0x41c6, 0x41cd, 0x24fa,
- 0x3c68, 0x41cd, 0x41f3, 0x41f9, 0x41fb, 0x78d8, 0x79dc, 0xa105,
- 0x00c0, 0x41df, 0x78b8, 0xa084, 0x001f, 0x00c0, 0x41df, 0x70b3,
- 0x0000, 0x7858, 0xa084, 0xfdff, 0x785a, 0x0078, 0x4835, 0xa684,
- 0x0100, 0x0040, 0x41f1, 0x7848, 0xa085, 0x0008, 0x784a, 0x1078,
- 0x47bc, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x70b3, 0x0000, 0x1078,
- 0x47f6, 0x0078, 0x4835, 0x70ab, 0x41f7, 0x0078, 0x24fa, 0x0078,
- 0x41cd, 0x1078, 0x248c, 0x70ab, 0x4201, 0x1078, 0x4805, 0x0078,
- 0x24fa, 0x1078, 0x484d, 0x0078, 0x24fa, 0x1078, 0x4805, 0x70ab,
- 0x420f, 0x2001, 0x0003, 0x1078, 0x478f, 0x0078, 0x4841, 0x1078,
- 0x47f6, 0x682c, 0x78d2, 0x6830, 0x78d6, 0x0078, 0x4835, 0x70b8,
- 0x6812, 0x70be, 0x8000, 0x70ba, 0x681b, 0x0000, 0xa684, 0x0008,
- 0x0040, 0x423a, 0x157e, 0x137e, 0x147e, 0x7890, 0x8004, 0x8004,
- 0x8004, 0x8004, 0xa084, 0x000f, 0x681a, 0x80ac, 0x789b, 0x0000,
- 0xaf80, 0x002b, 0x2098, 0xad80, 0x000b, 0x20a0, 0x53a5, 0x147f,
- 0x137f, 0x157f, 0xa6c4, 0x0f00, 0xa684, 0x0002, 0x00c0, 0x4249,
- 0x692c, 0x810d, 0x810d, 0x810d, 0xa184, 0x0007, 0x2008, 0x0078,
- 0x425c, 0x789b, 0x0010, 0x79ac, 0xa184, 0x0020, 0x0040, 0x425c,
- 0x017e, 0x2009, 0x0005, 0x2001, 0x3d00, 0x1078, 0x47c7, 0x6824,
- 0xa085, 0x003b, 0x6826, 0x017f, 0xa184, 0x001f, 0xa805, 0x6816,
- 0x1078, 0x3c3b, 0x68be, 0xa684, 0x0004, 0x0040, 0x426d, 0xa18c,
- 0xff00, 0x78a8, 0xa084, 0x00ff, 0xa105, 0x682a, 0xa6b4, 0x00ff,
- 0x6000, 0xa084, 0x0008, 0x0040, 0x4277, 0xa6b5, 0x4000, 0x6eb6,
- 0x007c, 0x157e, 0x137e, 0x147e, 0x6918, 0x7890, 0x8004, 0x8004,
- 0x8004, 0x8004, 0xa084, 0x000f, 0x007e, 0xa100, 0x681a, 0x007f,
- 0x8000, 0x8004, 0x0040, 0x4298, 0x20a8, 0x8104, 0xa080, 0x000b,
- 0xad00, 0x20a0, 0x789b, 0x0000, 0xaf80, 0x002b, 0x2098, 0x53a5,
- 0x147f, 0x137f, 0x157f, 0x007c, 0x682c, 0xa084, 0x0020, 0x00c0,
- 0x42a4, 0x620c, 0x0078, 0x42a5, 0x6210, 0x6b18, 0x2300, 0xa202,
- 0x0040, 0x42c5, 0x2018, 0xa382, 0x000e, 0x0048, 0x42b5, 0x0040,
- 0x42b5, 0x2019, 0x000e, 0x0078, 0x42b9, 0x7858, 0xa084, 0xffef,
- 0x785a, 0x783b, 0x1b01, 0x7893, 0x0000, 0x7ba2, 0x70b4, 0xa080,
- 0x008e, 0x781a, 0xa085, 0x0001, 0x007c, 0x7858, 0xa084, 0xffef,
- 0x785a, 0x7893, 0x0000, 0xa006, 0x007c, 0x6904, 0xa18c, 0x00ff,
- 0xa196, 0x0007, 0x0040, 0x42da, 0xa196, 0x000f, 0x0040, 0x42da,
- 0x6807, 0x0117, 0x6914, 0x1078, 0x3c3b, 0x6100, 0x8104, 0x00c8,
- 0x42f5, 0x601c, 0xa005, 0x0040, 0x42e9, 0x2001, 0x0800, 0x0078,
- 0x42f7, 0x0d7e, 0x6824, 0x007e, 0x1078, 0x4812, 0x007f, 0x6826,
- 0x2d00, 0x682e, 0x1078, 0x3bc6, 0x0d7f, 0x2001, 0x0200, 0x6924,
- 0xa18c, 0x00ff, 0xa10d, 0x6926, 0x8007, 0x789b, 0x000e, 0x78aa,
- 0x6820, 0xa085, 0x8000, 0x6822, 0x2031, 0x0400, 0x6eb6, 0x7e5a,
- 0x71b4, 0xa188, 0x0091, 0x791a, 0x007c, 0xa6c4, 0x0f00, 0xa684,
- 0x0002, 0x00c0, 0x4321, 0x692c, 0x810d, 0x810d, 0x810d, 0xa184,
- 0x0007, 0x2008, 0xa805, 0x6816, 0x1078, 0x3c3b, 0x68be, 0x0078,
- 0x4324, 0x6914, 0x1078, 0x3c3b, 0x6100, 0x8104, 0x00c8, 0x4382,
- 0xa184, 0x0300, 0x0040, 0x4330, 0x6807, 0x0117, 0x0078, 0x434e,
- 0x6004, 0xa005, 0x00c0, 0x4357, 0x6807, 0x0117, 0x601c, 0xa005,
- 0x00c0, 0x4344, 0x0d7e, 0x1078, 0x4812, 0x6827, 0x0034, 0x2d00,
- 0x682e, 0x1078, 0x3bc6, 0x0d7f, 0xa684, 0x0004, 0x0040, 0x434e,
- 0x2031, 0x0400, 0x2001, 0x2800, 0x0078, 0x4352, 0x2031, 0x0400,
- 0x2001, 0x0800, 0x71b4, 0xa188, 0x0091, 0x0078, 0x43b0, 0x6018,
- 0xa005, 0x00c0, 0x4344, 0x601c, 0xa005, 0x00c0, 0x4344, 0x689f,
- 0x0000, 0x6827, 0x003d, 0xa684, 0x0001, 0x0040, 0x43be, 0xd694,
- 0x00c0, 0x437b, 0x6100, 0xd1d4, 0x0040, 0x437b, 0x692c, 0xa18c,
- 0x00ff, 0x0040, 0x43be, 0xa186, 0x0003, 0x0040, 0x43be, 0xa186,
- 0x0012, 0x0040, 0x43be, 0xa6b5, 0x0800, 0x71b4, 0xa188, 0x00ae,
- 0x0078, 0x43b9, 0x6807, 0x0117, 0x2031, 0x0400, 0x692c, 0xa18c,
- 0x00ff, 0xa186, 0x0012, 0x00c0, 0x4393, 0x2001, 0x43cb, 0x2009,
- 0x0001, 0x0078, 0x43a4, 0xa186, 0x0003, 0x00c0, 0x439d, 0x2001,
- 0x43cc, 0x2009, 0x0012, 0x0078, 0x43a4, 0x2001, 0x0200, 0x71b4,
- 0xa188, 0x0091, 0x0078, 0x43b0, 0x1078, 0x47e1, 0x78a3, 0x0000,
- 0x681c, 0xa085, 0x0040, 0x681e, 0x71b4, 0xa188, 0x00da, 0xa006,
- 0x6826, 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000,
- 0x6822, 0x6eb6, 0x7e5a, 0x791a, 0x0078, 0x24fa, 0x6eb6, 0x1078,
- 0x3bc6, 0x6810, 0x70be, 0x7003, 0x0007, 0x70a3, 0x0000, 0x704b,
- 0x0000, 0x0078, 0x24fa, 0x0023, 0x0070, 0x0005, 0x0000, 0x0a00,
- 0x0000, 0x0000, 0x0025, 0x0000, 0x0000, 0x683b, 0x0000, 0x6837,
- 0x0000, 0xa684, 0x0200, 0x0040, 0x43ec, 0x78b8, 0xa08c, 0x001f,
- 0xa084, 0x8000, 0x0040, 0x43e5, 0x8108, 0x78d8, 0xa100, 0x6836,
- 0x78dc, 0xa081, 0x0000, 0x683a, 0x007c, 0x7990, 0x810f, 0xa5ac,
- 0x0007, 0x2021, 0x0000, 0xa480, 0x0010, 0x789a, 0x79a8, 0xa18c,
- 0x00ff, 0xa184, 0x0080, 0x00c0, 0x441b, 0xa182, 0x0020, 0x00c8,
- 0x4439, 0xa182, 0x0012, 0x00c8, 0x4781, 0x2100, 0x1079, 0x4409,
- 0x007c, 0x4781, 0x45eb, 0x4781, 0x4781, 0x4446, 0x4449, 0x4483,
- 0x44b9, 0x44ed, 0x44f0, 0x4781, 0x4781, 0x44a4, 0x4514, 0x454e,
- 0x4781, 0x4781, 0x4574, 0xa184, 0x0020, 0x00c0, 0x45a8, 0xa18c,
- 0x001f, 0x6814, 0xa084, 0x001f, 0xa106, 0x0040, 0x4436, 0x70b4,
- 0xa080, 0x00cd, 0x781a, 0x2001, 0x0014, 0x1078, 0x4797, 0x1078,
- 0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x2001, 0x0000,
- 0x007c, 0xa182, 0x0024, 0x00c8, 0x4781, 0xa184, 0x0003, 0x1079,
- 0x4409, 0x007c, 0x4781, 0x4781, 0x4781, 0x4781, 0x1078, 0x4781,
- 0x007c, 0x2200, 0x0079, 0x444c, 0x4577, 0x4577, 0x4470, 0x4470,
- 0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x446e, 0x4470,
- 0x4465, 0x4470, 0x4470, 0x4470, 0x4470, 0x4470, 0x4478, 0x447b,
- 0x4577, 0x447b, 0x4470, 0x4470, 0x4470, 0x0c7e, 0x077e, 0x6f14,
- 0x1078, 0x37b0, 0x077f, 0x0c7f, 0x0078, 0x4470, 0x1078, 0x468e,
- 0x6827, 0x02b3, 0x2009, 0x000b, 0x2001, 0x4800, 0x0078, 0x45ab,
- 0x1078, 0x4773, 0x007c, 0x6827, 0x0093, 0x2009, 0x000b, 0x2001,
- 0x4800, 0x0078, 0x4593, 0x2d58, 0x6804, 0xa084, 0x00ff, 0xa086,
- 0x0006, 0x00c0, 0x448d, 0x6807, 0x0117, 0x6827, 0x0002, 0x1078,
- 0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078,
- 0x3b96, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6, 0x0d7f, 0x1078,
- 0x3bc6, 0x2001, 0x0002, 0x007c, 0x1078, 0x45d3, 0x2001, 0x0017,
- 0x1078, 0x4797, 0x70a3, 0x0000, 0x2009, 0x5238, 0x200b, 0x0006,
- 0x70af, 0x0017, 0x2009, 0x0200, 0x1078, 0x3ad4, 0x2001, 0x0001,
- 0x007c, 0x2200, 0x0079, 0x44bc, 0x4577, 0x45a8, 0x45a8, 0x45a8,
- 0x44dd, 0x45ba, 0x44e5, 0x45ba, 0x45ba, 0x45bd, 0x45bd, 0x45c2,
- 0x45c2, 0x44d5, 0x44d5, 0x45a8, 0x45a8, 0x45ba, 0x45a8, 0x44e5,
- 0x4577, 0x44e5, 0x44e5, 0x44e5, 0x44e5, 0x6827, 0x0084, 0x2009,
- 0x000b, 0x2001, 0x4300, 0x0078, 0x45cc, 0x6827, 0x000d, 0x2009,
- 0x000b, 0x2001, 0x4300, 0x0078, 0x45ab, 0x6827, 0x0093, 0x2009,
- 0x000b, 0x2001, 0x4300, 0x0078, 0x4593, 0x2001, 0x0000, 0x007c,
- 0x2200, 0x0079, 0x44f3, 0x4577, 0x450c, 0x450c, 0x450c, 0x450c,
- 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba, 0x45ba,
- 0x450c, 0x450c, 0x450c, 0x450c, 0x45ba, 0x450c, 0x450c, 0x45ba,
- 0x45ba, 0x45ba, 0x45ba, 0x4577, 0x6827, 0x0093, 0x2009, 0x000b,
- 0x2001, 0x4300, 0x0078, 0x4593, 0xa684, 0x0004, 0x00c0, 0x4528,
- 0x6804, 0xa084, 0x00ff, 0xa086, 0x0006, 0x00c0, 0x4781, 0x1078,
- 0x45d3, 0x6807, 0x0117, 0x1078, 0x3bc6, 0x2001, 0x0002, 0x007c,
- 0x6000, 0xa084, 0x0004, 0x0040, 0x4781, 0x2d58, 0x6804, 0xa084,
- 0x00ff, 0xa086, 0x0006, 0x00c0, 0x4537, 0x6807, 0x0117, 0x6827,
- 0x0002, 0x1078, 0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e,
- 0x0d7e, 0x1078, 0x3ba5, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6,
- 0x0d7f, 0x1078, 0x3bc6, 0x2001, 0x0002, 0x007c, 0x6000, 0xa084,
- 0x0004, 0x0040, 0x4781, 0x6a04, 0xa294, 0x00ff, 0xa286, 0x0006,
- 0x00c0, 0x455c, 0x6807, 0x0117, 0x6827, 0x0002, 0x2d58, 0x1078,
- 0x4812, 0x6827, 0x0036, 0x6932, 0x2d00, 0x682e, 0x0d7e, 0x1078,
- 0x3bb5, 0x1078, 0x45d3, 0x2b68, 0x1078, 0x3bc6, 0x0d7f, 0x1078,
- 0x3bc6, 0x2001, 0x0002, 0x007c, 0x1078, 0x4781, 0x007c, 0x70b4,
- 0xa080, 0x00cd, 0x781a, 0x2001, 0x0001, 0x1078, 0x4797, 0x1078,
- 0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c, 0x1078, 0x47c7,
- 0x1078, 0x47fe, 0x1078, 0x43d5, 0x1078, 0x42cd, 0x1078, 0x4805,
- 0x2001, 0x0001, 0x007c, 0x1078, 0x47c7, 0x1078, 0x47fe, 0x1078,
- 0x43d5, 0x70b4, 0xa080, 0x00cd, 0x781a, 0x2001, 0x0013, 0x1078,
- 0x4797, 0x1078, 0x4805, 0x7003, 0x0000, 0x2001, 0x0002, 0x007c,
- 0x1078, 0x4781, 0x007c, 0x1078, 0x47c7, 0x1078, 0x47fe, 0x1078,
- 0x43d5, 0x1078, 0x42cd, 0x1078, 0x4805, 0x1078, 0x484d, 0x2001,
- 0x0001, 0x007c, 0x2001, 0x0003, 0x007c, 0x1078, 0x468e, 0x2001,
- 0x0000, 0x007c, 0x0c7e, 0x077e, 0x6f14, 0x1078, 0x37b0, 0x077f,
- 0x0c7f, 0x2001, 0x0000, 0x007c, 0x1078, 0x47c7, 0x1078, 0x4781,
- 0x2001, 0x0006, 0x007c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007,
- 0x0040, 0x45de, 0xa186, 0x000f, 0x00c0, 0x45e2, 0x1078, 0x47fe,
- 0x1078, 0x43d5, 0x70b4, 0xa080, 0x00cd, 0x781a, 0x1078, 0x4805,
- 0x7003, 0x0000, 0x007c, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084,
- 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x4781, 0x1079, 0x45f8, 0x007c,
- 0x4781, 0x45fc, 0x4781, 0x4695, 0xa282, 0x0003, 0x0040, 0x4603,
- 0x1078, 0x4781, 0x007c, 0x7da8, 0xa5ac, 0x00ff, 0x7ca8, 0xa4a4,
- 0x00ff, 0x69b8, 0xa184, 0x0100, 0x0040, 0x4642, 0xa18c, 0xfeff,
- 0x69ba, 0x78a0, 0xa005, 0x00c0, 0x4642, 0xa4a4, 0x00ff, 0x0040,
- 0x4636, 0xa482, 0x000c, 0x0040, 0x461f, 0x00c8, 0x4629, 0x852b,
- 0x852b, 0x1078, 0x382e, 0x0040, 0x4629, 0x1078, 0x3627, 0x0078,
- 0x4638, 0x1078, 0x4760, 0x1078, 0x3652, 0x69b8, 0xa18d, 0x0100,
- 0x69ba, 0xa6b5, 0x1000, 0x7e5a, 0x0078, 0x463b, 0x1078, 0x3652,
- 0xa6b4, 0xefff, 0x7e5a, 0x70b4, 0xa080, 0x0091, 0x781a, 0x2001,
- 0x0001, 0x007c, 0x0c7e, 0x1078, 0x4682, 0x6200, 0xd2e4, 0x0040,
- 0x4673, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048,
- 0x4655, 0x0040, 0x4655, 0x2011, 0x000c, 0x2400, 0xa202, 0x00c8,
- 0x465a, 0x2220, 0x6208, 0xa294, 0x00ff, 0x701c, 0xa202, 0x00c8,
- 0x4662, 0x721c, 0x2200, 0xa502, 0x00c8, 0x4667, 0x2228, 0x1078,
- 0x4764, 0x852b, 0x852b, 0x1078, 0x382e, 0x0040, 0x4673, 0x1078,
- 0x362e, 0x0078, 0x4677, 0x1078, 0x4760, 0x1078, 0x3659, 0xa6b5,
- 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004,
- 0x0c7f, 0x007c, 0x007e, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa0e0, 0x5480, 0x007f, 0x007c, 0x0c7e, 0x1078,
- 0x4682, 0x1078, 0x3659, 0x0c7f, 0x007c, 0xa282, 0x0002, 0x00c0,
- 0x4781, 0x7aa8, 0xa294, 0x00ff, 0x69b8, 0xa184, 0x0200, 0x0040,
- 0x46cc, 0xa18c, 0xfdff, 0x69ba, 0x78a0, 0xa005, 0x00c0, 0x46cc,
- 0xa282, 0x0002, 0x00c8, 0x376b, 0x1078, 0x472a, 0x1078, 0x36f9,
- 0x1078, 0x3652, 0xa684, 0x0100, 0x0040, 0x46c2, 0x682c, 0xa084,
- 0x0001, 0x0040, 0x46c2, 0xc6fc, 0x7888, 0xa084, 0x0040, 0x0040,
- 0x46c2, 0xc6fd, 0xa6b5, 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x0091,
- 0x781a, 0x2001, 0x0001, 0x007c, 0x0c7e, 0x1078, 0x4682, 0xa284,
- 0xfffe, 0x0040, 0x46d7, 0x2011, 0x0001, 0x0078, 0x46db, 0xa284,
- 0x0001, 0x0040, 0x46e1, 0x6100, 0xd1ec, 0x00c0, 0x46e1, 0x2011,
- 0x0000, 0x1078, 0x471c, 0x1078, 0x3700, 0x1078, 0x3659, 0xa684,
- 0x0100, 0x0040, 0x46f7, 0x682c, 0xa084, 0x0001, 0x0040, 0x46f7,
- 0xc6fc, 0x7888, 0xa084, 0x0040, 0x0040, 0x46f7, 0xc6fd, 0xa6b5,
- 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004,
- 0x0c7f, 0x007c, 0x0c7e, 0x2960, 0x6000, 0x2011, 0x0001, 0xa084,
- 0x2000, 0x00c0, 0x470d, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
- 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x68b8, 0xa085,
- 0x0200, 0x68ba, 0x0c7f, 0x007c, 0x789b, 0x0018, 0x78ab, 0x0001,
- 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0081, 0x78ab,
- 0x0004, 0x007c, 0x0c7e, 0x7054, 0x2060, 0x6000, 0xa084, 0x1000,
- 0x00c0, 0x4738, 0x2029, 0x0032, 0x2021, 0x0000, 0x0078, 0x4758,
- 0x6508, 0xa5ac, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0, 0x4748,
- 0xa582, 0x0019, 0x00c8, 0x474e, 0x2029, 0x0019, 0x0078, 0x474e,
- 0xa582, 0x000c, 0x00c8, 0x474e, 0x2029, 0x000c, 0x6408, 0x8427,
- 0xa4a4, 0x00ff, 0xa482, 0x000c, 0x0048, 0x4758, 0x2021, 0x000c,
- 0x1078, 0x4764, 0x68b8, 0xa085, 0x0100, 0x68ba, 0x0c7f, 0x007c,
- 0x2021, 0x0000, 0x2029, 0x0032, 0x789b, 0x0018, 0x78ab, 0x0001,
- 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7caa, 0x789b, 0x0081,
- 0x78ab, 0x0005, 0x007c, 0x2001, 0x0003, 0x1078, 0x478f, 0xa6b5,
- 0x1000, 0x7e5a, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0005,
- 0x007c, 0x2001, 0x0007, 0x1078, 0x478f, 0xa6b5, 0x1000, 0x7e5a,
- 0x70b4, 0xa080, 0x00b9, 0x781a, 0x2001, 0x0004, 0x007c, 0x789b,
- 0x0018, 0x78aa, 0x789b, 0x0081, 0x78ab, 0x0001, 0x007c, 0x6904,
- 0xa18c, 0x00ff, 0xa196, 0x0007, 0x0040, 0x47a5, 0xa196, 0x000f,
- 0x0040, 0x47a5, 0x1078, 0x19ac, 0x007c, 0x6924, 0xa194, 0x003f,
- 0x00c0, 0x47ae, 0xa18c, 0xffc0, 0xa105, 0x6826, 0x1078, 0x3bc6,
- 0x691c, 0xa184, 0x0100, 0x0040, 0x47bb, 0x6914, 0x1078, 0x3c3b,
- 0x6204, 0x8210, 0x6206, 0x007c, 0x692c, 0x6834, 0x682e, 0xa112,
- 0x6930, 0x6838, 0x6832, 0xa11b, 0xa200, 0xa301, 0x007c, 0x0c7e,
- 0xade0, 0x0018, 0x6003, 0x0070, 0x6106, 0x600b, 0x0000, 0x600f,
- 0x0a00, 0x6013, 0x0000, 0x6017, 0x0000, 0x8007, 0x601a, 0x601f,
- 0x0000, 0x6023, 0x0000, 0x0c7f, 0x6824, 0xa085, 0x0080, 0x6826,
- 0x007c, 0x157e, 0x137e, 0x147e, 0x2098, 0xaf80, 0x002d, 0x20a0,
- 0x81ac, 0x0040, 0x47ec, 0x53a6, 0xa184, 0x0001, 0x0040, 0x47f2,
- 0x3304, 0x78be, 0x147f, 0x137f, 0x157f, 0x007c, 0x70b0, 0xa005,
- 0x10c0, 0x248c, 0x70b3, 0x8000, 0x0078, 0x4b4b, 0x71b0, 0x81ff,
- 0x0040, 0x4804, 0x1078, 0x4c41, 0x007c, 0x71b0, 0x81ff, 0x0040,
- 0x4811, 0x7848, 0xa085, 0x0008, 0x784a, 0x70b3, 0x0000, 0x1078,
- 0x4887, 0x007c, 0x0c7e, 0x0d7e, 0x1078, 0x1989, 0x00c0, 0x481a,
- 0x1078, 0x248c, 0x0c7f, 0x157e, 0x137e, 0x147e, 0x2da0, 0x2c98,
- 0x20a9, 0x0031, 0x53a3, 0x147f, 0x137f, 0x157f, 0x6807, 0x010d,
- 0x680b, 0x0000, 0x7004, 0x8007, 0x681a, 0x6823, 0x0000, 0x681f,
- 0x0000, 0x689f, 0x0000, 0x0c7f, 0x007c, 0x70b4, 0xa080, 0x0091,
- 0x781a, 0x0078, 0x24fa, 0x70b4, 0xa080, 0x0081, 0x781a, 0x0078,
- 0x24fa, 0x70b4, 0xa080, 0x00b9, 0x781a, 0x0078, 0x24fa, 0x70b4,
- 0xa080, 0x00c3, 0x781a, 0x0078, 0x24fa, 0x6904, 0xa18c, 0x00ff,
- 0xa196, 0x0007, 0x0040, 0x485a, 0xa196, 0x000f, 0x0040, 0x485a,
- 0x6807, 0x0117, 0x6824, 0xa084, 0x00ff, 0xa085, 0x0200, 0x6826,
- 0x8007, 0x789b, 0x000e, 0x78aa, 0x6820, 0xa085, 0x8000, 0x6822,
- 0x2031, 0x0400, 0x6eb6, 0x7e5a, 0x71b4, 0xa188, 0x0091, 0x791a,
- 0x007c, 0x1078, 0x4805, 0x7848, 0xa085, 0x000c, 0x784a, 0x70b4,
- 0xa080, 0x00cd, 0x781a, 0x2009, 0x000b, 0x2001, 0x4400, 0x1078,
- 0x47c7, 0x2001, 0x0013, 0x1078, 0x4797, 0x0078, 0x3c68, 0x127e,
- 0x2091, 0x2200, 0x2049, 0x4887, 0x7000, 0x7204, 0xa205, 0x720c,
- 0xa215, 0x7008, 0xa084, 0xfff7, 0xa205, 0x0040, 0x4899, 0x0078,
- 0x489e, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x7000, 0xa084,
- 0x0001, 0x00c0, 0x48cc, 0x7108, 0x8103, 0x00c8, 0x48ab, 0x1078,
- 0x49ce, 0x0078, 0x48a3, 0x700c, 0xa08c, 0x00ff, 0x0040, 0x48cc,
- 0x7004, 0x8004, 0x00c8, 0x48c3, 0x7014, 0xa005, 0x00c0, 0x48bf,
- 0x7010, 0xa005, 0x0040, 0x48c3, 0xa102, 0x00c8, 0x48a3, 0x7007,
- 0x0010, 0x0078, 0x48cc, 0x8aff, 0x0040, 0x48cc, 0x1078, 0x4c18,
- 0x00c0, 0x48c6, 0x0040, 0x48a3, 0x1078, 0x4957, 0x7003, 0x0000,
- 0x127f, 0x2000, 0x007c, 0x017e, 0x6104, 0xa18c, 0x00ff, 0xa186,
- 0x0007, 0x0040, 0x48df, 0xa18e, 0x000f, 0x00c0, 0x48e2, 0x6040,
- 0x0078, 0x48e3, 0x6428, 0x017f, 0x84ff, 0x0040, 0x490d, 0x2c70,
- 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x491d, 0x273c, 0x87fb, 0x00c0,
- 0x48fb, 0x0048, 0x48f5, 0x1078, 0x248c, 0x609c, 0xa075, 0x0040,
- 0x490d, 0x0078, 0x48e8, 0x2704, 0xae68, 0x6808, 0xa630, 0x680c,
- 0xa529, 0x8421, 0x0040, 0x490d, 0x8738, 0x2704, 0xa005, 0x00c0,
- 0x48fc, 0x709c, 0xa075, 0x00c0, 0x48e8, 0x007c, 0x0000, 0x0005,
- 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
- 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4912, 0x490f,
- 0x0000, 0x0000, 0x8000, 0x0000, 0x4912, 0x0000, 0x491a, 0x4917,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x491a, 0x0000, 0x4915, 0x4915,
- 0x0000, 0x0000, 0x8000, 0x0000, 0x4915, 0x0000, 0x491b, 0x491b,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x491b, 0x127e, 0x2091, 0x2200,
- 0x2079, 0x5200, 0x2071, 0x0010, 0x7007, 0x000a, 0x7007, 0x0002,
- 0x7003, 0x0000, 0x2071, 0x0020, 0x7007, 0x000a, 0x7007, 0x0002,
- 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000, 0x007c, 0x2049,
- 0x4957, 0x2019, 0x0000, 0x7004, 0x8004, 0x00c8, 0x49aa, 0x7007,
- 0x0012, 0x7108, 0x7008, 0xa106, 0x00c0, 0x4961, 0xa184, 0x01e0,
- 0x0040, 0x496c, 0x1078, 0x248c, 0x2001, 0x04fd, 0x2004, 0xa082,
- 0x0005, 0x00c8, 0x4977, 0xa184, 0x4000, 0x00c0, 0x4961, 0xa19c,
- 0x300c, 0xa386, 0x2004, 0x0040, 0x4985, 0xa386, 0x0008, 0x0040,
- 0x4990, 0xa386, 0x200c, 0x00c0, 0x4961, 0x7200, 0x8204, 0x0048,
- 0x4990, 0x730c, 0xa384, 0x00ff, 0x0040, 0x4990, 0x1078, 0x248c,
- 0x7007, 0x0012, 0x7000, 0xa084, 0x0001, 0x00c0, 0x49aa, 0x7008,
- 0xa084, 0x01e0, 0x00c0, 0x49aa, 0x7310, 0x7014, 0xa305, 0x0040,
- 0x49aa, 0x710c, 0xa184, 0x0300, 0x00c0, 0x49aa, 0xa184, 0x00ff,
- 0x00c0, 0x4957, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084,
- 0x0008, 0x00c0, 0x49ae, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048,
- 0x49b3, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c, 0x107e, 0x007e,
- 0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078, 0x49ce, 0x157f,
- 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7204, 0x7500,
- 0x730c, 0xa384, 0x0300, 0x00c0, 0x49f5, 0xa184, 0x01e0, 0x00c0,
- 0x4a19, 0x7108, 0xa184, 0x01e0, 0x00c0, 0x4a19, 0x2001, 0x04fd,
- 0x2004, 0xa082, 0x0005, 0x00c8, 0x49e9, 0xa184, 0x4000, 0x00c0,
- 0x49d9, 0xa184, 0x0007, 0x0079, 0x49ed, 0x49f7, 0x4a09, 0x49f5,
- 0x4a09, 0x49f5, 0x4a55, 0x49f5, 0x4a53, 0x1078, 0x248c, 0x7004,
- 0xa084, 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff, 0x00c0, 0x4a04,
- 0x2049, 0x0000, 0x0078, 0x4a08, 0x1078, 0x4c18, 0x00c0, 0x4a04,
- 0x007c, 0x7004, 0xa084, 0x0010, 0xa085, 0x0002, 0x7006, 0x8aff,
- 0x00c0, 0x4a14, 0x0078, 0x4a18, 0x1078, 0x4c18, 0x00c0, 0x4a14,
- 0x007c, 0x7007, 0x0012, 0x7108, 0x00e0, 0x4a1c, 0x2091, 0x6000,
- 0x00e0, 0x4a20, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008,
- 0x7004, 0xa084, 0x0008, 0x00c0, 0x4a28, 0x7007, 0x0012, 0x7108,
- 0x8103, 0x0048, 0x4a2d, 0x7003, 0x0000, 0x7000, 0xa005, 0x00c0,
- 0x4a41, 0x7004, 0xa005, 0x00c0, 0x4a41, 0x700c, 0xa005, 0x0040,
- 0x4a43, 0x0078, 0x4a24, 0x2049, 0x0000, 0x1078, 0x38d7, 0x6818,
- 0xa084, 0x8000, 0x0040, 0x4a4e, 0x681b, 0x0002, 0x007c, 0x1078,
- 0x248c, 0x1078, 0x248c, 0x1078, 0x4ab1, 0x7210, 0x7114, 0x700c,
- 0xa09c, 0x00ff, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000, 0x1078,
- 0x4ab1, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200, 0xa322, 0x630c,
- 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x4a78, 0x00c8, 0x4a78,
- 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078, 0x4a5f,
- 0x2b60, 0x8a07, 0x007e, 0x6004, 0xa084, 0x0008, 0x0040, 0x4a84,
- 0xa7ba, 0x4917, 0x0078, 0x4a86, 0xa7ba, 0x490f, 0x007f, 0xa73d,
- 0x2c00, 0x6886, 0x6f8a, 0x6c92, 0x6b8e, 0x7007, 0x0012, 0x1078,
- 0x4957, 0x007c, 0x8738, 0x2704, 0xa005, 0x00c0, 0x4aa5, 0x609c,
- 0xa005, 0x0040, 0x4aae, 0x2060, 0x6004, 0xa084, 0x000f, 0xa080,
- 0x491d, 0x203c, 0x87fb, 0x1040, 0x248c, 0x8a51, 0x0040, 0x4aad,
- 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x007c, 0x2051, 0x0000,
- 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x4ac5, 0x6000,
- 0xa064, 0x00c0, 0x4abc, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080,
- 0x492d, 0x203c, 0x87fb, 0x1040, 0x248c, 0x007c, 0x127e, 0x0d7e,
- 0x2091, 0x2200, 0x0d7f, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90,
- 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x007e, 0x6804, 0xa084,
- 0x0008, 0x007f, 0x0040, 0x4ae0, 0xa0b8, 0x4917, 0x0078, 0x4ae2,
- 0xa0b8, 0x490f, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff,
- 0xa186, 0x0007, 0x0040, 0x4af0, 0xa18e, 0x000f, 0x00c0, 0x4af9,
- 0x681c, 0xa084, 0x0040, 0x0040, 0x4b00, 0xa6b5, 0x0001, 0x0078,
- 0x4b00, 0x681c, 0xa084, 0x0040, 0x0040, 0x4b00, 0xa6b5, 0x0001,
- 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4b02, 0x2400,
- 0xa305, 0x00c0, 0x4b0d, 0x0078, 0x4b33, 0x2c58, 0x2704, 0x6104,
- 0xac60, 0x6000, 0xa400, 0x701a, 0x6004, 0xa301, 0x701e, 0xa184,
- 0x0008, 0x0040, 0x4b23, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014,
- 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c,
- 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078,
- 0x4a92, 0x0078, 0x4b35, 0x1078, 0x4c18, 0x00c0, 0x4b33, 0x127f,
- 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007,
- 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4b41, 0x7003, 0x0008,
- 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f,
- 0x2049, 0x4b4b, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
- 0x4b54, 0x7e08, 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186,
- 0x0007, 0x0040, 0x4b67, 0xa18e, 0x000f, 0x00c0, 0x4b72, 0x681c,
- 0xa084, 0x0040, 0x0040, 0x4b6e, 0xa6b5, 0x0001, 0x6840, 0x2050,
- 0x0078, 0x4b7b, 0x681c, 0xa084, 0x0020, 0x00c0, 0x4b79, 0xa6b5,
- 0x0001, 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f, 0xa7b8,
- 0x491d, 0x273c, 0x87fb, 0x00c0, 0x4b8f, 0x0048, 0x4b89, 0x1078,
- 0x248c, 0x689c, 0xa065, 0x0040, 0x4b93, 0x0078, 0x4b7c, 0x1078,
- 0x4c18, 0x00c0, 0x4b8f, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e,
- 0x017e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08,
- 0xa6b5, 0x000c, 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040,
- 0x4bad, 0xa18e, 0x000f, 0x00c0, 0x4bb6, 0x681c, 0xa084, 0x0040,
- 0x0040, 0x4bbd, 0xa6b5, 0x0001, 0x0078, 0x4bbd, 0x681c, 0xa084,
- 0x0040, 0x0040, 0x4bbd, 0xa6b5, 0x0001, 0x2049, 0x4b96, 0x017e,
- 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4bcb, 0xa18e,
- 0x000f, 0x00c0, 0x4bce, 0x6840, 0x0078, 0x4bcf, 0x6828, 0x017f,
- 0xa055, 0x0040, 0x4c15, 0x2d70, 0x2e60, 0x7004, 0xa0bc, 0x000f,
- 0xa7b8, 0x491d, 0x273c, 0x87fb, 0x00c0, 0x4be9, 0x0048, 0x4be2,
- 0x1078, 0x248c, 0x709c, 0xa075, 0x2060, 0x0040, 0x4c15, 0x0078,
- 0x4bd5, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0048,
- 0x4c02, 0x8a51, 0x00c0, 0x4bf6, 0x1078, 0x248c, 0x8738, 0x2704,
- 0xa005, 0x00c0, 0x4bea, 0x709c, 0xa075, 0x2060, 0x0040, 0x4c15,
- 0x0078, 0x4bd5, 0x8422, 0x8420, 0x831a, 0xa399, 0x0000, 0x6908,
- 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8, 0x4c11, 0x1078,
- 0x248c, 0x2071, 0x0020, 0x0078, 0x4b00, 0x127f, 0x2000, 0x007c,
- 0x7008, 0xa084, 0x0003, 0xa086, 0x0003, 0x0040, 0x4c40, 0x2704,
- 0xac08, 0x2104, 0x701a, 0x8108, 0x2104, 0x701e, 0x8108, 0x2104,
- 0x7012, 0x8108, 0x2104, 0x7016, 0x6004, 0xa084, 0x0008, 0x0040,
- 0x4c37, 0x8108, 0x2104, 0x7022, 0x8108, 0x2104, 0x7026, 0x7602,
- 0x7004, 0xa084, 0x0010, 0xa085, 0x0001, 0x7006, 0x1078, 0x4a92,
- 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x2049, 0x4c41,
- 0x0d7f, 0x087f, 0x7108, 0xa184, 0x0003, 0x00c0, 0x4c6b, 0x017e,
- 0x6904, 0xa18c, 0x00ff, 0xa186, 0x0007, 0x0040, 0x4c5b, 0xa18e,
- 0x000f, 0x00c0, 0x4c5e, 0x6840, 0x0078, 0x4c5f, 0x6828, 0x017f,
- 0xa005, 0x0040, 0x4c79, 0x0078, 0x489e, 0x0020, 0x4c6b, 0x1078,
- 0x4a55, 0x0078, 0x4c79, 0x00a0, 0x4c72, 0x7108, 0x1078, 0x49ce,
- 0x0078, 0x4c4a, 0x7007, 0x0010, 0x00a0, 0x4c74, 0x7108, 0x1078,
- 0x49ce, 0x7008, 0xa086, 0x0008, 0x00c0, 0x4c4a, 0x7000, 0xa005,
- 0x00c0, 0x4c4a, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f, 0x2000,
- 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x2091,
- 0x2200, 0x0d7f, 0x2049, 0x4c89, 0xad80, 0x0011, 0x20a0, 0x2099,
- 0x0031, 0x700c, 0xa084, 0x00ff, 0x682a, 0x7007, 0x0008, 0x7007,
- 0x0002, 0x7003, 0x0001, 0x0040, 0x4ca8, 0x8000, 0x80ac, 0x53a5,
- 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4caa, 0x0c7f,
- 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f,
- 0x2000, 0x007c, 0x2091, 0x6000, 0x2091, 0x8000, 0x78cc, 0xa005,
- 0x0040, 0x4cd1, 0x7994, 0x70d0, 0xa106, 0x00c0, 0x4cd1, 0x7804,
- 0xa005, 0x0040, 0x4cd1, 0x7807, 0x0000, 0x0068, 0x4cd1, 0x2091,
- 0x4080, 0x7820, 0x8001, 0x7822, 0x00c0, 0x4d2c, 0x7824, 0x7822,
- 0x2069, 0x5240, 0x6800, 0xa084, 0x0007, 0x0040, 0x4cef, 0xa086,
- 0x0002, 0x0040, 0x4cef, 0x6834, 0xa00d, 0x0040, 0x4cef, 0x2104,
- 0xa005, 0x0040, 0x4cef, 0x8001, 0x200a, 0x0040, 0x4dd4, 0x7848,
- 0xa005, 0x0040, 0x4cfd, 0x8001, 0x784a, 0x00c0, 0x4cfd, 0x2009,
- 0x0102, 0x6844, 0x200a, 0x1078, 0x226f, 0x6890, 0xa005, 0x0040,
- 0x4d09, 0x8001, 0x6892, 0x00c0, 0x4d09, 0x686f, 0x0000, 0x6873,
- 0x0001, 0x2061, 0x5500, 0x20a9, 0x0100, 0x2009, 0x0002, 0x6034,
- 0xa005, 0x0040, 0x4d1f, 0x8001, 0x6036, 0x00c0, 0x4d1f, 0x6010,
- 0xa005, 0x0040, 0x4d1f, 0x017e, 0x1078, 0x226f, 0x017f, 0xace0,
- 0x0010, 0x0070, 0x4d25, 0x0078, 0x4d0f, 0x8109, 0x0040, 0x4d2c,
- 0x20a9, 0x0100, 0x0078, 0x4d0f, 0x1078, 0x4d39, 0x1078, 0x4d5e,
- 0x2009, 0x5251, 0x2104, 0x2009, 0x0102, 0x200a, 0x2091, 0x8001,
- 0x007c, 0x7834, 0x8001, 0x7836, 0x00c0, 0x4d5d, 0x7838, 0x7836,
- 0x2091, 0x8000, 0x7844, 0xa005, 0x00c0, 0x4d48, 0x2001, 0x0101,
- 0x8001, 0x7846, 0xa080, 0x7500, 0x2040, 0x2004, 0xa065, 0x0040,
- 0x4d5d, 0x6024, 0xa005, 0x0040, 0x4d59, 0x8001, 0x6026, 0x0040,
- 0x4d8d, 0x6000, 0x2c40, 0x0078, 0x4d4e, 0x007c, 0x7828, 0x8001,
- 0x782a, 0x00c0, 0x4d8c, 0x782c, 0x782a, 0x7830, 0xa005, 0x00c0,
- 0x4d6b, 0x2001, 0x0200, 0x8001, 0x7832, 0x8003, 0x8003, 0x8003,
- 0x8003, 0xa090, 0x5500, 0xa298, 0x0002, 0x2304, 0xa084, 0x0008,
- 0x0040, 0x4d8c, 0xa290, 0x0009, 0x2204, 0xa005, 0x0040, 0x4d84,
- 0x8001, 0x2012, 0x00c0, 0x4d8c, 0x2304, 0xa084, 0xfff7, 0xa085,
- 0x0080, 0x201a, 0x1078, 0x226f, 0x007c, 0x2069, 0x5240, 0x6800,
- 0xa005, 0x0040, 0x4d97, 0x6848, 0xac06, 0x0040, 0x4dd4, 0x601b,
- 0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
- 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x6714, 0x6f82, 0x1078,
- 0x19c5, 0x6818, 0xa005, 0x0040, 0x4daf, 0x8001, 0x681a, 0x6808,
- 0xa084, 0xffef, 0x680a, 0x6810, 0x8001, 0x00d0, 0x4db9, 0x1078,
- 0x248c, 0x6812, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078,
- 0x1cdc, 0x2069, 0x5240, 0x7944, 0xa184, 0x0100, 0x2001, 0x0006,
- 0x686e, 0x00c0, 0x4dcf, 0x6986, 0x2001, 0x0004, 0x686e, 0x1078,
- 0x226a, 0x2091, 0x8001, 0x007c, 0x2069, 0x0100, 0x2009, 0x5240,
- 0x2104, 0xa084, 0x0007, 0x0040, 0x4e30, 0xa086, 0x0007, 0x00c0,
- 0x4dea, 0x0d7e, 0x2009, 0x5252, 0x216c, 0x1078, 0x3b1c, 0x0d7f,
- 0x0078, 0x4e30, 0x2009, 0x5252, 0x2164, 0x1078, 0x2437, 0x601b,
- 0x0006, 0x6858, 0xa084, 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff,
- 0xa085, 0x0048, 0x6022, 0x602f, 0x0000, 0x6033, 0x0000, 0x6830,
- 0xa084, 0x0040, 0x0040, 0x4e24, 0x684b, 0x0004, 0x20a9, 0x0014,
- 0x6848, 0xa084, 0x0004, 0x0040, 0x4e11, 0x0070, 0x4e11, 0x0078,
- 0x4e08, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001,
- 0x0040, 0x4e1e, 0x0070, 0x4e1e, 0x0078, 0x4e15, 0x20a9, 0x00fa,
- 0x0070, 0x4e24, 0x0078, 0x4e20, 0x6808, 0xa084, 0xfffd, 0x680a,
- 0x681b, 0x0048, 0x2009, 0x525b, 0x200b, 0x0007, 0x784c, 0x784a,
- 0x2091, 0x8001, 0x007c, 0x2079, 0x5200, 0x1078, 0x4e5e, 0x1078,
- 0x4e42, 0x1078, 0x4e50, 0x7833, 0x0000, 0x7847, 0x0000, 0x784b,
- 0x0000, 0x007c, 0x2019, 0x0003, 0x2011, 0x5246, 0x2204, 0xa086,
- 0x003c, 0x0040, 0x4e4d, 0x2019, 0x0002, 0x7b2a, 0x7b2e, 0x007c,
- 0x2019, 0x0039, 0x2011, 0x5246, 0x2204, 0xa086, 0x003c, 0x0040,
- 0x4e5b, 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x3971,
- 0x2011, 0x5246, 0x2204, 0xa086, 0x003c, 0x0040, 0x4e69, 0x2019,
- 0x2626, 0x7b22, 0x7b26, 0x783f, 0x0000, 0x7843, 0x000a, 0x007c,
- 0x0020, 0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014,
- 0x0014, 0x0014, 0x0014, 0x0014, 0x0014, 0x0080, 0x000f, 0x0000,
- 0x0201, 0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b,
- 0xa201, 0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0x0000, 0x006c,
- 0x0002, 0x0014, 0x98cd, 0x009e, 0x0093, 0xa202, 0x8838, 0x3806,
- 0x8839, 0x20c3, 0x0864, 0x9885, 0x28c1, 0x9cae, 0xa203, 0x300c,
- 0x2846, 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0x9865, 0x28f2,
- 0x9c91, 0x9858, 0x300c, 0x28e1, 0x9c91, 0x2802, 0xa206, 0x64c3,
- 0x282e, 0xa207, 0x64a0, 0x6de0, 0x67a0, 0x6fc0, 0x1814, 0x883b,
- 0x7824, 0x68c1, 0x7864, 0x883e, 0x9879, 0x8576, 0x8677, 0x206b,
- 0x28c1, 0x9cae, 0x2044, 0x2103, 0x20a2, 0x2081, 0x9865, 0xa209,
- 0x2901, 0x988d, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a, 0x883c,
- 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c91, 0x0014, 0xa204,
- 0xa300, 0x3009, 0x19e2, 0xf864, 0x856e, 0x883f, 0x08e6, 0x9891,
- 0xf881, 0x988c, 0xc801, 0x0014, 0xf8c1, 0x0016, 0x85b2, 0x80f0,
- 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532, 0xf241, 0x0014, 0x1de2,
- 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208, 0x6043, 0x8008, 0x1dc1,
- 0x0016, 0x8300, 0x8160, 0x842a, 0xf041, 0x3008, 0x84a8, 0x11d6,
- 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x8000, 0x2847,
- 0x1011, 0x98c0, 0x8000, 0xa000, 0x2802, 0x1011, 0x98c6, 0x9865,
- 0x283e, 0x1011, 0x98ca, 0xa20b, 0x0017, 0x300c, 0xa300, 0x1de2,
- 0xdb81, 0x0014, 0x0210, 0x98d7, 0x0014, 0x26e0, 0x873a, 0xfb02,
- 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9cb3, 0x0704,
- 0x0000, 0x006c, 0x0002, 0x984f, 0x0014, 0x009e, 0x00a0, 0x0017,
- 0x60ff, 0x300c, 0x8720, 0xa211, 0x9cd0, 0x8772, 0x8837, 0x2101,
- 0x987a, 0x10d2, 0x78e2, 0x9cd3, 0x9859, 0xd984, 0xf0e2, 0xf0a1,
- 0x98cd, 0x0014, 0x8831, 0xd166, 0x8830, 0x800f, 0x9401, 0xb520,
- 0xc802, 0x8820, 0x987a, 0x2301, 0x987a, 0x10d2, 0x78e4, 0x9cd3,
- 0x8821, 0x8820, 0x9859, 0xf123, 0xf142, 0xf101, 0x98c6, 0x10d2,
- 0x70f6, 0x8832, 0x8203, 0x870c, 0xd99e, 0x6001, 0x0014, 0x6845,
- 0x0214, 0xa21b, 0x9cd0, 0x2001, 0x98c5, 0x8201, 0x1852, 0xd184,
- 0xd163, 0x8834, 0x8001, 0x988d, 0x3027, 0x84a8, 0x1a56, 0x8833,
- 0x0014, 0xa218, 0x6981, 0x9cbc, 0x6926, 0x6902, 0x1a34, 0x9899,
- 0x1a14, 0x7021, 0x0014, 0xa300, 0x6141, 0x6964, 0x8010, 0x8592,
- 0x8026, 0x84b9, 0x69e4, 0x8023, 0x16e1, 0x8001, 0x10f1, 0x6946,
- 0xa213, 0x1462, 0xa213, 0x8000, 0x16e1, 0x98b5, 0x6969, 0xa214,
- 0x61c2, 0x8002, 0x14e1, 0x8004, 0x16e1, 0x0101, 0x300a, 0x8827,
- 0x0014, 0xa217, 0x9cbc, 0x0014, 0xa300, 0x8181, 0x842a, 0x84a8,
- 0x1ce6, 0x882c, 0x0016, 0xa212, 0x9cd0, 0x10d2, 0x70e4, 0x0004,
- 0x8007, 0x9424, 0xcc1a, 0x9cd3, 0x98c5, 0x8827, 0x300a, 0x0013,
- 0x8000, 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e, 0xa21d, 0x0014,
- 0x878e, 0x0016, 0xa21c, 0x1035, 0x9891, 0xa210, 0xa000, 0x8010,
- 0x8592, 0x853b, 0xd044, 0x8022, 0x3807, 0x84bb, 0x98ea, 0x8021,
- 0x3807, 0x84b9, 0x300c, 0x817e, 0x872b, 0x8772, 0x9891, 0x0000,
- 0x0020, 0x002b, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0014, 0x0014, 0x9849, 0x0014, 0x0014,
- 0x98e2, 0x98cd, 0x0014, 0x0014, 0x0014, 0x0080, 0x0137, 0x0000,
- 0x0201, 0x0604, 0x0c08, 0x2120, 0x4022, 0xf880, 0x0018, 0x300b,
- 0xa201, 0x0014, 0xa200, 0x0014, 0xa200, 0x0214, 0xa202, 0x8838,
- 0x3806, 0x8839, 0x20c3, 0x0864, 0xa82f, 0x28c1, 0x9cae, 0xa203,
- 0x300c, 0x2846, 0x8161, 0x846a, 0x8300, 0x1856, 0x883a, 0xa804,
- 0x28f2, 0x9c91, 0xa8f4, 0x300c, 0x28e1, 0x9c91, 0x2802, 0xa206,
- 0x64c3, 0x282e, 0xa207, 0x64a0, 0x6de0, 0x67a0, 0x6fc0, 0x1814,
- 0x883b, 0x7824, 0x68c1, 0x7864, 0x883e, 0xa802, 0x8576, 0x8677,
- 0x206b, 0x28c1, 0x9cae, 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8e4,
- 0xa209, 0x2901, 0xa809, 0x0014, 0xa205, 0xa300, 0x1872, 0x879a,
- 0x883c, 0x1fe2, 0xc601, 0xa20a, 0x856e, 0x0704, 0x9c91, 0x0014,
- 0xa204, 0xa300, 0x3009, 0x19e2, 0xf864, 0x856e, 0x883f, 0x08e6,
- 0xa8f7, 0xf881, 0xa8f0, 0xc801, 0x0014, 0xf8c1, 0x0016, 0x85b2,
- 0x80f0, 0x9532, 0xfb02, 0x1de2, 0x0014, 0x8532, 0xf241, 0x0014,
- 0x1de2, 0x84a8, 0xd7a0, 0x1fe6, 0x0014, 0xa208, 0x6043, 0x8008,
- 0x1dc1, 0x0016, 0x8300, 0x8160, 0x842a, 0xf041, 0x3008, 0x84a8,
- 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x8000,
- 0x2847, 0x1011, 0xa8fc, 0x8000, 0xa000, 0x2802, 0x1011, 0xa8fd,
- 0xa89b, 0x283e, 0x1011, 0xa8fd, 0xa20b, 0x0017, 0x300c, 0xa300,
- 0x1de2, 0xdb81, 0x0014, 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a,
- 0xfb02, 0x19f2, 0x1fe2, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9cb3,
- 0x0704, 0x0017, 0x60ff, 0x300c, 0x8720, 0xa211, 0x9d63, 0x8772,
- 0x8837, 0x2101, 0xa821, 0x10d2, 0x78e2, 0x9d66, 0xa8fc, 0xd984,
- 0xf0e2, 0xf0a1, 0xa86c, 0x0014, 0x8831, 0xd166, 0x8830, 0x800f,
- 0x9401, 0xb520, 0xc802, 0x8820, 0xa80f, 0x2301, 0xa80d, 0x10d2,
- 0x78e4, 0x9d66, 0x8821, 0x8820, 0xa8e6, 0xf123, 0xf142, 0xf101,
- 0xa84f, 0x10d2, 0x70f6, 0x8832, 0x8203, 0x870c, 0xd99e, 0x6001,
- 0x0014, 0x6845, 0x0214, 0xa21b, 0x9d63, 0x2001, 0xa840, 0x8201,
- 0x1852, 0xd184, 0xd163, 0x8834, 0x8001, 0xa801, 0x3027, 0x84a8,
- 0x1a56, 0x8833, 0x0014, 0xa218, 0x6981, 0x9d4f, 0x6926, 0x6902,
- 0x1a34, 0xa801, 0x1a14, 0x7021, 0x0014, 0xa300, 0x6141, 0x6964,
- 0x8010, 0x8592, 0x8026, 0x84b9, 0x69e4, 0x8023, 0x16e1, 0x8001,
- 0x10f1, 0x6946, 0xa213, 0x1462, 0xa213, 0x8000, 0x16e1, 0xa807,
- 0x6969, 0xa214, 0x61c2, 0x8002, 0x14e1, 0x8004, 0x16e1, 0x0101,
- 0x300a, 0x8827, 0x0014, 0xa217, 0x9d4f, 0x0014, 0xa300, 0x8181,
- 0x842a, 0x84a8, 0x1ce6, 0x882c, 0x0016, 0xa212, 0x9d63, 0x10d2,
- 0x70e4, 0x0004, 0x8007, 0x9424, 0xcc1a, 0x9d66, 0xa8f8, 0x8827,
- 0x300a, 0x0013, 0x8000, 0x84a4, 0x0016, 0x11c2, 0x211e, 0x870e,
- 0xa21d, 0x0014, 0x878e, 0x0016, 0xa21c, 0x1035, 0xa8b4, 0xa210,
- 0x3807, 0x300c, 0x817e, 0x872b, 0x8772, 0xa8ad, 0x0000, 0x0d0c
-};
-static unsigned short risc_code_length01 = 0x4158;
diff --git a/drivers/scsi/ql12160_fw.h b/drivers/scsi/ql12160_fw.h
deleted file mode 100644
index d89dac0cc9d..00000000000
--- a/drivers/scsi/ql12160_fw.h
+++ /dev/null
@@ -1,1811 +0,0 @@
-/*****************************************************************************
- * QLOGIC LINUX SOFTWARE
- *
- * QLogic ISP12160 device driver for Linux 2.2.x and 2.4.x
- * Copyright (C) 2002 Qlogic Corporation (www.qlogic.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- *****************************************************************************/
-
-/************************************************************************
- * --- ISP12160A Initiator Firmware --- *
- * 32 LUN Support *
- ************************************************************************/
-
-/*
- * Firmware Version 10.04.42 (15:44 Apr 18, 2003)
- */
-
-#ifdef UNIQUE_FW_NAME
-static unsigned char fw12160i_version_str[] = {10,4,42};
-#else
-static unsigned char firmware_version[] = {10,4,42};
-#endif
-
-#ifdef UNIQUE_FW_NAME
-#define fw12160i_VERSION_STRING "10.04.42"
-#else
-#define FW_VERSION_STRING "10.04.42"
-#endif
-
-#ifdef UNIQUE_FW_NAME
-static unsigned short fw12160i_addr01 = 0x1000;
-#else
-static unsigned short risc_code_addr01 = 0x1000;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-static unsigned short fw12160i_code01[] = {
-#else
-static unsigned short risc_code01[] = {
-#endif
- 0x0804, 0x1041, 0x0000, 0x36c9, 0x0000, 0x2043, 0x4f50, 0x5952,
- 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
- 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
- 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
- 0x3132, 0x3136, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
- 0x6572, 0x7369, 0x6f6e, 0x2031, 0x302e, 0x3034, 0x2020, 0x2043,
- 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
- 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
- 0x2400, 0x20c9, 0x90ff, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2001,
- 0x01ff, 0x2004, 0xd0fc, 0x1120, 0x2071, 0x0100, 0x70a0, 0x70a2,
- 0x20c1, 0x0020, 0x2089, 0x1221, 0x2071, 0x0010, 0x70c3, 0x0004,
- 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x000a,
- 0x2001, 0x04fd, 0x2004, 0x70d6, 0x2009, 0xfeff, 0x2130, 0x2128,
- 0xa1a2, 0x4700, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
- 0xa192, 0x9100, 0x2009, 0x0000, 0x2001, 0x0032, 0x080c, 0x1e05,
- 0x2218, 0x2079, 0x4700, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
- 0x0040, 0x42a4, 0x8109, 0x1dd8, 0x2009, 0xff00, 0x3400, 0xa102,
- 0x0218, 0x0110, 0x20a8, 0x42a4, 0x781b, 0x0064, 0x7814, 0xc0cd,
- 0xc0d5, 0x7816, 0x2071, 0x0200, 0x00d6, 0x2069, 0x4740, 0x080c,
- 0x465c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1130, 0x2069, 0x4780,
- 0x2071, 0x0100, 0x080c, 0x465c, 0x7814, 0xc0d4, 0x7816, 0x00de,
- 0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800, 0xc08d, 0x7802,
- 0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002, 0x7827, 0x0002,
- 0x2009, 0x0002, 0x2069, 0x4740, 0x681b, 0x0003, 0x6823, 0x0007,
- 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028, 0x6837, 0x0006,
- 0x6833, 0x0008, 0x683b, 0x0000, 0x8109, 0x0500, 0x68cf, 0x000a,
- 0x68bf, 0x47c0, 0x2079, 0x4700, 0x68d3, 0x762d, 0x68c3, 0x4cc0,
- 0x68c7, 0x4bc0, 0x68cb, 0x8cc0, 0x68a7, 0x8f44, 0x68ab, 0x8f49,
- 0x68af, 0x8f44, 0x68b3, 0x8f44, 0x68a3, 0x0001, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x11c8, 0x2069, 0x4780, 0x0870, 0x68cf, 0x000a,
- 0x68bf, 0x49c0, 0x68d3, 0x7839, 0x68c3, 0x6cc0, 0x68c7, 0x4c40,
- 0x68cb, 0x8dd0, 0x68a7, 0x8f49, 0x68ab, 0x8f4e, 0x68af, 0x8f49,
- 0x68b3, 0x8f49, 0x68a3, 0x0001, 0x00e6, 0x2069, 0x4bc0, 0x2071,
- 0x0200, 0x70ec, 0xd0e4, 0x2019, 0x1809, 0x2021, 0x0009, 0x1120,
- 0x2019, 0x180c, 0x2021, 0x000c, 0x080c, 0x1d75, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x1188, 0x2069, 0x4c40, 0x2071, 0x0100, 0x70ec,
- 0xd0e4, 0x2019, 0x1809, 0x2021, 0x0009, 0x1120, 0x2019, 0x180c,
- 0x2021, 0x000c, 0x080c, 0x1d75, 0x00ee, 0x2011, 0x0002, 0x2069,
- 0x4cc0, 0x2009, 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b,
- 0x0040, 0x7bc8, 0xa386, 0xfeff, 0x1128, 0x6817, 0x0100, 0x681f,
- 0x0064, 0x0020, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010,
- 0x1f04, 0x1135, 0x8109, 0x1d38, 0x2001, 0x01ff, 0x2004, 0xd0fc,
- 0x1128, 0x8211, 0x0118, 0x2069, 0x6cc0, 0x08d8, 0x080c, 0x22f6,
- 0x080c, 0x403d, 0x080c, 0x1b8c, 0x080c, 0x4615, 0x2091, 0x2200,
- 0x2079, 0x4700, 0x2071, 0x0050, 0x2091, 0x2400, 0x2079, 0x4700,
- 0x2071, 0x0020, 0x2091, 0x2600, 0x2079, 0x0200, 0x2071, 0x4740,
- 0x2091, 0x2800, 0x2079, 0x0100, 0x2071, 0x4780, 0x2091, 0x2000,
- 0x2079, 0x4700, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
- 0x2071, 0x0010, 0x70c3, 0x0000, 0x1004, 0x118c, 0x70c0, 0xa086,
- 0x0002, 0x1110, 0x080c, 0x13ba, 0x2039, 0x0000, 0x080c, 0x12ab,
- 0x78ac, 0xa005, 0x1180, 0x0e04, 0x119a, 0x786c, 0xa065, 0x0110,
- 0x080c, 0x20a1, 0x080c, 0x1e26, 0x0e04, 0x11af, 0x786c, 0xa065,
- 0x0110, 0x080c, 0x20a1, 0x0e04, 0x11af, 0x2009, 0x4747, 0x2011,
- 0x4787, 0x2104, 0x220c, 0xa105, 0x0110, 0x080c, 0x1c9b, 0x2071,
- 0x4740, 0x70a0, 0xa005, 0x01e8, 0x744c, 0xa485, 0x0000, 0x01c8,
- 0x2079, 0x0200, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d, 0x2190,
- 0x080c, 0x274c, 0x2091, 0x8000, 0x2091, 0x303d, 0x0e04, 0x11d1,
- 0x2079, 0x4700, 0x786c, 0xa065, 0x0120, 0x2071, 0x0010, 0x080c,
- 0x20a1, 0x1d04, 0x11d9, 0x2079, 0x4700, 0x2071, 0x0010, 0x080c,
- 0x4429, 0x2071, 0x4780, 0x70a0, 0xa005, 0x0188, 0x704c, 0xa025,
- 0x0170, 0x2079, 0x0100, 0x2091, 0x8000, 0x72d0, 0xa28c, 0x303d,
- 0x2190, 0x080c, 0x274c, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079,
- 0x4700, 0x2071, 0x0010, 0x0e04, 0x11fa, 0x786c, 0xa065, 0x0110,
- 0x080c, 0x20a1, 0x1d04, 0x118e, 0x080c, 0x4429, 0x0804, 0x118e,
- 0x3c00, 0xa084, 0x0007, 0x0002, 0x120c, 0x120c, 0x120e, 0x120e,
- 0x1213, 0x1213, 0x1218, 0x1218, 0x080c, 0x2575, 0x2091, 0x2400,
- 0x080c, 0x40d5, 0x0005, 0x2091, 0x2200, 0x080c, 0x40d5, 0x0005,
- 0x2091, 0x2200, 0x080c, 0x40d5, 0x2091, 0x2400, 0x080c, 0x40d5,
- 0x0005, 0x1241, 0x1241, 0x1242, 0x1242, 0x124d, 0x124d, 0x124d,
- 0x124d, 0x1256, 0x1256, 0x1261, 0x1261, 0x124d, 0x124d, 0x124d,
- 0x124d, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270,
- 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270, 0x1270,
- 0x1270, 0x0cf8, 0x0006, 0x0106, 0x0126, 0x2091, 0x2800, 0x080c,
- 0x2592, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106, 0x0126,
- 0x080c, 0x1200, 0x012e, 0x010e, 0x000e, 0x000d, 0x0006, 0x0106,
- 0x0126, 0x2091, 0x2600, 0x080c, 0x2592, 0x012e, 0x010e, 0x000e,
- 0x000d, 0x0006, 0x0106, 0x0126, 0x2091, 0x2600, 0x080c, 0x2592,
- 0x2091, 0x2800, 0x080c, 0x2592, 0x012e, 0x010e, 0x000e, 0x000d,
- 0x0006, 0x0106, 0x0126, 0x00d6, 0x00e6, 0x00f6, 0x2079, 0x4700,
- 0x2071, 0x0200, 0x2069, 0x4740, 0x3d00, 0xd08c, 0x0130, 0x70ec,
- 0xa084, 0x1c00, 0x78e2, 0x080c, 0x465c, 0x3d00, 0xd084, 0x0150,
- 0x2069, 0x4780, 0x2071, 0x0100, 0x70ec, 0xa084, 0x1c00, 0x78e6,
- 0x080c, 0x465c, 0x080c, 0x2526, 0x00fe, 0x00ee, 0x00de, 0x012e,
- 0x010e, 0x000e, 0x000d, 0x7008, 0x800b, 0x1240, 0x7007, 0x0002,
- 0xa08c, 0x01e0, 0x1120, 0xd09c, 0x0108, 0x0887, 0x0897, 0x70c3,
- 0x4002, 0x0804, 0x13bd, 0x0e04, 0x131e, 0x2061, 0x0000, 0x6018,
- 0xd084, 0x1904, 0x131e, 0x7828, 0xa005, 0x1120, 0x0004, 0x131f,
- 0x0804, 0x131e, 0xd0fc, 0x0130, 0x0006, 0x080c, 0x1b29, 0x000e,
- 0x0150, 0x0028, 0x0006, 0x080c, 0x1b1e, 0x000e, 0x0120, 0x2001,
- 0x4007, 0x0804, 0x13bc, 0x7910, 0xd0fc, 0x1128, 0x2061, 0x4740,
- 0xc19c, 0xc7fc, 0x0020, 0x2061, 0x4780, 0xc19d, 0xc7fd, 0x6060,
- 0xa005, 0x1904, 0x131e, 0x7912, 0x607e, 0x7828, 0xc0fc, 0xa086,
- 0x0018, 0x1120, 0x00c6, 0x080c, 0x1926, 0x00ce, 0x782b, 0x0000,
- 0x6078, 0xa065, 0x01e0, 0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce,
- 0x609f, 0x0000, 0x080c, 0x1a60, 0x2009, 0x0018, 0x6087, 0x0103,
- 0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
- 0x080c, 0x1b34, 0x000e, 0x7812, 0x1198, 0x080c, 0x1b7f, 0x7810,
- 0xd09c, 0x1118, 0x2061, 0x4740, 0x0020, 0x2061, 0x4780, 0xc09c,
- 0x7812, 0x607b, 0x0000, 0x60d0, 0xd0c4, 0x0130, 0xc0c4, 0x60d2,
- 0x2001, 0x4005, 0x0804, 0x13bc, 0x0804, 0x13ba, 0x0005, 0xa006,
- 0x70c2, 0x70c6, 0x70ca, 0x70ce, 0x70da, 0x70c0, 0xa03d, 0xa08a,
- 0x0040, 0x1a04, 0x136c, 0x0002, 0x13ba, 0x1408, 0x13d6, 0x143c,
- 0x1470, 0x1470, 0x13ce, 0x1a78, 0x147a, 0x13c8, 0x13da, 0x13db,
- 0x13dc, 0x13dd, 0x1a7c, 0x13c8, 0x1487, 0x14db, 0x1941, 0x1a72,
- 0x13de, 0x17c8, 0x17fe, 0x1830, 0x1876, 0x1785, 0x1792, 0x17a5,
- 0x17b7, 0x15bf, 0x13c8, 0x150d, 0x1518, 0x1526, 0x1534, 0x154b,
- 0x1559, 0x155c, 0x156e, 0x157c, 0x1586, 0x15a5, 0x15b1, 0x13c8,
- 0x13c8, 0x13c8, 0x13c8, 0x15cc, 0x15dd, 0x15f7, 0x162b, 0x1654,
- 0x1666, 0x1669, 0x1693, 0x16cc, 0x16de, 0x1753, 0x1763, 0x13c8,
- 0x13c8, 0x13c8, 0x13c8, 0x1775, 0x2100, 0xa08a, 0x0040, 0x1a04,
- 0x13c8, 0x0002, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x1a9e,
- 0x1aa4, 0x13c8, 0x13c8, 0x13c8, 0x1aa8, 0x1ae8, 0x13c8, 0x13c8,
- 0x13c8, 0x13c8, 0x1403, 0x146b, 0x1482, 0x14d6, 0x193c, 0x13c8,
- 0x13c8, 0x190b, 0x13c8, 0x1aec, 0x1a90, 0x1a9a, 0x13c8, 0x13c8,
- 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
- 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
- 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
- 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8, 0x13c8,
- 0x13c8, 0x13c8, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0028, 0x73ce,
- 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0e04, 0x13bd, 0x2061,
- 0x0000, 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x0005,
- 0x70c3, 0x4001, 0x0c90, 0x70c3, 0x4006, 0x0c78, 0x2099, 0x0041,
- 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0c20, 0x70c4, 0x70c3,
- 0x0004, 0x0807, 0x08f8, 0x08f0, 0x08e8, 0x08e0, 0x2091, 0x8000,
- 0x70c3, 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020,
- 0x70d3, 0x000a, 0x2001, 0x0004, 0x70d6, 0x2079, 0x0000, 0x781b,
- 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051,
- 0x0445, 0x2061, 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091,
- 0x4080, 0x0804, 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0018,
- 0x2029, 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0,
- 0x2099, 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e,
- 0x7422, 0x7526, 0x2021, 0x0040, 0x81ff, 0x0904, 0x13ba, 0xa182,
- 0x0040, 0x1210, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x7007,
- 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002,
- 0xa084, 0x01e0, 0x0120, 0x70c3, 0x4002, 0x0804, 0x13bd, 0x24a8,
- 0x53a5, 0x0c10, 0x0804, 0x13ba, 0x2029, 0x0000, 0x2520, 0x71d0,
- 0x72c8, 0x73cc, 0x70c4, 0x2098, 0x20a1, 0x0030, 0x7003, 0x0000,
- 0x7007, 0x0006, 0x731a, 0x721e, 0x7422, 0x7526, 0x2021, 0x0040,
- 0x7007, 0x0006, 0x81ff, 0x0904, 0x13ba, 0xa182, 0x0040, 0x1210,
- 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x24a8, 0x53a6, 0x7007,
- 0x0001, 0x7008, 0xd0fc, 0x0de8, 0xa084, 0x01e0, 0x0d48, 0x70c3,
- 0x4002, 0x0804, 0x13bd, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0878,
- 0x71c4, 0x70c8, 0x2114, 0xa79e, 0x0004, 0x1108, 0x200a, 0x72ca,
- 0x0804, 0x13b9, 0x70c7, 0x000a, 0x70cb, 0x0004, 0x70cf, 0x002a,
- 0x0804, 0x13ba, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0018, 0x2029,
- 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca,
- 0x73ce, 0x74d2, 0xa005, 0x05e8, 0xa40a, 0x0108, 0x1240, 0x8001,
- 0x7872, 0xa084, 0xfc00, 0x0138, 0x78ac, 0xc085, 0x78ae, 0x2001,
- 0x4005, 0x0804, 0x13bc, 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76,
- 0xa48c, 0xff00, 0x0170, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c,
- 0x810f, 0xa118, 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000,
- 0x0050, 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1,
- 0x0000, 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605,
- 0x0118, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, 0x78ae,
- 0x0018, 0x78ac, 0xc085, 0x78ae, 0x0804, 0x13ba, 0x75d8, 0x76dc,
- 0x75da, 0x76de, 0x0018, 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8,
- 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0500,
- 0xa40a, 0x0110, 0x1a04, 0x13bc, 0x8001, 0x7892, 0xa084, 0xfc00,
- 0x0138, 0x78ac, 0xc0c5, 0x78ae, 0x2001, 0x4005, 0x0804, 0x13bc,
- 0x7a9a, 0x7b9e, 0x7da2, 0x7ea6, 0x2600, 0xa505, 0x0118, 0x7a10,
- 0xc2c5, 0x7a12, 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0018,
- 0x78ac, 0xc0c5, 0x78ae, 0x0804, 0x13ba, 0x2009, 0x0000, 0x786c,
- 0xa065, 0x0118, 0x8108, 0x6000, 0x0cd8, 0x7ac4, 0x0804, 0x13b8,
- 0x2009, 0x4748, 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904,
- 0x13b9, 0x2011, 0x4788, 0x2214, 0x0804, 0x13b8, 0x2009, 0x4749,
- 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
- 0x4789, 0x2214, 0x0804, 0x13b8, 0x2061, 0x4740, 0x6128, 0x622c,
- 0x8214, 0x8214, 0x8214, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1148,
- 0x2061, 0x4780, 0x6328, 0x73da, 0x632c, 0x831c, 0x831c, 0x831c,
- 0x73de, 0x0804, 0x13b8, 0x2009, 0x474c, 0x210c, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011, 0x478c, 0x2214, 0x0804,
- 0x13b8, 0x7918, 0x0804, 0x13b9, 0x2009, 0x0202, 0x210c, 0xa18c,
- 0x0f30, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
- 0x0102, 0x2214, 0xa294, 0x0f30, 0x0804, 0x13b8, 0x2009, 0x474d,
- 0x210c, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2011,
- 0x478d, 0x2214, 0x0804, 0x13b8, 0x7920, 0x2001, 0x01ff, 0x2004,
- 0xd0fc, 0x1904, 0x13b9, 0x7a24, 0x0804, 0x13b8, 0x2011, 0x4c40,
- 0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4bc0, 0x8107, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa268, 0x6a00, 0x6b08, 0x6c1c, 0x74da,
- 0xd1fc, 0x1118, 0x2021, 0x023b, 0x0010, 0x2021, 0x013b, 0x2424,
- 0xa4a4, 0x1c00, 0x74de, 0x0804, 0x13b7, 0x77c4, 0x080c, 0x1b9a,
- 0x2091, 0x8000, 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0804,
- 0x13b7, 0x2061, 0x4740, 0x6118, 0x2001, 0x01ff, 0x2004, 0xd0fc,
- 0x1904, 0x13b9, 0x2061, 0x4780, 0x6218, 0x0804, 0x13b8, 0x77c4,
- 0x080c, 0x1b9a, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x77da,
- 0x2091, 0x8001, 0x0804, 0x13b7, 0x71c4, 0x2110, 0xa294, 0x000f,
- 0xa282, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23b4, 0xa384, 0x4000,
- 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x71c4, 0x2100, 0xc0bc,
- 0xa082, 0x0010, 0x1a04, 0x13b3, 0xd1bc, 0x1120, 0x2011, 0x4748,
- 0x2204, 0x0020, 0x2011, 0x4788, 0x2204, 0xc0bd, 0x0006, 0x2100,
- 0xc0bc, 0x2012, 0x080c, 0x2358, 0x001e, 0x0804, 0x13b9, 0x71c4,
- 0x2021, 0x4749, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0030, 0x71c8,
- 0x2021, 0x4789, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1623, 0x20a9,
- 0x0008, 0x2204, 0xa106, 0x0138, 0x8210, 0x1f04, 0x1609, 0x71c4,
- 0x72c8, 0x0804, 0x13b2, 0xa292, 0x1623, 0x0026, 0x2122, 0x001e,
- 0x080c, 0x236a, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1110, 0xd3fc,
- 0x09f0, 0x0804, 0x13ba, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0004,
- 0x0001, 0x0002, 0x0003, 0x2061, 0x4740, 0x6128, 0x622c, 0x8214,
- 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003, 0x8003,
- 0x602e, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x11a0, 0x0026, 0x0016,
- 0x2061, 0x4780, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
- 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, 0x72de,
- 0x001e, 0x002e, 0x0804, 0x13b8, 0x2061, 0x4740, 0x6130, 0x70c4,
- 0x6032, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x2061,
- 0x4780, 0x6230, 0x70c8, 0x6032, 0x0804, 0x13b8, 0x7918, 0x0804,
- 0x13b9, 0x71c4, 0xa184, 0xf0cf, 0x0148, 0x2001, 0x01ff, 0x2004,
- 0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2, 0x2019, 0x0000,
- 0x080c, 0x23a6, 0x0036, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118,
- 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa184, 0xf0cf, 0x0128, 0x000e,
- 0x2110, 0x71c4, 0x0804, 0x13b2, 0xc3fd, 0x080c, 0x23a6, 0x2310,
- 0x001e, 0x0804, 0x13b8, 0x71c4, 0xa182, 0x0010, 0x0248, 0x2001,
- 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b3, 0x72c8, 0x0804, 0x13b2,
- 0x2011, 0x474d, 0x2204, 0x0006, 0x8104, 0x1208, 0x8108, 0x2112,
- 0x2019, 0x0000, 0x080c, 0x2393, 0x2001, 0x01ff, 0x2004, 0xd0fc,
- 0x0118, 0x001e, 0x0804, 0x13b9, 0x71c8, 0xa182, 0x0010, 0x0228,
- 0x0006, 0x2110, 0x71c4, 0x0804, 0x13b2, 0x2011, 0x478d, 0x2204,
- 0x0006, 0x8104, 0x1208, 0x8108, 0x2112, 0xc3fd, 0x080c, 0x2393,
- 0x002e, 0x001e, 0x0804, 0x13b8, 0x71c4, 0x72c8, 0xa184, 0xfffd,
- 0x1904, 0x13b2, 0xa284, 0xfffd, 0x1904, 0x13b2, 0x2100, 0x7920,
- 0x7822, 0x2200, 0x7a24, 0x7826, 0x0804, 0x13b8, 0x2011, 0x4c40,
- 0x71c4, 0xd1fc, 0x1110, 0x2011, 0x4bc0, 0x8107, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa268, 0x72c8, 0x73cc, 0x74d8, 0x71c6,
- 0x6800, 0x70ca, 0x73ce, 0x74da, 0x2091, 0x8000, 0x6a02, 0xd2ac,
- 0x1118, 0x2021, 0x0000, 0x0090, 0xa484, 0x00ff, 0xa082, 0x0002,
- 0x1a04, 0x174f, 0x843f, 0xa7bc, 0x00ff, 0x0140, 0xa786, 0x0002,
- 0x1904, 0x174f, 0xa484, 0x00ff, 0x0904, 0x174f, 0x2061, 0x0200,
- 0xd1fc, 0x0110, 0x2061, 0x0100, 0x2029, 0x0009, 0x2031, 0x0062,
- 0x843f, 0xa7bc, 0x00ff, 0x0130, 0x8307, 0xa084, 0x00ff, 0x1110,
- 0xa73d, 0x1138, 0x2041, 0x0019, 0xa384, 0x00ff, 0xa082, 0x001a,
- 0x0210, 0xa4a4, 0x00ff, 0x8307, 0xa084, 0x00ff, 0x0188, 0xa842,
- 0x02f0, 0xa086, 0x0010, 0x1120, 0xa39c, 0x00ff, 0xa39d, 0x0f00,
- 0xa3bc, 0x00ff, 0x2500, 0xa702, 0x0290, 0x2600, 0xa702, 0x1278,
- 0x2039, 0x003a, 0x6804, 0xa705, 0x6806, 0x6b0a, 0x6b0c, 0x73ce,
- 0x681c, 0x70da, 0x6c1e, 0x2091, 0x8001, 0x0804, 0x13ba, 0x2091,
- 0x8001, 0x0804, 0x13b4, 0x77c4, 0x080c, 0x1b9a, 0x2091, 0x8000,
- 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e,
- 0x2708, 0x0804, 0x13b7, 0x70c4, 0x2061, 0x4740, 0x6118, 0x601a,
- 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x13b9, 0x70c8, 0x2061,
- 0x4780, 0x6218, 0x601a, 0x0804, 0x13b8, 0x71c4, 0x72c8, 0x73cc,
- 0xa182, 0x0010, 0x1a04, 0x13b3, 0x080c, 0x23d8, 0xa384, 0x4000,
- 0x0110, 0xa295, 0x0020, 0x0804, 0x13b7, 0x77c4, 0x080c, 0x1b9a,
- 0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708,
- 0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b9a, 0x2091, 0x8000, 0x6a08,
- 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0110, 0x080c, 0x22d5,
- 0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4, 0x080c, 0x1b9a,
- 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005, 0x0110,
- 0x080c, 0x22d5, 0x2091, 0x8001, 0x2708, 0x0804, 0x13b8, 0x77c4,
- 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000,
- 0x080c, 0x1bb2, 0x2091, 0x8001, 0x2708, 0x6a08, 0x0804, 0x13b8,
- 0x77c4, 0xd7fc, 0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc,
- 0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc, 0x73c8, 0x72cc, 0x77c6,
- 0x73ca, 0x72ce, 0x080c, 0x1c2a, 0x11e8, 0x6818, 0xa005, 0x01a0,
- 0x2708, 0x0076, 0x080c, 0x23f7, 0x007e, 0x1170, 0x2001, 0x0015,
- 0xd7fc, 0x1118, 0x2061, 0x4740, 0x0018, 0xc0fd, 0x2061, 0x4780,
- 0x782a, 0x2091, 0x8001, 0x0005, 0x2091, 0x8001, 0x2001, 0x4005,
- 0x0804, 0x13bc, 0x2091, 0x8001, 0x0804, 0x13ba, 0x77c4, 0xd7fc,
- 0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc, 0x080c, 0x1b1e,
- 0x0110, 0x0804, 0x13bc, 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005,
- 0x2051, 0x0020, 0x2091, 0x8000, 0x080c, 0x1bb2, 0x2009, 0x0016,
- 0xd7fc, 0x1118, 0x2061, 0x4740, 0x0018, 0x2061, 0x4780, 0xc1fd,
- 0x6063, 0x0003, 0x607b, 0x0000, 0x6772, 0x607f, 0x000f, 0x792a,
- 0x61d0, 0xc1c4, 0x61d2, 0x080c, 0x22d5, 0x2091, 0x8001, 0x0005,
- 0x77c8, 0x77ca, 0x77c4, 0x77c6, 0xd7fc, 0x0128, 0x080c, 0x1b29,
- 0x0138, 0x0804, 0x13bc, 0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc,
- 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x1118,
- 0x2061, 0x4740, 0x0018, 0x2061, 0x4780, 0xc1fd, 0x607b, 0x0000,
- 0x6063, 0x0002, 0x6772, 0x607f, 0x000f, 0x792a, 0x61d0, 0xc1c4,
- 0x61d2, 0x080c, 0x22d5, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049,
- 0x0005, 0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0118,
- 0x60d0, 0xc0fd, 0x60d2, 0x080c, 0x1bb2, 0x70c8, 0x6836, 0x8738,
- 0xa784, 0x001f, 0x1dc0, 0x2091, 0x8001, 0x0005, 0x2019, 0x0000,
- 0x72c8, 0xd284, 0x0128, 0x080c, 0x1b29, 0x0138, 0x0804, 0x13bc,
- 0x080c, 0x1b1e, 0x0110, 0x0804, 0x13bc, 0x72c8, 0x72ca, 0x78ac,
- 0xa084, 0x0003, 0x1518, 0x2039, 0x0000, 0xd284, 0x0108, 0xc7fd,
- 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x080c, 0x1b9a,
- 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d, 0x690a, 0x6837, 0x0000,
- 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x1d80, 0xa7bc, 0xff00,
- 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d40, 0x2091, 0x8000,
- 0x72c8, 0x2069, 0x0100, 0xd284, 0x1110, 0x2069, 0x0200, 0x6808,
- 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4, 0x01b0, 0x684b, 0x0004,
- 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110, 0x1f04, 0x18c2, 0x684b,
- 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0110, 0x1f04, 0x18cb,
- 0x20a9, 0x00fa, 0x1f04, 0x18d2, 0x2079, 0x4700, 0x2009, 0x0018,
- 0x72c8, 0xd284, 0x1118, 0x2061, 0x4740, 0x0018, 0x2061, 0x4780,
- 0xc1fd, 0x607b, 0x0000, 0x792a, 0x6063, 0x0001, 0x607f, 0x000f,
- 0x60a3, 0x0000, 0x60a4, 0x60ae, 0x60b2, 0x60d0, 0xd0b4, 0x0160,
- 0xc0b4, 0x60d2, 0x00c6, 0x60b4, 0xa065, 0x6008, 0xc0d4, 0x600a,
- 0x6018, 0x8001, 0x601a, 0x00ce, 0x60d0, 0xa084, 0x7eff, 0x60d2,
- 0x78ac, 0xc08d, 0x78ae, 0x83ff, 0x0108, 0x0005, 0x681b, 0x0054,
- 0x2091, 0x8001, 0x0005, 0x73cc, 0x080c, 0x1878, 0x69ec, 0x6a48,
- 0xa185, 0x1800, 0x684a, 0xa185, 0x0040, 0x68ee, 0x73cc, 0x2021,
- 0x0004, 0x20a9, 0x09ff, 0x1f04, 0x191b, 0x8421, 0x1dd0, 0x8319,
- 0x1db0, 0x69ee, 0x6a4a, 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118,
- 0x2069, 0x4740, 0x0010, 0x2069, 0x4780, 0x71c4, 0x71c6, 0x6916,
- 0x81ff, 0x1110, 0x68a3, 0x0001, 0x78ac, 0xc08c, 0x78ae, 0xd084,
- 0x1110, 0x080c, 0x1c7a, 0x0005, 0x75d8, 0x74dc, 0x75da, 0x74de,
- 0x0010, 0xa02e, 0x2520, 0x71c4, 0x73c8, 0x72cc, 0x71c6, 0x73ca,
- 0x72ce, 0x2079, 0x4700, 0x7dde, 0x7cda, 0x7bd6, 0x7ad2, 0x080c,
- 0x1b77, 0x0904, 0x1a5c, 0x20a9, 0x0005, 0x20a1, 0x4714, 0x2091,
- 0x8000, 0x41a1, 0x2091, 0x8001, 0x2009, 0x0040, 0x080c, 0x1d41,
- 0x0120, 0x080c, 0x1b7f, 0x0804, 0x1a5c, 0x6004, 0xa08c, 0x00ff,
- 0xa18e, 0x0009, 0x1120, 0x0006, 0x080c, 0x2086, 0x000e, 0xa084,
- 0xff00, 0x8007, 0x8009, 0x0904, 0x19f1, 0x00c6, 0x2c68, 0x080c,
- 0x1b77, 0x05a8, 0x2c00, 0x689e, 0x8109, 0x1dc0, 0x609f, 0x0000,
- 0x00ce, 0x00c6, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040,
- 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda,
- 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0904, 0x19f0, 0x2009,
- 0x0040, 0x080c, 0x1d41, 0x15a0, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x0002, 0x0150, 0x6004, 0xa084, 0x00ff, 0xa086, 0x000a, 0x1138,
- 0x0016, 0x080c, 0x2083, 0x001e, 0x2d00, 0x6002, 0x0898, 0x00ce,
- 0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce, 0x609f, 0x0000, 0x080c,
- 0x1a60, 0x2009, 0x0018, 0x6008, 0xc0cd, 0x600a, 0x6004, 0x6086,
- 0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
- 0x080c, 0x1b34, 0x000e, 0x7812, 0x080c, 0x1b7f, 0x0804, 0x1a5c,
- 0x00ce, 0x00c6, 0x609c, 0x080c, 0x1bf3, 0x00ce, 0x609f, 0x0000,
- 0x080c, 0x1a60, 0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003,
- 0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff, 0x0110, 0xc0c5, 0x7812,
- 0x080c, 0x1b34, 0x000e, 0x7812, 0x080c, 0x1b7f, 0x0804, 0x1a5c,
- 0x00ce, 0x6114, 0xd1fc, 0x0120, 0x080c, 0x1b29, 0x01f0, 0x0018,
- 0x080c, 0x1b1e, 0x01d0, 0x080c, 0x1a60, 0x2009, 0x0018, 0x6087,
- 0x0103, 0x601b, 0x0021, 0x7810, 0x0006, 0x84ff, 0x1110, 0x85ff,
- 0x0110, 0xc0c5, 0x7812, 0x080c, 0x1b34, 0x000e, 0x7812, 0x080c,
- 0x1b7f, 0x2001, 0x4007, 0x0804, 0x13bc, 0x6104, 0xa18c, 0x00ff,
- 0xa186, 0x0005, 0x1118, 0x601c, 0xc0bd, 0x601e, 0x74c4, 0x73c8,
- 0x72cc, 0x6014, 0x2091, 0x8000, 0x00e6, 0x2009, 0x0012, 0xd0fc,
- 0x1118, 0x2071, 0x4740, 0x0018, 0x2071, 0x4780, 0xc1fd, 0x792a,
- 0x7063, 0x0005, 0x71d0, 0xc1c4, 0x71d2, 0x7366, 0x726a, 0x746e,
- 0x7072, 0x7077, 0x0000, 0x2c00, 0x707a, 0xa02e, 0x2530, 0x611c,
- 0xa184, 0x0060, 0x0110, 0x080c, 0x3fe9, 0x00ee, 0x6596, 0x65a6,
- 0x669a, 0x66aa, 0x60af, 0x0000, 0x60b3, 0x0000, 0x6714, 0x6023,
- 0x0000, 0x6024, 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x080c,
- 0x22d5, 0x2091, 0x8001, 0x0005, 0x70c3, 0x4005, 0x0804, 0x13bd,
- 0x20a9, 0x0005, 0x2099, 0x4714, 0x2091, 0x8000, 0x530a, 0x2091,
- 0x8001, 0x2100, 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9,
- 0x0000, 0x0005, 0x71c4, 0x70c7, 0x0000, 0x791e, 0x0804, 0x13ba,
- 0x71c4, 0x71c6, 0x2168, 0x0010, 0x2069, 0x1000, 0x690c, 0xa016,
- 0x2d04, 0xa210, 0x8d68, 0x8109, 0x1dd8, 0xa285, 0x0000, 0x1118,
- 0x70c3, 0x4000, 0x0010, 0x70c3, 0x4003, 0x70ca, 0x0804, 0x13bd,
- 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x1a04, 0x13b3, 0x7966,
- 0x0804, 0x13ba, 0x7964, 0x71c6, 0x0804, 0x13ba, 0x7900, 0x71c6,
- 0x71c4, 0x7902, 0x0804, 0x13ba, 0x7900, 0x71c6, 0x0804, 0x13ba,
- 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0160, 0x810c, 0x0230,
- 0x8210, 0x810c, 0x810c, 0x0210, 0x8210, 0x810c, 0x81ff, 0x1904,
- 0x13b4, 0x8210, 0x7a0e, 0xd28c, 0x0538, 0x7910, 0xc1cd, 0x7912,
- 0x2009, 0x0021, 0x2019, 0x0003, 0xd284, 0x01c0, 0x8108, 0x2019,
- 0x0041, 0x2011, 0x8f4e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312,
- 0x2019, 0x0043, 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312,
- 0x2019, 0x0047, 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x8f53,
- 0x2112, 0x2011, 0x8f73, 0x2312, 0x7904, 0x7806, 0x0804, 0x13b9,
- 0x7804, 0x70c6, 0x0804, 0x13ba, 0x71c4, 0xd1fc, 0x1118, 0x2011,
- 0x4bc0, 0x0010, 0x2011, 0x4c40, 0x8107, 0xa084, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa268, 0x2011, 0x0000, 0x6814, 0xd0fc, 0x0110,
- 0xa295, 0x0200, 0xd0b4, 0x0110, 0xa295, 0x0001, 0x6b0c, 0x6800,
- 0x70da, 0x0804, 0x13b7, 0x7814, 0xd0f4, 0x0130, 0x2001, 0x4007,
- 0x70db, 0x0000, 0xa005, 0x0048, 0xd0fc, 0x0130, 0x2001, 0x4007,
- 0x70db, 0x0001, 0xa005, 0x0008, 0xa006, 0x0005, 0x7814, 0xd0f4,
- 0x0130, 0x2001, 0x4007, 0x70db, 0x0000, 0xa005, 0x0008, 0xa006,
- 0x0005, 0x7814, 0xd0fc, 0x0130, 0x2001, 0x4007, 0x70db, 0x0001,
- 0xa005, 0x0008, 0xa006, 0x0005, 0x7112, 0x721a, 0x731e, 0x7810,
- 0xd0c4, 0x0110, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c,
- 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2,
- 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0140, 0x810f,
- 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107,
- 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211, 0x7d10,
- 0xd5c4, 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc,
- 0x0de8, 0x7003, 0x0001, 0x7007, 0x0006, 0x711a, 0x721e, 0x7d10,
- 0xd5c4, 0x0110, 0x7322, 0x7426, 0xa084, 0x01e0, 0x0005, 0x7848,
- 0xa065, 0x0120, 0x2c04, 0x784a, 0x2063, 0x0000, 0x0005, 0x00f6,
- 0x2079, 0x4700, 0x7848, 0x2062, 0x2c00, 0xa005, 0x1110, 0x080c,
- 0x2575, 0x784a, 0x00fe, 0x0005, 0x2011, 0x9100, 0x7a4a, 0x7bc4,
- 0x8319, 0x0128, 0xa280, 0x0032, 0x2012, 0x2010, 0x0cc8, 0x2013,
- 0x0000, 0x0005, 0x0016, 0x0026, 0xd7fc, 0x1118, 0x2011, 0x4cc0,
- 0x0010, 0x2011, 0x6cc0, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f,
- 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xa268, 0x002e,
- 0x001e, 0x0005, 0x0c39, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808,
- 0xa084, 0xf9ef, 0xa80d, 0x690a, 0x00e6, 0xd7fc, 0x1128, 0x2009,
- 0x4752, 0x2071, 0x4740, 0x0020, 0x2009, 0x4792, 0x2071, 0x4780,
- 0x210c, 0x6804, 0xa005, 0x0148, 0xa116, 0x1138, 0x2060, 0x6000,
- 0x6806, 0x0016, 0x200b, 0x0000, 0x0018, 0x2009, 0x0000, 0x0016,
- 0x6804, 0xa065, 0x0178, 0x6000, 0x6806, 0x0421, 0x080c, 0x1db2,
- 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x6812, 0x1d88, 0x7910,
- 0xc1a5, 0x7912, 0x001e, 0x6902, 0x6906, 0x2d00, 0x2060, 0x080c,
- 0x26bf, 0x00ee, 0x0005, 0xa065, 0x0160, 0x2008, 0x609c, 0xa005,
- 0x0128, 0x2062, 0x609f, 0x0000, 0xa065, 0x0cc0, 0x7848, 0x794a,
- 0x2062, 0x0005, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c,
- 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a,
- 0x682c, 0x6022, 0x0005, 0x00e6, 0xd7fc, 0x1128, 0x2071, 0x4740,
- 0x2031, 0x47c0, 0x0020, 0x2071, 0x4780, 0x2031, 0x49c0, 0x704c,
- 0xa08c, 0x0200, 0x1128, 0xa608, 0x2d0a, 0x8000, 0x704e, 0xa006,
- 0x00ee, 0x0005, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x4740, 0x0010,
- 0x2079, 0x4780, 0x080c, 0x1b9a, 0x2091, 0x8000, 0x6804, 0x780a,
- 0xa065, 0x05f0, 0x0030, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065,
- 0x05b8, 0x6010, 0xa306, 0x1db8, 0x600c, 0xa206, 0x1da0, 0x2c28,
- 0x7848, 0xac06, 0x1108, 0x0448, 0x6804, 0xac06, 0x1140, 0x6000,
- 0x2060, 0x6806, 0xa005, 0x1118, 0x6803, 0x0000, 0x0048, 0x6400,
- 0x7808, 0x2060, 0x6402, 0xa486, 0x0000, 0x1110, 0x2c00, 0x6802,
- 0x2560, 0x080c, 0x1c02, 0x601b, 0x0005, 0x6023, 0x0020, 0x00fe,
- 0x080c, 0x1db2, 0x00f6, 0x7908, 0x8109, 0x790a, 0x6810, 0x8001,
- 0x6812, 0x1118, 0x7810, 0xc0a5, 0x7812, 0x2001, 0xffff, 0xa005,
- 0x00fe, 0x0005, 0x0076, 0x2700, 0x2039, 0x0000, 0xd0fc, 0x0108,
- 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x2091,
- 0x8000, 0x080c, 0x1bb2, 0x8738, 0xa784, 0x001f, 0x1dd0, 0xa7bc,
- 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x1d90, 0x2091,
- 0x8001, 0x007e, 0x0005, 0x786c, 0x2009, 0x8f74, 0x210c, 0xa10d,
- 0x0118, 0xa065, 0x0804, 0x20a1, 0x2061, 0x0000, 0x6018, 0xd084,
- 0x11b8, 0x7810, 0xd08c, 0x0130, 0xc08c, 0x7812, 0xc7fc, 0x2069,
- 0x4740, 0x0028, 0xc08d, 0x7812, 0x2069, 0x4780, 0xc7fd, 0x2091,
- 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001, 0xa005, 0x1108,
- 0x0005, 0xa08c, 0xfff0, 0x0110, 0x080c, 0x2575, 0x0002, 0x1cd7,
- 0x1cda, 0x1ce0, 0x1ce4, 0x1cd8, 0x1ce8, 0x1cd8, 0x1cd8, 0x1cd8,
- 0x1cee, 0x1d18, 0x1d1b, 0x1d20, 0x1d29, 0x1cd8, 0x1cd8, 0x0005,
- 0x080c, 0x2575, 0x080c, 0x1c7a, 0x2001, 0x8001, 0x0804, 0x1d32,
- 0x2001, 0x8003, 0x0804, 0x1d32, 0x2001, 0x8004, 0x0804, 0x1d32,
- 0x080c, 0x1c7a, 0x2001, 0x8006, 0x0804, 0x1d32, 0x2011, 0x800a,
- 0x2091, 0x8000, 0xd7fc, 0x1118, 0x2069, 0x4740, 0x0010, 0x2069,
- 0x4780, 0x2038, 0x6800, 0xa086, 0x0000, 0x0120, 0x6f1e, 0x2091,
- 0x8001, 0x0005, 0x0026, 0x6870, 0xa0bc, 0xff00, 0x2041, 0x0021,
- 0x2049, 0x0004, 0x2051, 0x0010, 0x080c, 0x1bb2, 0x8738, 0xa784,
- 0x001f, 0x1dd0, 0x2091, 0x8001, 0x000e, 0x6970, 0x71c6, 0x00d0,
- 0x2001, 0x800c, 0x00b8, 0x080c, 0x1c7a, 0x2001, 0x800d, 0x0090,
- 0xd7fc, 0x0110, 0x78e4, 0x0008, 0x78e0, 0x70c6, 0x2001, 0x800e,
- 0x0048, 0xd7fc, 0x0110, 0x78ec, 0x0008, 0x78e8, 0x70c6, 0x2001,
- 0x800f, 0x0000, 0x70c2, 0xd7fc, 0x1118, 0x70db, 0x0000, 0x0010,
- 0x70db, 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080,
- 0x0005, 0xac80, 0x0001, 0x81ff, 0x0518, 0x2099, 0x0030, 0x20a0,
- 0x700c, 0xa084, 0x07ff, 0x0100, 0x7018, 0x0006, 0x701c, 0x0006,
- 0x7020, 0x0006, 0x7024, 0x0006, 0x7112, 0x81ac, 0x721a, 0x731e,
- 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008, 0x800b,
- 0x1ee8, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x1110, 0x53a5, 0xa006,
- 0x7003, 0x0000, 0x7007, 0x0004, 0x000e, 0x7026, 0x000e, 0x7022,
- 0x000e, 0x701e, 0x000e, 0x701a, 0x0005, 0x2011, 0x0020, 0x2009,
- 0x0010, 0x6b0a, 0x6c0e, 0x681f, 0x0201, 0x6803, 0xfd20, 0x6807,
- 0x0038, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004, 0x8109,
- 0x1d80, 0x0005, 0x70ec, 0xd0dc, 0x1520, 0x2029, 0x0001, 0x7814,
- 0xd0cc, 0x1160, 0x70ec, 0xd0e4, 0x2019, 0x0c0a, 0x2021, 0x000a,
- 0x1120, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x0070, 0x70ec, 0xd0e4,
- 0x1128, 0x2019, 0x180c, 0x2021, 0x000c, 0x0030, 0x2019, 0x1809,
- 0x2021, 0x0009, 0xa5ad, 0x0200, 0x6b0a, 0x6c0e, 0x6d1e, 0x6807,
- 0x0038, 0x0005, 0x6004, 0x6086, 0x2c08, 0x2063, 0x0000, 0x7868,
- 0xa005, 0x796a, 0x0110, 0x2c02, 0x0008, 0x796e, 0x0005, 0x00c6,
- 0x2061, 0x4700, 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068,
- 0xa005, 0x616a, 0x0110, 0x2d02, 0x0008, 0x616e, 0x00ce, 0x0005,
- 0x2091, 0x8000, 0x2c04, 0x786e, 0xa005, 0x1108, 0x786a, 0x2091,
- 0x8001, 0x609c, 0xa005, 0x0188, 0x00c6, 0x2060, 0x2008, 0x609c,
- 0xa005, 0x0138, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c, 0xa005,
- 0x1dc8, 0x7848, 0x794a, 0x2062, 0x00ce, 0x7848, 0x2062, 0x609f,
- 0x0000, 0xac85, 0x0000, 0x1110, 0x080c, 0x2575, 0x784a, 0x0005,
- 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x1208, 0xa200,
- 0x1f04, 0x1dfc, 0x8086, 0x818e, 0x0005, 0x0156, 0x20a9, 0x0010,
- 0xa005, 0x01b8, 0xa11a, 0x12a8, 0x8213, 0x818d, 0x0228, 0xa11a,
- 0x1220, 0x1f04, 0x1e0c, 0x0028, 0xa11a, 0x2308, 0x8210, 0x1f04,
- 0x1e0c, 0x0006, 0x3200, 0xa084, 0xefff, 0x2080, 0x000e, 0x015e,
- 0x0005, 0x0006, 0x3200, 0xa085, 0x1000, 0x0cb8, 0x7d74, 0x70d0,
- 0xa506, 0x0904, 0x1eda, 0x7810, 0x2050, 0x080c, 0x1b77, 0x0904,
- 0x1eda, 0xa046, 0x7970, 0x2500, 0x8000, 0xa112, 0x2009, 0x0040,
- 0x1208, 0x0030, 0x72d0, 0xa206, 0x0118, 0x8840, 0x2009, 0x0080,
- 0x00c6, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020,
- 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0110, 0x080c,
- 0x1b77, 0x7008, 0xd0fc, 0x0de8, 0x7007, 0x0002, 0x2091, 0x8001,
- 0xa08c, 0x01e0, 0x1538, 0x53a5, 0x8cff, 0x1120, 0x88ff, 0x0904,
- 0x1ec7, 0x0050, 0x2c00, 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001,
- 0x20a0, 0x53a5, 0x0804, 0x1ec7, 0xa046, 0x7218, 0x731c, 0xdac4,
- 0x0110, 0x7420, 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3,
- 0x0000, 0xa5ab, 0x0000, 0x721a, 0x731e, 0xdac4, 0x0118, 0x7422,
- 0x7526, 0xa006, 0x7007, 0x0004, 0x0904, 0x1ec7, 0x8cff, 0x0110,
- 0x080c, 0x1b7f, 0x00ce, 0x080c, 0x1b7f, 0xa046, 0x7888, 0x8000,
- 0x788a, 0xa086, 0x0002, 0x01c0, 0x7a7c, 0x7b78, 0xdac4, 0x0110,
- 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399,
- 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a, 0x731e, 0xdac4,
- 0x0588, 0x7422, 0x7526, 0x0470, 0x6014, 0xd0fc, 0x1118, 0x2069,
- 0x4740, 0x0010, 0x2069, 0x4780, 0x2091, 0x8000, 0x681f, 0x0002,
- 0x88ff, 0x0120, 0xa046, 0x788c, 0x2060, 0x0c70, 0x788b, 0x0000,
- 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0098, 0x00ce,
- 0x788b, 0x0000, 0x080c, 0x205c, 0x6004, 0xa084, 0x000f, 0x0059,
- 0x88ff, 0x0130, 0x788c, 0x2060, 0x6004, 0xa084, 0x000f, 0x0019,
- 0x0804, 0x1e26, 0x0005, 0x0002, 0x1eec, 0x1f07, 0x1f20, 0x1eec,
- 0x1f2d, 0x1efd, 0x1eec, 0x1eec, 0x1eec, 0x1f05, 0x1f1e, 0x1eec,
- 0x1eec, 0x1eec, 0x1eec, 0x1eec, 0x2039, 0x0400, 0x78bc, 0xa705,
- 0x78be, 0x6008, 0xa705, 0x600a, 0x080c, 0x1f69, 0x609c, 0x78ba,
- 0x609f, 0x0000, 0x080c, 0x2048, 0x0005, 0x78bc, 0xd0c4, 0x0108,
- 0x0c58, 0x601c, 0xc0bd, 0x601e, 0x0030, 0x080c, 0x2086, 0x78bc,
- 0xd0c4, 0x0108, 0x0c08, 0x78bf, 0x0000, 0x6004, 0x8007, 0xa084,
- 0x00ff, 0x78b2, 0x8001, 0x0138, 0x080c, 0x1f69, 0x0120, 0x78bc,
- 0xc0c5, 0x78be, 0x0010, 0x0804, 0x1f84, 0x0005, 0x080c, 0x2083,
- 0x78bc, 0xa08c, 0x0e00, 0x1110, 0xd0c4, 0x1108, 0x0828, 0x080c,
- 0x1f69, 0x1110, 0x0804, 0x1f84, 0x0005, 0x78bc, 0xd0c4, 0x0110,
- 0x0804, 0x1eec, 0x78bf, 0x0000, 0x6714, 0x2011, 0x0001, 0x22a8,
- 0x6018, 0xa084, 0x00ff, 0xa005, 0x0188, 0xa7bc, 0xff00, 0x20a9,
- 0x0020, 0xa08e, 0x0001, 0x0150, 0xa7bc, 0x8000, 0x2011, 0x0002,
- 0x20a9, 0x0100, 0xa08e, 0x0002, 0x0108, 0x00c0, 0x080c, 0x1b9a,
- 0x2d00, 0x2091, 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808,
- 0xa084, 0xffde, 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x1f04,
- 0x1f51, 0x8211, 0x0118, 0x20a9, 0x0100, 0x0c58, 0x080c, 0x1b7f,
- 0x0005, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x1110,
- 0x78ba, 0x0038, 0x689e, 0x2d00, 0x6002, 0x78b8, 0xad06, 0x1108,
- 0x6002, 0x78b0, 0x8001, 0x78b2, 0x1130, 0x78bc, 0xc0c4, 0x78be,
- 0x78b8, 0x2060, 0xa006, 0x0005, 0x00e6, 0xa02e, 0x2530, 0x7dba,
- 0x7db6, 0x65ae, 0x65b2, 0x601c, 0x60a2, 0x2048, 0xa984, 0xe1ff,
- 0x601e, 0xa984, 0x0060, 0x0160, 0x080c, 0x3fe9, 0x86ff, 0x1140,
- 0x85ff, 0x1130, 0x2039, 0x0800, 0x080c, 0x2048, 0x0804, 0x2046,
- 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714, 0x2071, 0x4780, 0xd7fc,
- 0x1110, 0x2071, 0x4740, 0xa784, 0x0f00, 0x800b, 0xa784, 0x001f,
- 0x0120, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0x71c0, 0xa168,
- 0x2700, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0x71c4,
- 0xa100, 0x60c2, 0x2091, 0x8000, 0x7814, 0xd0c4, 0x0138, 0xd7fc,
- 0x1118, 0xd0f4, 0x1140, 0x0010, 0xd0fc, 0x1128, 0x6e08, 0xd684,
- 0x01f0, 0xd9fc, 0x11e0, 0x2091, 0x8001, 0x080c, 0x1c02, 0x2091,
- 0x8000, 0x080c, 0x1db2, 0x2091, 0x8001, 0x7814, 0xd0c4, 0x0904,
- 0x2046, 0xd7fc, 0x1120, 0xd0f4, 0x1130, 0x0804, 0x2046, 0xd0fc,
- 0x1110, 0x0804, 0x2046, 0x601b, 0x0021, 0x0804, 0x2046, 0x6024,
- 0xa096, 0x0001, 0x1110, 0x8000, 0x6026, 0x6a10, 0x6814, 0xa202,
- 0x0268, 0x0160, 0x2091, 0x8001, 0x2039, 0x0200, 0x609c, 0x78ba,
- 0x609f, 0x0000, 0x080c, 0x2048, 0x0804, 0x2046, 0x2c08, 0xd9fc,
- 0x01f0, 0x6800, 0xa065, 0x01d8, 0x6a04, 0x7000, 0xa084, 0x0002,
- 0x0168, 0x7048, 0xa206, 0x1150, 0x6b04, 0x2160, 0x2304, 0x6002,
- 0xa005, 0x1108, 0x6902, 0x2260, 0x6102, 0x0098, 0x2d00, 0x2060,
- 0x080c, 0x26bf, 0x6e08, 0x2160, 0x6202, 0x6906, 0x0050, 0x6800,
- 0x6902, 0xa065, 0x0110, 0x6102, 0x0008, 0x6906, 0x2160, 0x6003,
- 0x0000, 0x2160, 0xd9fc, 0x0118, 0xa6b4, 0xfffc, 0x6e0a, 0x6810,
- 0x7d08, 0x8528, 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4,
- 0x0128, 0xa6b6, 0x0040, 0x6e0a, 0x080c, 0x1c13, 0x00ee, 0x0005,
- 0x6008, 0xa705, 0x600a, 0x2091, 0x8000, 0x080c, 0x1db2, 0x2091,
- 0x8001, 0x78b8, 0xa065, 0x0128, 0x609c, 0x78ba, 0x609f, 0x0000,
- 0x0c78, 0x78b6, 0x78ba, 0x0005, 0x7970, 0x7874, 0x2818, 0xd384,
- 0x0118, 0x8000, 0xa112, 0x0220, 0x8000, 0xa112, 0x1278, 0xc384,
- 0x7a7c, 0x721a, 0x7a78, 0x721e, 0xdac4, 0x0120, 0x7a84, 0x7222,
- 0x7a80, 0x7226, 0xa006, 0xd384, 0x0108, 0x8000, 0x7876, 0x70d2,
- 0x781c, 0xa005, 0x0138, 0x8001, 0x781e, 0x1120, 0x0e04, 0x2082,
- 0x2091, 0x4080, 0x0005, 0x2039, 0x2098, 0x0010, 0x2039, 0x209e,
- 0x2704, 0xa005, 0x0160, 0xac00, 0x2068, 0x6908, 0x6810, 0x6912,
- 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738, 0x0c88, 0x0005,
- 0x0003, 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0015, 0x001b,
- 0x0000, 0x2041, 0x0000, 0x780c, 0x0002, 0x224a, 0x2225, 0x20a9,
- 0x2119, 0x2039, 0x8f74, 0x2734, 0x7d10, 0x00c0, 0x6084, 0xa086,
- 0x0103, 0x1904, 0x2103, 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff,
- 0x11d8, 0x0804, 0x2103, 0x8603, 0xa080, 0x8f55, 0x620c, 0x2202,
- 0x8000, 0x6210, 0x2202, 0x080c, 0x1dd0, 0x8630, 0xa68e, 0x000f,
- 0x0904, 0x2184, 0x786c, 0xa065, 0x1d08, 0x7808, 0xa602, 0x1220,
- 0xd5ac, 0x1110, 0x263a, 0x0005, 0xa682, 0x0003, 0x1a04, 0x2184,
- 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x11f8, 0x2011,
- 0x8f55, 0x2204, 0x70c6, 0x8210, 0x2204, 0x70ca, 0xd684, 0x1130,
- 0x8210, 0x2204, 0x70da, 0x8210, 0x2204, 0x70de, 0xa685, 0x8020,
- 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf,
- 0x7812, 0x2091, 0x8001, 0x203b, 0x0000, 0x0005, 0x7810, 0xc0ad,
- 0x7812, 0x0804, 0x2184, 0x263a, 0x080c, 0x2250, 0x1904, 0x226c,
- 0x786c, 0xa065, 0x1904, 0x20ae, 0x2091, 0x8000, 0x7810, 0xa084,
- 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0804,
- 0x226c, 0x2039, 0x8f74, 0x2734, 0x7d10, 0x00a0, 0x6084, 0xa086,
- 0x0103, 0x1904, 0x216e, 0x6114, 0x6018, 0xa105, 0x0120, 0x86ff,
- 0x11b8, 0x0804, 0x216e, 0xa680, 0x8f55, 0x620c, 0x2202, 0x080c,
- 0x1dd0, 0x8630, 0xa68e, 0x001e, 0x0904, 0x2184, 0x786c, 0xa065,
- 0x1d28, 0x7808, 0xa602, 0x1220, 0xd5ac, 0x1110, 0x263a, 0x0005,
- 0xa682, 0x0006, 0x1a04, 0x2184, 0x2091, 0x8000, 0x2069, 0x0000,
- 0x6818, 0xd084, 0x11f8, 0x2011, 0x8f55, 0x2009, 0x8f4e, 0x26a8,
- 0x211c, 0x2204, 0x201a, 0x8108, 0x8210, 0x1f04, 0x2150, 0xa685,
- 0x8030, 0x70c2, 0x681b, 0x0001, 0x2091, 0x4080, 0x7810, 0xa084,
- 0xffcf, 0x7812, 0x2091, 0x8001, 0xa006, 0x2009, 0x8f75, 0x200a,
- 0x203a, 0x0005, 0x7810, 0xc0ad, 0x7812, 0x00b0, 0x263a, 0x080c,
- 0x2250, 0x1904, 0x226c, 0x786c, 0xa065, 0x1904, 0x211e, 0x2091,
- 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0108, 0xc0ad, 0x7812,
- 0x2091, 0x8001, 0x0804, 0x226c, 0x2091, 0x8000, 0x7007, 0x0004,
- 0x7994, 0x70d4, 0xa102, 0x0228, 0x0168, 0x7b90, 0xa302, 0x1150,
- 0x0010, 0x8002, 0x1138, 0x263a, 0x7810, 0xc0ad, 0x7812, 0x2091,
- 0x8001, 0x0005, 0xa184, 0xff00, 0x0140, 0x810f, 0x810c, 0x810c,
- 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107, 0x8004, 0x8004,
- 0x7a9c, 0xa210, 0x721a, 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4,
- 0x0130, 0x7aa4, 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1,
- 0x0030, 0x7003, 0x0000, 0x2009, 0x8f54, 0x260a, 0x8109, 0x2198,
- 0x2104, 0xd084, 0x0108, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6,
- 0x8603, 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a,
- 0x1208, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0140, 0x810f,
- 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0018, 0x8107,
- 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006, 0xa211, 0xd4c4,
- 0x0120, 0x7b84, 0xa319, 0x7c80, 0xa421, 0x7008, 0xd0fc, 0x0de8,
- 0xa084, 0x01e0, 0x01d0, 0x7d10, 0x2031, 0x8f54, 0x2634, 0x78a8,
- 0x8000, 0x78aa, 0xd08c, 0x1138, 0x7007, 0x0006, 0x7004, 0xd094,
- 0x1de8, 0x0804, 0x2186, 0x2069, 0x4747, 0x206b, 0x0003, 0x78ac,
- 0xa085, 0x0300, 0x78ae, 0xa006, 0x0048, 0x2030, 0x75d6, 0x2091,
- 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001,
- 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a, 0x721e,
- 0xd5c4, 0x0110, 0x7322, 0x7426, 0x0005, 0x6084, 0xa086, 0x0103,
- 0x11d8, 0x6114, 0x6018, 0xa105, 0x11b8, 0x2069, 0x0000, 0x6818,
- 0xd084, 0x1190, 0x600c, 0x70c6, 0x6010, 0x70ca, 0x70c3, 0x8020,
- 0x681b, 0x0001, 0x2091, 0x4080, 0x080c, 0x1dd0, 0x0e04, 0x2243,
- 0x786c, 0xa065, 0x1d10, 0x0005, 0x0059, 0x1530, 0x786c, 0xa065,
- 0x19e0, 0x0410, 0x0029, 0x1500, 0x786c, 0xa065, 0x1dd8, 0x00e0,
- 0x6084, 0xa086, 0x0103, 0x1168, 0x6018, 0xc0fc, 0x601a, 0xa086,
- 0x0004, 0x1138, 0x7804, 0xd0a4, 0x0120, 0x080c, 0x1dd0, 0xa006,
- 0x0005, 0x0079, 0x1118, 0xa085, 0x0001, 0x0005, 0x00b9, 0x1110,
- 0x2041, 0x0001, 0x7d10, 0x0005, 0x88ff, 0x0110, 0x2091, 0x4080,
- 0x0005, 0x7b90, 0x7994, 0x70d4, 0xa102, 0x1118, 0xa385, 0x0000,
- 0x0005, 0x0210, 0xa302, 0x0005, 0x8002, 0x0005, 0xa184, 0xff00,
- 0x0140, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
- 0x0018, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4, 0x7da0,
- 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018, 0x6028,
- 0xa005, 0x0110, 0x2009, 0x0040, 0x080c, 0x1b34, 0x01d0, 0x78a8,
- 0x8000, 0x78aa, 0xd08c, 0x1510, 0x6014, 0xd0fc, 0x1118, 0x2069,
- 0x4740, 0x0010, 0x2069, 0x4780, 0x2091, 0x8000, 0x681f, 0x0003,
- 0x78ab, 0x0000, 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001,
- 0x0068, 0x78ab, 0x0000, 0x080c, 0x1dd0, 0x7990, 0x7894, 0x8000,
- 0xa10a, 0x1208, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010,
- 0x2091, 0x8001, 0x0005, 0xd7fc, 0x1118, 0x2009, 0x4758, 0x0010,
- 0x2009, 0x4798, 0x2091, 0x8000, 0x200a, 0x00f6, 0x2009, 0x4780,
- 0x2079, 0x0100, 0xd7fc, 0x1120, 0x2009, 0x4740, 0x2079, 0x0200,
- 0x2104, 0xa086, 0x0000, 0x1180, 0xd7fc, 0x1118, 0x2009, 0x4745,
- 0x0010, 0x2009, 0x4785, 0x2104, 0xa005, 0x1130, 0x7830, 0xa084,
- 0x00c0, 0x1110, 0x781b, 0x0052, 0x00fe, 0x0005, 0x2009, 0x0002,
- 0x2069, 0x4700, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1904, 0x234b,
- 0x2071, 0x4780, 0x2079, 0x0100, 0x2021, 0x49bf, 0x784b, 0x000f,
- 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x0118, 0x2019, 0x3e37, 0x0030,
- 0x20a1, 0x012b, 0x2019, 0x3e37, 0xd184, 0x0110, 0x20a1, 0x022b,
- 0x2304, 0xa005, 0x0140, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398,
- 0x53a6, 0x3318, 0x0ca8, 0x789b, 0x0000, 0x789b, 0x0020, 0x20a9,
- 0x0010, 0x78af, 0x0000, 0x78af, 0x2020, 0x1f04, 0x2329, 0x7003,
- 0x0000, 0x0016, 0xd18c, 0x2009, 0x0000, 0x0108, 0xc1bd, 0x080c,
- 0x246c, 0x001e, 0x7020, 0xa084, 0x000f, 0xa085, 0x6300, 0x7806,
- 0x780f, 0x9000, 0x7843, 0x00d8, 0x7853, 0x0090, 0x780b, 0x2f08,
- 0x7452, 0x704f, 0x0000, 0x8109, 0x0140, 0x2071, 0x4740, 0x2079,
- 0x0200, 0x2021, 0x47bf, 0x0804, 0x2306, 0x080c, 0x2526, 0x0005,
- 0x0016, 0x2011, 0x0101, 0xd1bc, 0x1110, 0x2011, 0x0201, 0xa18c,
- 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x001e, 0x080c,
- 0x246c, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011, 0x0201,
- 0x20a9, 0x0009, 0x810b, 0x1f04, 0x2372, 0xa18c, 0x0e00, 0x2204,
- 0xa084, 0xf1ff, 0xa105, 0x2012, 0x0005, 0x2019, 0x0002, 0x2009,
- 0x0101, 0x20a9, 0x0005, 0x8213, 0x1f04, 0x2383, 0xa294, 0x00e0,
- 0x2104, 0xa084, 0xff1f, 0xa205, 0x200a, 0x8319, 0x0118, 0x2009,
- 0x0201, 0x0c78, 0x0005, 0x2011, 0x0101, 0xd3fc, 0x1110, 0x2011,
- 0x0201, 0x20a9, 0x000c, 0x810b, 0x1f04, 0x239b, 0xa18c, 0xf000,
- 0x2204, 0xa084, 0x0fff, 0xa105, 0x2012, 0x0005, 0x2011, 0x0102,
- 0xd3fc, 0x1110, 0x2011, 0x0202, 0x2204, 0xa09c, 0x0f30, 0xa084,
- 0xf0cf, 0xa105, 0x2012, 0x0005, 0x00c6, 0x2061, 0x0100, 0xd1bc,
- 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020,
- 0x609a, 0x62ac, 0x63ac, 0x00ce, 0x0005, 0x00c6, 0x2061, 0x0100,
- 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc, 0x8103, 0x8003, 0xa080,
- 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x00ce, 0x0005,
- 0x00c6, 0x2061, 0x0100, 0xd1bc, 0x1110, 0x2061, 0x0200, 0xc1bc,
- 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c, 0x0020,
- 0x0118, 0xc2ac, 0xa39d, 0x4000, 0xc3ec, 0xd3b4, 0x1108, 0xc3ed,
- 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018, 0x00ce, 0x0005, 0x2091,
- 0x8000, 0x00c6, 0x00e6, 0x6818, 0xa005, 0x0904, 0x2450, 0xd1fc,
- 0x0118, 0x2061, 0x8ed0, 0x0010, 0x2061, 0x8dc0, 0x080c, 0x2458,
- 0x0560, 0x20a9, 0x0101, 0xd1fc, 0x0118, 0x2061, 0x8dd0, 0x0010,
- 0x2061, 0x8cc0, 0x00c6, 0x080c, 0x2458, 0x0128, 0x00ce, 0x8c60,
- 0x1f04, 0x2412, 0x04a8, 0x000e, 0xd1fc, 0x0128, 0xa082, 0x8dd0,
- 0x2071, 0x4780, 0x0020, 0xa082, 0x8cc0, 0x2071, 0x4740, 0x7076,
- 0x7172, 0x2138, 0x2001, 0x0004, 0x7062, 0x707f, 0x000f, 0x71d0,
- 0xc1c4, 0x71d2, 0x080c, 0x22cb, 0x00c0, 0xd1fc, 0x1118, 0x2071,
- 0x4740, 0x0010, 0x2071, 0x4780, 0x6020, 0xc0dd, 0x6022, 0x7172,
- 0x2138, 0x2c00, 0x707a, 0x2001, 0x0006, 0x7062, 0x707f, 0x000f,
- 0x71d0, 0xc1c4, 0x71d2, 0x080c, 0x22cb, 0x2001, 0x0000, 0x0010,
- 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x00ee, 0x00ce, 0x0005,
- 0x2c04, 0xa005, 0x0170, 0x2060, 0x6010, 0xa306, 0x1140, 0x600c,
- 0xa206, 0x1128, 0x6014, 0xa106, 0x1110, 0xa006, 0x0020, 0x6000,
- 0x0c80, 0xa085, 0x0001, 0x0005, 0x00f6, 0x00e6, 0x0016, 0x2079,
- 0x4780, 0x2071, 0x0100, 0xd1bc, 0x1120, 0x2079, 0x4740, 0x2071,
- 0x0200, 0x7920, 0xa18c, 0x000f, 0x70ec, 0xd0c4, 0x1110, 0x001e,
- 0x0060, 0x810b, 0x810b, 0x810b, 0x810b, 0x000e, 0xa18d, 0x0800,
- 0xd0bc, 0x1110, 0xa18d, 0x0f00, 0x2104, 0x00ee, 0x00fe, 0x0005,
- 0x2001, 0x4701, 0x2004, 0xd0ac, 0x1138, 0x68e4, 0xd0ac, 0x0120,
- 0xa084, 0x0006, 0x1108, 0x0009, 0x0005, 0x6014, 0x00e6, 0x0036,
- 0x2018, 0x2071, 0x4c40, 0xd0fc, 0x1110, 0x2071, 0x4bc0, 0x8007,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084,
- 0x000a, 0x1904, 0x2523, 0x7108, 0xa194, 0xff00, 0x0904, 0x2523,
- 0xa18c, 0x00ff, 0x701c, 0xa084, 0xff00, 0x01c0, 0x7004, 0xa085,
- 0x003a, 0x7006, 0x2001, 0x0009, 0xa102, 0x16d8, 0x2001, 0x000a,
- 0xa102, 0x16d0, 0x2001, 0x000c, 0xa102, 0x16c8, 0x701c, 0xa084,
- 0x00ff, 0x701e, 0x7004, 0xa084, 0xffdf, 0x7006, 0x2001, 0x000a,
- 0xa106, 0x01a8, 0x2001, 0x000c, 0xa106, 0x01a0, 0x2001, 0x0012,
- 0xa106, 0x0198, 0x2001, 0x0014, 0xa106, 0x0190, 0x2001, 0x0019,
- 0xa106, 0x0188, 0x2001, 0x0032, 0xa106, 0x0180, 0x00d8, 0x2009,
- 0x000c, 0x00d0, 0x2009, 0x0012, 0x00b8, 0x2009, 0x0014, 0x00a0,
- 0x2009, 0x0019, 0x0088, 0x2009, 0x0020, 0x0070, 0x2009, 0x003f,
- 0x0058, 0x2009, 0x000a, 0x0040, 0x2009, 0x000c, 0x0028, 0x2009,
- 0x0019, 0x0010, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x7004,
- 0xa085, 0x000a, 0x7006, 0x2071, 0x4700, 0x7004, 0xd0bc, 0x0158,
- 0xd3fc, 0x1120, 0x73ea, 0x2071, 0x4740, 0x0018, 0x73ee, 0x2071,
- 0x4780, 0x701f, 0x000d, 0x003e, 0x00ee, 0x0005, 0x2001, 0x01ff,
- 0x2004, 0xd0fc, 0x11d0, 0x2001, 0x04fd, 0x2004, 0xa082, 0x0005,
- 0x12a0, 0x2071, 0x0200, 0x71ec, 0xa18c, 0x1c00, 0x810f, 0x810c,
- 0x810c, 0x2079, 0x0100, 0x78ec, 0xa084, 0x1c00, 0x8007, 0x8004,
- 0x8004, 0xa105, 0xa08a, 0x0007, 0x0208, 0x0005, 0x0002, 0x2574,
- 0x255b, 0x2574, 0x255b, 0x254e, 0x2568, 0x254e, 0x7008, 0xa084,
- 0xc3ff, 0xa085, 0x3000, 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085,
- 0x3000, 0x780a, 0x0005, 0x7008, 0xa084, 0xc3ff, 0xa085, 0x2000,
- 0x700a, 0x7808, 0xa084, 0xc3ff, 0xa085, 0x2000, 0x780a, 0x0005,
- 0x7008, 0xa084, 0xc3ff, 0xa085, 0x0c00, 0x700a, 0x7808, 0xa084,
- 0xc3ff, 0xa085, 0x0c00, 0x780a, 0x0005, 0x0e04, 0x2575, 0x2091,
- 0x8000, 0x2071, 0x0000, 0x0006, 0x7018, 0xd084, 0x1de8, 0x000e,
- 0x2071, 0x0010, 0x70ca, 0x000e, 0x70c6, 0x70c3, 0x8002, 0x70db,
- 0x0a04, 0x70df, 0x002a, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091,
- 0x4080, 0x0cf8, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708a,
- 0x758e, 0x7492, 0x7696, 0x779a, 0xa594, 0x003f, 0xd4f4, 0x0138,
- 0xd7bc, 0x1128, 0xa784, 0x007d, 0x1904, 0x3c9c, 0x0871, 0xa49c,
- 0x000f, 0xa382, 0x0004, 0x0320, 0xa3a6, 0x0007, 0x1930, 0x2418,
- 0x8507, 0xa084, 0x000f, 0x0002, 0x2b6c, 0x2c57, 0x2c95, 0x2efb,
- 0x3279, 0x32d0, 0x3376, 0x3405, 0x34d9, 0x35ab, 0x25c7, 0x25c4,
- 0x299e, 0x2a85, 0x324d, 0x25c4, 0x080c, 0x2575, 0x0005, 0xa006,
- 0x0038, 0x7808, 0xc08d, 0x780a, 0xa006, 0x7002, 0x704a, 0x7042,
- 0x70ce, 0x705c, 0xa005, 0x1904, 0x2718, 0x7060, 0xa084, 0x0007,
- 0x0002, 0x25e1, 0x2652, 0x265a, 0x2663, 0x266c, 0x26fe, 0x2675,
- 0x2652, 0x7830, 0xd0bc, 0x1d10, 0x71d0, 0xd1bc, 0x19f8, 0xd1b4,
- 0x1904, 0x262f, 0x70a0, 0xa086, 0x0001, 0x09c0, 0x7014, 0xa005,
- 0x19a8, 0x70b0, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0080,
- 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d,
- 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d,
- 0x6e1c, 0x2001, 0x0010, 0x0804, 0x284b, 0x705c, 0xa005, 0x1904,
- 0x25c6, 0x00c6, 0x00d6, 0x70b0, 0xa06d, 0x6800, 0xa065, 0xa055,
- 0x789b, 0x0080, 0x6b0c, 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804,
- 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0118, 0x69bc, 0x7daa, 0x79aa,
- 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0020, 0x0804, 0x284b, 0x080c,
- 0x3c5b, 0x1904, 0x25c6, 0x781b, 0x0068, 0x70b8, 0xa06d, 0x68b4,
- 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808,
- 0xc08d, 0x780a, 0x68bc, 0x703e, 0xc1b4, 0x71d2, 0x70b4, 0xa065,
- 0x68c0, 0x7056, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009,
- 0x7042, 0x0005, 0x080c, 0x3c5b, 0x1120, 0x781b, 0x0054, 0x7003,
- 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011, 0x000c, 0x0419,
- 0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011, 0x0006,
- 0x00d1, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1128, 0x2011,
- 0x000d, 0x0089, 0x7003, 0x0004, 0x0005, 0x080c, 0x3c5b, 0x1150,
- 0x2011, 0x0006, 0x0041, 0x7078, 0x707b, 0x0000, 0x2068, 0x704a,
- 0x7003, 0x0004, 0x0005, 0x7170, 0xc1fc, 0x8107, 0x7882, 0x789b,
- 0x0080, 0xa286, 0x000c, 0x1120, 0x7aaa, 0x2001, 0x0001, 0x0098,
- 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d, 0x0120,
- 0x7aaa, 0x2001, 0x0002, 0x0038, 0x78ab, 0x0020, 0x7174, 0x79aa,
- 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060, 0x78aa, 0x785b, 0x0004,
- 0x781b, 0x0113, 0x080c, 0x3c6e, 0x707f, 0x000f, 0x70d0, 0xd0b4,
- 0x0168, 0xc0b4, 0x70d2, 0x00c6, 0x70b4, 0xa065, 0x6008, 0xa084,
- 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x00ce, 0x0005, 0x7014,
- 0xa005, 0x1138, 0x70d0, 0xd0b4, 0x0128, 0x70b4, 0xac06, 0x1110,
- 0x0c29, 0x0005, 0x0016, 0x71a0, 0xa186, 0x0001, 0x0528, 0x00d6,
- 0x0026, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b0, 0x2068, 0x6800,
- 0xac06, 0x0120, 0x8211, 0x01b0, 0x00c9, 0x0cc8, 0x00c6, 0x2100,
- 0x2011, 0x0001, 0xa212, 0x70b0, 0x2068, 0x6800, 0x2060, 0x6008,
- 0xa084, 0xfbef, 0x600a, 0x8211, 0x0110, 0x0041, 0x0cb0, 0x70a3,
- 0x0001, 0x00ce, 0x002e, 0x00de, 0x001e, 0x0005, 0xade8, 0x0005,
- 0x70a8, 0xad06, 0x1110, 0x70a4, 0x2068, 0x0005, 0x080c, 0x3c5b,
- 0x1904, 0x25c6, 0x7078, 0x2068, 0x7770, 0x080c, 0x3b95, 0x2c50,
- 0x080c, 0x3cf6, 0x789b, 0x0080, 0x6814, 0xa084, 0x001f, 0xc0bd,
- 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0804, 0x2850,
- 0x080c, 0x3c5b, 0x1904, 0x25c6, 0x789b, 0x0080, 0x705c, 0x2068,
- 0x6f14, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6, 0x70b4,
- 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a,
- 0x00ce, 0x080c, 0x3b95, 0x2c50, 0x080c, 0x3cf6, 0x6824, 0xa005,
- 0x0130, 0xa082, 0x0006, 0x0208, 0x0010, 0x6827, 0x0005, 0x6814,
- 0xa084, 0x001f, 0xc0bd, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001,
- 0x2001, 0x0003, 0x0804, 0x2850, 0xc28d, 0x72d2, 0x72bc, 0xa200,
- 0xa015, 0x7150, 0x8108, 0xa12a, 0x0208, 0x71bc, 0x2164, 0x6504,
- 0x85ff, 0x1170, 0x7152, 0x8421, 0x1da8, 0x70d0, 0xd08c, 0x0128,
- 0x70cc, 0xa005, 0x1110, 0x70cf, 0x000a, 0x0005, 0x2200, 0x0c90,
- 0x70d0, 0xc08c, 0x70d2, 0x70cf, 0x0000, 0x6034, 0xa005, 0x1db0,
- 0x6708, 0xa784, 0x073f, 0x01d0, 0xd7d4, 0x1d80, 0xa784, 0x0021,
- 0x1d68, 0xa784, 0x0002, 0x0130, 0xa784, 0x0004, 0x0d38, 0xa7bc,
- 0xfffb, 0x670a, 0xa784, 0x0218, 0x1d08, 0xa784, 0x0100, 0x0130,
- 0x6018, 0xa005, 0x19d8, 0xa7bc, 0xfeff, 0x670a, 0x2568, 0x6823,
- 0x0000, 0x6e1c, 0xa684, 0x000e, 0x6318, 0x0128, 0x601c, 0xa302,
- 0x0220, 0x0118, 0x0858, 0x83ff, 0x1948, 0x2d58, 0x2c50, 0x7152,
- 0xd7bc, 0x1120, 0x7028, 0x6022, 0x603a, 0x0010, 0xc7bc, 0x670a,
- 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001, 0x6b14,
- 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0110, 0xd684, 0x0110,
- 0xa39c, 0xffbf, 0xd6a4, 0x0110, 0xa39d, 0x0020, 0xa684, 0x000e,
- 0x1904, 0x2802, 0xc7a5, 0x670a, 0x2c00, 0x68c6, 0x77a0, 0xa786,
- 0x0001, 0x1178, 0x70d0, 0xd0b4, 0x1160, 0x7000, 0xa082, 0x0002,
- 0x1240, 0x7830, 0xd0bc, 0x1128, 0x789b, 0x0080, 0x7baa, 0x0804,
- 0x2849, 0x8739, 0x77a2, 0x2750, 0x77ac, 0xa7b0, 0x0005, 0x70a8,
- 0xa606, 0x1108, 0x76a4, 0x76ae, 0x2c3a, 0x8738, 0x2d3a, 0x8738,
- 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc, 0x0150,
- 0x2091, 0x8000, 0x2091, 0x303d, 0x70d0, 0xa084, 0x303d, 0x2091,
- 0x8000, 0x2090, 0xaad5, 0x0000, 0x0120, 0x8421, 0x2200, 0x1904,
- 0x2751, 0x0005, 0xd1dc, 0x0904, 0x37f1, 0x2029, 0x0020, 0xd69c,
- 0x1120, 0x8528, 0xd68c, 0x1108, 0x8528, 0x8840, 0x6f14, 0x610c,
- 0x8108, 0xa18c, 0x00ff, 0x70c8, 0xa160, 0x2c64, 0x8cff, 0x0188,
- 0x6014, 0xa706, 0x1dd0, 0x60b8, 0x8001, 0x60ba, 0x1d88, 0x2a60,
- 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x1904, 0x2751,
- 0x0005, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008,
- 0xc0d5, 0x600a, 0x77a0, 0xa786, 0x0001, 0x1904, 0x27d9, 0x70d0,
- 0xd0b4, 0x1904, 0x27d9, 0x7000, 0xa082, 0x0002, 0x1a04, 0x27d9,
- 0x7830, 0xd0bc, 0x1904, 0x27d9, 0x789b, 0x0080, 0x7baa, 0x7daa,
- 0x79aa, 0x2001, 0x0002, 0x0006, 0x6018, 0x8000, 0x601a, 0x0008,
- 0x0006, 0x2960, 0x6104, 0x2a60, 0x080c, 0x3d09, 0x1590, 0xa184,
- 0x0018, 0x0180, 0xa184, 0x0010, 0x0118, 0x080c, 0x399a, 0x1548,
- 0xa184, 0x0008, 0x0138, 0x69a0, 0xa184, 0x0600, 0x1118, 0x080c,
- 0x38b8, 0x00f8, 0x69a0, 0xa184, 0x1e00, 0x0528, 0xa184, 0x0800,
- 0x0178, 0x00c6, 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104,
- 0xa18d, 0x0010, 0x6106, 0x00ce, 0x080c, 0x399a, 0x1150, 0x69a0,
- 0xa184, 0x0200, 0x0118, 0x080c, 0x38fd, 0x0018, 0xa184, 0x0400,
- 0x19f0, 0x69a0, 0xa184, 0x1000, 0x0130, 0x6914, 0xa18c, 0xff00,
- 0x810f, 0x080c, 0x23c5, 0x002e, 0xa68c, 0x00e0, 0xa684, 0x0060,
- 0x0128, 0xa086, 0x0060, 0x1110, 0xa18d, 0x4000, 0xa18d, 0x0104,
- 0x69b6, 0x789b, 0x0060, 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a,
- 0xd6bc, 0x0168, 0xc0fc, 0x7083, 0x0000, 0xa08a, 0x000d, 0x0328,
- 0xa08a, 0x000c, 0x7182, 0x2001, 0x000c, 0x800c, 0x7186, 0x78aa,
- 0x3518, 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0,
- 0x789b, 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898,
- 0x25a0, 0xa286, 0x0020, 0x1508, 0x70d0, 0xc0b5, 0x70d2, 0x2c00,
- 0x70b6, 0x2d00, 0x70ba, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286,
- 0x0002, 0x0904, 0x2921, 0x70a0, 0x8000, 0x70a2, 0x74b0, 0xa498,
- 0x0005, 0x70a8, 0xa306, 0x1108, 0x73a4, 0x73b2, 0xa286, 0x0010,
- 0x0904, 0x25c6, 0x00de, 0x00ce, 0x0005, 0x7000, 0xa005, 0x19e0,
- 0xa286, 0x0002, 0x1904, 0x2938, 0x080c, 0x3c5b, 0x19a8, 0x6814,
- 0xc0fc, 0x8007, 0x7882, 0x2091, 0x8000, 0x781b, 0x0068, 0x68b4,
- 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x2091,
- 0x8001, 0x7808, 0xc08d, 0x780a, 0x0126, 0x00d6, 0x00c6, 0x70d0,
- 0xa084, 0x2e00, 0x2090, 0x00ce, 0x00de, 0x012e, 0x2900, 0x7056,
- 0x68bc, 0x703e, 0x7003, 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009,
- 0x7042, 0x7830, 0xd0bc, 0x0140, 0x2091, 0x303d, 0x70d0, 0xa084,
- 0x303d, 0x2091, 0x8000, 0x2090, 0x70a0, 0xa005, 0x1108, 0x0005,
- 0x8421, 0x0de8, 0x724c, 0x70bc, 0xa200, 0xa015, 0x0804, 0x2751,
- 0xa286, 0x0010, 0x1560, 0x080c, 0x3c5b, 0x1904, 0x28cc, 0x6814,
- 0xc0fc, 0x8007, 0x7882, 0x781b, 0x0068, 0x68b4, 0x785a, 0x6894,
- 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a,
- 0x70a0, 0x8000, 0x70a2, 0x74b0, 0xa490, 0x0005, 0x70a8, 0xa206,
- 0x1108, 0x72a4, 0x72b2, 0x2900, 0x7056, 0x68bc, 0x703e, 0x7003,
- 0x0002, 0x2d00, 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0x6bb4,
- 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94,
- 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x0068, 0x2900,
- 0x7056, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0170,
- 0x70d0, 0xa084, 0x2e00, 0xa086, 0x2600, 0x1118, 0x2009, 0x0000,
- 0x0010, 0x2009, 0x0001, 0xa284, 0x000f, 0x0033, 0xad80, 0x0009,
- 0x7042, 0x2d00, 0x704a, 0x0005, 0x299c, 0x4208, 0x4208, 0x41f6,
- 0x4208, 0x299c, 0x299c, 0x299c, 0x080c, 0x2575, 0x7808, 0xa084,
- 0xfffd, 0x780a, 0x00f6, 0x2079, 0x4700, 0x78ac, 0x00fe, 0xd084,
- 0x01c0, 0x7160, 0xa186, 0x0001, 0x0904, 0x2a61, 0xa186, 0x0007,
- 0x0170, 0xa186, 0x0005, 0x1158, 0x7078, 0x2068, 0x681b, 0x0004,
- 0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x7063,
- 0x0000, 0x70a3, 0x0000, 0x70a4, 0x70ae, 0x70b2, 0x080c, 0x26ae,
- 0x0156, 0x2011, 0x0004, 0x7160, 0xa186, 0x0001, 0x0158, 0xa186,
- 0x0007, 0x1118, 0x701f, 0x0005, 0x0010, 0x701f, 0x0001, 0x70d0,
- 0xc0c5, 0x70d2, 0x2001, 0x470a, 0x2004, 0xa084, 0x00ff, 0xa086,
- 0x0018, 0x0130, 0x7018, 0x7016, 0xa005, 0x1110, 0x70a3, 0x0001,
- 0x0066, 0x080c, 0x3f4e, 0x20a9, 0x0010, 0x2039, 0x0000, 0x080c,
- 0x3a8b, 0xa7b8, 0x0100, 0x1f04, 0x29ef, 0x006e, 0x7000, 0x0002,
- 0x2a2c, 0x2a0a, 0x2a0a, 0x2a02, 0x2a2c, 0x2a2c, 0x2a2c, 0x2a00,
- 0x080c, 0x2575, 0x705c, 0xa005, 0x0538, 0xad06, 0x1118, 0x6800,
- 0x705e, 0x0080, 0x6820, 0xd084, 0x1148, 0x6f14, 0x080c, 0x3b95,
- 0x6008, 0xc0d4, 0x600a, 0x080c, 0x37c7, 0x0020, 0x7058, 0x2060,
- 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818, 0xd0fc, 0x0108,
- 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff,
- 0xc09d, 0x6822, 0x080c, 0x1dbf, 0x2011, 0x0004, 0x74c8, 0xa4a0,
- 0x0100, 0x04b1, 0xaea0, 0x0017, 0x0499, 0x20a9, 0x0101, 0x74c8,
- 0x0479, 0x8420, 0x1f04, 0x2a38, 0x70c0, 0x2060, 0x2021, 0x0002,
- 0x20a9, 0x0100, 0x6110, 0x81ff, 0x0198, 0x6018, 0x0016, 0x0006,
- 0x2011, 0x4702, 0x220c, 0xa102, 0x2012, 0x000e, 0x001e, 0xa102,
- 0x0338, 0x6012, 0x1128, 0x2011, 0x4704, 0x2204, 0xc0a5, 0x2012,
- 0x601b, 0x0000, 0xace0, 0x0010, 0x1f04, 0x2a42, 0x8421, 0x1d00,
- 0x015e, 0x7063, 0x0000, 0x7003, 0x0000, 0x704b, 0x0000, 0x0005,
- 0x0046, 0x2404, 0xa005, 0x01a8, 0x2068, 0x6800, 0x0006, 0x6a1a,
- 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e,
- 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x080c, 0x1dbf, 0x000e,
- 0x0c48, 0x004e, 0x2023, 0x0000, 0x0005, 0xa282, 0x0003, 0x0310,
- 0x080c, 0x2575, 0x2300, 0x0002, 0x2a8f, 0x2b0c, 0x2b1a, 0xa282,
- 0x0002, 0x0110, 0x080c, 0x2575, 0x7060, 0x7063, 0x0000, 0x707f,
- 0x0000, 0x0022, 0x77d0, 0xc7c5, 0x77d2, 0x0002, 0x2aa6, 0x2aa6,
- 0x2aa8, 0x2ae0, 0x37fb, 0x2aa6, 0x2ae0, 0x2aa6, 0x080c, 0x2575,
- 0x7770, 0x080c, 0x3a8b, 0x7770, 0xa7bc, 0x8f00, 0x080c, 0x3b95,
- 0x6018, 0xa005, 0x0528, 0xd7fc, 0x1118, 0x2021, 0x8dc0, 0x0010,
- 0x2021, 0x8ed0, 0x2009, 0x0005, 0x2011, 0x0010, 0x080c, 0x2b34,
- 0x01b8, 0x0156, 0x20a9, 0x0101, 0xd7fc, 0x1118, 0x2021, 0x8cc0,
- 0x0010, 0x2021, 0x8dd0, 0x0046, 0x2009, 0x0005, 0x2011, 0x0010,
- 0x080c, 0x2b34, 0x004e, 0x0118, 0x8420, 0x1f04, 0x2acb, 0x015e,
- 0x8738, 0xa784, 0x001f, 0x1990, 0x0804, 0x25c9, 0x0804, 0x25c9,
- 0x7770, 0x080c, 0x3b95, 0x6018, 0xa005, 0x0520, 0xd7fc, 0x1118,
- 0x2021, 0x8dc0, 0x0010, 0x2021, 0x8ed0, 0x2009, 0x0005, 0x2011,
- 0x0020, 0x080c, 0x2b34, 0x01b0, 0x0156, 0x20a9, 0x0101, 0xd7fc,
- 0x1118, 0x2021, 0x8cc0, 0x0010, 0x2021, 0x8dd0, 0x0046, 0x2009,
- 0x0005, 0x2011, 0x0020, 0x0481, 0x004e, 0x0118, 0x8420, 0x1f04,
- 0x2afe, 0x015e, 0x0804, 0x25c9, 0x2200, 0x0002, 0x2b11, 0x2b13,
- 0x2b13, 0x080c, 0x2575, 0x7063, 0x0000, 0x70d0, 0xc0c5, 0x70d2,
- 0x0804, 0x25c9, 0x2200, 0x0002, 0x2b21, 0x2b13, 0x2b1f, 0x080c,
- 0x2575, 0x080c, 0x3f4e, 0x7000, 0xa086, 0x0002, 0x1904, 0x3780,
- 0x080c, 0x37e1, 0x6008, 0xa084, 0xfbef, 0x600a, 0x080c, 0x3772,
- 0x0904, 0x3780, 0x0804, 0x25c9, 0x2404, 0xa005, 0x0590, 0x2068,
- 0x2d04, 0x0006, 0x6814, 0xa706, 0x0118, 0x2d20, 0x000e, 0x0ca8,
- 0x000e, 0x2022, 0x691a, 0x6817, 0x0000, 0x682b, 0x0000, 0x68b4,
- 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084, 0x00ff, 0xa205, 0x6822,
- 0x080c, 0x1dbf, 0x2021, 0x4702, 0x241c, 0x8319, 0x2322, 0x6010,
- 0x8001, 0x6012, 0x1128, 0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022,
- 0x6008, 0xa084, 0xf9ef, 0x600a, 0x080c, 0x26ca, 0x080c, 0x37e1,
- 0x0005, 0xa085, 0x0001, 0x0ce0, 0x2300, 0x0002, 0x2b73, 0x2b71,
- 0x2bee, 0x080c, 0x2575, 0x78e4, 0xa005, 0x17b0, 0x3208, 0xa18c,
- 0x0800, 0x0118, 0x0104, 0x25c6, 0x0010, 0x0304, 0x25c6, 0x2008,
- 0xa084, 0x0030, 0x1110, 0x0804, 0x324d, 0x78ec, 0xa084, 0x0003,
- 0x0dd0, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
- 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
- 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
- 0x0001, 0x0002, 0x2bd1, 0x2bda, 0x2bc7, 0x2baa, 0x3c4f, 0x3c4f,
- 0x2baa, 0x2be4, 0x080c, 0x2575, 0x7000, 0xa086, 0x0004, 0x1190,
- 0x7060, 0xa086, 0x0002, 0x1130, 0x2011, 0x0002, 0x2019, 0x0000,
- 0x0804, 0x2a85, 0x7060, 0xa086, 0x0006, 0x0db0, 0x7060, 0xa086,
- 0x0004, 0x0d90, 0x79e4, 0x2001, 0x0003, 0x0804, 0x2f3b, 0x6818,
- 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a61, 0x781b, 0x006e,
- 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c, 0x3a61,
- 0x0804, 0x3c2d, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x001d, 0x080c,
- 0x3a61, 0x781b, 0x00fa, 0x0005, 0x6818, 0xd0fc, 0x0110, 0x681b,
- 0x001d, 0x080c, 0x3a61, 0x781b, 0x00cb, 0x0005, 0xa584, 0x000f,
- 0x11c0, 0x7000, 0x0002, 0x25c9, 0x2bfb, 0x2bfd, 0x3780, 0x3780,
- 0x3780, 0x2bfb, 0x2bfb, 0x080c, 0x2575, 0x080c, 0x37e1, 0x6008,
- 0xa084, 0xfbef, 0x600a, 0x080c, 0x3772, 0x0904, 0x3780, 0x0804,
- 0x25c9, 0x78e4, 0xa005, 0x1b04, 0x2bac, 0x3208, 0xa18c, 0x0800,
- 0x0118, 0x0104, 0x2bac, 0x0010, 0x0304, 0x2bac, 0x2008, 0xa084,
- 0x0030, 0x1118, 0x781b, 0x0068, 0x0005, 0x78ec, 0xa084, 0x0003,
- 0x0dc8, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
- 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
- 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
- 0x0001, 0x0002, 0x2c49, 0x2c4d, 0x2c44, 0x2c42, 0x3c4f, 0x3c4f,
- 0x2c42, 0x3c49, 0x080c, 0x2575, 0x080c, 0x3a67, 0x781b, 0x006e,
- 0x0005, 0x080c, 0x3a67, 0x0804, 0x3c2d, 0x080c, 0x3a67, 0x781b,
- 0x00fa, 0x0005, 0x080c, 0x3a67, 0x781b, 0x00cb, 0x0005, 0x2300,
- 0x0002, 0x2c5e, 0x2c5c, 0x2c60, 0x080c, 0x2575, 0x0804, 0x3405,
- 0x681b, 0x0016, 0x78a3, 0x0000, 0x79e4, 0xa184, 0x0030, 0x0904,
- 0x3405, 0x78ec, 0xa084, 0x0003, 0x0904, 0x3405, 0xa184, 0x0100,
- 0x0d98, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007, 0x0090, 0xa184,
- 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000, 0x0050, 0xa184,
- 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007, 0x0010, 0x2001,
- 0x0001, 0x0002, 0x2c92, 0x2c4d, 0x2bc7, 0x3c0b, 0x3c4f, 0x3c4f,
- 0x3c0b, 0x3c49, 0x080c, 0x3c17, 0x0005, 0xa282, 0x0005, 0x0310,
- 0x080c, 0x2575, 0x7898, 0x2040, 0x2300, 0x0002, 0x2ca1, 0x2ecb,
- 0x2ed5, 0x2200, 0x0002, 0x2cbd, 0x2caa, 0x2cbd, 0x2ca8, 0x2ead,
- 0x080c, 0x2575, 0x789b, 0x0018, 0x78a8, 0x2010, 0xa084, 0x00ff,
- 0xa082, 0x0020, 0x0a04, 0x3a30, 0xa08a, 0x0004, 0x1a04, 0x3a30,
- 0x0002, 0x3a30, 0x3a30, 0x3a30, 0x39e4, 0x789b, 0x0018, 0x79a8,
- 0xa184, 0x0080, 0x0148, 0x0804, 0x3a30, 0x7000, 0xa005, 0x1dd8,
- 0x2011, 0x0004, 0x0804, 0x35b7, 0xa184, 0x00ff, 0xa08a, 0x0010,
- 0x1a04, 0x3a30, 0x0002, 0x2ce5, 0x2ce3, 0x2cf7, 0x2cfb, 0x2da9,
- 0x3a30, 0x3a30, 0x2dab, 0x3a30, 0x3a30, 0x2ea9, 0x2ea9, 0x3a30,
- 0x3a30, 0x3a30, 0x2eab, 0x080c, 0x2575, 0xd6e4, 0x0140, 0x2001,
- 0x0300, 0x8000, 0x8000, 0x783a, 0x781b, 0x00c7, 0x0005, 0x6818,
- 0xd0fc, 0x0118, 0x681b, 0x001d, 0x0c90, 0x0804, 0x3c0b, 0x681b,
- 0x001d, 0x0804, 0x3a5b, 0x6920, 0x6922, 0xa684, 0x1800, 0x1904,
- 0x2d4c, 0x6820, 0xd084, 0x1904, 0x2d54, 0x6818, 0xa086, 0x0008,
- 0x1110, 0x681b, 0x0000, 0xd6d4, 0x0568, 0xd6bc, 0x0558, 0x7083,
- 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d, 0x0718, 0xa08a,
- 0x000c, 0x7182, 0x2001, 0x000c, 0x800c, 0x7186, 0x789b, 0x0061,
- 0x78aa, 0x0156, 0x0136, 0x0146, 0x0016, 0x3208, 0xa18c, 0x0600,
- 0x0118, 0x20a1, 0x022b, 0x0010, 0x20a1, 0x012b, 0x001e, 0x789b,
- 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x014e,
- 0x013e, 0x015e, 0x6038, 0xa005, 0x1150, 0x681c, 0xa084, 0x000e,
- 0x0904, 0x3a5b, 0x080c, 0x3a6d, 0x782b, 0x3008, 0x0010, 0x8001,
- 0x603a, 0x781b, 0x0071, 0x0005, 0xd6e4, 0x0130, 0x781b, 0x0083,
- 0x0005, 0x781b, 0x0083, 0x0005, 0xa684, 0x0060, 0x0dd0, 0xd6dc,
- 0x0dc0, 0xd6fc, 0x01a0, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8,
- 0x78d0, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000, 0x6b98,
- 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0xd6f4,
- 0x0118, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086, 0x0003, 0x1148,
- 0x0006, 0x080c, 0x3f4e, 0x080c, 0x4208, 0x000e, 0x781b, 0x0080,
- 0x0005, 0xa006, 0x080c, 0x42e8, 0x6ab0, 0x69ac, 0x6c98, 0x6b94,
- 0x2200, 0xa105, 0x0120, 0x2200, 0xa422, 0x2100, 0xa31b, 0x6caa,
- 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6, 0x7bde, 0x2300, 0xa405, 0x1130,
- 0xc6f5, 0x7e5a, 0x6eb6, 0x781b, 0x0080, 0x0005, 0x781b, 0x0080,
- 0x2200, 0xa115, 0x1118, 0x080c, 0x4208, 0x0005, 0x080c, 0x4235,
- 0x0005, 0x080c, 0x2575, 0x0804, 0x2e3f, 0x00c6, 0x7054, 0x2060,
- 0x6920, 0xa18c, 0xecff, 0x6922, 0x6000, 0xa084, 0xcfdf, 0x6002,
- 0x080c, 0x3917, 0xa006, 0x2040, 0x2038, 0x080c, 0x39bf, 0x0804,
- 0x2e33, 0x00c6, 0x7054, 0x2060, 0x2c48, 0x7aa8, 0xa294, 0x00ff,
- 0xa286, 0x0004, 0x11d8, 0x6920, 0xd1e4, 0x1170, 0x2039, 0x0000,
- 0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x391a,
- 0x080c, 0x39bf, 0x0804, 0x2e33, 0xa18c, 0xecff, 0x6922, 0x6104,
- 0xa18c, 0xffdd, 0x6106, 0x6000, 0xc0ac, 0x6002, 0xa286, 0x0003,
- 0x01d0, 0x6104, 0xa184, 0x0010, 0x0548, 0x080c, 0x3b91, 0x080c,
- 0x399a, 0x88ff, 0x0518, 0x00ce, 0x789b, 0x0060, 0x2800, 0x78aa,
- 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005,
- 0x781b, 0x0082, 0x0005, 0x6920, 0xd1cc, 0x0130, 0xa18c, 0xfdff,
- 0x6922, 0x6000, 0xc0ec, 0x6002, 0x2039, 0x0000, 0x2041, 0x0000,
- 0x2031, 0x0000, 0xa006, 0x2010, 0x080c, 0x39bf, 0xa286, 0x0001,
- 0x0158, 0x6104, 0xa184, 0x0008, 0x01b0, 0x080c, 0x3b91, 0x080c,
- 0x38b8, 0x88ff, 0x1980, 0x0078, 0x6920, 0xd1c4, 0x0130, 0xa18c,
- 0xfeff, 0x6922, 0x6000, 0xc0e4, 0x6002, 0x2031, 0x0000, 0xa006,
- 0x2010, 0x080c, 0x391a, 0x00ce, 0x7e58, 0xd6d4, 0x1118, 0x781b,
- 0x0071, 0x0005, 0x781b, 0x0083, 0x0005, 0x0804, 0x3a57, 0x2808,
- 0x789b, 0x0080, 0x2019, 0x0080, 0x78a8, 0xa094, 0x00ff, 0xa286,
- 0x0001, 0x11b8, 0x2300, 0xa102, 0xa086, 0x0001, 0x0904, 0x2dad,
- 0x7ca8, 0xa4a4, 0x00ff, 0xa480, 0x0002, 0xa300, 0x2018, 0xa102,
- 0x0a04, 0x2dc1, 0x0904, 0x2dc1, 0x24a8, 0x7aa8, 0x1f04, 0x2e5d,
- 0x0c18, 0xa284, 0x00f0, 0xa082, 0x0020, 0x06b8, 0x2200, 0xa082,
- 0x0021, 0x1698, 0x7aa8, 0x8318, 0x8318, 0x2100, 0xa302, 0x0aa0,
- 0xa286, 0x0023, 0x0950, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58,
- 0xa684, 0xfff1, 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a,
- 0x78a0, 0xa005, 0x0904, 0x2e34, 0x20a8, 0x7998, 0x789b, 0x0060,
- 0x78aa, 0x2011, 0x0080, 0x799a, 0x78a8, 0x7998, 0x7a9a, 0x78aa,
- 0x7a98, 0x1f04, 0x2e8b, 0xc695, 0x7e5a, 0xd6d4, 0x1118, 0x781b,
- 0x006e, 0x0005, 0x781b, 0x0082, 0x0005, 0x8318, 0x2100, 0xa302,
- 0x0a04, 0x2e44, 0xa284, 0x0080, 0x1904, 0x3a5b, 0x78a0, 0xa005,
- 0x08c8, 0x0804, 0x3a5b, 0x0804, 0x3a30, 0x7054, 0xa04d, 0x789b,
- 0x0018, 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0110, 0x080c,
- 0x2575, 0x7aa8, 0xa294, 0x00ff, 0x784b, 0x0008, 0x78a8, 0xa084,
- 0x00ff, 0xa08a, 0x0005, 0x1a04, 0x3a30, 0x0002, 0x3a30, 0x382f,
- 0x3a30, 0x394a, 0x3d59, 0xa282, 0x0000, 0x1110, 0x080c, 0x2575,
- 0x080c, 0x3a61, 0x781b, 0x0082, 0x0005, 0xa282, 0x0003, 0x1110,
- 0x080c, 0x2575, 0xd4fc, 0x11d0, 0x7060, 0xa005, 0x0110, 0x080c,
- 0x2575, 0x6f14, 0x7772, 0xa7bc, 0x8f00, 0x080c, 0x3b95, 0x6008,
- 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f, 0x1db0, 0x080c,
- 0x3a64, 0x7063, 0x0002, 0x701f, 0x0009, 0x0010, 0x080c, 0x3a70,
- 0x781b, 0x0082, 0x0005, 0xa282, 0x0004, 0x0310, 0x080c, 0x2575,
- 0x2300, 0x0002, 0x2f05, 0x309b, 0x30d7, 0xa286, 0x0003, 0x0598,
- 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x71d0, 0xd1b4, 0x0528, 0xd1bc,
- 0x1518, 0x2001, 0x4701, 0x2004, 0xd0c4, 0x11f0, 0x7868, 0xa084,
- 0x00ff, 0x11d0, 0xa282, 0x0002, 0x12b8, 0x00d6, 0x783b, 0x8300,
- 0x781b, 0x0059, 0x70b8, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6,
- 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030,
- 0x00de, 0x2001, 0x0000, 0x0058, 0x783b, 0x1300, 0x781b, 0x0057,
- 0x2001, 0x0000, 0x0020, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x7046,
- 0x68a0, 0xd0ec, 0x0118, 0x6008, 0xc08d, 0x600a, 0xa284, 0x000f,
- 0x0002, 0x307c, 0x2f56, 0x2f53, 0x31a7, 0x3232, 0x25c9, 0x2f51,
- 0x2f51, 0x080c, 0x2575, 0x6008, 0xc0d4, 0x600a, 0xd6e4, 0x0120,
- 0x7044, 0xa086, 0x0014, 0x11e8, 0x080c, 0x3f4e, 0x2009, 0x0000,
- 0x6818, 0xd0fc, 0x0108, 0x7044, 0xa086, 0x0014, 0x0168, 0x6818,
- 0xa086, 0x0008, 0x1904, 0x303e, 0x7858, 0xd09c, 0x0904, 0x303e,
- 0x6820, 0xd0ac, 0x0904, 0x303e, 0x681b, 0x0014, 0x2009, 0x0002,
- 0x04a8, 0x7868, 0xa08c, 0x00ff, 0x0588, 0xa186, 0x0008, 0x1158,
- 0x6008, 0xc0a4, 0x600a, 0x080c, 0x3772, 0x0540, 0x080c, 0x37e1,
- 0x080c, 0x3f4e, 0x0060, 0xa186, 0x0028, 0x1500, 0x6018, 0xa005,
- 0x0d78, 0x8001, 0x0d68, 0x8001, 0x0d58, 0x601e, 0x0c48, 0x6820,
- 0xd084, 0x0904, 0x25c9, 0xc084, 0x6822, 0x080c, 0x26bf, 0x7058,
- 0x00c6, 0x2060, 0x6800, 0x6002, 0x00ce, 0x6004, 0x6802, 0xa005,
- 0x2d00, 0x1108, 0x6002, 0x6006, 0x0804, 0x25c9, 0x0016, 0x81ff,
- 0x15f0, 0x7000, 0xa086, 0x0030, 0x05d0, 0x71d0, 0xd1bc, 0x15b8,
- 0xd1b4, 0x11e8, 0x705c, 0xa005, 0x1590, 0x70a0, 0xa086, 0x0001,
- 0x0570, 0x7003, 0x0000, 0x0046, 0x0056, 0x0076, 0x0066, 0x00c6,
- 0x00d6, 0x080c, 0x25f1, 0x00de, 0x00ce, 0x006e, 0x007e, 0x005e,
- 0x004e, 0x71d0, 0xd1b4, 0x11d8, 0x7003, 0x0040, 0x00c0, 0x080c,
- 0x3c5b, 0x11a8, 0x781b, 0x0068, 0x00d6, 0x70b8, 0xa06d, 0x68b4,
- 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4,
- 0x71d2, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a, 0x00de, 0x080c,
- 0x30ff, 0x001e, 0x81ff, 0x0904, 0x303e, 0xa684, 0xdf00, 0x681e,
- 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x1904, 0x303f, 0x6818,
- 0xa086, 0x0014, 0x1130, 0x2008, 0xd6e4, 0x0118, 0x7868, 0xa08c,
- 0x00ff, 0x080c, 0x3a7a, 0x080c, 0x26ca, 0x6820, 0xd0dc, 0x1578,
- 0x8717, 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xb284, 0x0600,
- 0x0118, 0xa290, 0x4bc0, 0x0010, 0xa290, 0x4c40, 0xa290, 0x0000,
- 0x221c, 0xd3c4, 0x0170, 0x6820, 0xd0e4, 0x0128, 0xa084, 0xefff,
- 0x6822, 0xc3ac, 0x2312, 0x8210, 0x2204, 0xa085, 0x0038, 0x2012,
- 0x8211, 0xd3d4, 0x0138, 0x68a0, 0xd0c4, 0x1120, 0x080c, 0x3167,
- 0x0804, 0x25c9, 0x6008, 0xc08d, 0x600a, 0x0008, 0x692a, 0x6916,
- 0x6818, 0xd0fc, 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00, 0x691e,
- 0x6410, 0x84ff, 0x0168, 0x2009, 0x4702, 0x2104, 0x8001, 0x200a,
- 0x8421, 0x6412, 0x1128, 0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022,
- 0x6018, 0xa005, 0x0118, 0x8001, 0x601a, 0x1118, 0x6008, 0xc0a4,
- 0x600a, 0x6820, 0xd084, 0x1130, 0x6800, 0xa005, 0x1108, 0x6002,
- 0x6006, 0x0020, 0x7058, 0x2060, 0x6800, 0x6002, 0x2061, 0x4700,
- 0x6887, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a,
- 0x0110, 0x2d02, 0x0008, 0x616e, 0x7200, 0xa286, 0x0030, 0x0158,
- 0xa286, 0x0040, 0x1904, 0x25c9, 0x7003, 0x0002, 0x7048, 0x2068,
- 0x68c4, 0x2060, 0x0005, 0x7003, 0x0002, 0x70b8, 0xa06d, 0x68bc,
- 0x703e, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00, 0x704a, 0xad80,
- 0x0009, 0x7042, 0x0005, 0xa282, 0x0004, 0x0210, 0x080c, 0x2575,
- 0x2200, 0x0002, 0x30a6, 0x30b5, 0x30c1, 0x30b5, 0xa586, 0x1300,
- 0x0160, 0xa586, 0x8300, 0x1d90, 0x7003, 0x0000, 0x6018, 0x8001,
- 0x601a, 0x6008, 0xa084, 0xfbef, 0x600a, 0x7000, 0xa086, 0x0005,
- 0x0128, 0x080c, 0x3a61, 0x781b, 0x0082, 0x0005, 0x781b, 0x0083,
- 0x0005, 0x7890, 0x8007, 0x8001, 0xa084, 0x0007, 0xa080, 0x0018,
- 0x789a, 0x79a8, 0xa18c, 0x00ff, 0xa186, 0x0003, 0x0128, 0xa186,
- 0x0000, 0x0110, 0x0804, 0x3a30, 0x781b, 0x0083, 0x0005, 0x6820,
- 0xc095, 0x6822, 0x82ff, 0x1118, 0x080c, 0x3a61, 0x0030, 0x8211,
- 0x0110, 0x080c, 0x2575, 0x080c, 0x3a70, 0x781b, 0x0082, 0x0005,
- 0x080c, 0x3c6e, 0x7830, 0xa084, 0x00c0, 0x1170, 0x0016, 0x3208,
- 0xa18c, 0x0800, 0x001e, 0x0118, 0x0104, 0x30fc, 0x0010, 0x0304,
- 0x30fc, 0x791a, 0xa006, 0x0005, 0xa085, 0x0001, 0x0005, 0xa684,
- 0x0060, 0x1130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, 0x3166,
- 0xd6dc, 0x1198, 0x68b4, 0xd0dc, 0x1180, 0x6998, 0x6a94, 0x692e,
- 0x6a32, 0x7044, 0xa005, 0x1130, 0x2200, 0xa105, 0x0904, 0x3f4e,
- 0x7047, 0x0015, 0x0804, 0x3f4e, 0x0005, 0xd6ac, 0x01f0, 0xd6f4,
- 0x0130, 0x682f, 0x0000, 0x6833, 0x0000, 0x0804, 0x3f4e, 0x68b4,
- 0xa084, 0x4000, 0xa635, 0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110,
- 0x7047, 0x0015, 0xd6dc, 0x1128, 0x68b4, 0xd0dc, 0x0110, 0x6ca8,
- 0x6da4, 0x6c2e, 0x6d32, 0x0804, 0x3f4e, 0xd6f4, 0x0130, 0x682f,
- 0x0000, 0x6833, 0x0000, 0x0804, 0x3f4e, 0x68b4, 0xa084, 0x4800,
- 0xa635, 0xd6f4, 0x1da0, 0x7044, 0xa005, 0x1110, 0x7047, 0x0015,
- 0x2408, 0x2510, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291,
- 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x1110, 0x0804, 0x3f4e,
- 0x7000, 0xa086, 0x0006, 0x0110, 0x0804, 0x3f4e, 0x0005, 0x6946,
- 0x6008, 0xc0cd, 0xd3cc, 0x0108, 0xc08d, 0x600a, 0x6818, 0x683a,
- 0x681b, 0x0006, 0x688f, 0x0000, 0x6893, 0x0000, 0x6a30, 0x692c,
- 0x6a3e, 0x6942, 0x682f, 0x0003, 0x6833, 0x0000, 0x6837, 0x0020,
- 0x6897, 0x0000, 0x689b, 0x0020, 0x7000, 0x0002, 0x25c9, 0x3196,
- 0x3190, 0x318e, 0x318e, 0x318e, 0x318e, 0x318e, 0x080c, 0x2575,
- 0x6820, 0xd084, 0x1118, 0x080c, 0x37c7, 0x0030, 0x7058, 0x2c50,
- 0x2060, 0x6800, 0x6002, 0x2a60, 0xaea0, 0x0017, 0x2404, 0xa005,
- 0x0110, 0x2020, 0x0cd8, 0x2d22, 0x206b, 0x0000, 0x0005, 0x080c,
- 0x37cd, 0x080c, 0x37e1, 0x6008, 0xc0cc, 0x600a, 0x682b, 0x0000,
- 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944, 0x6916, 0x2009,
- 0x0000, 0xae86, 0x4740, 0x0110, 0x2009, 0x0001, 0x080c, 0x431f,
- 0xd6dc, 0x01c8, 0x691c, 0xc1ed, 0x691e, 0x6828, 0xa082, 0x000e,
- 0x0290, 0x6848, 0xa084, 0x000f, 0xa086, 0x000b, 0x1160, 0x685c,
- 0xa086, 0x0047, 0x1140, 0x2001, 0x4701, 0x2004, 0xd0ac, 0x1118,
- 0x2700, 0x080c, 0x249e, 0x6818, 0xd0fc, 0x0140, 0x681b, 0x0000,
- 0x7868, 0xa08c, 0x00ff, 0x0110, 0x681b, 0x001e, 0xaea0, 0x0017,
- 0x6800, 0x2022, 0x6a3c, 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060,
- 0x6000, 0xd0a4, 0x0580, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051,
- 0x0020, 0x00d6, 0x00f6, 0x0156, 0x0146, 0x2079, 0x4700, 0x080c,
- 0x1bb2, 0x014e, 0x015e, 0x00fe, 0x70c8, 0x2010, 0x2009, 0x0101,
- 0x0026, 0x2204, 0xa06d, 0x0140, 0x6814, 0xa706, 0x0110, 0x6800,
- 0x0cc8, 0x6820, 0xc0d5, 0x6822, 0x002e, 0x8210, 0x8109, 0x1d80,
- 0x00de, 0x7063, 0x0003, 0x707b, 0x0000, 0x7772, 0x707f, 0x000f,
- 0x71d0, 0xc1c4, 0x71d2, 0x6818, 0xa086, 0x0002, 0x1138, 0x6817,
- 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec, 0x681e, 0x080c, 0x1dbf,
- 0x0804, 0x25c9, 0x7cd8, 0x7ddc, 0x7fd0, 0x080c, 0x30ff, 0x682b,
- 0x0000, 0x789b, 0x000e, 0x6f14, 0x080c, 0x3c72, 0xa08c, 0x00ff,
- 0x6916, 0x6818, 0xd0fc, 0x0110, 0x7044, 0x681a, 0xa68c, 0xdf00,
- 0x691e, 0x7063, 0x0000, 0x0804, 0x25c9, 0x7000, 0xa005, 0x1110,
- 0x0804, 0x25c9, 0xa006, 0x080c, 0x3f4e, 0x6920, 0xd1ac, 0x1110,
- 0x681b, 0x0014, 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820,
- 0xa084, 0x00ff, 0x6822, 0x7000, 0x0002, 0x25c9, 0x326f, 0x326f,
- 0x3272, 0x3272, 0x3272, 0x326d, 0x326d, 0x080c, 0x2575, 0x6818,
- 0x0804, 0x2f3b, 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0804,
- 0x3795, 0x2300, 0x0002, 0x327e, 0x3280, 0x32ce, 0x080c, 0x2575,
- 0xd6fc, 0x1904, 0x2d5b, 0x7000, 0xa00d, 0x0002, 0x25c9, 0x3290,
- 0x3290, 0x32ba, 0x3290, 0x32cb, 0x328e, 0x328e, 0x080c, 0x2575,
- 0xa684, 0x0060, 0x0538, 0xa086, 0x0060, 0x1510, 0xc6ac, 0xc6f4,
- 0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac, 0x681e, 0xa186, 0x0002,
- 0x0148, 0x080c, 0x3f4e, 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c,
- 0x4235, 0x0010, 0x080c, 0x4208, 0x781b, 0x0083, 0x71d0, 0xd1b4,
- 0x1904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d, 0x0005,
- 0xd6ec, 0x09f0, 0x6818, 0xd0fc, 0x0170, 0xd6f4, 0x1130, 0x681b,
- 0x0015, 0x781b, 0x0083, 0x0804, 0x25c6, 0x681b, 0x0007, 0x682f,
- 0x0000, 0x6833, 0x0000, 0x080c, 0x3c17, 0x0005, 0x080c, 0x2575,
- 0x2300, 0x0002, 0x32d7, 0x32f9, 0x3351, 0x080c, 0x2575, 0x7000,
- 0x0002, 0x32e1, 0x32e3, 0x32ea, 0x32e1, 0x32e1, 0x32e1, 0x32e1,
- 0x32e1, 0x080c, 0x2575, 0x69ac, 0x68b0, 0xa115, 0x0118, 0x080c,
- 0x4235, 0x0010, 0x080c, 0x4208, 0x681c, 0xc0b4, 0x681e, 0x70d0,
- 0xd0b4, 0x1904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d,
- 0x0005, 0xd6fc, 0x1904, 0x3341, 0x7000, 0xa00d, 0x0002, 0x25c9,
- 0x330f, 0x3309, 0x3339, 0x330f, 0x333e, 0x3307, 0x3307, 0x080c,
- 0x2575, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684,
- 0x0060, 0x0538, 0xa086, 0x0060, 0x1510, 0xa6b4, 0xbfbf, 0xc6ed,
- 0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0148, 0x080c, 0x3f4e, 0x69ac,
- 0x68b0, 0xa115, 0x0118, 0x080c, 0x4235, 0x0010, 0x080c, 0x4208,
- 0x781b, 0x0083, 0x681c, 0xc0b4, 0x681e, 0x71d0, 0xd1b4, 0x1904,
- 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904, 0x260d, 0x0005, 0xd6ec,
- 0x09f0, 0x6818, 0xd0fc, 0x0110, 0x681b, 0x0007, 0x781b, 0x00fb,
- 0x0005, 0xc6fc, 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302,
- 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0083,
- 0x0005, 0xd6dc, 0x0130, 0x782b, 0x3009, 0x781b, 0x0083, 0x0804,
- 0x25c6, 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x1150,
- 0xa484, 0x0200, 0x0108, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b, 0x0083,
- 0x0804, 0x25c6, 0x6820, 0xc095, 0x6822, 0x080c, 0x3c02, 0xc6dd,
- 0x080c, 0x3a61, 0x781b, 0x0082, 0x0804, 0x25c6, 0x2300, 0x0002,
- 0x337b, 0x337d, 0x337f, 0x080c, 0x2575, 0x0804, 0x3a5b, 0x7d98,
- 0xd6d4, 0x15a8, 0x79e4, 0xd1ac, 0x0130, 0x78ec, 0xa084, 0x0003,
- 0x0110, 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684,
- 0xfffb, 0x785a, 0x7d9a, 0x79e4, 0xd1ac, 0x0120, 0x78ec, 0xa084,
- 0x0003, 0x1120, 0x2001, 0x0014, 0x0804, 0x2f3b, 0x7884, 0xd0fc,
- 0x1118, 0xa184, 0x0007, 0x0090, 0xa184, 0x0007, 0xa086, 0x0004,
- 0x1118, 0x2001, 0x0000, 0x0050, 0xa184, 0x0007, 0xa086, 0x0005,
- 0x0118, 0xa184, 0x0007, 0x0010, 0x2001, 0x0001, 0x04c2, 0x7a90,
- 0xa294, 0x0007, 0x789b, 0x0060, 0x79a8, 0x81ff, 0x0568, 0x789b,
- 0x0080, 0x7ba8, 0xa384, 0x0001, 0x11d0, 0x7ba8, 0x7ba8, 0xa386,
- 0x0004, 0x1118, 0x2009, 0xffdf, 0x0058, 0xa386, 0x0001, 0x1118,
- 0x2009, 0xfff7, 0x0028, 0xa386, 0x0003, 0x1148, 0x2009, 0xffef,
- 0x00c6, 0x7054, 0x2060, 0x6004, 0xa104, 0x6006, 0x00ce, 0x789b,
- 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x782b, 0x3009,
- 0x6920, 0xa18c, 0xecff, 0x6922, 0x7d9a, 0x0804, 0x3c0b, 0x2bd1,
- 0x2bda, 0x33f9, 0x33ff, 0x33f7, 0x33f7, 0x3c0b, 0x3c0b, 0x080c,
- 0x2575, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0804, 0x3c11, 0x6920,
- 0xa18c, 0xfcff, 0x6922, 0x0804, 0x3c0b, 0x79e4, 0xa184, 0x0030,
- 0x0120, 0x78ec, 0xa084, 0x0003, 0x1570, 0x7000, 0xa086, 0x0004,
- 0x1190, 0x7060, 0xa086, 0x0002, 0x1130, 0x2011, 0x0002, 0x2019,
- 0x0000, 0x0804, 0x2a85, 0x7060, 0xa086, 0x0006, 0x0db0, 0x7060,
- 0xa086, 0x0004, 0x0d90, 0x7000, 0xa086, 0x0000, 0x0904, 0x25c6,
- 0x6920, 0xa184, 0x0420, 0x0128, 0xc1d4, 0x6922, 0x6818, 0x0804,
- 0x2f3b, 0x6818, 0xa08e, 0x0002, 0x0120, 0xc0fd, 0x681a, 0x2001,
- 0x0014, 0x0804, 0x2f3b, 0x7884, 0xd0fc, 0x1118, 0xa184, 0x0007,
- 0x0090, 0xa184, 0x0007, 0xa086, 0x0004, 0x1118, 0x2001, 0x0000,
- 0x0050, 0xa184, 0x0007, 0xa086, 0x0005, 0x0118, 0xa184, 0x0007,
- 0x0010, 0x2001, 0x0001, 0x0002, 0x3c0b, 0x3c0b, 0x345c, 0x3c0b,
- 0x3c4f, 0x3c4f, 0x3c0b, 0x3c0b, 0xd6bc, 0x0570, 0x7180, 0x81ff,
- 0x0558, 0xa182, 0x000d, 0x1318, 0x7083, 0x0000, 0x0028, 0xa182,
- 0x000c, 0x7082, 0x2009, 0x000c, 0x789b, 0x0061, 0x79aa, 0x0156,
- 0x0136, 0x0146, 0x7084, 0x8114, 0xa210, 0x7286, 0xa080, 0x000b,
- 0xad00, 0x2098, 0xb284, 0x0600, 0x0118, 0x20a1, 0x022b, 0x0010,
- 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x014e,
- 0x013e, 0x015e, 0x0804, 0x3c11, 0xd6d4, 0x1904, 0x34cf, 0x6820,
- 0xd084, 0x0904, 0x3c11, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0120,
- 0xa086, 0x0060, 0x1108, 0xc1f5, 0xc194, 0x795a, 0x69b6, 0x789b,
- 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818, 0xc0fd, 0x681a,
- 0x78aa, 0x8008, 0x810c, 0x0904, 0x37f6, 0xa18c, 0x00f8, 0x1904,
- 0x37f6, 0x0156, 0x0136, 0x0146, 0x0016, 0x20a1, 0x012b, 0x3208,
- 0xa18c, 0x0600, 0x0110, 0x20a1, 0x022b, 0x001e, 0x789b, 0x0000,
- 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x014e, 0x013e,
- 0x015e, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0804, 0x3c11, 0x6818,
- 0xd0fc, 0x0110, 0x681b, 0x0008, 0x080c, 0x3a61, 0x781b, 0x00ed,
- 0x0005, 0x2300, 0x0002, 0x34e0, 0x359d, 0x34de, 0x080c, 0x2575,
- 0x7cd8, 0x7ddc, 0x7fd0, 0x82ff, 0x1528, 0x7200, 0xa286, 0x0003,
- 0x0904, 0x2f09, 0x71d0, 0xd1bc, 0x11f8, 0xd1b4, 0x01e8, 0x2001,
- 0x4701, 0x2004, 0xd0c4, 0x11c0, 0x00d6, 0x783b, 0x8800, 0x781b,
- 0x0059, 0x70b8, 0xa06d, 0x68b4, 0xc0a5, 0x785a, 0x6894, 0x78d6,
- 0x78de, 0x6898, 0x78d2, 0x78da, 0xc1b4, 0x71d2, 0x7003, 0x0030,
- 0x00de, 0x0030, 0x7200, 0x0020, 0x783b, 0x1800, 0x781b, 0x0057,
- 0xa284, 0x000f, 0x0002, 0x3588, 0x3545, 0x351d, 0x2f38, 0x351b,
- 0x3588, 0x351b, 0x351b, 0x080c, 0x2575, 0x681c, 0xd0ec, 0x0118,
- 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006,
- 0xa005, 0x1108, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c, 0xa084,
- 0x000e, 0x1120, 0x71c8, 0xa188, 0x0100, 0x0028, 0x7030, 0x68ba,
- 0x713c, 0x70c8, 0xa108, 0x2104, 0x6802, 0x2d0a, 0x715a, 0xd6dc,
- 0x1120, 0xc6fc, 0x6eb6, 0x0804, 0x3588, 0x6eb6, 0xa684, 0x0060,
- 0x1120, 0xa684, 0x7fff, 0x68b6, 0x04d8, 0xd6dc, 0x1150, 0xa684,
- 0x7fff, 0x68b6, 0x6894, 0x68a6, 0x6898, 0x68aa, 0x080c, 0x3f4e,
- 0x0478, 0xd6ac, 0x0140, 0xa006, 0x080c, 0x3f4e, 0x2408, 0x2510,
- 0x69aa, 0x6aa6, 0x0068, 0x2408, 0x2510, 0x2700, 0x8007, 0xa084,
- 0x007f, 0xa108, 0xa291, 0x0000, 0x69aa, 0x6aa6, 0x080c, 0x3f4e,
- 0xd6fc, 0x01b0, 0xa684, 0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac,
- 0x1138, 0x2700, 0x8007, 0xa084, 0x007f, 0xa108, 0xa291, 0x0000,
- 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
- 0x7000, 0xa086, 0x0030, 0x1904, 0x25c9, 0x7003, 0x0002, 0x70b8,
- 0xa06d, 0x68bc, 0x703e, 0x70b4, 0xa065, 0x68c0, 0x7056, 0x2d00,
- 0x704a, 0xad80, 0x0009, 0x7042, 0x0005, 0xa586, 0x8800, 0x1148,
- 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
- 0x600a, 0x0804, 0x3a5b, 0x7043, 0x0000, 0xa282, 0x0006, 0x0310,
- 0x080c, 0x2575, 0x2300, 0x0002, 0x35b7, 0x35c8, 0x35d2, 0x2200,
- 0x0002, 0x35bf, 0x3a5b, 0x35c1, 0x35bf, 0x3603, 0x3651, 0x080c,
- 0x2575, 0x7a80, 0xa294, 0x0f00, 0x080c, 0x36a5, 0x0804, 0x3a30,
- 0x00c1, 0x0002, 0x3a5b, 0x35d0, 0x35d0, 0x3603, 0x35d0, 0x3a5b,
- 0x080c, 0x2575, 0x0071, 0x0002, 0x35dc, 0x35da, 0x35da, 0x35dc,
- 0x35da, 0x35dc, 0x080c, 0x2575, 0x080c, 0x3a70, 0x781b, 0x0082,
- 0x0005, 0x7000, 0xa086, 0x0002, 0x1150, 0x080c, 0x37e1, 0x0010,
- 0x080c, 0x3f4e, 0x6008, 0xa084, 0xfbef, 0x600a, 0x0020, 0x7000,
- 0xa086, 0x0003, 0x0da8, 0x7003, 0x0005, 0x2001, 0x8ee0, 0xae8e,
- 0x4740, 0x0110, 0x2001, 0x8f12, 0x2068, 0x704a, 0xad80, 0x0009,
- 0x7042, 0x2200, 0x0005, 0x7000, 0xa086, 0x0002, 0x1158, 0x70d0,
- 0xc0b5, 0x70d2, 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x0038, 0x080c,
- 0x3f4e, 0x0020, 0x7000, 0xa086, 0x0003, 0x0dc8, 0x7003, 0x0001,
- 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f,
- 0xa215, 0x2069, 0x8dc0, 0xb284, 0x0600, 0x1118, 0xc2fd, 0x2069,
- 0x8ed0, 0x2d04, 0x2d08, 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206,
- 0x0120, 0x6800, 0x0cb8, 0x080c, 0x36a5, 0x6eb4, 0x7e5a, 0x6920,
- 0xa184, 0x0c00, 0x0904, 0x36cb, 0x7060, 0xa086, 0x0006, 0x1128,
- 0x7070, 0xa206, 0x1110, 0x7062, 0x707a, 0x681b, 0x0005, 0xc1ad,
- 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x080c, 0x3a67, 0x0804,
- 0x36cb, 0x7200, 0xa286, 0x0002, 0x1158, 0x70d0, 0xc0b5, 0x70d2,
- 0x2c00, 0x70b6, 0x2d00, 0x70ba, 0x0030, 0x080c, 0x3f4e, 0x0018,
- 0xa286, 0x0003, 0x0dd0, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00,
- 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0xae86, 0x4740,
- 0x0108, 0xc2fd, 0x79a8, 0x79a8, 0xa18c, 0x00ff, 0x2118, 0x70c8,
- 0xa168, 0x2d04, 0x2d08, 0x715a, 0xa06d, 0x0128, 0x6814, 0xa206,
- 0x0118, 0x6800, 0x0cb8, 0x0409, 0x6eb4, 0x6920, 0xa184, 0x0c00,
- 0x0904, 0x36cb, 0xd0dc, 0x0178, 0x7060, 0xa086, 0x0004, 0x1140,
- 0x7070, 0xa206, 0x1128, 0x7074, 0xa306, 0x1110, 0x7062, 0x707a,
- 0x080c, 0x3a6d, 0x0480, 0x681b, 0x0005, 0xc1ad, 0xc1d4, 0x6922,
- 0x080c, 0x3a67, 0x707b, 0x0000, 0x0430, 0x7003, 0x0005, 0xb284,
- 0x0600, 0x0118, 0x2001, 0x8ee0, 0x0010, 0x2001, 0x8f12, 0x2068,
- 0x704a, 0x0156, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x1f04,
- 0x36b4, 0x015e, 0xb284, 0x0600, 0x0110, 0xc2fc, 0x0008, 0xc2fd,
- 0x6a16, 0xad80, 0x0009, 0x7042, 0x68b7, 0x0700, 0x6823, 0x0800,
- 0x6827, 0x0003, 0x0005, 0xc6ec, 0xa6ac, 0x0060, 0x0904, 0x3712,
- 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x11e0, 0x7bd2, 0x7bda,
- 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x05c8, 0xd6f4, 0x1108, 0xc6ed,
- 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0128, 0x2009,
- 0x0082, 0x2019, 0x0000, 0x2320, 0x791a, 0xd6ec, 0x0588, 0x080c,
- 0x4208, 0x0470, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305,
- 0x01f8, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x1108,
- 0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0083, 0xd69c, 0x0128, 0x2011,
- 0x0082, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec, 0x0188, 0x080c,
- 0x4235, 0x0070, 0x2019, 0x0000, 0x2320, 0x0010, 0xa6b4, 0xb7ff,
- 0x7e5a, 0x2009, 0x0083, 0xd69c, 0x0110, 0x2009, 0x0082, 0x791a,
- 0x68c0, 0x7056, 0x2d00, 0x704a, 0x68c4, 0x2060, 0x71d0, 0x2001,
- 0x4701, 0x2004, 0xd0c4, 0x15c8, 0x70d4, 0xa02d, 0x01b8, 0xd1bc,
- 0x0548, 0x7a80, 0xa294, 0x0f00, 0x70d8, 0xa206, 0x0118, 0x78e0,
- 0xa504, 0x1558, 0x70d6, 0xc1bc, 0x71d2, 0x0438, 0x2031, 0x0001,
- 0x852c, 0x0218, 0x8633, 0x8210, 0x0cd8, 0x0005, 0x7de0, 0xa594,
- 0xff00, 0x0130, 0x2011, 0x0008, 0x852f, 0x0c81, 0x8637, 0x0008,
- 0x0c69, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206, 0x0170, 0x72da,
- 0x76d6, 0x0058, 0x7a80, 0xa294, 0x0f00, 0x70d8, 0xa236, 0x0dc0,
- 0x78e0, 0xa534, 0x0da8, 0xc1bd, 0x71d2, 0xd1b4, 0x1904, 0x25c6,
- 0x2300, 0xa405, 0x0904, 0x25c6, 0x70a0, 0xa086, 0x0001, 0x1904,
- 0x260d, 0x0005, 0x6020, 0xa005, 0x0150, 0x8001, 0x6022, 0x6008,
- 0xa085, 0x0008, 0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x0005,
- 0xa006, 0x080c, 0x3f4e, 0x7000, 0xa086, 0x0002, 0x0120, 0x7060,
- 0xa086, 0x0005, 0x1150, 0x682b, 0x0000, 0x6817, 0x0000, 0x681b,
- 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084, 0x000f,
- 0x0002, 0x25c9, 0x37a6, 0x37a3, 0x37c3, 0x37af, 0x25c9, 0x37a1,
- 0x37a1, 0x080c, 0x2575, 0x0449, 0x0411, 0x0028, 0x0431, 0x7058,
- 0x2060, 0x6800, 0x6002, 0x080c, 0x1dbf, 0x0804, 0x25c9, 0x7060,
- 0x7063, 0x0000, 0x707f, 0x0000, 0x0002, 0x37bf, 0x37bf, 0x37bd,
- 0x37bd, 0x37bd, 0x37bf, 0x37bd, 0x37bf, 0x0804, 0x2a9a, 0x7063,
- 0x0000, 0x0804, 0x25c9, 0x681b, 0x0000, 0x0804, 0x31a7, 0x6800,
- 0xa005, 0x1108, 0x6002, 0x6006, 0x0005, 0x6410, 0x84ff, 0x0168,
- 0x2009, 0x4702, 0x2104, 0x8001, 0x200a, 0x8421, 0x6412, 0x1128,
- 0x2021, 0x4704, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a,
- 0x0005, 0x6018, 0xa005, 0x0110, 0x8001, 0x601a, 0x0005, 0x080c,
- 0x3c6e, 0x681b, 0x0018, 0x0490, 0x080c, 0x3c6e, 0x681b, 0x0019,
- 0x0468, 0x080c, 0x3c6e, 0x681b, 0x001a, 0x0440, 0x080c, 0x3c6e,
- 0x681b, 0x0003, 0x0418, 0x7770, 0x080c, 0x3b95, 0x7174, 0xa18c,
- 0x00ff, 0x3210, 0xa294, 0x0600, 0x0118, 0xa1e8, 0x8cc0, 0x0010,
- 0xa1e8, 0x8dd0, 0x2d04, 0x2d08, 0x2068, 0xa005, 0x1118, 0x707a,
- 0x0804, 0x25c9, 0x6814, 0x7270, 0xa206, 0x0110, 0x6800, 0x0c98,
- 0x6800, 0x200a, 0x681b, 0x0005, 0x707b, 0x0000, 0x080c, 0x37cd,
- 0x6820, 0xd084, 0x1110, 0x080c, 0x37c7, 0x080c, 0x37e1, 0x681f,
- 0x0000, 0x6823, 0x0020, 0x080c, 0x1dbf, 0x0804, 0x25c9, 0xa282,
- 0x0003, 0x1904, 0x3a35, 0x7da8, 0xa5ac, 0x00ff, 0x7ea8, 0xa6b4,
- 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x05b0, 0xc1c4, 0x6922,
- 0xa6b4, 0x00ff, 0x0530, 0xa682, 0x0018, 0x0218, 0x0110, 0x2031,
- 0x0018, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x2041,
- 0x0000, 0x080c, 0x3aee, 0x0118, 0x080c, 0x391a, 0x00a0, 0x080c,
- 0x3aba, 0x080c, 0x3917, 0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695,
- 0x7e5a, 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082,
- 0x0005, 0x080c, 0x3917, 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071,
- 0x0005, 0x781b, 0x0083, 0x0005, 0x00c6, 0x7054, 0x2060, 0x6100,
- 0xd1e4, 0x0598, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x0018,
- 0x0218, 0x0110, 0x2011, 0x0018, 0x2600, 0xa202, 0x1208, 0x2230,
- 0xa686, 0x0010, 0x1108, 0x8630, 0x6208, 0xa294, 0x00ff, 0x78ec,
- 0xd0e4, 0x0130, 0xa282, 0x000a, 0x1240, 0x2011, 0x000a, 0x0028,
- 0xa282, 0x000c, 0x1210, 0x2011, 0x000c, 0x2200, 0xa502, 0x1208,
- 0x2228, 0x080c, 0x3abe, 0x852b, 0x852b, 0x2041, 0x0000, 0x080c,
- 0x3aee, 0x0118, 0x080c, 0x391a, 0x0020, 0x080c, 0x3aba, 0x080c,
- 0x3917, 0x7858, 0xc095, 0x785a, 0x00ce, 0x781b, 0x0082, 0x0005,
- 0x00c6, 0x2960, 0x6000, 0xd0e4, 0x1188, 0xd0b4, 0x1150, 0x6010,
- 0xa084, 0x000f, 0x1130, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x00ce,
- 0x0005, 0x2011, 0x0032, 0x2019, 0x0000, 0x00f0, 0x68a0, 0xd0cc,
- 0x1dc0, 0x6208, 0xa294, 0x00ff, 0x78ec, 0xd0e4, 0x0130, 0xa282,
- 0x000b, 0x1218, 0x2011, 0x000a, 0x0028, 0xa282, 0x000c, 0x1210,
- 0x2011, 0x000c, 0x6308, 0x831f, 0xa39c, 0x00ff, 0xa382, 0x0018,
- 0x0218, 0x0110, 0x2019, 0x0018, 0x78ab, 0x0001, 0x78ab, 0x0003,
- 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5,
- 0x6822, 0x080c, 0x3a7a, 0x00ce, 0x0005, 0x00c6, 0x2960, 0x6104,
- 0xa18c, 0xfff5, 0x6106, 0x2011, 0x0032, 0x2019, 0x0000, 0x0000,
- 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa,
- 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822, 0x00ce, 0x0005, 0xa006,
- 0x2030, 0x2010, 0x00c6, 0x7154, 0x2160, 0x2018, 0x2008, 0xa084,
- 0xffe0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4,
- 0xa084, 0x7770, 0xa18c, 0x000f, 0xa105, 0x2029, 0x4705, 0x252c,
- 0xd5cc, 0x0140, 0xd3a4, 0x0110, 0xa085, 0x0800, 0xd3fc, 0x0110,
- 0xa085, 0x8080, 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x001f, 0x8637,
- 0x8204, 0x8004, 0xa605, 0x600e, 0x6004, 0xa084, 0xffd5, 0x6006,
- 0x00ce, 0x0005, 0xa282, 0x0002, 0x1904, 0x3a3f, 0x7aa8, 0x6920,
- 0xc1bd, 0x6922, 0xd1cc, 0x0568, 0xc1cc, 0x6922, 0xa294, 0x00ff,
- 0xa282, 0x0002, 0x1a04, 0x3a30, 0x080c, 0x39c1, 0x080c, 0x3917,
- 0xa980, 0x0001, 0x200c, 0x080c, 0x3b91, 0x080c, 0x38b8, 0x88ff,
- 0x0178, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a,
- 0xd6d4, 0x1118, 0x781b, 0x006e, 0x0005, 0x781b, 0x0082, 0x0005,
- 0x7e58, 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083,
- 0x0005, 0xa282, 0x0002, 0x1218, 0xa284, 0x0001, 0x0140, 0x7154,
- 0xa188, 0x0000, 0x210c, 0xd1ec, 0x1110, 0x2011, 0x0000, 0x080c,
- 0x3aac, 0x0479, 0x080c, 0x3917, 0x7858, 0xc095, 0x785a, 0x781b,
- 0x0082, 0x0005, 0x00c6, 0x0026, 0x2960, 0x6000, 0x2011, 0x0001,
- 0xd0ec, 0x1158, 0xd0bc, 0x1138, 0x6014, 0xd0b4, 0x1120, 0xc1a4,
- 0x6106, 0xa006, 0x0088, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
- 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x080c, 0x3a7a,
- 0x6820, 0xa085, 0x0200, 0x6822, 0x002e, 0x00ce, 0x0005, 0x8807,
- 0xa715, 0x00c6, 0x2009, 0x0000, 0x7054, 0x2060, 0x82ff, 0x0110,
- 0x2009, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4, 0xa084,
- 0xff9f, 0xa105, 0xc0ec, 0xd0b4, 0x1108, 0xc0ed, 0x6100, 0xd1f4,
- 0x0110, 0xa085, 0x0020, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084,
- 0xffef, 0x6006, 0x00ce, 0x0005, 0x0006, 0x7000, 0xa086, 0x0003,
- 0x0110, 0x000e, 0x0010, 0x000e, 0x0498, 0xd6ac, 0x0588, 0x7888,
- 0xa084, 0x0040, 0x0568, 0x7bb8, 0x8307, 0xa084, 0x007f, 0x1518,
- 0x8207, 0xa084, 0x00ff, 0x0904, 0x3a57, 0xa09a, 0x0004, 0x1a04,
- 0x3a57, 0xd6f4, 0x11d0, 0x79d8, 0x7adc, 0xa108, 0xa291, 0x0000,
- 0x79d2, 0x79da, 0x7ad6, 0x7ade, 0x080c, 0x42e8, 0x781b, 0x0080,
- 0xb284, 0x0600, 0x0118, 0x2001, 0x0000, 0x0010, 0x2001, 0x0001,
- 0x080c, 0x419a, 0x0005, 0x080c, 0x2575, 0x781b, 0x0080, 0x0005,
- 0x781b, 0x0083, 0x0005, 0x2039, 0x0000, 0x2041, 0x0000, 0x2031,
- 0x0000, 0xa006, 0x2010, 0x080c, 0x391a, 0x080c, 0x39bf, 0x7e58,
- 0x080c, 0x3a73, 0x781b, 0x0082, 0x0005, 0x0cd1, 0x6820, 0xc0c4,
- 0x6822, 0x00c6, 0x7054, 0x2060, 0x080c, 0x3944, 0x00b0, 0x0c81,
- 0x6820, 0xc0cc, 0x6822, 0x00c6, 0x7054, 0x2060, 0x080c, 0x39de,
- 0x0060, 0x0c31, 0x6820, 0xa084, 0xecff, 0x6822, 0x00c6, 0x7054,
- 0x2060, 0x6004, 0xa084, 0xffc5, 0x6006, 0x00ce, 0x0005, 0x0049,
- 0x781b, 0x0082, 0x0005, 0x6827, 0x0002, 0x0049, 0x781b, 0x0082,
- 0x0005, 0x2001, 0x0005, 0x0088, 0x2001, 0x000c, 0x0070, 0x6820,
- 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0040, 0x2001, 0x000d, 0x0028,
- 0x2001, 0x0009, 0x0010, 0x2001, 0x0007, 0x789b, 0x007e, 0x78aa,
- 0xc69d, 0x7e5a, 0x70d0, 0xd0b4, 0x0168, 0xc0b4, 0x70d2, 0x00c6,
- 0x70b4, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
- 0x601a, 0x00ce, 0x0005, 0x0076, 0x873f, 0xa7bc, 0x000f, 0x873b,
- 0x873b, 0x8703, 0xa0e0, 0x4bc0, 0xae8e, 0x4740, 0x0110, 0xa0e0,
- 0x4c40, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x7fe0, 0x78ae,
- 0x6012, 0x79a4, 0xa184, 0x773f, 0x78a6, 0x6016, 0x6004, 0xa085,
- 0x0038, 0x6006, 0x007e, 0x0005, 0x789b, 0x0080, 0x78ab, 0x0001,
- 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
- 0x0004, 0x0800, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b, 0x0080,
- 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa,
- 0x789b, 0x0060, 0x78ab, 0x0005, 0x0804, 0x3a7a, 0x0156, 0x8007,
- 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a, 0x79a4,
- 0xa18c, 0xffe0, 0x2021, 0x3b7a, 0x2019, 0x0011, 0x20a9, 0x000e,
- 0x2011, 0x0032, 0x2404, 0xa084, 0xffe0, 0xa106, 0x0128, 0x8420,
- 0x2300, 0xa210, 0x1f04, 0x3ae2, 0x015e, 0x0005, 0x0156, 0x0804,
- 0x3b30, 0x2021, 0x3b88, 0x20a9, 0x0009, 0x2011, 0x0029, 0xa582,
- 0x0028, 0x0550, 0x8420, 0x95a9, 0x2011, 0x0033, 0xa582, 0x0033,
- 0x0618, 0x8420, 0x95a9, 0x2019, 0x000a, 0x2011, 0x0065, 0x2200,
- 0xa502, 0x02d0, 0x8420, 0x2300, 0xa210, 0x1f04, 0x3b07, 0x015e,
- 0x0088, 0x2021, 0x3b7a, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
- 0x0033, 0x2200, 0xa502, 0x0240, 0x8420, 0x2300, 0xa210, 0x1f04,
- 0x3b19, 0x015e, 0xa006, 0x0005, 0x8211, 0x015e, 0xa582, 0x0064,
- 0x1220, 0x7808, 0xa085, 0x0070, 0x780a, 0x2404, 0xa005, 0x0005,
- 0xa886, 0x0002, 0x01e8, 0x2021, 0x3b66, 0x20a9, 0x000d, 0x2011,
- 0x0028, 0xa582, 0x0028, 0x0d48, 0x8420, 0x2019, 0x0019, 0x2011,
- 0x0033, 0x2200, 0xa502, 0x0e00, 0x8420, 0x2300, 0xa210, 0x1f04,
- 0x3b41, 0x015e, 0x2011, 0x0184, 0xa582, 0x0185, 0x0ab0, 0x0890,
- 0x2021, 0x3b75, 0x20a9, 0x0003, 0x2011, 0x0024, 0xa586, 0x0024,
- 0x0960, 0x8420, 0x2011, 0x0028, 0xa586, 0x0028, 0x0930, 0x8420,
- 0x2019, 0x0019, 0x2011, 0x0033, 0x0804, 0x3b19, 0x1021, 0x2202,
- 0x3403, 0x4604, 0x5805, 0x6a06, 0x7c07, 0x4610, 0x4612, 0x5812,
- 0x5a12, 0x6a14, 0x6c14, 0x6e14, 0x7e17, 0x9021, 0xb002, 0xe204,
- 0xe210, 0xe210, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403, 0x5404,
- 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07, 0x0e07,
- 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07, 0x7e07,
- 0x0e00, 0x789b, 0x0080, 0xa046, 0x0005, 0xa784, 0x0f00, 0x800b,
- 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105, 0xd7fc,
- 0x0118, 0xa0e0, 0x6cc0, 0x0010, 0xa0e0, 0x4cc0, 0x0005, 0x00e6,
- 0x00f6, 0xd084, 0x0138, 0x2079, 0x0100, 0x2009, 0x4780, 0x2071,
- 0x4780, 0x0030, 0x2009, 0x4740, 0x2079, 0x0200, 0x2071, 0x4740,
- 0x2091, 0x8000, 0x2104, 0xa084, 0x000f, 0x0002, 0x3bc8, 0x3bc8,
- 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc8, 0x3bc6, 0x3bc6, 0x080c, 0x2575,
- 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0580, 0x7858,
- 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, 0xa086, 0x1814,
- 0x1530, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004, 0x1de0, 0x784b,
- 0x0008, 0x7848, 0xa084, 0x0008, 0x1de0, 0x7830, 0xd0bc, 0x11b8,
- 0xb284, 0x0800, 0x0118, 0x0104, 0x3bff, 0x0010, 0x0304, 0x3bff,
- 0x79e4, 0xa184, 0x0030, 0x0158, 0x78ec, 0xa084, 0x0003, 0x0138,
- 0x681c, 0xd0ac, 0x1110, 0x00d9, 0x0010, 0x781b, 0x00fb, 0x00fe,
- 0x00ee, 0x0005, 0x2001, 0x4701, 0x2004, 0xd0ac, 0x1118, 0x6814,
- 0x080c, 0x249e, 0x0005, 0x781b, 0x0083, 0x0005, 0x781b, 0x0082,
- 0x0005, 0x781b, 0x0071, 0x0005, 0x781b, 0x006e, 0x0005, 0x2009,
- 0x4719, 0x210c, 0xa186, 0x0000, 0x0150, 0xa186, 0x0001, 0x0150,
- 0x701f, 0x000b, 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x781b,
- 0x00f3, 0x0005, 0x701f, 0x000a, 0x0005, 0x2009, 0x4719, 0x210c,
- 0xa186, 0x0000, 0x0168, 0xa186, 0x0001, 0x0138, 0x701f, 0x000b,
- 0x7063, 0x0001, 0x781b, 0x0054, 0x0005, 0x701f, 0x000a, 0x0005,
- 0x781b, 0x00f2, 0x0005, 0x781b, 0x00fb, 0x0005, 0x781b, 0x00fa,
- 0x0005, 0x781b, 0x00cc, 0x0005, 0x781b, 0x00cb, 0x0005, 0x6818,
- 0xd0fc, 0x0110, 0x681b, 0x001d, 0x701f, 0x000b, 0x7063, 0x0001,
- 0x781b, 0x0054, 0x0005, 0x7830, 0xa084, 0x00c0, 0x1170, 0x7808,
- 0xc08c, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000, 0x78ec, 0xa084,
- 0x0021, 0x0118, 0x7808, 0xc08d, 0x780a, 0x0005, 0x7808, 0xc08d,
- 0x780a, 0x0005, 0x7830, 0xa084, 0x0040, 0x1de0, 0xb284, 0x0800,
- 0x0118, 0x1104, 0x3c80, 0x0010, 0x1304, 0x3c80, 0x78ac, 0x0005,
- 0x7808, 0xa084, 0xfffd, 0x780a, 0xe000, 0xe000, 0xe000, 0xe000,
- 0x78ec, 0xa084, 0x0021, 0x0140, 0xb284, 0x0800, 0x0118, 0x1104,
- 0x3c8f, 0x0010, 0x1304, 0x3c92, 0x78ac, 0x0006, 0x7808, 0xa085,
- 0x0002, 0x780a, 0x000e, 0x0005, 0xa784, 0x0001, 0x1904, 0x324d,
- 0xa784, 0x0070, 0x0140, 0x00c6, 0x2d60, 0x2f68, 0x080c, 0x2490,
- 0x2d78, 0x2c68, 0x00ce, 0xa784, 0x0008, 0x0148, 0x784b, 0x0008,
- 0x78ec, 0xa084, 0x0003, 0x0904, 0x324d, 0x0804, 0x3c0b, 0xa784,
- 0x0004, 0x01c8, 0x78b8, 0xa084, 0x8000, 0x01a8, 0x784b, 0x0008,
- 0x78ec, 0xa084, 0x0003, 0x0904, 0x324d, 0x78e4, 0xa084, 0x0007,
- 0xa086, 0x0001, 0x1140, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a,
- 0x781b, 0x00fb, 0x0005, 0xa784, 0x0080, 0x0140, 0x7884, 0xd0fc,
- 0x0128, 0x080c, 0x3a57, 0x681b, 0x0022, 0x0005, 0x681b, 0x0003,
- 0x7858, 0xa084, 0x5f00, 0x681e, 0x682f, 0x0000, 0x6833, 0x0000,
- 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0904, 0x2bac, 0xb284,
- 0x0800, 0x0110, 0x0104, 0x25c6, 0x0304, 0x25c6, 0x6b14, 0x8307,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xd3fc, 0x0118, 0xa080,
- 0x4c40, 0x0010, 0xa080, 0x4bc0, 0x2060, 0x2048, 0x7056, 0x2a60,
- 0x0005, 0x00c6, 0x2960, 0x6000, 0xd0ac, 0x0904, 0x3d57, 0x68a0,
- 0xd1ac, 0x1120, 0xa084, 0x0e00, 0x0904, 0x3d55, 0x6108, 0x8117,
- 0xa18c, 0x00ff, 0x631c, 0x832f, 0xd0dc, 0x0110, 0xa39d, 0x0001,
- 0xd0cc, 0x11c8, 0xa584, 0x00ff, 0x0138, 0x78ec, 0xd0e4, 0x0110,
- 0x8213, 0x00b8, 0x2029, 0x0000, 0xa182, 0x000c, 0x1290, 0x78ec,
- 0xd0e4, 0x1118, 0x2009, 0x000c, 0x0060, 0xa182, 0x000b, 0x1248,
- 0x2009, 0x000a, 0x0030, 0x2009, 0x0032, 0x2011, 0x0000, 0x2029,
- 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab, 0x0004, 0x79aa,
- 0x78ab, 0x0000, 0x7aaa, 0x7baa, 0x7daa, 0xa8c0, 0x0008, 0x6820,
- 0xa085, 0x1000, 0x6822, 0x080c, 0x3a7a, 0xa085, 0x0001, 0x00ce,
- 0x0005, 0xa282, 0x0006, 0x1904, 0x3a49, 0x7da8, 0x7eac, 0x8637,
- 0xa5ac, 0x00ff, 0xa6b4, 0x00ff, 0x7fac, 0x8747, 0xa7bc, 0x00ff,
- 0xa8c4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1e4, 0x0904, 0x3dcb,
- 0xa18c, 0xecff, 0x6922, 0xa782, 0x0002, 0x1a04, 0x3a23, 0xa6b4,
- 0x00ff, 0x0904, 0x3dc8, 0xa682, 0x0031, 0x1a04, 0x3a23, 0xa582,
- 0x0009, 0x0a04, 0x3a23, 0xa882, 0x0003, 0x1a04, 0x3a23, 0xa886,
- 0x0002, 0x01d0, 0xa886, 0x0000, 0x1904, 0x3a23, 0x2001, 0x000c,
- 0x79ec, 0xd1e4, 0x0110, 0x2001, 0x000a, 0xa502, 0x1290, 0x080c,
- 0x3a23, 0x00c6, 0x2960, 0x6004, 0xa085, 0x001a, 0x6006, 0x6000,
- 0xc0ac, 0x6002, 0x00ce, 0x0005, 0xa786, 0x0000, 0x0904, 0x3a23,
- 0x8634, 0xa682, 0x0018, 0x0228, 0x0120, 0x2031, 0x0018, 0x0804,
- 0x3e19, 0xa686, 0x0010, 0x1108, 0x8630, 0x852b, 0x852b, 0x080c,
- 0x3aee, 0x0904, 0x3a23, 0x080c, 0x391a, 0x080c, 0x39bf, 0x7e58,
- 0xd6d4, 0x1118, 0x781b, 0x0071, 0x0005, 0x781b, 0x0083, 0x0005,
- 0x080c, 0x3917, 0x0c90, 0xa886, 0x0002, 0x1108, 0x8634, 0x7154,
- 0xa188, 0x0000, 0x210c, 0xd1ac, 0x0904, 0x3a23, 0xd1ec, 0x1120,
- 0x2039, 0x0000, 0x2041, 0x0000, 0xd1e4, 0x1120, 0x2031, 0x0000,
- 0x2041, 0x0000, 0xa782, 0x0002, 0x12c8, 0x621c, 0xa284, 0x00ff,
- 0xa706, 0x0110, 0x2039, 0x0000, 0xa605, 0x0190, 0x6108, 0x811f,
- 0xa39c, 0x00ff, 0x0168, 0xa302, 0x1208, 0x2330, 0x8807, 0xa705,
- 0xa086, 0x0201, 0x0160, 0xa886, 0x0000, 0x0168, 0x2039, 0x0000,
- 0x2041, 0x0000, 0x2031, 0x0000, 0xa006, 0x2010, 0x0070, 0xa284,
- 0xff00, 0x1108, 0x2040, 0xa184, 0x00ff, 0xa502, 0x0108, 0x2128,
- 0x852b, 0x852b, 0x080c, 0x3aee, 0x0d58, 0x080c, 0x391a, 0x080c,
- 0x39bf, 0x789b, 0x0080, 0x78ab, 0x0001, 0x78ab, 0x0006, 0x78ab,
- 0x0004, 0x7daa, 0x78ab, 0x0000, 0x7eaa, 0x7faa, 0x2800, 0x78aa,
- 0x789b, 0x0060, 0x78ab, 0x0008, 0x6820, 0xc0e5, 0x6822, 0x080c,
- 0x3a7a, 0x7858, 0xc095, 0x785a, 0x781b, 0x0082, 0x0005, 0x0020,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9855, 0x984d, 0x0014,
- 0x9911, 0x98ff, 0x0014, 0x0014, 0x0090, 0x00e7, 0x0100, 0x0402,
- 0x2008, 0xf880, 0x0018, 0x0017, 0x840f, 0xd8c1, 0x0014, 0x0016,
- 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014, 0x2500, 0x0013, 0x2500,
- 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
- 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0xa200, 0x3806,
- 0x8839, 0x20c4, 0x0864, 0xa850, 0x3008, 0x28c1, 0x9d18, 0xa201,
- 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a,
- 0xa808, 0x28e2, 0x9cce, 0xa8f3, 0x0864, 0xa83e, 0x300c, 0xa801,
- 0x3008, 0x28e1, 0x9cce, 0x28a2, 0x7163, 0xa831, 0x2021, 0xa818,
- 0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0, 0x6fc0, 0x67a4, 0x6c80,
- 0x0212, 0xa205, 0x883d, 0x882b, 0x1814, 0x883b, 0x7027, 0x85f2,
- 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa813, 0x883e, 0xa811,
- 0x2882, 0x7162, 0xa814, 0x280a, 0xa204, 0x64c0, 0x6de0, 0x67a0,
- 0x6fc0, 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa802, 0x7861,
- 0x883e, 0x206a, 0x28c1, 0x9d18, 0x2042, 0x2101, 0xa8ca, 0x2902,
- 0xa20e, 0xa80b, 0xa207, 0x0014, 0xa203, 0x8000, 0x85a4, 0x1872,
- 0x879a, 0x883c, 0x1fe2, 0xf601, 0xa208, 0x856e, 0x7121, 0x0014,
- 0x0704, 0x3008, 0x9cce, 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009,
- 0x84a8, 0x19e2, 0xf844, 0x856e, 0x883f, 0x08e6, 0xa8f5, 0xf861,
- 0xa8eb, 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532,
- 0xfaa2, 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8,
- 0xd6e0, 0x1fe6, 0x0014, 0x3008, 0x8000, 0x2849, 0x1011, 0xa8fc,
- 0x3008, 0x8000, 0xa000, 0x2081, 0x2802, 0x1011, 0xa8fc, 0xa889,
- 0x3008, 0x20a1, 0x283c, 0x1011, 0xa8fc, 0xa209, 0x0017, 0x300c,
- 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0x0210, 0xa801, 0x0014,
- 0x26e0, 0x873a, 0xfaa3, 0x19f2, 0x26e0, 0x18f2, 0x0014, 0xa20b,
- 0x0014, 0xa20d, 0x3806, 0x0210, 0x9d22, 0x0704, 0xa206, 0x6865,
- 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016, 0x6042, 0x8008, 0xa8fa,
- 0x8160, 0x842a, 0x8180, 0xf021, 0x3008, 0x84a8, 0x11d7, 0x7042,
- 0x20dd, 0x0011, 0x20d5, 0x8822, 0x0016, 0x0000, 0x0126, 0x70d0,
- 0xa084, 0x4c00, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
- 0x11a0, 0x720c, 0x82ff, 0x0128, 0x8aff, 0x1178, 0x7200, 0xd284,
- 0x1160, 0x7804, 0xd0cc, 0x0110, 0x080c, 0x435b, 0x7007, 0x0008,
- 0x7003, 0x0008, 0x012e, 0x2000, 0x0005, 0x7000, 0xa084, 0x0003,
- 0x7002, 0xc69c, 0xd084, 0x0588, 0x7108, 0xe000, 0x7008, 0xa106,
- 0x1dd8, 0xa184, 0x0003, 0x0904, 0x3fca, 0xa184, 0x01e0, 0x1904,
- 0x3fca, 0xd1f4, 0x1d88, 0xa184, 0x3000, 0xa086, 0x1000, 0x0d60,
- 0x2011, 0x0180, 0x710c, 0x8211, 0x0130, 0x7008, 0xd0f4, 0x1d20,
- 0x700c, 0xa106, 0x0dc0, 0x7007, 0x0012, 0x7108, 0xe000, 0x7008,
- 0xa106, 0x1dd8, 0xa184, 0x0003, 0x0568, 0xd194, 0x0db0, 0xd1f4,
- 0x0548, 0x7007, 0x0002, 0x0880, 0x0428, 0x7108, 0xd1fc, 0x0130,
- 0x080c, 0x40d6, 0x8aff, 0x0904, 0x3f54, 0x0cb8, 0x700c, 0xa08c,
- 0x07ff, 0x01e8, 0x7004, 0xd084, 0x0178, 0x7014, 0xa005, 0x1148,
- 0x7010, 0x7310, 0xa306, 0x1de0, 0x2300, 0xa005, 0x0128, 0xa102,
- 0x1e20, 0x7007, 0x0010, 0x0030, 0x8aff, 0x0148, 0x080c, 0x429a,
- 0x1de8, 0x09d8, 0x080c, 0x405c, 0x012e, 0x2000, 0x0005, 0x7204,
- 0x7108, 0xc19c, 0x8103, 0x1218, 0x7007, 0x0002, 0x0cc0, 0xa205,
- 0x1d88, 0x7007, 0x0008, 0x7003, 0x0008, 0x0006, 0x2001, 0x4701,
- 0x2004, 0xd0cc, 0x0110, 0x080c, 0x435b, 0x000e, 0x012e, 0x2000,
- 0x0005, 0x6428, 0x84ff, 0x0508, 0x2c70, 0x7004, 0xa0bc, 0x000f,
- 0xa7b8, 0x401d, 0x273c, 0x87fb, 0x1148, 0x0210, 0x080c, 0x2575,
- 0x609c, 0xa075, 0x0190, 0x0c88, 0x2039, 0x4012, 0x2704, 0xae68,
- 0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0138, 0x8738, 0x2704,
- 0xa005, 0x1da8, 0x709c, 0xa075, 0x1d00, 0x0005, 0x0000, 0x0005,
- 0x0009, 0x000d, 0x0011, 0x0015, 0x0019, 0x001d, 0x0000, 0x0003,
- 0x0009, 0x000f, 0x0015, 0x001b, 0x0000, 0x0000, 0x4012, 0x400f,
- 0x0000, 0x0000, 0x8000, 0x0000, 0x4012, 0x0000, 0x401a, 0x4017,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x401a, 0x0000, 0x4015, 0x4015,
- 0x0000, 0x0000, 0x8000, 0x0000, 0x4015, 0x0000, 0x401b, 0x401b,
- 0x0000, 0x0000, 0x0000, 0x0000, 0x401b, 0x2079, 0x4700, 0x2071,
- 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0001, 0x2009,
- 0x0002, 0x2071, 0x0050, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003,
- 0x0000, 0x2001, 0x01ff, 0x2004, 0xd0fc, 0x1128, 0x8109, 0x0118,
- 0x2071, 0x0020, 0x0c80, 0x0005, 0x7004, 0x8004, 0x1a04, 0x40b2,
- 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c,
- 0x410e, 0x0804, 0x40d2, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108,
- 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0120, 0x080c, 0x410e,
- 0x0804, 0x40d2, 0xa19c, 0x300c, 0xa386, 0x2004, 0x0190, 0xa386,
- 0x0008, 0x01c0, 0x7004, 0xd084, 0x1148, 0x7108, 0x7008, 0xa106,
- 0x1de0, 0xa184, 0x0003, 0x0110, 0x0804, 0x410e, 0xa386, 0x200c,
- 0x19f0, 0x7200, 0x8204, 0x0230, 0x730c, 0xa384, 0x07ff, 0x0110,
- 0x080c, 0x2575, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
- 0x0118, 0x080c, 0x410e, 0x0470, 0x7007, 0x0012, 0x7000, 0xd084,
- 0x1148, 0x7310, 0x7014, 0xa305, 0x0128, 0x710c, 0xa184, 0x07ff,
- 0x1904, 0x405c, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0,
- 0x0118, 0x080c, 0x410e, 0x00b0, 0x7007, 0x0012, 0x7007, 0x0008,
- 0x7004, 0xd09c, 0x1de8, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184,
- 0x01e0, 0x0118, 0x080c, 0x410e, 0x0028, 0x7007, 0x0012, 0x7108,
- 0x8103, 0x0e88, 0x7003, 0x0008, 0x0005, 0x7108, 0xa184, 0x01e0,
- 0x15a8, 0x7108, 0xa184, 0x01e0, 0x1588, 0xa184, 0x0007, 0x0002,
- 0x40ea, 0x40f8, 0x40e8, 0x40f8, 0x40e8, 0x4148, 0x40e8, 0x4146,
- 0x080c, 0x2575, 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x8aff,
- 0x1118, 0x2049, 0x0000, 0x0005, 0x080c, 0x429a, 0x1de8, 0x0005,
- 0x7004, 0xa084, 0x0010, 0xc08d, 0x7006, 0x7004, 0xd084, 0x1140,
- 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x0003, 0x0108, 0x0030,
- 0x8aff, 0x0118, 0x080c, 0x429a, 0x1de8, 0x0005, 0x7007, 0x0012,
- 0x7108, 0x1d04, 0x4111, 0x2091, 0x6000, 0x1d04, 0x4115, 0x2091,
- 0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xd09c, 0x1de8,
- 0x7007, 0x0012, 0x7108, 0xd1fc, 0x1dd8, 0x7003, 0x0000, 0x7000,
- 0xa005, 0x1130, 0x7004, 0xa005, 0x1118, 0x700c, 0xa005, 0x0108,
- 0x0c40, 0x2049, 0x0000, 0xb284, 0x0200, 0x0118, 0x2001, 0x0000,
- 0x0010, 0x2001, 0x0001, 0x080c, 0x3ba7, 0x681b, 0x0002, 0x2051,
- 0x0000, 0x0005, 0x080c, 0x2575, 0x080c, 0x2575, 0x080c, 0x4187,
- 0x7210, 0x7114, 0x700c, 0xa09c, 0x07ff, 0x2800, 0xa300, 0xa211,
- 0xa189, 0x0000, 0x04a1, 0x2704, 0x2c58, 0xac60, 0x6308, 0x2200,
- 0xa322, 0x630c, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0140, 0x1238,
- 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0c58, 0x2b60,
- 0x8a07, 0x0006, 0x6004, 0xd09c, 0x0118, 0xa7ba, 0x4017, 0x0010,
- 0xa7ba, 0x400f, 0x000e, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
- 0x6b8e, 0x7108, 0x7008, 0xa106, 0x1de0, 0xa184, 0x01e0, 0x0110,
- 0x080c, 0x410e, 0x7007, 0x0012, 0x080c, 0x405c, 0x0005, 0x8a50,
- 0x8739, 0x2704, 0xa004, 0x1168, 0x6000, 0xa064, 0x1108, 0x2d60,
- 0x6004, 0xa084, 0x000f, 0xa080, 0x402d, 0x203c, 0x87fb, 0x090c,
- 0x2575, 0x0005, 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004,
- 0x2090, 0x00de, 0x6884, 0x2060, 0x6888, 0x6b8c, 0x6c90, 0x8057,
- 0xaad4, 0x00ff, 0xa084, 0x00ff, 0x0006, 0x6804, 0xa084, 0x0008,
- 0x000e, 0x0118, 0xa0b8, 0x4017, 0x0010, 0xa0b8, 0x400f, 0xb284,
- 0x0200, 0x0110, 0x7e20, 0x0008, 0x7e24, 0xa6b5, 0x000c, 0x681c,
- 0xd0b4, 0x0108, 0xc685, 0x2400, 0xa305, 0x0550, 0x2c58, 0x2704,
- 0x6104, 0xac60, 0x6000, 0xa400, 0x2048, 0xa9cc, 0x0004, 0x0118,
- 0x080c, 0x43a3, 0x0400, 0x701a, 0x6004, 0xa301, 0x701e, 0xd19c,
- 0x0140, 0x6010, 0xa081, 0x0000, 0x7022, 0x6014, 0xa081, 0x0000,
- 0x7026, 0x6208, 0x2400, 0xa202, 0x7012, 0x620c, 0x2300, 0xa203,
- 0x7016, 0x7602, 0x7007, 0x0001, 0x2b60, 0x080c, 0x42c5, 0x0010,
- 0x080c, 0x429a, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x00d6,
- 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de, 0x7007, 0x0004,
- 0x7004, 0xd094, 0x1de8, 0x7003, 0x0008, 0x012e, 0x2000, 0x0005,
- 0x0126, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x00de,
- 0x7e20, 0xb284, 0x0200, 0x1108, 0x7e24, 0xa6b5, 0x000c, 0x681c,
- 0xd0ac, 0x1118, 0xc685, 0x7003, 0x0000, 0x6828, 0x2050, 0x2d60,
- 0x6004, 0xa0bc, 0x000f, 0xa7b8, 0x401d, 0x273c, 0x87fb, 0x1138,
- 0x0210, 0x080c, 0x2575, 0x689c, 0xa065, 0x0120, 0x0c88, 0x080c,
- 0x429a, 0x1de8, 0x012e, 0x2000, 0x0005, 0x0126, 0x0006, 0x0016,
- 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090, 0x7e20, 0xb284,
- 0x0200, 0x1108, 0x7e24, 0x00de, 0x003e, 0x004e, 0xa6b5, 0x000c,
- 0x681c, 0xd0b4, 0x0128, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004,
- 0x2049, 0x4235, 0x6828, 0xa055, 0x00d6, 0x0904, 0x4296, 0x2d70,
- 0x2e60, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x401d, 0x273c, 0x87fb,
- 0x1140, 0x0210, 0x080c, 0x2575, 0x709c, 0xa075, 0x2060, 0x0570,
- 0x0c80, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c, 0xa31b, 0x0268,
- 0x8a51, 0x1110, 0x080c, 0x2575, 0x8738, 0x2704, 0xa005, 0x1d90,
- 0x709c, 0xa075, 0x2060, 0x01d0, 0x08e0, 0x8422, 0x8420, 0x831a,
- 0xa399, 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b,
- 0x1210, 0x080c, 0x2575, 0xb284, 0x0200, 0x0118, 0x2071, 0x0050,
- 0x0010, 0x2071, 0x0020, 0x00de, 0x0804, 0x41c3, 0x00de, 0x012e,
- 0x2000, 0x0005, 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e, 0x0110,
- 0xa006, 0x0005, 0xa084, 0x0003, 0xa086, 0x0003, 0x1108, 0x0005,
- 0x2704, 0xac78, 0x7800, 0x2f08, 0xd094, 0x1904, 0x43a6, 0x701a,
- 0x7804, 0x701e, 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xd09c,
- 0x0120, 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084,
- 0x0010, 0xc085, 0x7006, 0x2079, 0x4700, 0x8a51, 0x01e8, 0x8738,
- 0x2704, 0xa005, 0x1168, 0x609c, 0xa005, 0x01b8, 0x2060, 0x6004,
- 0xa084, 0x000f, 0xa080, 0x401d, 0x203c, 0x87fb, 0x090c, 0x2575,
- 0x7008, 0x0006, 0xa084, 0x01e0, 0x000e, 0x0110, 0xa006, 0x0028,
- 0xa084, 0x0003, 0xa086, 0x0003, 0x0005, 0x2051, 0x0000, 0x0005,
- 0x0126, 0x0006, 0x00d6, 0x70d0, 0xa084, 0x4c00, 0x8004, 0x2090,
- 0x00de, 0x008e, 0x7108, 0xa184, 0x0003, 0x1128, 0x6828, 0xa005,
- 0x0178, 0x0804, 0x3f6d, 0x7108, 0xd1fc, 0x0118, 0x080c, 0x40d6,
- 0x0c88, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0de8, 0x080c, 0x40d6,
- 0x7008, 0xa086, 0x0008, 0x1d30, 0x7000, 0xa005, 0x1d18, 0x7003,
- 0x0000, 0x2049, 0x0000, 0x0006, 0x2001, 0x4701, 0x2004, 0xd0cc,
- 0x0110, 0x080c, 0x435b, 0x000e, 0x012e, 0x2000, 0x0005, 0x0126,
- 0x0146, 0x0136, 0x0156, 0x00c6, 0x00d6, 0x70d0, 0xa084, 0x4c00,
- 0x8004, 0x2090, 0x00de, 0x2049, 0x431f, 0xad80, 0x0011, 0x20a0,
- 0xb284, 0x0200, 0x0118, 0x2099, 0x0032, 0x0010, 0x2099, 0x0031,
- 0x700c, 0xa084, 0x07ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002,
- 0x7003, 0x0001, 0x0118, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084,
- 0x07ff, 0x0130, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x1de0,
- 0x00ce, 0x2049, 0x0000, 0x7003, 0x0000, 0x015e, 0x013e, 0x014e,
- 0x012e, 0x2000, 0x0005, 0x6814, 0xd0fc, 0x0904, 0x439e, 0x7000,
- 0xd084, 0x05e0, 0x7e24, 0xa6b5, 0x0004, 0x7007, 0x0004, 0x7004,
- 0xa084, 0x0004, 0x1de0, 0x7118, 0x0016, 0x711c, 0x0016, 0x7120,
- 0x0016, 0x7124, 0x0016, 0x701b, 0x0000, 0x701f, 0x3fff, 0x7023,
- 0x0000, 0x7027, 0x0000, 0x7013, 0x0004, 0x7017, 0x0000, 0x7602,
- 0x7007, 0x0001, 0x2001, 0xffff, 0x2009, 0x0031, 0x200a, 0x200a,
- 0x7108, 0x7008, 0xa106, 0x1de0, 0xd1fc, 0x0dd0, 0x002e, 0x7226,
- 0x002e, 0x7222, 0x002e, 0x721e, 0x002e, 0x721a, 0x7007, 0x0002,
- 0x7008, 0xa086, 0x0008, 0x0110, 0x0804, 0x410e, 0x7007, 0x0004,
- 0x7003, 0x0000, 0x0005, 0x2049, 0x41c3, 0x0068, 0x7008, 0xa084,
- 0x0003, 0x0110, 0xa006, 0x0005, 0xa006, 0x2020, 0x2018, 0x2c58,
- 0x2160, 0x2049, 0x0000, 0x8b58, 0x6100, 0x2100, 0xa408, 0x711a,
- 0x6004, 0xa301, 0x701e, 0x0006, 0x2b04, 0xa084, 0x0008, 0x0150,
- 0x6010, 0xa081, 0x0000, 0x7022, 0x0006, 0x6014, 0xa081, 0x0000,
- 0x7026, 0x0006, 0xa184, 0x0007, 0x2011, 0x0008, 0xa22a, 0x6208,
- 0x2400, 0xa212, 0x0026, 0x620c, 0x2240, 0x2300, 0xa843, 0x002e,
- 0x88ff, 0x1170, 0x2500, 0xa202, 0x0108, 0x1250, 0x2220, 0x2041,
- 0x0000, 0x2b04, 0xd09c, 0x0110, 0x000e, 0x000e, 0x000e, 0x0450,
- 0x7512, 0x7017, 0x0000, 0x7602, 0xa986, 0x41c3, 0x1118, 0x7007,
- 0x0001, 0x0028, 0x7004, 0xa084, 0x0010, 0xc085, 0x7006, 0x2500,
- 0xa100, 0x701a, 0x2b04, 0xa084, 0x0008, 0x0110, 0x000e, 0x004e,
- 0x001e, 0xa189, 0x0000, 0x711e, 0x2b0c, 0xa18c, 0x0008, 0x0130,
- 0xa4a1, 0x0000, 0x7422, 0xa081, 0x0000, 0x7026, 0x2500, 0xa222,
- 0xa8c3, 0x0000, 0x7412, 0x2820, 0x7416, 0x7602, 0xa986, 0x41c3,
- 0x1118, 0x7007, 0x0001, 0x0028, 0x7004, 0xa084, 0x0010, 0xc085,
- 0x7006, 0x8b59, 0x2b60, 0x2079, 0x4700, 0x080c, 0x42c5, 0xa006,
- 0x0005, 0x2091, 0x8000, 0x2091, 0x6000, 0x78ac, 0xa005, 0x1168,
- 0x7974, 0x70d0, 0xa106, 0x1148, 0x781c, 0xa005, 0x0130, 0x781f,
- 0x0000, 0x0e04, 0x443d, 0x2091, 0x4080, 0x2069, 0x4780, 0xc7fd,
- 0x6800, 0xa084, 0x000f, 0x1198, 0x68d0, 0xd0b4, 0x0180, 0xd0bc,
- 0x1170, 0x00f6, 0x2079, 0x0100, 0xd7fc, 0x1110, 0x2079, 0x0200,
- 0x7830, 0xa084, 0x00c0, 0x1110, 0x080c, 0x22d5, 0x00fe, 0xd7fc,
- 0x0120, 0x2069, 0x4740, 0xc7fc, 0x0c18, 0x7830, 0x8001, 0x7832,
- 0x1904, 0x44c7, 0x7834, 0x7832, 0x2061, 0x6cc0, 0x2069, 0x4780,
- 0xc7fd, 0x68cc, 0xa005, 0x0128, 0x8001, 0x68ce, 0x1110, 0x080c,
- 0x4639, 0x6800, 0xa084, 0x000f, 0x0168, 0xa086, 0x0001, 0x0150,
- 0x6840, 0xa00d, 0x0138, 0x2104, 0xa005, 0x0120, 0x8001, 0x200a,
- 0x0904, 0x45d6, 0x6814, 0xa005, 0x01a8, 0x8001, 0x6816, 0x1190,
- 0x68a3, 0x0001, 0x00f6, 0xd7fc, 0x1118, 0x2079, 0x0200, 0x0010,
- 0x2079, 0x0100, 0x080c, 0x3c6e, 0x00fe, 0x6860, 0xa005, 0x0110,
- 0x080c, 0x22d5, 0x687c, 0xa005, 0x0140, 0x8001, 0x687e, 0x1128,
- 0x6863, 0x0000, 0x68d0, 0xc0c5, 0x68d2, 0x68d0, 0xd0fc, 0x01b0,
- 0xc0fc, 0x68d2, 0x20a9, 0x0200, 0x6034, 0xa005, 0x0158, 0x8001,
- 0x6036, 0x68d0, 0xc0fd, 0x68d2, 0x1128, 0x6010, 0xa005, 0x0110,
- 0x080c, 0x22d5, 0xace0, 0x0010, 0x1f04, 0x44ac, 0xd7fc, 0x0138,
- 0x2061, 0x4cc0, 0x2069, 0x4740, 0xc7fc, 0x0804, 0x4469, 0x0459,
- 0x7838, 0x8001, 0x783a, 0x11a0, 0x783c, 0x783a, 0x2061, 0x4cc0,
- 0x2069, 0x4740, 0xc7fc, 0x680c, 0xa005, 0x0110, 0x080c, 0x4543,
- 0xd7fc, 0x1130, 0x2061, 0x6cc0, 0x2069, 0x4780, 0xc7fd, 0x0c98,
- 0x7810, 0xd0cc, 0x0168, 0xd0ac, 0x1120, 0xd0a4, 0x0148, 0xc0ad,
- 0x7812, 0x2091, 0x8001, 0x0e04, 0x44ef, 0x080c, 0x20a1, 0x0005,
- 0x2091, 0x8001, 0x0005, 0x7840, 0x8001, 0x7842, 0x1904, 0x4542,
- 0x7844, 0x7842, 0x2069, 0x4740, 0xc7fc, 0x2079, 0x0200, 0x68d4,
- 0xa005, 0x0138, 0x7de0, 0xa504, 0x1120, 0x68d6, 0x68d0, 0xc0bc,
- 0x68d2, 0x2079, 0x4700, 0x6810, 0xa005, 0x1110, 0x2001, 0x0101,
- 0x8001, 0x6812, 0xd7fc, 0x0118, 0xa080, 0x8dd0, 0x0010, 0xa080,
- 0x8cc0, 0x2040, 0x2004, 0xa065, 0x01e0, 0x6024, 0xa005, 0x01b0,
- 0x8001, 0x6026, 0x1198, 0x6800, 0xa005, 0x0130, 0x6848, 0xac06,
- 0x1118, 0x080c, 0x45d6, 0x0068, 0x6860, 0xa005, 0x0118, 0x6027,
- 0x0001, 0x0020, 0x080c, 0x4584, 0x2804, 0x0c28, 0x6000, 0x2c40,
- 0x0c10, 0xd7fc, 0x1138, 0x2069, 0x4780, 0xc7fd, 0x2079, 0x0100,
- 0x0804, 0x44ff, 0x0005, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008,
- 0xd09c, 0x0558, 0x6024, 0xa005, 0x0118, 0x8001, 0x6026, 0x0418,
- 0x6008, 0xc09c, 0xd084, 0x1110, 0xd0ac, 0x01c0, 0x600a, 0x6004,
- 0xa005, 0x01d8, 0x00d6, 0x00c6, 0x0016, 0x2068, 0x6010, 0x8001,
- 0x6012, 0x080c, 0x37c7, 0x2d00, 0x2c68, 0x2060, 0x080c, 0x1c02,
- 0x080c, 0x1db2, 0x001e, 0x00ce, 0x00de, 0x0038, 0xc0bd, 0x600a,
- 0xa18d, 0x0001, 0x0010, 0xa18d, 0x0100, 0xace0, 0x0010, 0x1f04,
- 0x4547, 0xa184, 0x0001, 0x0130, 0xa18c, 0xfffe, 0x690e, 0x080c,
- 0x22d5, 0x0008, 0x690e, 0x0005, 0x2c00, 0x687a, 0x6714, 0x6f72,
- 0x6017, 0x0000, 0x602b, 0x0000, 0x601b, 0x0006, 0x60b4, 0xa084,
- 0x5f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022,
- 0x6000, 0x2042, 0x2069, 0x4780, 0xd7fc, 0x1110, 0x2069, 0x4740,
- 0x6858, 0xac06, 0x1110, 0x2800, 0x685a, 0x080c, 0x1b9a, 0x6818,
- 0xa005, 0x0110, 0x8001, 0x681a, 0x6808, 0xc0a4, 0x680a, 0x6810,
- 0x7908, 0x8109, 0x790a, 0x8001, 0x1310, 0x080c, 0x2575, 0x6812,
- 0x1118, 0x7910, 0xc1a5, 0x7912, 0x602f, 0x0000, 0x6033, 0x0000,
- 0x2c68, 0x080c, 0x1dbf, 0xd7fc, 0x1118, 0x2069, 0x4740, 0x0010,
- 0x2069, 0x4780, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x1118,
- 0x6976, 0x2001, 0x0004, 0x080c, 0x22cb, 0x0005, 0x00d6, 0x6948,
- 0x2160, 0xd7fc, 0x1118, 0x2069, 0x0200, 0x0010, 0x2069, 0x0100,
- 0x080c, 0x2490, 0x601b, 0x0006, 0x6858, 0xa084, 0x5f00, 0x601e,
- 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022, 0x602f, 0x0000,
- 0x6033, 0x0000, 0x6808, 0xa084, 0xfffd, 0x680a, 0x6830, 0xd0b4,
- 0x01b0, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848, 0xd094, 0x0110,
- 0x1f04, 0x45fd, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084,
- 0x0110, 0x1f04, 0x4606, 0x20a9, 0x00fa, 0x1f04, 0x460d, 0x681b,
- 0x0054, 0x00de, 0x6863, 0x0007, 0x0005, 0x2079, 0x4700, 0x00e1,
- 0x0089, 0x00a9, 0x2009, 0x0002, 0x2069, 0x4780, 0x680f, 0x0000,
- 0x6813, 0x0000, 0x6817, 0x0000, 0x8109, 0x0118, 0x2069, 0x4740,
- 0x0ca8, 0x0005, 0x2019, 0x00a3, 0x7b3a, 0x7b3e, 0x0005, 0x2019,
- 0x0033, 0x7b42, 0x7b46, 0x0005, 0x2019, 0x32dd, 0x7b32, 0x7b36,
- 0x0005, 0x6a4c, 0xa285, 0x0000, 0x01f0, 0x6950, 0x6bbc, 0xa300,
- 0x00c6, 0x2164, 0x6304, 0x83ff, 0x1138, 0x8211, 0x0148, 0x8108,
- 0xa11a, 0x0eb8, 0x69bc, 0x0ca8, 0x68cf, 0x000a, 0x00ce, 0x0005,
- 0x694c, 0x6abc, 0x2264, 0x6008, 0xc0b5, 0x600a, 0x8210, 0x8109,
- 0x1dc8, 0x694e, 0x00ce, 0x0005, 0x0016, 0x1d04, 0x465d, 0x2091,
- 0x6000, 0x1d04, 0x4661, 0x2091, 0x6000, 0x70ec, 0xd0dc, 0x1118,
- 0xd0d4, 0x0190, 0x00a0, 0xae8e, 0x0100, 0x0138, 0x7814, 0xc0f5,
- 0xc0c5, 0x7816, 0xd0d4, 0x1580, 0x0460, 0x7814, 0xc0fd, 0xc0c5,
- 0x7816, 0xd0d4, 0x1548, 0x0428, 0xd0e4, 0x0904, 0x46c4, 0x1d04,
- 0x467f, 0x2091, 0x6000, 0x2009, 0x000c, 0x1d04, 0x4685, 0x2091,
- 0x6000, 0x8109, 0x1dd0, 0x70e4, 0xa084, 0x01ff, 0xa086, 0x01ff,
- 0x1110, 0x70ec, 0x08c0, 0xae8e, 0x0100, 0x0128, 0x7814, 0xc0f4,
- 0xd0fc, 0x1130, 0x0020, 0x7814, 0xc0fc, 0xd0f4, 0x1108, 0xc0c4,
- 0x7816, 0x7804, 0xd08c, 0x0500, 0x00c6, 0x2061, 0x0000, 0x6018,
- 0xd084, 0x11b8, 0xae86, 0x0200, 0x00e6, 0x2071, 0x0010, 0x0120,
- 0x70db, 0x0001, 0x78e4, 0x0018, 0x70db, 0x0000, 0x78e0, 0x70c6,
- 0x70c3, 0x800e, 0x601b, 0x0001, 0x2091, 0x4080, 0x00ee, 0x00ce,
- 0x0018, 0x00ce, 0x681f, 0x000c, 0x001e, 0x70a0, 0x70a2, 0x0005,
- 0x0c26
-};
-#ifdef UNIQUE_FW_NAME
-static unsigned short fw12160i_length01 = 0x36c9;
-#else
-static unsigned short risc_code_length01 = 0x36c9;
-#endif
-
diff --git a/drivers/scsi/ql1280_fw.h b/drivers/scsi/ql1280_fw.h
deleted file mode 100644
index 784f2a04bf2..00000000000
--- a/drivers/scsi/ql1280_fw.h
+++ /dev/null
@@ -1,2048 +0,0 @@
-/*****************************************************************************
- * QLOGIC LINUX SOFTWARE
- *
- * QLogic ISP1280/ device driver for Linux 2.2.x and 2.4.x
- * Copyright (C) 2001 Qlogic Corporation (www.qlogic.com)
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- *****************************************************************************/
-
-/************************************************************************
- * --- ISP1240/1080/1280 Initiator Firmware --- *
- * 32 LUN Support *
- ************************************************************************/
-
-
-/*
- * Firmware Version 8.15.11 (10:20 Jan 02, 2002)
- */
-
-#ifdef UNIQUE_FW_NAME
-static unsigned char fw1280ei_version_str[] = {8,15,11};
-#else
-static unsigned char firmware_version[] = {8,15,11};
-#endif
-
-#ifdef UNIQUE_FW_NAME
-#define fw1280ei_VERSION_STRING "8.15.11"
-#else
-#define FW_VERSION_STRING "8.15.11"
-#endif
-
-#ifdef UNIQUE_FW_NAME
-static unsigned short fw1280ei_addr01 = 0x1000 ;
-#else
-static unsigned short risc_code_addr01 = 0x1000 ;
-#endif
-
-#ifdef UNIQUE_FW_NAME
-static unsigned short fw1280ei_code01[] = {
-#else
-static unsigned short risc_code01[] = {
-#endif
- 0x0078, 0x1041, 0x0000, 0x3e2e, 0x0000, 0x2043, 0x4f50, 0x5952,
- 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932, 0x2c31,
- 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749, 0x4320,
- 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049, 0x5350,
- 0x3132, 0x3430, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520, 0x2056,
- 0x6572, 0x7369, 0x6f6e, 0x2030, 0x382e, 0x3135, 0x2020, 0x2043,
- 0x7573, 0x746f, 0x6d65, 0x7220, 0x4e6f, 0x2e20, 0x3030, 0x2050,
- 0x726f, 0x6475, 0x6374, 0x204e, 0x6f2e, 0x2020, 0x3030, 0x2020,
- 0x2400, 0x20c9, 0x98ff, 0x2001, 0x04fc, 0x2004, 0xa086, 0x1080,
- 0x00c0, 0x1054, 0x2071, 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010,
- 0x2089, 0x1374, 0x0078, 0x106d, 0x2001, 0x04fc, 0x2004, 0xa086,
- 0x1280, 0x00c0, 0x1069, 0x2071, 0x0200, 0x70a0, 0x70a2, 0x2071,
- 0x0100, 0x70a0, 0x70a2, 0x20c1, 0x0010, 0x2089, 0x13f8, 0x0078,
- 0x106d, 0x20c1, 0x0020, 0x2089, 0x131c, 0x2071, 0x0010, 0x70c3,
- 0x0004, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3,
- 0x0008, 0x2001, 0x04fe, 0x70d6, 0x20c1, 0x0021, 0x2019, 0x0000,
- 0x2009, 0xfeff, 0x2100, 0x200b, 0xa5a5, 0xa1ec, 0x7fff, 0x2d64,
- 0x206b, 0x0a0a, 0xaddc, 0x3fff, 0x2b54, 0x205b, 0x5050, 0x2114,
- 0xa286, 0xa5a5, 0x0040, 0x10a4, 0xa386, 0x000f, 0x0040, 0x10a0,
- 0x2c6a, 0x2a5a, 0x20c1, 0x0020, 0x2019, 0x000f, 0x0078, 0x1080,
- 0x2c6a, 0x2a5a, 0x0078, 0x10a2, 0x2c6a, 0x2a5a, 0x2130, 0x2128,
- 0xa1a2, 0x4f00, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424, 0x8424,
- 0xa192, 0x9900, 0x2009, 0x0000, 0x2001, 0x0032, 0x1078, 0x20c1,
- 0x2218, 0x2079, 0x4f00, 0x2fa0, 0x2408, 0x2011, 0x0000, 0x20a9,
- 0x0040, 0x42a4, 0x8109, 0x00c0, 0x10bf, 0x2009, 0xff00, 0x3400,
- 0xa102, 0x0048, 0x10cf, 0x0040, 0x10cf, 0x20a8, 0x42a4, 0x2001,
- 0x04fc, 0x2004, 0xa086, 0x1080, 0x00c0, 0x10e5, 0x2071, 0x0100,
- 0x0d7e, 0x2069, 0x4f40, 0x1078, 0x4db0, 0x0d7f, 0x7810, 0xc0ed,
- 0x7812, 0x781b, 0x0064, 0x0078, 0x110a, 0x2001, 0x04fc, 0x2004,
- 0xa086, 0x1280, 0x00c0, 0x1105, 0x7814, 0xc0ed, 0xc0d5, 0x7816,
- 0x781b, 0x0064, 0x2071, 0x0200, 0x0d7e, 0x2069, 0x4f40, 0x1078,
- 0x4db0, 0x2069, 0x4f80, 0x2071, 0x0100, 0x1078, 0x4db0, 0x7814,
- 0xc0d4, 0x7816, 0x0d7f, 0x0078, 0x110a, 0x7814, 0xc0e5, 0x7816,
- 0x781b, 0x003c, 0x7eca, 0x7cc2, 0x7bc6, 0x7867, 0x0000, 0x7800,
- 0xc08d, 0x7802, 0x2031, 0x0030, 0x78af, 0x0101, 0x7823, 0x0002,
- 0x7827, 0x0002, 0x2009, 0x0002, 0x2069, 0x4f40, 0x681b, 0x0003,
- 0x6823, 0x0007, 0x6827, 0x00fa, 0x682b, 0x0008, 0x682f, 0x0028,
- 0x6837, 0x0000, 0x683b, 0x0006, 0x6833, 0x0008, 0x683f, 0x0000,
- 0x8109, 0x0040, 0x115e, 0x68d3, 0x000a, 0x68c3, 0x4fc0, 0x2079,
- 0x4f00, 0x7814, 0xd0e4, 0x00c0, 0x1144, 0xd0ec, 0x00c0, 0x1148,
- 0x68d7, 0x7329, 0x0078, 0x114a, 0x68d7, 0x730d, 0x0078, 0x114a,
- 0x68d7, 0x732d, 0x68c7, 0x54c0, 0x68cb, 0x53c0, 0x68cf, 0x94c0,
- 0x68ab, 0x9744, 0x68af, 0x9749, 0x68b3, 0x9744, 0x68b7, 0x9744,
- 0x68a7, 0x0001, 0x2069, 0x4f80, 0x0078, 0x111e, 0x68d3, 0x000a,
- 0x68c3, 0x51c0, 0x7814, 0xd0e4, 0x00c0, 0x116a, 0x68d7, 0x7439,
- 0x0078, 0x116c, 0x68d7, 0x7419, 0x68c7, 0x74c0, 0x68cb, 0x5440,
- 0x68cf, 0x95d0, 0x68ab, 0x9749, 0x68af, 0x974e, 0x68b3, 0x9749,
- 0x68b7, 0x9749, 0x68a7, 0x0001, 0x7810, 0xd0ec, 0x00c0, 0x11c2,
- 0x7814, 0xd0e4, 0x00c0, 0x11b4, 0x0e7e, 0x2069, 0x53c0, 0x2071,
- 0x0200, 0x70ec, 0xd0e4, 0x00c0, 0x1195, 0x2019, 0x0c0c, 0x2021,
- 0x000c, 0x1078, 0x2050, 0x0078, 0x119b, 0x2019, 0x0c0a, 0x2021,
- 0x000a, 0x1078, 0x2050, 0x2069, 0x5440, 0x2071, 0x0100, 0x70ec,
- 0xd0e4, 0x00c0, 0x11ab, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
- 0x2050, 0x0078, 0x11b1, 0x2019, 0x0c0a, 0x2021, 0x000a, 0x1078,
- 0x2050, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0c, 0x2021, 0x000c,
- 0x2069, 0x53c0, 0x1078, 0x2050, 0x2069, 0x5440, 0x1078, 0x2050,
- 0x0078, 0x11db, 0x2069, 0x53c0, 0x0e7e, 0x2071, 0x0100, 0x70ec,
- 0xd0e4, 0x00c0, 0x11d4, 0x2019, 0x0c0c, 0x2021, 0x000c, 0x1078,
- 0x2050, 0x0e7f, 0x0078, 0x11db, 0x2019, 0x0c0a, 0x2021, 0x000a,
- 0x1078, 0x2050, 0x0e7f, 0x2011, 0x0002, 0x2069, 0x54c0, 0x2009,
- 0x0002, 0x20a9, 0x0100, 0x6837, 0x0000, 0x680b, 0x0040, 0x7bc8,
- 0xa386, 0xfeff, 0x00c0, 0x11f2, 0x6817, 0x0100, 0x681f, 0x0064,
- 0x0078, 0x11f6, 0x6817, 0x0064, 0x681f, 0x0002, 0xade8, 0x0010,
- 0x00f0, 0x11e3, 0x8109, 0x00c0, 0x11e1, 0x8211, 0x0040, 0x1204,
- 0x2069, 0x74c0, 0x0078, 0x11df, 0x1078, 0x26a2, 0x1078, 0x4712,
- 0x1078, 0x1e1b, 0x1078, 0x4d42, 0x2091, 0x2100, 0x2079, 0x4f00,
- 0x7810, 0xd0ec, 0x0040, 0x1218, 0x2071, 0x0020, 0x0078, 0x121a,
- 0x2071, 0x0050, 0x2091, 0x2200, 0x2079, 0x4f00, 0x2071, 0x0020,
- 0x2091, 0x2300, 0x2079, 0x4f00, 0x7810, 0xd0ec, 0x0040, 0x122c,
- 0x2079, 0x0100, 0x0078, 0x122e, 0x2079, 0x0200, 0x2071, 0x4f40,
- 0x2091, 0x2400, 0x2079, 0x0100, 0x2071, 0x4f80, 0x2091, 0x2000,
- 0x2079, 0x4f00, 0x2071, 0x0010, 0x3200, 0xa085, 0x303d, 0x2090,
- 0x2071, 0x0010, 0x70c3, 0x0000, 0x0090, 0x124d, 0x70c0, 0xa086,
- 0x0002, 0x00c0, 0x124d, 0x1078, 0x15c1, 0x2039, 0x0000, 0x7810,
- 0xd0ec, 0x00c0, 0x12cf, 0x1078, 0x148e, 0x78ac, 0xa005, 0x00c0,
- 0x126b, 0x0068, 0x1261, 0x786c, 0xa065, 0x0040, 0x1261, 0x1078,
- 0x23dc, 0x1078, 0x20e8, 0x0068, 0x1278, 0x786c, 0xa065, 0x0040,
- 0x126b, 0x1078, 0x23dc, 0x0068, 0x1278, 0x2009, 0x4f47, 0x2011,
- 0x4f87, 0x2104, 0x220c, 0xa105, 0x0040, 0x1278, 0x1078, 0x1f51,
- 0x2071, 0x4f40, 0x70a4, 0xa005, 0x0040, 0x129d, 0x7450, 0xa485,
- 0x0000, 0x0040, 0x129d, 0x2079, 0x0200, 0x2091, 0x8000, 0x72d4,
- 0xa28c, 0x303d, 0x2190, 0x1078, 0x2bb1, 0x2091, 0x8000, 0x2091,
- 0x303d, 0x0068, 0x129d, 0x2079, 0x4f00, 0x786c, 0xa065, 0x0040,
- 0x129d, 0x2071, 0x0010, 0x1078, 0x23dc, 0x00e0, 0x12a5, 0x2079,
- 0x4f00, 0x2071, 0x0010, 0x1078, 0x4b16, 0x2071, 0x4f80, 0x70a4,
- 0xa005, 0x0040, 0x12bd, 0x7050, 0xa025, 0x0040, 0x12bd, 0x2079,
- 0x0100, 0x2091, 0x8000, 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078,
- 0x2bb1, 0x2091, 0x8000, 0x2091, 0x303d, 0x2079, 0x4f00, 0x2071,
- 0x0010, 0x0068, 0x12c9, 0x786c, 0xa065, 0x0040, 0x12c9, 0x1078,
- 0x23dc, 0x00e0, 0x1253, 0x1078, 0x4b16, 0x0078, 0x1253, 0x1078,
- 0x148e, 0x78ac, 0xa005, 0x00c0, 0x12e7, 0x0068, 0x12dd, 0x786c,
- 0xa065, 0x0040, 0x12dd, 0x1078, 0x23dc, 0x1078, 0x20e8, 0x0068,
- 0x12f1, 0x786c, 0xa065, 0x0040, 0x12e7, 0x1078, 0x23dc, 0x0068,
- 0x12f1, 0x2009, 0x4f47, 0x2104, 0xa005, 0x0040, 0x12f1, 0x1078,
- 0x1f51, 0x2071, 0x4f40, 0x70a4, 0xa005, 0x0040, 0x130c, 0x7450,
- 0xa485, 0x0000, 0x0040, 0x130c, 0x2079, 0x0100, 0x2091, 0x8000,
- 0x72d4, 0xa28c, 0x303d, 0x2190, 0x1078, 0x2bb1, 0x2091, 0x8000,
- 0x2091, 0x303d, 0x2079, 0x4f00, 0x2071, 0x0010, 0x0068, 0x1316,
- 0x786c, 0xa065, 0x0040, 0x1316, 0x1078, 0x23dc, 0x00e0, 0x12cf,
- 0x1078, 0x4b16, 0x0078, 0x12cf, 0x133c, 0x133c, 0x133e, 0x133e,
- 0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363,
- 0x134b, 0x134b, 0x134b, 0x134b, 0x133c, 0x133c, 0x133e, 0x133e,
- 0x134b, 0x134b, 0x134b, 0x134b, 0x1356, 0x1356, 0x1363, 0x1363,
- 0x134b, 0x134b, 0x134b, 0x134b, 0x0078, 0x133c, 0x007e, 0x107e,
- 0x127e, 0x2091, 0x2400, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
- 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13c8,
- 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e, 0x107e,
- 0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
- 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300,
- 0x1078, 0x29d1, 0x2091, 0x2400, 0x1078, 0x29d1, 0x127f, 0x107f,
- 0x007f, 0x2091, 0x8001, 0x007c, 0x1394, 0x1394, 0x1396, 0x1396,
- 0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13ae, 0x13ae, 0x1396, 0x1396,
- 0x13a3, 0x13a3, 0x13a3, 0x13a3, 0x13af, 0x13af, 0x13af, 0x13af,
- 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af, 0x13af,
- 0x13af, 0x13af, 0x13af, 0x13af, 0x0078, 0x1394, 0x007e, 0x107e,
- 0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f,
- 0x2091, 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x1078, 0x13d5,
- 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007c, 0x107e,
- 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x007e, 0x2071, 0x0100, 0x2069,
- 0x4f40, 0x2079, 0x4f00, 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078,
- 0x4db0, 0x007f, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f, 0x107f, 0x007c,
- 0x3c00, 0xa084, 0x0007, 0x0079, 0x13cd, 0x13de, 0x13de, 0x13e0,
- 0x13e0, 0x13e5, 0x13e5, 0x13ea, 0x13ea, 0x3c00, 0xa084, 0x0003,
- 0x0079, 0x13da, 0x13de, 0x13de, 0x13f3, 0x13f3, 0x1078, 0x29b2,
- 0x2091, 0x2200, 0x1078, 0x47ec, 0x007c, 0x2091, 0x2100, 0x1078,
- 0x47ec, 0x007c, 0x2091, 0x2100, 0x1078, 0x47ec, 0x2091, 0x2200,
- 0x1078, 0x47ec, 0x007c, 0x2091, 0x2100, 0x1078, 0x47ec, 0x007c,
- 0x1418, 0x1418, 0x141a, 0x141a, 0x1427, 0x1427, 0x1427, 0x1427,
- 0x1432, 0x1432, 0x143f, 0x143f, 0x1427, 0x1427, 0x1427, 0x1427,
- 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450,
- 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450, 0x1450,
- 0x0078, 0x1418, 0x007e, 0x107e, 0x127e, 0x2091, 0x2400, 0x1078,
- 0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
- 0x107e, 0x127e, 0x1078, 0x13c8, 0x127f, 0x107f, 0x007f, 0x2091,
- 0x8001, 0x007c, 0x007e, 0x107e, 0x127e, 0x2091, 0x2300, 0x1078,
- 0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c, 0x007e,
- 0x107e, 0x127e, 0x2091, 0x2300, 0x1078, 0x29d1, 0x2091, 0x2400,
- 0x1078, 0x29d1, 0x127f, 0x107f, 0x007f, 0x2091, 0x8001, 0x007c,
- 0x007e, 0x107e, 0x127e, 0x0d7e, 0x0e7e, 0x0f7e, 0x2079, 0x4f00,
- 0x2071, 0x0200, 0x2069, 0x4f40, 0x3d00, 0xd08c, 0x0040, 0x1466,
- 0x70ec, 0xa084, 0x1c00, 0x78e2, 0x1078, 0x4db0, 0x3d00, 0xd084,
- 0x0040, 0x1474, 0x2069, 0x4f80, 0x2071, 0x0100, 0x70ec, 0xa084,
- 0x1c00, 0x78e6, 0x1078, 0x4db0, 0x0f7f, 0x0e7f, 0x0d7f, 0x127f,
- 0x107f, 0x007f, 0x007c, 0x7008, 0x800b, 0x00c8, 0x1489, 0x7007,
- 0x0002, 0xa08c, 0x01e0, 0x00c0, 0x148a, 0xd09c, 0x0040, 0x1489,
- 0x087a, 0x097a, 0x70c3, 0x4002, 0x0078, 0x15c4, 0x0068, 0x151a,
- 0x2061, 0x0000, 0x6018, 0xd084, 0x00c0, 0x151a, 0x7828, 0xa005,
- 0x00c0, 0x149e, 0x0010, 0x151b, 0x0078, 0x151a, 0x7910, 0xd1f4,
- 0x0040, 0x14a4, 0x0078, 0x14b9, 0x7914, 0xd1ec, 0x0040, 0x14bd,
- 0xd0fc, 0x0040, 0x14b3, 0x007e, 0x1078, 0x1dae, 0x007f, 0x0040,
- 0x14bd, 0x0078, 0x14b9, 0x007e, 0x1078, 0x1da1, 0x007f, 0x0040,
- 0x14bd, 0x2001, 0x4007, 0x0078, 0x15c3, 0x7910, 0xd0fc, 0x00c0,
- 0x14c7, 0x2061, 0x4f40, 0xc19c, 0xc7fc, 0x0078, 0x14cb, 0x2061,
- 0x4f80, 0xc19d, 0xc7fd, 0x6064, 0xa005, 0x00c0, 0x151a, 0x7912,
- 0x6082, 0x7828, 0xc0fc, 0xa086, 0x0018, 0x00c0, 0x14db, 0x0c7e,
- 0x1078, 0x1b85, 0x0c7f, 0x782b, 0x0000, 0x607c, 0xa065, 0x0040,
- 0x1500, 0x0c7e, 0x609c, 0x1078, 0x1e90, 0x0c7f, 0x609f, 0x0000,
- 0x1078, 0x1cd5, 0x2009, 0x0018, 0x6087, 0x0103, 0x7810, 0x007e,
- 0x84ff, 0x00c0, 0x14f6, 0x85ff, 0x0040, 0x14f8, 0xc0c5, 0x7812,
- 0x1078, 0x1dbb, 0x007f, 0x7812, 0x00c0, 0x1514, 0x1078, 0x1e0d,
- 0x7810, 0xd09c, 0x00c0, 0x1508, 0x2061, 0x4f40, 0x0078, 0x150c,
- 0x2061, 0x4f80, 0xc09c, 0x7812, 0x607f, 0x0000, 0x60d4, 0xd0dc,
- 0x0040, 0x1518, 0xc0dc, 0x60d6, 0x2001, 0x4005, 0x0078, 0x15c3,
- 0x0078, 0x15c1, 0x007c, 0x7810, 0xd0f4, 0x0040, 0x1523, 0x2001,
- 0x4007, 0x0078, 0x15c3, 0xa006, 0x70c2, 0x70c6, 0x70ca, 0x70ce,
- 0x70da, 0x70c0, 0xa03d, 0xa08a, 0x0040, 0x00c8, 0x1531, 0x0079,
- 0x1538, 0x2100, 0xa08a, 0x0040, 0x00c8, 0x15cf, 0x0079, 0x1578,
- 0x15c1, 0x1617, 0x15e0, 0x164f, 0x1687, 0x1687, 0x15d7, 0x1ced,
- 0x1692, 0x15cf, 0x15e4, 0x15e6, 0x15e8, 0x15ea, 0x1cf2, 0x15cf,
- 0x16a0, 0x16fd, 0x1ba5, 0x1ce7, 0x15ec, 0x19ea, 0x1a2c, 0x1a67,
- 0x1ab8, 0x19a5, 0x19b2, 0x19c6, 0x19d9, 0x17eb, 0x15cf, 0x1734,
- 0x1741, 0x174d, 0x1759, 0x176f, 0x177b, 0x177e, 0x178a, 0x1796,
- 0x179e, 0x17d3, 0x17df, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x17f8,
- 0x180a, 0x1826, 0x185c, 0x1884, 0x1894, 0x1897, 0x18c8, 0x18f9,
- 0x190b, 0x1974, 0x1984, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x1994,
- 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x1d17, 0x1d1d, 0x15cf,
- 0x15cf, 0x15cf, 0x1d21, 0x1d66, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
- 0x1611, 0x1681, 0x169a, 0x16f7, 0x1b9f, 0x15cf, 0x15cf, 0x1b68,
- 0x15cf, 0x1d6a, 0x1d09, 0x1d13, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
- 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
- 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
- 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
- 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf, 0x15cf,
- 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x15c3, 0x73ce, 0x72ca,
- 0x71c6, 0x2001, 0x4000, 0x70c2, 0x0068, 0x15c4, 0x2061, 0x0000,
- 0x601b, 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c, 0x70c3,
- 0x4001, 0x0078, 0x15c4, 0x70c3, 0x4006, 0x0078, 0x15c4, 0x2099,
- 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005, 0x53a3, 0x0078, 0x15c1,
- 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078, 0x15c1, 0x0078, 0x15c1,
- 0x0078, 0x15c1, 0x0078, 0x15c1, 0x2091, 0x8000, 0x70c3, 0x0004,
- 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf, 0x2020, 0x70d3, 0x0008,
- 0x2001, 0x000f, 0x70d6, 0x2079, 0x0000, 0x781b, 0x0001, 0x2031,
- 0x0030, 0x2059, 0x1000, 0x2029, 0x041a, 0x2051, 0x0445, 0x2061,
- 0x0447, 0x20c1, 0x0020, 0x2091, 0x5000, 0x2091, 0x4080, 0x0078,
- 0x0418, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x161a, 0x2029,
- 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x20a0, 0x2099,
- 0x0030, 0x7003, 0x0001, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422,
- 0x7526, 0x2021, 0x0040, 0x81ff, 0x0040, 0x15c1, 0xa182, 0x0040,
- 0x00c8, 0x1634, 0x2120, 0xa006, 0x2008, 0x8403, 0x7012, 0x7007,
- 0x0004, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040, 0x163b, 0x7007,
- 0x0002, 0xa084, 0x01e0, 0x0040, 0x1649, 0x70c3, 0x4002, 0x0078,
- 0x15c4, 0x24a8, 0x53a5, 0x0078, 0x162b, 0x0078, 0x15c1, 0x2029,
- 0x0000, 0x2520, 0x71d0, 0x72c8, 0x73cc, 0x70c4, 0x2098, 0x20a1,
- 0x0030, 0x7003, 0x0000, 0x7007, 0x0006, 0x731a, 0x721e, 0x7422,
- 0x7526, 0x2021, 0x0040, 0x7007, 0x0006, 0x81ff, 0x0040, 0x15c1,
- 0xa182, 0x0040, 0x00c8, 0x166e, 0x2120, 0xa006, 0x2008, 0x8403,
- 0x7012, 0x24a8, 0x53a6, 0x7007, 0x0001, 0x7008, 0xd0fc, 0x0040,
- 0x1675, 0xa084, 0x01e0, 0x0040, 0x1663, 0x70c3, 0x4002, 0x0078,
- 0x15c4, 0x75d8, 0x74dc, 0x75da, 0x74de, 0x0078, 0x1652, 0x71c4,
- 0x70c8, 0x2114, 0xa79e, 0x0004, 0x00c0, 0x168f, 0x200a, 0x72ca,
- 0x0078, 0x15c0, 0x70c7, 0x0008, 0x70cb, 0x000f, 0x70cf, 0x000b,
- 0x0078, 0x15c1, 0x75d8, 0x76dc, 0x75da, 0x76de, 0x0078, 0x16a3,
- 0x2029, 0x0000, 0x2530, 0x70c4, 0x72c8, 0x73cc, 0x74d0, 0x70c6,
- 0x72ca, 0x73ce, 0x74d2, 0xa005, 0x0040, 0x16f2, 0xa40a, 0x0040,
- 0x16b3, 0x00c8, 0x16bc, 0x8001, 0x7872, 0xa084, 0xfc00, 0x0040,
- 0x16c0, 0x78ac, 0xc085, 0x78ae, 0x2001, 0x4005, 0x0078, 0x15c3,
- 0x7b7e, 0x7a7a, 0x7e86, 0x7d82, 0x7c76, 0xa48c, 0xff00, 0x0040,
- 0x16d8, 0x8407, 0x8004, 0x8004, 0x810c, 0x810c, 0x810f, 0xa118,
- 0xa291, 0x0000, 0xa6b1, 0x0000, 0xa581, 0x0000, 0x0078, 0x16e2,
- 0x8407, 0x8004, 0x8004, 0xa318, 0xa291, 0x0000, 0xa6b1, 0x0000,
- 0xa581, 0x0000, 0x731a, 0x721e, 0x7622, 0x7026, 0xa605, 0x0040,
- 0x16ec, 0x7a10, 0xc2c5, 0x7a12, 0x78ac, 0xa084, 0xfffc, 0x78ae,
- 0x0078, 0x16f5, 0x78ac, 0xc085, 0x78ae, 0x0078, 0x15c1, 0x75d8,
- 0x76dc, 0x75da, 0x76de, 0x0078, 0x1700, 0x2029, 0x0000, 0x2530,
- 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6, 0x72ca, 0x73ce, 0x74d6,
- 0xa005, 0x0040, 0x172f, 0xa40a, 0x0040, 0x1710, 0x00c8, 0x1719,
- 0x8001, 0x7892, 0xa084, 0xfc00, 0x0040, 0x171d, 0x78ac, 0xc0c5,
- 0x78ae, 0x2001, 0x4005, 0x0078, 0x15c3, 0x7a9a, 0x7b9e, 0x7da2,
- 0x7ea6, 0x2600, 0xa505, 0x0040, 0x1728, 0x7a10, 0xc2c5, 0x7a12,
- 0x7c96, 0x78ac, 0xa084, 0xfcff, 0x78ae, 0x0078, 0x1732, 0x78ac,
- 0xc0c5, 0x78ae, 0x0078, 0x15c1, 0x2009, 0x0000, 0x786c, 0xa065,
- 0x0040, 0x173e, 0x8108, 0x6000, 0x0078, 0x1737, 0x7ac4, 0x0078,
- 0x15bf, 0x2009, 0x4f48, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0,
- 0x2011, 0x4f88, 0x2214, 0x0078, 0x15bf, 0x2009, 0x4f49, 0x210c,
- 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f89, 0x2214, 0x0078,
- 0x15bf, 0x2061, 0x4f40, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214,
- 0x7810, 0xd0ec, 0x00c0, 0x176d, 0x2061, 0x4f80, 0x6328, 0x73da,
- 0x632c, 0x831c, 0x831c, 0x831c, 0x73de, 0x0078, 0x15bf, 0x2009,
- 0x4f4c, 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f8c,
- 0x2214, 0x0078, 0x15bf, 0x7918, 0x0078, 0x15c0, 0x2009, 0x4f4d,
- 0x210c, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2011, 0x4f8d, 0x2214,
- 0x0078, 0x15bf, 0x2009, 0x4f4e, 0x210c, 0x7810, 0xd0ec, 0x00c0,
- 0x15c0, 0x2011, 0x4f8e, 0x2214, 0x0078, 0x15bf, 0x7920, 0x7810,
- 0xd0ec, 0x00c0, 0x15c0, 0x7a24, 0x0078, 0x15bf, 0x71c4, 0xd1fc,
- 0x00c0, 0x17a6, 0x2011, 0x53c0, 0x0078, 0x17a8, 0x2011, 0x5440,
- 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa268, 0x6a00,
- 0x6804, 0xd09c, 0x0040, 0x17b7, 0x6b08, 0x0078, 0x17b8, 0x6b0c,
- 0xd1fc, 0x00c0, 0x17bf, 0x2021, 0x023b, 0x0078, 0x17c1, 0x2021,
- 0x013b, 0x2424, 0x7914, 0xd1e4, 0x0040, 0x17cd, 0xd4c4, 0x00c0,
- 0x17cc, 0xc4d5, 0x0078, 0x17cd, 0xc4dd, 0xa4a4, 0x1c00, 0x74de,
- 0x71c4, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000,
- 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x15be, 0x2061,
- 0x4f40, 0x6118, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2061, 0x4f80,
- 0x6218, 0x0078, 0x15bf, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000,
- 0x6908, 0x6a18, 0x6b10, 0x77da, 0x2091, 0x8001, 0x0078, 0x15be,
- 0x71c4, 0x2110, 0xa294, 0x000f, 0xa282, 0x0010, 0x00c8, 0x15b9,
- 0x1078, 0x27c6, 0xa384, 0x4000, 0x0040, 0x1808, 0xa295, 0x0020,
- 0x0078, 0x15be, 0x71c4, 0x2100, 0xc0bc, 0xa082, 0x0010, 0x00c8,
- 0x15b9, 0xd1bc, 0x00c0, 0x1819, 0x2011, 0x4f48, 0x2204, 0x0078,
- 0x181d, 0x2011, 0x4f88, 0x2204, 0xc0bd, 0x007e, 0x2100, 0xc0bc,
- 0x2012, 0x1078, 0x2723, 0x017f, 0x0078, 0x15c0, 0x71c4, 0x2021,
- 0x4f49, 0x2404, 0x70c6, 0x2019, 0x0000, 0x0078, 0x1835, 0x71c8,
- 0x2021, 0x4f89, 0x2404, 0x70ca, 0xc3fd, 0x2011, 0x1854, 0x20a9,
- 0x0008, 0x2204, 0xa106, 0x0040, 0x1844, 0x8210, 0x00f0, 0x1839,
- 0x71c4, 0x72c8, 0x0078, 0x15b8, 0xa292, 0x1854, 0x027e, 0x2122,
- 0x017f, 0x1078, 0x2744, 0x7810, 0xd0ec, 0x00c0, 0x1852, 0xd3fc,
- 0x0040, 0x182f, 0x0078, 0x15c1, 0x03e8, 0x00fa, 0x01f4, 0x02ee,
- 0x0004, 0x0001, 0x0002, 0x0003, 0x2061, 0x4f40, 0x6128, 0x622c,
- 0x8214, 0x8214, 0x8214, 0x70c4, 0x602a, 0x70c8, 0x8003, 0x8003,
- 0x8003, 0x602e, 0x7810, 0xd0ec, 0x00c0, 0x1882, 0x027e, 0x017e,
- 0x2061, 0x4f80, 0x6128, 0x622c, 0x8214, 0x8214, 0x8214, 0x70d8,
- 0x602a, 0x70dc, 0x8003, 0x8003, 0x8003, 0x602e, 0x71da, 0x72de,
- 0x017f, 0x027f, 0x0078, 0x15bf, 0x2061, 0x4f40, 0x6130, 0x70c4,
- 0x6032, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x2061, 0x4f80, 0x6230,
- 0x70c8, 0x6032, 0x0078, 0x15bf, 0x7918, 0x0078, 0x15c0, 0x71c4,
- 0xa184, 0xffcf, 0x0040, 0x18a3, 0x7810, 0xd0ec, 0x00c0, 0x15b9,
- 0x72c8, 0x0078, 0x15b8, 0x2011, 0x4f4d, 0x2204, 0x2112, 0x007e,
- 0x2019, 0x0000, 0x1078, 0x27ab, 0x7810, 0xd0ec, 0x0040, 0x18b3,
- 0x017f, 0x0078, 0x15c0, 0x71c8, 0xa184, 0xffcf, 0x0040, 0x18bc,
- 0x2110, 0x71c4, 0x0078, 0x15b8, 0x2011, 0x4f8d, 0x2204, 0x2112,
- 0x007e, 0xc3fd, 0x1078, 0x27ab, 0x027f, 0x017f, 0x0078, 0x15bf,
- 0x71c4, 0xa182, 0x0010, 0x0048, 0x18d4, 0x7810, 0xd0ec, 0x00c0,
- 0x15b9, 0x72c8, 0x0078, 0x15b8, 0x2011, 0x4f4e, 0x2204, 0x007e,
- 0x2112, 0x2019, 0x0000, 0x1078, 0x2789, 0x7810, 0xd0ec, 0x0040,
- 0x18e4, 0x017f, 0x0078, 0x15c0, 0x71c8, 0xa182, 0x0010, 0x0048,
- 0x18ed, 0x2110, 0x71c4, 0x0078, 0x15b8, 0x2011, 0x4f8e, 0x2204,
- 0x007e, 0x2112, 0xc3fd, 0x1078, 0x2789, 0x027f, 0x017f, 0x0078,
- 0x15bf, 0x71c4, 0x72c8, 0xa184, 0xfffd, 0x00c0, 0x15b8, 0xa284,
- 0xfffd, 0x00c0, 0x15b8, 0x2100, 0x7920, 0x7822, 0x2200, 0x7a24,
- 0x7826, 0x0078, 0x15bf, 0x71c4, 0xd1fc, 0x00c0, 0x1913, 0x2011,
- 0x53c0, 0x0078, 0x1915, 0x2011, 0x5440, 0x8107, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa268, 0x2019, 0x0000, 0x72c8, 0xd2bc,
- 0x0040, 0x1924, 0xa39d, 0x0010, 0xd2b4, 0x0040, 0x1929, 0xa39d,
- 0x0008, 0x2091, 0x8000, 0x6800, 0x007e, 0xa226, 0x0040, 0x1948,
- 0x6a02, 0xd4ec, 0x0040, 0x1935, 0xc3a5, 0xd4e4, 0x0040, 0x1939,
- 0xc39d, 0xd4f4, 0x0040, 0x1948, 0x810f, 0xd2f4, 0x0040, 0x1944,
- 0x1078, 0x2808, 0x0078, 0x1948, 0x1078, 0x27e6, 0x0078, 0x1948,
- 0x72cc, 0x6808, 0xa206, 0x0040, 0x196a, 0xa2a4, 0x00ff, 0x7814,
- 0xd0e4, 0x00c0, 0x195b, 0xa482, 0x0028, 0x0048, 0x1967, 0x0040,
- 0x1967, 0x0078, 0x195f, 0xa482, 0x0043, 0x0048, 0x1967, 0x71c4,
- 0x71c6, 0x027f, 0x72ca, 0x2091, 0x8001, 0x0078, 0x15ba, 0x6a0a,
- 0xa39d, 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4,
- 0x2091, 0x8001, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b, 0x2091,
- 0x8000, 0x6a14, 0x6b1c, 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc,
- 0x681e, 0x2708, 0x0078, 0x15be, 0x70c4, 0x2061, 0x4f40, 0x6118,
- 0x601a, 0x7810, 0xd0ec, 0x00c0, 0x15c0, 0x70c8, 0x2061, 0x4f80,
- 0x6218, 0x601a, 0x0078, 0x15bf, 0x71c4, 0x72c8, 0x73cc, 0xa182,
- 0x0010, 0x00c8, 0x15b9, 0x1078, 0x282a, 0xa384, 0x4000, 0x0040,
- 0x19a3, 0xa295, 0x0020, 0x0078, 0x15be, 0x77c4, 0x1078, 0x1e2b,
- 0x2091, 0x8000, 0x6a08, 0xc28d, 0x6a0a, 0x2091, 0x8001, 0x2708,
- 0x0078, 0x15bf, 0x77c4, 0x1078, 0x1e2b, 0x2091, 0x8000, 0x6a08,
- 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x19c1, 0x1078,
- 0x266f, 0x2091, 0x8001, 0x2708, 0x0078, 0x15bf, 0x77c4, 0x1078,
- 0x1e2b, 0x2091, 0x8000, 0x6a08, 0xc295, 0x6a0a, 0x6804, 0xa005,
- 0x0040, 0x19d4, 0x1078, 0x266f, 0x2091, 0x8001, 0x2708, 0x0078,
- 0x15bf, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051, 0x0020,
- 0x2091, 0x8000, 0x1078, 0x1e46, 0x2091, 0x8001, 0x2708, 0x6a08,
- 0x0078, 0x15bf, 0x77c4, 0x7814, 0xd0e4, 0x00c0, 0x19fe, 0xd7fc,
- 0x0040, 0x19f8, 0x1078, 0x1dae, 0x0040, 0x19fe, 0x0078, 0x15c3,
- 0x1078, 0x1da1, 0x0040, 0x19fe, 0x0078, 0x15c3, 0x73c8, 0x72cc,
- 0x77c6, 0x73ca, 0x72ce, 0x1078, 0x1ecd, 0x00c0, 0x1a28, 0x6818,
- 0xa005, 0x0040, 0x1a22, 0x2708, 0x077e, 0x1078, 0x285a, 0x077f,
- 0x00c0, 0x1a22, 0x2001, 0x0015, 0xd7fc, 0x00c0, 0x1a1b, 0x2061,
- 0x4f40, 0x0078, 0x1a1e, 0xc0fd, 0x2061, 0x4f80, 0x782a, 0x2091,
- 0x8001, 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, 0x0078, 0x15c3,
- 0x2091, 0x8001, 0x0078, 0x15c1, 0x77c4, 0x7814, 0xd0e4, 0x00c0,
- 0x1a40, 0xd7fc, 0x0040, 0x1a3a, 0x1078, 0x1dae, 0x0040, 0x1a40,
- 0x0078, 0x15c3, 0x1078, 0x1da1, 0x0040, 0x1a40, 0x0078, 0x15c3,
- 0x77c6, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091,
- 0x8000, 0x1078, 0x1e46, 0x2009, 0x0016, 0xd7fc, 0x00c0, 0x1a54,
- 0x2061, 0x4f40, 0x0078, 0x1a57, 0x2061, 0x4f80, 0xc1fd, 0x6067,
- 0x0003, 0x607f, 0x0000, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4,
- 0xc1dc, 0x61d6, 0x1078, 0x266f, 0x2091, 0x8001, 0x007c, 0x77c8,
- 0x77ca, 0x77c4, 0x77c6, 0x7814, 0xd0e4, 0x00c0, 0x1a7e, 0xd7fc,
- 0x0040, 0x1a78, 0x1078, 0x1dae, 0x0040, 0x1a7e, 0x0078, 0x15c3,
- 0x1078, 0x1da1, 0x0040, 0x1a7e, 0x0078, 0x15c3, 0xa7bc, 0xff00,
- 0x2091, 0x8000, 0x2009, 0x0017, 0xd7fc, 0x00c0, 0x1a8b, 0x2061,
- 0x4f40, 0x0078, 0x1a8e, 0x2061, 0x4f80, 0xc1fd, 0x607f, 0x0000,
- 0x6067, 0x0002, 0x6776, 0x6083, 0x000f, 0x792a, 0x61d4, 0xc1dc,
- 0x61d6, 0x1078, 0x266f, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049,
- 0x0005, 0x2051, 0x0010, 0x2091, 0x8000, 0x70c8, 0xa005, 0x0040,
- 0x1aac, 0x60d4, 0xc0fd, 0x60d6, 0x1078, 0x1e46, 0x70c8, 0x6836,
- 0x8738, 0xa784, 0x001f, 0x00c0, 0x1aac, 0x2091, 0x8001, 0x007c,
- 0x2019, 0x0000, 0x7814, 0xd0e4, 0x00c0, 0x1ace, 0x72c8, 0xd284,
- 0x0040, 0x1ac8, 0x1078, 0x1dae, 0x0040, 0x1ace, 0x0078, 0x15c3,
- 0x1078, 0x1da1, 0x0040, 0x1ace, 0x0078, 0x15c3, 0x72c8, 0x72ca,
- 0x78ac, 0xa084, 0x0003, 0x00c0, 0x1af9, 0x2039, 0x0000, 0xd284,
- 0x0040, 0x1adb, 0xc7fd, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051,
- 0x0008, 0x1078, 0x1e2b, 0x2091, 0x8000, 0x6808, 0xc0d4, 0xa80d,
- 0x690a, 0x2091, 0x8001, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1ae1,
- 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00, 0x00c0,
- 0x1ae1, 0x2091, 0x8000, 0x72c8, 0xd284, 0x00c0, 0x1b0b, 0x7810,
- 0xd0ec, 0x0040, 0x1b07, 0x2069, 0x0100, 0x0078, 0x1b0d, 0x2069,
- 0x0200, 0x0078, 0x1b0d, 0x2069, 0x0100, 0x6808, 0xa084, 0xfffd,
- 0x680a, 0x6830, 0xd0b4, 0x0040, 0x1b2d, 0x684b, 0x0004, 0x20a9,
- 0x0014, 0x6848, 0xd094, 0x0040, 0x1b1f, 0x00f0, 0x1b19, 0x684b,
- 0x0009, 0x20a9, 0x0014, 0x6848, 0xd084, 0x0040, 0x1b29, 0x00f0,
- 0x1b23, 0x20a9, 0x00fa, 0x00f0, 0x1b2b, 0x2079, 0x4f00, 0x2009,
- 0x0018, 0x72c8, 0xd284, 0x00c0, 0x1b39, 0x2061, 0x4f40, 0x0078,
- 0x1b3c, 0x2061, 0x4f80, 0xc1fd, 0x607f, 0x0000, 0x792a, 0x6067,
- 0x0001, 0x6083, 0x000f, 0x60a7, 0x0000, 0x60a8, 0x60b2, 0x60b6,
- 0x60d4, 0xd0b4, 0x0040, 0x1b58, 0xc0b4, 0x60d6, 0x0c7e, 0x60b8,
- 0xa065, 0x6008, 0xc0d4, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f,
- 0x60d4, 0xa084, 0x77ff, 0x60d6, 0x78ac, 0xc08d, 0x78ae, 0x83ff,
- 0x0040, 0x1b63, 0x007c, 0x681b, 0x0047, 0x2091, 0x8001, 0x007c,
- 0x73cc, 0x1078, 0x1aba, 0x69ec, 0x6a48, 0xa185, 0x1800, 0x684a,
- 0xa185, 0x0040, 0x68ee, 0x73cc, 0x2021, 0x0004, 0x20a9, 0x09ff,
- 0x00f0, 0x1b78, 0x8421, 0x00c0, 0x1b76, 0x8319, 0x00c0, 0x1b74,
- 0x69ee, 0x6a4a, 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x1b8c,
- 0x2069, 0x4f40, 0x0078, 0x1b8e, 0x2069, 0x4f80, 0x71c4, 0x71c6,
- 0x6916, 0x81ff, 0x00c0, 0x1b96, 0x68a7, 0x0001, 0x78ac, 0xc08c,
- 0x78ae, 0xd084, 0x00c0, 0x1b9e, 0x1078, 0x1f2d, 0x007c, 0x75d8,
- 0x74dc, 0x75da, 0x74de, 0x0078, 0x1ba7, 0xa02e, 0x2520, 0x71c4,
- 0x73c8, 0x72cc, 0x71c6, 0x73ca, 0x72ce, 0x2079, 0x4f00, 0x7dde,
- 0x7cda, 0x7bd6, 0x7ad2, 0x1078, 0x1e04, 0x0040, 0x1cd1, 0x20a9,
- 0x0005, 0x20a1, 0x4f14, 0x2091, 0x8000, 0x41a1, 0x2091, 0x8001,
- 0x2009, 0x0040, 0x1078, 0x2018, 0x0040, 0x1bca, 0x1078, 0x1e0d,
- 0x0078, 0x1cd1, 0x6004, 0xa08c, 0x00ff, 0xa18e, 0x0009, 0x00c0,
- 0x1bd5, 0x007e, 0x1078, 0x23bf, 0x007f, 0xa084, 0xff00, 0x8007,
- 0x8009, 0x0040, 0x1c61, 0x0c7e, 0x2c68, 0x1078, 0x1e04, 0x0040,
- 0x1c1b, 0x2c00, 0x689e, 0x8109, 0x00c0, 0x1bdc, 0x609f, 0x0000,
- 0x0c7f, 0x0c7e, 0x7ddc, 0x7cd8, 0x7bd4, 0x7ad0, 0xa290, 0x0040,
- 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x7dde, 0x7cda,
- 0x7bd6, 0x7ad2, 0x2c68, 0x689c, 0xa065, 0x0040, 0x1c60, 0x2009,
- 0x0040, 0x1078, 0x2018, 0x00c0, 0x1c3e, 0x6004, 0xa084, 0x00ff,
- 0xa086, 0x0002, 0x00c0, 0x1c1b, 0x6004, 0xa084, 0x00ff, 0xa086,
- 0x000a, 0x00c0, 0x1c17, 0x017e, 0x1078, 0x23bb, 0x017f, 0x2d00,
- 0x6002, 0x0078, 0x1bea, 0x0c7f, 0x0c7e, 0x609c, 0x1078, 0x1e90,
- 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1cd5, 0x2009, 0x0018, 0x6008,
- 0xc0cd, 0x600a, 0x6004, 0x6086, 0x7810, 0x007e, 0x84ff, 0x00c0,
- 0x1c34, 0x85ff, 0x0040, 0x1c36, 0xc0c5, 0x7812, 0x1078, 0x1dbb,
- 0x007f, 0x7812, 0x1078, 0x1e0d, 0x0078, 0x1cd1, 0x0c7f, 0x0c7e,
- 0x609c, 0x1078, 0x1e90, 0x0c7f, 0x609f, 0x0000, 0x1078, 0x1cd5,
- 0x2009, 0x0018, 0x6087, 0x0103, 0x601b, 0x0003, 0x7810, 0x007e,
- 0x84ff, 0x00c0, 0x1c56, 0x85ff, 0x0040, 0x1c58, 0xc0c5, 0x7812,
- 0x1078, 0x1dbb, 0x007f, 0x7812, 0x1078, 0x1e0d, 0x0078, 0x1cd1,
- 0x0c7f, 0x7814, 0xd0e4, 0x00c0, 0x1c8f, 0x6114, 0xd1fc, 0x0040,
- 0x1c6f, 0x1078, 0x1dae, 0x0040, 0x1c8f, 0x0078, 0x1c73, 0x1078,
- 0x1da1, 0x0040, 0x1c8f, 0x1078, 0x1cd5, 0x2009, 0x0018, 0x6087,
- 0x0103, 0x601b, 0x0021, 0x7810, 0x007e, 0x84ff, 0x00c0, 0x1c83,
- 0x85ff, 0x0040, 0x1c85, 0xc0c5, 0x7812, 0x1078, 0x1dbb, 0x007f,
- 0x7812, 0x1078, 0x1e0d, 0x2001, 0x4007, 0x0078, 0x15c3, 0x74c4,
- 0x73c8, 0x72cc, 0x6014, 0x2091, 0x8000, 0x0e7e, 0x2009, 0x0012,
- 0xd0fc, 0x00c0, 0x1c9f, 0x2071, 0x4f40, 0x0078, 0x1ca2, 0x2071,
- 0x4f80, 0xc1fd, 0x792a, 0x7067, 0x0005, 0x71d4, 0xc1dc, 0x71d6,
- 0x736a, 0x726e, 0x7472, 0x7076, 0x707b, 0x0000, 0x2c00, 0x707e,
- 0xa02e, 0x2530, 0x611c, 0xa184, 0x0060, 0x0040, 0x1cb9, 0x1078,
- 0x46b6, 0x0e7f, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x60af, 0x0000,
- 0x60b3, 0x0000, 0x6714, 0x6023, 0x0000, 0x6024, 0xa096, 0x0001,
- 0x00c0, 0x1ccc, 0x8000, 0x6026, 0x1078, 0x266f, 0x2091, 0x8001,
- 0x007c, 0x70c3, 0x4005, 0x0078, 0x15c4, 0x20a9, 0x0005, 0x2099,
- 0x4f14, 0x2091, 0x8000, 0x530a, 0x2091, 0x8001, 0x2100, 0xa210,
- 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x007c, 0x71c4,
- 0x70c7, 0x0000, 0x791e, 0x0078, 0x15c1, 0x71c4, 0x71c6, 0x2168,
- 0x0078, 0x1cf4, 0x2069, 0x1000, 0x690c, 0xa016, 0x2d04, 0xa210,
- 0x8d68, 0x8109, 0x00c0, 0x1cf6, 0xa285, 0x0000, 0x00c0, 0x1d04,
- 0x70c3, 0x4000, 0x0078, 0x1d06, 0x70c3, 0x4003, 0x70ca, 0x0078,
- 0x15c4, 0x7964, 0x71c6, 0x71c4, 0xa182, 0x0003, 0x00c8, 0x15b9,
- 0x7966, 0x0078, 0x15c1, 0x7964, 0x71c6, 0x0078, 0x15c1, 0x7900,
- 0x71c6, 0x71c4, 0x7902, 0x0078, 0x15c1, 0x7900, 0x71c6, 0x0078,
- 0x15c1, 0x70c4, 0x2011, 0x0000, 0xa08c, 0x000d, 0x0040, 0x1d36,
- 0x810c, 0x0048, 0x1d32, 0x8210, 0x810c, 0x810c, 0x0048, 0x1d32,
- 0x8210, 0x810c, 0x81ff, 0x00c0, 0x15ba, 0x8210, 0x7a0e, 0xd28c,
- 0x0040, 0x1d62, 0x7910, 0xc1cd, 0x7912, 0x2009, 0x0021, 0x2019,
- 0x0003, 0xd284, 0x0040, 0x1d5c, 0x8108, 0x2019, 0x0041, 0x2011,
- 0x974e, 0x2312, 0x2019, 0x0042, 0x8210, 0x2312, 0x2019, 0x0043,
- 0x8210, 0x2312, 0x2019, 0x0046, 0x8210, 0x2312, 0x2019, 0x0047,
- 0x8210, 0x2312, 0x2019, 0x0006, 0x2011, 0x9753, 0x2112, 0x2011,
- 0x9773, 0x2312, 0x7904, 0x7806, 0x0078, 0x15c0, 0x7804, 0x70c6,
- 0x0078, 0x15c1, 0x71c4, 0xd1fc, 0x00c0, 0x1d72, 0x2011, 0x53c0,
- 0x0078, 0x1d74, 0x2011, 0x5440, 0x8107, 0xa084, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa268, 0x6a14, 0xd2b4, 0x0040, 0x1d83, 0x2011,
- 0x0001, 0x0078, 0x1d85, 0x2011, 0x0000, 0x6b0c, 0x6800, 0x70da,
- 0x0078, 0x15be, 0x7814, 0xd0f4, 0x0040, 0x1d95, 0x2001, 0x4007,
- 0x70db, 0x0000, 0xa005, 0x0078, 0x1da0, 0xd0fc, 0x0040, 0x1d9f,
- 0x2001, 0x4007, 0x70db, 0x0001, 0xa005, 0x0078, 0x1da0, 0xa006,
- 0x007c, 0x7814, 0xd0f4, 0x0040, 0x1dac, 0x2001, 0x4007, 0x70db,
- 0x0000, 0xa005, 0x0078, 0x1dad, 0xa006, 0x007c, 0x7814, 0xd0fc,
- 0x0040, 0x1db9, 0x2001, 0x4007, 0x70db, 0x0001, 0xa005, 0x0078,
- 0x1dba, 0xa006, 0x007c, 0x7112, 0x721a, 0x731e, 0x7810, 0xd0c4,
- 0x0040, 0x1dc4, 0x7422, 0x7526, 0xac80, 0x0001, 0x8108, 0x810c,
- 0x81a9, 0x8098, 0x20a1, 0x0030, 0x7003, 0x0000, 0x6084, 0x20a2,
- 0x53a6, 0x7007, 0x0001, 0x7974, 0xa184, 0xff00, 0x0040, 0x1de1,
- 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078,
- 0x1de4, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006,
- 0xa211, 0x7d10, 0xd5c4, 0x0040, 0x1df1, 0x7b84, 0xa319, 0x7c80,
- 0xa421, 0x7008, 0xd0fc, 0x0040, 0x1df1, 0x7003, 0x0001, 0x7007,
- 0x0006, 0x711a, 0x721e, 0x7d10, 0xd5c4, 0x0040, 0x1e01, 0x7322,
- 0x7426, 0xa084, 0x01e0, 0x007c, 0x7848, 0xa065, 0x0040, 0x1e0c,
- 0x2c04, 0x784a, 0x2063, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x4f00,
- 0x7848, 0x2062, 0x2c00, 0xa005, 0x00c0, 0x1e18, 0x1078, 0x29b2,
- 0x784a, 0x0f7f, 0x007c, 0x2011, 0x9900, 0x7a4a, 0x7bc4, 0x8319,
- 0x0040, 0x1e28, 0xa280, 0x0032, 0x2012, 0x2010, 0x0078, 0x1e1f,
- 0x2013, 0x0000, 0x007c, 0x017e, 0x027e, 0xd7fc, 0x00c0, 0x1e34,
- 0x2011, 0x54c0, 0x0078, 0x1e36, 0x2011, 0x74c0, 0xa784, 0x0f00,
- 0x800b, 0xa784, 0x001f, 0x0040, 0x1e41, 0x8003, 0x8003, 0x8003,
- 0x8003, 0xa105, 0xa268, 0x027f, 0x017f, 0x007c, 0x1078, 0x1e2b,
- 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xf9ef, 0xa80d,
- 0x690a, 0x0e7e, 0xd7fc, 0x00c0, 0x1e5b, 0x2009, 0x4f53, 0x2071,
- 0x4f40, 0x0078, 0x1e5f, 0x2009, 0x4f93, 0x2071, 0x4f80, 0x210c,
- 0x6804, 0xa005, 0x0040, 0x1e6f, 0xa116, 0x00c0, 0x1e6f, 0x2060,
- 0x6000, 0x6806, 0x017e, 0x200b, 0x0000, 0x0078, 0x1e72, 0x2009,
- 0x0000, 0x017e, 0x6804, 0xa065, 0x0040, 0x1e87, 0x6000, 0x6806,
- 0x1078, 0x1ea2, 0x1078, 0x2064, 0x6810, 0x7908, 0x8109, 0x790a,
- 0x8001, 0x6812, 0x00c0, 0x1e72, 0x7910, 0xc1a5, 0x7912, 0x017f,
- 0x6902, 0x6906, 0x2d00, 0x2060, 0x1078, 0x2b13, 0x0e7f, 0x007c,
- 0xa065, 0x0040, 0x1ea1, 0x2008, 0x609c, 0xa005, 0x0040, 0x1e9e,
- 0x2062, 0x609f, 0x0000, 0xa065, 0x0078, 0x1e94, 0x7848, 0x794a,
- 0x2062, 0x007c, 0x6007, 0x0103, 0x608f, 0x0000, 0x20a9, 0x001c,
- 0xac80, 0x0005, 0x20a0, 0x2001, 0x0000, 0x40a4, 0x6828, 0x601a,
- 0x682c, 0x6022, 0x007c, 0x0e7e, 0xd7fc, 0x00c0, 0x1ebd, 0x2071,
- 0x4f40, 0x2031, 0x4fc0, 0x0078, 0x1ec1, 0x2071, 0x4f80, 0x2031,
- 0x51c0, 0x7050, 0xa08c, 0x0200, 0x00c0, 0x1ecb, 0xa608, 0x2d0a,
- 0x8000, 0x7052, 0xa006, 0x0e7f, 0x007c, 0x0f7e, 0xd7fc, 0x00c0,
- 0x1ed5, 0x2079, 0x4f40, 0x0078, 0x1ed7, 0x2079, 0x4f80, 0x1078,
- 0x1e2b, 0x2091, 0x8000, 0x6804, 0x780a, 0xa065, 0x0040, 0x1f2b,
- 0x0078, 0x1ee9, 0x2c00, 0x780a, 0x2060, 0x6000, 0xa065, 0x0040,
- 0x1f2b, 0x6010, 0xa306, 0x00c0, 0x1ee2, 0x600c, 0xa206, 0x00c0,
- 0x1ee2, 0x2c28, 0x784c, 0xac06, 0x00c0, 0x1ef8, 0x0078, 0x1f28,
- 0x6804, 0xac06, 0x00c0, 0x1f06, 0x6000, 0x2060, 0x6806, 0xa005,
- 0x00c0, 0x1f06, 0x6803, 0x0000, 0x0078, 0x1f10, 0x6400, 0x7808,
- 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1f10, 0x2c00, 0x6802,
- 0x2560, 0x0f7f, 0x1078, 0x1ea2, 0x0f7e, 0x601b, 0x0005, 0x6023,
- 0x0020, 0x0f7f, 0x1078, 0x2064, 0x0f7e, 0x7908, 0x8109, 0x790a,
- 0x6810, 0x8001, 0x6812, 0x00c0, 0x1f28, 0x7810, 0xc0a5, 0x7812,
- 0x2001, 0xffff, 0xa005, 0x0f7f, 0x007c, 0x077e, 0x2700, 0x2039,
- 0x0000, 0xd0fc, 0x0040, 0x1f35, 0xc7fd, 0x2041, 0x0021, 0x2049,
- 0x0004, 0x2051, 0x0008, 0x2091, 0x8000, 0x1078, 0x1e46, 0x8738,
- 0xa784, 0x001f, 0x00c0, 0x1f3d, 0xa7bc, 0xff00, 0x873f, 0x8738,
- 0x873f, 0xa784, 0x0f00, 0x00c0, 0x1f3d, 0x2091, 0x8001, 0x077f,
- 0x007c, 0x786c, 0x2009, 0x9774, 0x210c, 0xa10d, 0x0040, 0x1f5b,
- 0xa065, 0x0078, 0x23dc, 0x2061, 0x0000, 0x6018, 0xd084, 0x00c0,
- 0x1f7b, 0x7810, 0xd08c, 0x0040, 0x1f6c, 0xc08c, 0x7812, 0xc7fc,
- 0x2069, 0x4f40, 0x0078, 0x1f71, 0xc08d, 0x7812, 0x2069, 0x4f80,
- 0xc7fd, 0x2091, 0x8000, 0x681c, 0x681f, 0x0000, 0x2091, 0x8001,
- 0xa005, 0x00c0, 0x1f7c, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1f82,
- 0x1078, 0x29b2, 0x0079, 0x1f84, 0x1f94, 0x1f97, 0x1f9d, 0x1fa1,
- 0x1f95, 0x1fa5, 0x1f95, 0x1f95, 0x1f95, 0x1fab, 0x1fdc, 0x1fe0,
- 0x1fe6, 0x1ffb, 0x1f95, 0x1f95, 0x007c, 0x1078, 0x29b2, 0x1078,
- 0x1f2d, 0x2001, 0x8001, 0x0078, 0x2007, 0x2001, 0x8003, 0x0078,
- 0x2007, 0x2001, 0x8004, 0x0078, 0x2007, 0x1078, 0x1f2d, 0x2001,
- 0x8006, 0x0078, 0x2007, 0x2091, 0x8000, 0x077e, 0xd7fc, 0x00c0,
- 0x1fb7, 0x2069, 0x4f40, 0x2039, 0x0009, 0x0078, 0x1fbb, 0x2069,
- 0x4f80, 0x2039, 0x0009, 0x6800, 0xa086, 0x0000, 0x0040, 0x1fc5,
- 0x007f, 0x6f1e, 0x2091, 0x8001, 0x007c, 0x6874, 0x077f, 0xa0bc,
- 0xff00, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0010, 0x1078,
- 0x1e46, 0x8738, 0xa784, 0x001f, 0x00c0, 0x1fcf, 0x2091, 0x8001,
- 0x2001, 0x800a, 0x0078, 0x2007, 0x2001, 0x800c, 0x0078, 0x2007,
- 0x1078, 0x1f2d, 0x2001, 0x800d, 0x0078, 0x2007, 0x7814, 0xd0e4,
- 0x00c0, 0x1ff9, 0xd0ec, 0x0040, 0x1ff3, 0xd7fc, 0x0040, 0x1ff3,
- 0x78e4, 0x0078, 0x1ff4, 0x78e0, 0x70c6, 0x2001, 0x800e, 0x0078,
- 0x2007, 0x0078, 0x1f95, 0xd7fc, 0x0040, 0x2001, 0x78ec, 0x0078,
- 0x2002, 0x78e8, 0x70c6, 0x2001, 0x800f, 0x0078, 0x2007, 0x70c2,
- 0xd7fc, 0x00c0, 0x200f, 0x70db, 0x0000, 0x0078, 0x2011, 0x70db,
- 0x0001, 0x2061, 0x0000, 0x601b, 0x0001, 0x2091, 0x4080, 0x007c,
- 0xac80, 0x0001, 0x81ff, 0x0040, 0x2043, 0x2099, 0x0030, 0x20a0,
- 0x700c, 0xa084, 0x03ff, 0x0040, 0x2025, 0x7018, 0x007e, 0x701c,
- 0x007e, 0x7020, 0x007e, 0x7024, 0x007e, 0x7112, 0x81ac, 0x721a,
- 0x731e, 0x7422, 0x7526, 0x7003, 0x0001, 0x7007, 0x0001, 0x7008,
- 0x800b, 0x00c8, 0x2037, 0x7007, 0x0002, 0xa08c, 0x01e0, 0x00c0,
- 0x2043, 0x53a5, 0xa006, 0x7003, 0x0000, 0x7007, 0x0004, 0x007f,
- 0x7026, 0x007f, 0x7022, 0x007f, 0x701e, 0x007f, 0x701a, 0x007c,
- 0x2011, 0x0020, 0x2009, 0x0010, 0x6b0a, 0x6c0e, 0x6803, 0xfd00,
- 0x6807, 0x0018, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
- 0x8109, 0x00c0, 0x2054, 0x007c, 0x6004, 0x6086, 0x2c08, 0x2063,
- 0x0000, 0x7868, 0xa005, 0x796a, 0x0040, 0x2071, 0x2c02, 0x0078,
- 0x2072, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x4f00, 0x6887, 0x0103,
- 0x2d08, 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x2083,
- 0x2d02, 0x0078, 0x2084, 0x616e, 0x0c7f, 0x007c, 0x2091, 0x8000,
- 0x2c04, 0x786e, 0xa005, 0x00c0, 0x208e, 0x786a, 0x2091, 0x8001,
- 0x609c, 0xa005, 0x0040, 0x20a7, 0x0c7e, 0x2060, 0x2008, 0x609c,
- 0xa005, 0x0040, 0x20a3, 0x2062, 0x609f, 0x0000, 0xa065, 0x609c,
- 0xa005, 0x00c0, 0x209b, 0x7848, 0x794a, 0x2062, 0x0c7f, 0x7848,
- 0x2062, 0x609f, 0x0000, 0xac85, 0x0000, 0x00c0, 0x20b1, 0x1078,
- 0x29b2, 0x784a, 0x007c, 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086,
- 0x818e, 0x00c8, 0x20bc, 0xa200, 0x00f0, 0x20b7, 0x8086, 0x818e,
- 0x007c, 0x157e, 0x20a9, 0x0010, 0xa005, 0x0040, 0x20e2, 0xa11a,
- 0x00c8, 0x20e2, 0x8213, 0x818d, 0x0048, 0x20d5, 0xa11a, 0x00c8,
- 0x20d6, 0x00f0, 0x20ca, 0x0078, 0x20da, 0xa11a, 0x2308, 0x8210,
- 0x00f0, 0x20ca, 0x007e, 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f,
- 0x157f, 0x007c, 0x007e, 0x3200, 0xa085, 0x0800, 0x0078, 0x20de,
- 0x7d74, 0x70d0, 0xa506, 0x0040, 0x21ce, 0x7810, 0x2050, 0x7800,
- 0xd08c, 0x0040, 0x210a, 0xdaec, 0x0040, 0x210a, 0x0e7e, 0x2091,
- 0x8000, 0x2071, 0x0020, 0x7004, 0xa005, 0x00c0, 0x2107, 0x7008,
- 0x0e7f, 0xa086, 0x0008, 0x0040, 0x210a, 0x0078, 0x21ce, 0x0e7f,
- 0x0078, 0x21ce, 0x1078, 0x1e04, 0x0040, 0x21ce, 0xa046, 0x7970,
- 0x2500, 0x8000, 0xa112, 0x2009, 0x0040, 0x00c8, 0x2119, 0x0078,
- 0x2120, 0x72d0, 0xa206, 0x0040, 0x2120, 0x8840, 0x2009, 0x0080,
- 0x0c7e, 0x7112, 0x7007, 0x0001, 0x2099, 0x0030, 0x20a9, 0x0020,
- 0xac80, 0x0001, 0x20a0, 0x2061, 0x0000, 0x88ff, 0x0040, 0x2132,
- 0x1078, 0x1e04, 0x7008, 0xd0fc, 0x0040, 0x2132, 0x7007, 0x0002,
- 0x2091, 0x8001, 0xa08c, 0x01e0, 0x00c0, 0x2169, 0x53a5, 0x8cff,
- 0x00c0, 0x2147, 0x88ff, 0x0040, 0x21b8, 0x0078, 0x2151, 0x2c00,
- 0x788e, 0x20a9, 0x0020, 0xac80, 0x0001, 0x20a0, 0x53a5, 0x0078,
- 0x21b8, 0xa046, 0x7218, 0x731c, 0xdac4, 0x0040, 0x2159, 0x7420,
- 0x7524, 0xa292, 0x0040, 0xa39b, 0x0000, 0xa4a3, 0x0000, 0xa5ab,
- 0x0000, 0x721a, 0x731e, 0xdac4, 0x0040, 0x2169, 0x7422, 0x7526,
- 0xa006, 0x7007, 0x0004, 0x0040, 0x21b8, 0x8cff, 0x0040, 0x2172,
- 0x1078, 0x1e0d, 0x0c7f, 0x1078, 0x1e0d, 0xa046, 0x7888, 0x8000,
- 0x788a, 0xa086, 0x0002, 0x0040, 0x2198, 0x7a7c, 0x7b78, 0xdac4,
- 0x0040, 0x2184, 0x7c84, 0x7d80, 0x7974, 0x8107, 0x8004, 0x8004,
- 0xa210, 0xa399, 0x0000, 0xa4a1, 0x0000, 0xa5a9, 0x0000, 0x721a,
- 0x731e, 0xdac4, 0x0040, 0x21ce, 0x7422, 0x7526, 0x0078, 0x21ce,
- 0x6014, 0xd0fc, 0x00c0, 0x21a0, 0x2069, 0x4f40, 0x0078, 0x21a2,
- 0x2069, 0x4f80, 0x2091, 0x8000, 0x681f, 0x0002, 0x88ff, 0x0040,
- 0x21ae, 0xa046, 0x788c, 0x2060, 0x0078, 0x2198, 0x788b, 0x0000,
- 0x78ac, 0xa085, 0x0003, 0x78ae, 0x2091, 0x8001, 0x0078, 0x21ce,
- 0x0c7f, 0x788b, 0x0000, 0x1078, 0x238d, 0x6004, 0xa084, 0x000f,
- 0x1078, 0x21cf, 0x88ff, 0x0040, 0x21cc, 0x788c, 0x2060, 0x6004,
- 0xa084, 0x000f, 0x1078, 0x21cf, 0x0078, 0x20e8, 0x007c, 0x0079,
- 0x21d1, 0x21e1, 0x21ff, 0x221d, 0x21e1, 0x222e, 0x21f2, 0x21e1,
- 0x21e1, 0x21e1, 0x21fd, 0x221b, 0x21e1, 0x21e1, 0x21e1, 0x21e1,
- 0x21e1, 0x2039, 0x0400, 0x78bc, 0xa705, 0x78be, 0x6008, 0xa705,
- 0x600a, 0x1078, 0x2271, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078,
- 0x2377, 0x007c, 0x78bc, 0xd0c4, 0x0040, 0x21f8, 0x0078, 0x21e1,
- 0x601c, 0xc0bd, 0x601e, 0x0078, 0x2205, 0x1078, 0x23bf, 0x78bc,
- 0xd0c4, 0x0040, 0x2205, 0x0078, 0x21e1, 0x78bf, 0x0000, 0x6004,
- 0x8007, 0xa084, 0x00ff, 0x78b2, 0x8001, 0x0040, 0x2218, 0x1078,
- 0x2271, 0x0040, 0x2218, 0x78bc, 0xc0c5, 0x78be, 0x0078, 0x221a,
- 0x0078, 0x2290, 0x007c, 0x1078, 0x23bb, 0x78bc, 0xa08c, 0x0e00,
- 0x00c0, 0x2225, 0xd0c4, 0x00c0, 0x2227, 0x0078, 0x21e1, 0x1078,
- 0x2271, 0x00c0, 0x222d, 0x0078, 0x2290, 0x007c, 0x78bc, 0xd0c4,
- 0x0040, 0x2234, 0x0078, 0x21e1, 0x78bf, 0x0000, 0x6714, 0x2011,
- 0x0001, 0x22a8, 0x6018, 0xa084, 0x00ff, 0xa005, 0x0040, 0x2254,
- 0xa7bc, 0xff00, 0x20a9, 0x0020, 0xa08e, 0x0001, 0x0040, 0x2254,
- 0xa7bc, 0x8000, 0x2011, 0x0002, 0x20a9, 0x0100, 0xa08e, 0x0002,
- 0x0040, 0x2254, 0x0078, 0x226e, 0x1078, 0x1e2b, 0x2d00, 0x2091,
- 0x8000, 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde,
- 0x680a, 0xade8, 0x0010, 0x2091, 0x8001, 0x00f0, 0x2257, 0x8211,
- 0x0040, 0x226e, 0x20a9, 0x0100, 0x0078, 0x2257, 0x1078, 0x1e0d,
- 0x007c, 0x609f, 0x0000, 0x78b4, 0xa06d, 0x2c00, 0x78b6, 0x00c0,
- 0x227c, 0x78ba, 0x0078, 0x2284, 0x689e, 0x2d00, 0x6002, 0x78b8,
- 0xad06, 0x00c0, 0x2284, 0x6002, 0x78b0, 0x8001, 0x78b2, 0x00c0,
- 0x228f, 0x78bc, 0xc0c4, 0x78be, 0x78b8, 0x2060, 0xa006, 0x007c,
- 0x0e7e, 0xa02e, 0x2530, 0x7dba, 0x7db6, 0x65ae, 0x65b2, 0x601c,
- 0x60a2, 0x2048, 0xa984, 0xe1ff, 0x601e, 0xa984, 0x0060, 0x0040,
- 0x22a3, 0x1078, 0x46b6, 0x6596, 0x65a6, 0x669a, 0x66aa, 0x6714,
- 0x2071, 0x4f80, 0xd7fc, 0x00c0, 0x22af, 0x2071, 0x4f40, 0xa784,
- 0x0f00, 0x800b, 0xa784, 0x001f, 0x0040, 0x22ba, 0x8003, 0x8003,
- 0x8003, 0x8003, 0xa105, 0x71c4, 0xa168, 0x2700, 0x8007, 0xa084,
- 0x000f, 0x8003, 0x8003, 0x8003, 0x71c8, 0xa100, 0x60c2, 0x2091,
- 0x8000, 0x7814, 0xd0c4, 0x0040, 0x22df, 0xd0ec, 0x0040, 0x22db,
- 0xd7fc, 0x00c0, 0x22d8, 0xd0f4, 0x00c0, 0x22e6, 0x0078, 0x22df,
- 0xd0fc, 0x00c0, 0x22e6, 0x7810, 0xd0f4, 0x00c0, 0x22e6, 0x6e08,
- 0xd684, 0x0040, 0x2310, 0xd9fc, 0x00c0, 0x2310, 0x2091, 0x8001,
- 0x1078, 0x1ea2, 0x2091, 0x8000, 0x1078, 0x2064, 0x2091, 0x8001,
- 0x7814, 0xd0e4, 0x00c0, 0x2375, 0x7814, 0xd0c4, 0x0040, 0x2375,
- 0xd0ec, 0x0040, 0x2308, 0xd7fc, 0x00c0, 0x2303, 0xd0f4, 0x00c0,
- 0x230c, 0x0078, 0x2375, 0xd0fc, 0x00c0, 0x230c, 0x0078, 0x2375,
- 0x7810, 0xd0f4, 0x0040, 0x2375, 0x601b, 0x0021, 0x0078, 0x2375,
- 0x6024, 0xa096, 0x0001, 0x00c0, 0x2317, 0x8000, 0x6026, 0x6a10,
- 0x6814, 0xa202, 0x0048, 0x232a, 0x0040, 0x232a, 0x2091, 0x8001,
- 0x2039, 0x0200, 0x609c, 0x78ba, 0x609f, 0x0000, 0x1078, 0x2377,
- 0x0078, 0x2375, 0x2c08, 0xd9fc, 0x0040, 0x2352, 0x6800, 0xa065,
- 0x0040, 0x2352, 0x6a04, 0x7000, 0xa084, 0x0002, 0x0040, 0x2348,
- 0x704c, 0xa206, 0x00c0, 0x2348, 0x6b04, 0x2160, 0x2304, 0x6002,
- 0xa005, 0x00c0, 0x2344, 0x6902, 0x2260, 0x6102, 0x0078, 0x235e,
- 0x2d00, 0x2060, 0x1078, 0x2b13, 0x6e08, 0x2160, 0x6202, 0x6906,
- 0x0078, 0x235e, 0x6800, 0x6902, 0xa065, 0x0040, 0x235a, 0x6102,
- 0x0078, 0x235b, 0x6906, 0x2160, 0x6003, 0x0000, 0x2160, 0xd9fc,
- 0x0040, 0x2365, 0xa6b4, 0xfffc, 0x6e0a, 0x6810, 0x7d08, 0x8528,
- 0x7d0a, 0x8000, 0x6812, 0x2091, 0x8001, 0xd6b4, 0x0040, 0x2375,
- 0xa6b6, 0x0040, 0x6e0a, 0x1078, 0x1eb3, 0x0e7f, 0x007c, 0x6008,
- 0xa705, 0x600a, 0x2091, 0x8000, 0x1078, 0x2064, 0x2091, 0x8001,
- 0x78b8, 0xa065, 0x0040, 0x238a, 0x609c, 0x78ba, 0x609f, 0x0000,
- 0x0078, 0x2377, 0x78b6, 0x78ba, 0x007c, 0x7970, 0x7874, 0x2818,
- 0xd384, 0x0040, 0x2397, 0x8000, 0xa112, 0x0048, 0x239c, 0x8000,
- 0xa112, 0x00c8, 0x23ac, 0xc384, 0x7a7c, 0x721a, 0x7a78, 0x721e,
- 0xdac4, 0x0040, 0x23a7, 0x7a84, 0x7222, 0x7a80, 0x7226, 0xa006,
- 0xd384, 0x0040, 0x23ac, 0x8000, 0x7876, 0x70d2, 0x781c, 0xa005,
- 0x0040, 0x23ba, 0x8001, 0x781e, 0x00c0, 0x23ba, 0x0068, 0x23ba,
- 0x2091, 0x4080, 0x007c, 0x2039, 0x23d3, 0x0078, 0x23c1, 0x2039,
- 0x23d9, 0x2704, 0xa005, 0x0040, 0x23d2, 0xac00, 0x2068, 0x6908,
- 0x6810, 0x6912, 0x680a, 0x690c, 0x6814, 0x6916, 0x680e, 0x8738,
- 0x0078, 0x23c1, 0x007c, 0x0003, 0x0009, 0x000f, 0x0015, 0x001b,
- 0x0000, 0x0015, 0x001b, 0x0000, 0x2041, 0x0000, 0x780c, 0x0079,
- 0x23e1, 0x25b3, 0x2586, 0x23e5, 0x245e, 0x2039, 0x9774, 0x2734,
- 0x7d10, 0x0078, 0x2405, 0x6084, 0xa086, 0x0103, 0x00c0, 0x2447,
- 0x6114, 0x6018, 0xa105, 0x0040, 0x23fa, 0x86ff, 0x00c0, 0x2416,
- 0x0078, 0x2447, 0x8603, 0xa080, 0x9755, 0x620c, 0x2202, 0x8000,
- 0x6210, 0x2202, 0x1078, 0x2086, 0x8630, 0xa68e, 0x000f, 0x0040,
- 0x24d2, 0x786c, 0xa065, 0x00c0, 0x23eb, 0x7808, 0xa602, 0x00c8,
- 0x2416, 0xd5ac, 0x00c0, 0x2416, 0x263a, 0x007c, 0xa682, 0x0003,
- 0x00c8, 0x24d2, 0x2091, 0x8000, 0x2069, 0x0000, 0x6818, 0xd084,
- 0x00c0, 0x2442, 0x2011, 0x9755, 0x2204, 0x70c6, 0x8210, 0x2204,
- 0x70ca, 0xd684, 0x00c0, 0x2432, 0x8210, 0x2204, 0x70da, 0x8210,
- 0x2204, 0x70de, 0xa685, 0x8020, 0x70c2, 0x681b, 0x0001, 0x2091,
- 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001, 0x203b,
- 0x0000, 0x007c, 0x7810, 0xc0ad, 0x7812, 0x0078, 0x24d2, 0x263a,
- 0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c, 0xa065, 0x00c0, 0x23eb,
- 0x2091, 0x8000, 0x7810, 0xa084, 0xffcf, 0x86ff, 0x0040, 0x2459,
- 0xc0ad, 0x7812, 0x2091, 0x8001, 0x0078, 0x25e0, 0x2039, 0x9774,
- 0x2734, 0x7d10, 0x0078, 0x247a, 0x6084, 0xa086, 0x0103, 0x00c0,
- 0x24bb, 0x6114, 0x6018, 0xa105, 0x0040, 0x2473, 0x86ff, 0x00c0,
- 0x248b, 0x0078, 0x24bb, 0xa680, 0x9755, 0x620c, 0x2202, 0x1078,
- 0x2086, 0x8630, 0xa68e, 0x001e, 0x0040, 0x24d2, 0x786c, 0xa065,
- 0x00c0, 0x2464, 0x7808, 0xa602, 0x00c8, 0x248b, 0xd5ac, 0x00c0,
- 0x248b, 0x263a, 0x007c, 0xa682, 0x0006, 0x00c8, 0x24d2, 0x2091,
- 0x8000, 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x24b6, 0x2011,
- 0x9755, 0x2009, 0x974e, 0x26a8, 0x211c, 0x2204, 0x201a, 0x8108,
- 0x8210, 0x00f0, 0x249c, 0xa685, 0x8030, 0x70c2, 0x681b, 0x0001,
- 0x2091, 0x4080, 0x7810, 0xa084, 0xffcf, 0x7812, 0x2091, 0x8001,
- 0xa006, 0x2009, 0x9775, 0x200a, 0x203a, 0x007c, 0x7810, 0xc0ad,
- 0x7812, 0x0078, 0x24d2, 0x263a, 0x1078, 0x25bd, 0x00c0, 0x25e0,
- 0x786c, 0xa065, 0x00c0, 0x2464, 0x2091, 0x8000, 0x7810, 0xa084,
- 0xffcf, 0x86ff, 0x0040, 0x24cd, 0xc0ad, 0x7812, 0x2091, 0x8001,
- 0x0078, 0x25e0, 0x2091, 0x8000, 0x7007, 0x0004, 0x7994, 0x70d4,
- 0xa102, 0x0048, 0x24e3, 0x0040, 0x24ed, 0x7b90, 0xa302, 0x00c0,
- 0x24ed, 0x0078, 0x24e6, 0x8002, 0x00c0, 0x24ed, 0x263a, 0x7810,
- 0xc0ad, 0x7812, 0x2091, 0x8001, 0x007c, 0xa184, 0xff00, 0x0040,
- 0x24fa, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
- 0x0078, 0x24fd, 0x8107, 0x8004, 0x8004, 0x7a9c, 0xa210, 0x721a,
- 0x7a98, 0xa006, 0xa211, 0x721e, 0xd4c4, 0x0040, 0x250d, 0x7aa4,
- 0xa211, 0x7222, 0x7aa0, 0xa211, 0x7226, 0x20a1, 0x0030, 0x7003,
- 0x0000, 0x2009, 0x9754, 0x260a, 0x8109, 0x2198, 0x2104, 0xd084,
- 0x0040, 0x251b, 0x8633, 0xa6b0, 0x0002, 0x26a8, 0x53a6, 0x8603,
- 0x7012, 0x7007, 0x0001, 0x7990, 0x7894, 0x8000, 0xa10a, 0x00c8,
- 0x252a, 0xa006, 0x2028, 0x7974, 0xa184, 0xff00, 0x0040, 0x2539,
- 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100, 0x0078,
- 0x253c, 0x8107, 0x8004, 0x8004, 0x797c, 0xa108, 0x7a78, 0xa006,
- 0xa211, 0xd4c4, 0x0040, 0x2548, 0x7b84, 0xa319, 0x7c80, 0xa421,
- 0x7008, 0xd0fc, 0x0040, 0x2548, 0xa084, 0x01e0, 0x0040, 0x256d,
- 0x7d10, 0x2031, 0x9754, 0x2634, 0x78a8, 0x8000, 0x78aa, 0xd08c,
- 0x00c0, 0x2562, 0x7007, 0x0006, 0x7004, 0xd094, 0x00c0, 0x255c,
- 0x0078, 0x24d4, 0x2069, 0x4f47, 0x206b, 0x0003, 0x78ac, 0xa085,
- 0x0300, 0x78ae, 0xa006, 0x0078, 0x2576, 0x2030, 0x75d6, 0x2091,
- 0x4080, 0x7d96, 0x7d10, 0xa5ac, 0xffcf, 0x7d12, 0x2091, 0x8001,
- 0x78aa, 0x7007, 0x0006, 0x263a, 0x7003, 0x0001, 0x711a, 0x721e,
- 0xd5c4, 0x0040, 0x2585, 0x7322, 0x7426, 0x007c, 0x6084, 0xa086,
- 0x0103, 0x00c0, 0x25a9, 0x6114, 0x6018, 0xa105, 0x00c0, 0x25a9,
- 0x2069, 0x0000, 0x6818, 0xd084, 0x00c0, 0x25a9, 0x600c, 0x70c6,
- 0x6010, 0x70ca, 0x70c3, 0x8020, 0x681b, 0x0001, 0x2091, 0x4080,
- 0x1078, 0x2086, 0x0068, 0x25a8, 0x786c, 0xa065, 0x00c0, 0x2586,
- 0x007c, 0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c, 0xa065, 0x00c0,
- 0x2586, 0x0078, 0x25e0, 0x1078, 0x25bd, 0x00c0, 0x25e0, 0x786c,
- 0xa065, 0x00c0, 0x25b3, 0x0078, 0x25e0, 0x6084, 0xa086, 0x0103,
- 0x00c0, 0x25d1, 0x6018, 0xc0fc, 0x601a, 0xa086, 0x0004, 0x00c0,
- 0x25d1, 0x7804, 0xd0a4, 0x0040, 0x25d1, 0x1078, 0x2086, 0xa006,
- 0x007c, 0x1078, 0x25e6, 0x00c0, 0x25d8, 0xa085, 0x0001, 0x007c,
- 0x1078, 0x25f5, 0x00c0, 0x25de, 0x2041, 0x0001, 0x7d10, 0x007c,
- 0x88ff, 0x0040, 0x25e5, 0x2091, 0x4080, 0x007c, 0x7b90, 0x7994,
- 0x70d4, 0xa102, 0x00c0, 0x25ef, 0xa385, 0x0000, 0x007c, 0x0048,
- 0x25f3, 0xa302, 0x007c, 0x8002, 0x007c, 0x7810, 0xd0ec, 0x0040,
- 0x260d, 0x0e7e, 0x2091, 0x8000, 0x2071, 0x0020, 0x7004, 0xa005,
- 0x00c0, 0x260a, 0x7008, 0x0e7f, 0xa086, 0x0008, 0x0040, 0x260d,
- 0x0078, 0x265e, 0x0e7f, 0x0078, 0x265e, 0xa184, 0xff00, 0x0040,
- 0x261a, 0x810f, 0x810c, 0x810c, 0x8004, 0x8004, 0x8007, 0xa100,
- 0x0078, 0x261d, 0x8107, 0x8004, 0x8004, 0x7a9c, 0x7b98, 0x7ca4,
- 0x7da0, 0xa210, 0xa006, 0xa319, 0xa421, 0xa529, 0x2009, 0x0018,
- 0x6028, 0xa005, 0x0040, 0x262e, 0x2009, 0x0040, 0x1078, 0x1dbb,
- 0x0040, 0x2650, 0x78a8, 0x8000, 0x78aa, 0xd08c, 0x00c0, 0x265e,
- 0x6014, 0xd0fc, 0x00c0, 0x2640, 0x2069, 0x4f40, 0x0078, 0x2642,
- 0x2069, 0x4f80, 0x2091, 0x8000, 0x681f, 0x0003, 0x78ab, 0x0000,
- 0x78ac, 0xa085, 0x0300, 0x78ae, 0x2091, 0x8001, 0x0078, 0x265e,
- 0x78ab, 0x0000, 0x1078, 0x2086, 0x7990, 0x7894, 0x8000, 0xa10a,
- 0x00c8, 0x265b, 0xa006, 0x7896, 0x70d6, 0xa006, 0x2071, 0x0010,
- 0x2091, 0x8001, 0x007c, 0xd7fc, 0x00c0, 0x266a, 0x2009, 0x4f59,
- 0x0078, 0x266c, 0x2009, 0x4f99, 0x2091, 0x8000, 0x200a, 0x0f7e,
- 0xd7fc, 0x00c0, 0x2683, 0x2009, 0x4f40, 0x2001, 0x4f04, 0x2004,
- 0xd0ec, 0x0040, 0x267f, 0x2079, 0x0100, 0x0078, 0x2687, 0x2079,
- 0x0200, 0x0078, 0x2687, 0x2009, 0x4f80, 0x2079, 0x0100, 0x2104,
- 0xa086, 0x0000, 0x00c0, 0x26a0, 0xd7fc, 0x00c0, 0x2693, 0x2009,
- 0x4f45, 0x0078, 0x2695, 0x2009, 0x4f85, 0x2104, 0xa005, 0x00c0,
- 0x26a0, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x26a0, 0x781b, 0x0045,
- 0x0f7f, 0x007c, 0x2009, 0x0002, 0x2069, 0x4f00, 0x6810, 0xd0ec,
- 0x00c0, 0x270f, 0x2071, 0x4f80, 0x2079, 0x0100, 0x2021, 0x51bf,
- 0x784b, 0x000f, 0x2019, 0x44a7, 0xd184, 0x0040, 0x26c3, 0x6810,
- 0xd0ec, 0x0040, 0x26bf, 0x20a1, 0x012b, 0x0078, 0x26c5, 0x20a1,
- 0x022b, 0x0078, 0x26c5, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040,
- 0x26d2, 0x789a, 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318,
- 0x0078, 0x26c5, 0x789b, 0x0020, 0x20a9, 0x0010, 0x6814, 0xd0e4,
- 0x0040, 0x26e2, 0x78af, 0x0000, 0x78af, 0x9020, 0x00f0, 0x26da,
- 0x0078, 0x26e8, 0x78af, 0x0000, 0x78af, 0x8020, 0x00f0, 0x26e2,
- 0x7003, 0x0000, 0x017e, 0xd18c, 0x2009, 0x0000, 0x0040, 0x26f1,
- 0xc1bd, 0x1078, 0x28e2, 0x017f, 0x7020, 0xa084, 0x000f, 0x007e,
- 0x6814, 0xd0e4, 0x007f, 0x00c0, 0x2701, 0xa085, 0x6340, 0x0078,
- 0x2703, 0xa085, 0x62c0, 0x7806, 0x780f, 0x9200, 0x7843, 0x00d8,
- 0x7853, 0x0080, 0x780b, 0x0008, 0x7456, 0x7053, 0x0000, 0x8109,
- 0x0040, 0x2722, 0x2071, 0x4f40, 0x6810, 0xd0ec, 0x0040, 0x271c,
- 0x2079, 0x0100, 0x0078, 0x271e, 0x2079, 0x0200, 0x2021, 0x4fbf,
- 0x0078, 0x26b0, 0x007c, 0x017e, 0xd1bc, 0x00c0, 0x2737, 0x007e,
- 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2733, 0x2011,
- 0x0101, 0x0078, 0x2739, 0x2011, 0x0201, 0x0078, 0x2739, 0x2011,
- 0x0101, 0xa18c, 0x000f, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012,
- 0x017f, 0x1078, 0x28e2, 0x007c, 0xd3fc, 0x00c0, 0x2757, 0x007e,
- 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x2753, 0x2011,
- 0x0101, 0x0078, 0x2759, 0x2011, 0x0201, 0x0078, 0x2759, 0x2011,
- 0x0101, 0x20a9, 0x0009, 0x810b, 0x00f0, 0x275b, 0xa18c, 0x0e00,
- 0x2204, 0xa084, 0xf1ff, 0xa105, 0x2012, 0x007c, 0x2019, 0x0002,
- 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x0040, 0x2773, 0x8319, 0x2009,
- 0x0101, 0x0078, 0x2775, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213,
- 0x00f0, 0x2777, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f, 0xa205,
- 0x200a, 0x8319, 0x0040, 0x2788, 0x2009, 0x0201, 0x0078, 0x2775,
- 0x007c, 0xd3fc, 0x00c0, 0x279c, 0x007e, 0x2001, 0x4f04, 0x2004,
- 0xd0ec, 0x007f, 0x0040, 0x2798, 0x2011, 0x0101, 0x0078, 0x279e,
- 0x2011, 0x0201, 0x0078, 0x279e, 0x2011, 0x0101, 0x20a9, 0x000c,
- 0x810b, 0x00f0, 0x27a0, 0xa18c, 0xf000, 0x2204, 0xa084, 0x0fff,
- 0xa105, 0x2012, 0x007c, 0xd3fc, 0x00c0, 0x27be, 0x007e, 0x2001,
- 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x27ba, 0x2011, 0x0102,
- 0x0078, 0x27c0, 0x2011, 0x0202, 0x0078, 0x27c0, 0x2011, 0x0102,
- 0x2204, 0xa084, 0xffcf, 0xa105, 0x2012, 0x007c, 0x0c7e, 0xd1bc,
- 0x00c0, 0x27da, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
- 0x0040, 0x27d6, 0x2061, 0x0100, 0x0078, 0x27dc, 0x2061, 0x0200,
- 0x0078, 0x27dc, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080,
- 0x0020, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c, 0x0c7e, 0xd1bc,
- 0x00c0, 0x27fa, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
- 0x0040, 0x27f6, 0x2061, 0x0100, 0x0078, 0x27fc, 0x2061, 0x0200,
- 0x0078, 0x27fc, 0x2061, 0x0100, 0xc1bc, 0x8103, 0x8003, 0xa080,
- 0x0022, 0x609a, 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c,
- 0x0c7e, 0xd1bc, 0x00c0, 0x281c, 0x007e, 0x2001, 0x4f04, 0x2004,
- 0xd0ec, 0x007f, 0x0040, 0x2818, 0x2061, 0x0100, 0x0078, 0x281e,
- 0x2061, 0x0200, 0x0078, 0x281e, 0x2061, 0x0100, 0xc1bc, 0x8103,
- 0x8003, 0xa080, 0x0022, 0x609a, 0x60a4, 0xa085, 0x0020, 0x60ae,
- 0x0c7f, 0x007c, 0x0c7e, 0xd1bc, 0x00c0, 0x283e, 0x007e, 0x2001,
- 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x283a, 0x2061, 0x0100,
- 0x0078, 0x2840, 0x2061, 0x0200, 0x0078, 0x2840, 0x2061, 0x0100,
- 0xc1bc, 0x8103, 0x8003, 0xa080, 0x0020, 0x609a, 0x60a4, 0xa28c,
- 0x0020, 0x0040, 0x284e, 0xc2ac, 0xa39d, 0x4000, 0xc3fc, 0xd3b4,
- 0x00c0, 0x2853, 0xc3fd, 0x62ae, 0x2010, 0x60a4, 0x63ae, 0x2018,
- 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e, 0x6818, 0xa005,
- 0x0040, 0x28c0, 0xd1fc, 0x0040, 0x2869, 0x2061, 0x96d0, 0x0078,
- 0x286b, 0x2061, 0x95c0, 0x1078, 0x28c8, 0x0040, 0x28a2, 0x20a9,
- 0x0101, 0xd1fc, 0x0040, 0x2878, 0x2061, 0x95d0, 0x0078, 0x287a,
- 0x2061, 0x94c0, 0x0c7e, 0x1078, 0x28c8, 0x0040, 0x2885, 0x0c7f,
- 0x8c60, 0x00f0, 0x287a, 0x0078, 0x28c0, 0x007f, 0xd1fc, 0x0040,
- 0x288f, 0xa082, 0x95d0, 0x2071, 0x4f80, 0x0078, 0x2893, 0xa082,
- 0x94c0, 0x2071, 0x4f40, 0x707a, 0x7176, 0x2138, 0x2001, 0x0004,
- 0x7066, 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x1078, 0x2663,
- 0x0078, 0x28bc, 0xd1fc, 0x00c0, 0x28a9, 0x2071, 0x4f40, 0x0078,
- 0x28ab, 0x2071, 0x4f80, 0x6020, 0xc0dd, 0x6022, 0x7176, 0x2138,
- 0x2c00, 0x707e, 0x2001, 0x0006, 0x7066, 0x7083, 0x000f, 0x71d4,
- 0xc1dc, 0x71d6, 0x1078, 0x2663, 0x2001, 0x0000, 0x0078, 0x28c2,
- 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f, 0x007c,
- 0x2c04, 0xa005, 0x0040, 0x28df, 0x2060, 0x6010, 0xa306, 0x00c0,
- 0x28dc, 0x600c, 0xa206, 0x00c0, 0x28dc, 0x6014, 0xa106, 0x00c0,
- 0x28dc, 0xa006, 0x0078, 0x28e1, 0x6000, 0x0078, 0x28c9, 0xa085,
- 0x0001, 0x007c, 0x0f7e, 0x0e7e, 0x017e, 0xd1bc, 0x00c0, 0x28fa,
- 0x2079, 0x4f40, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
- 0x0040, 0x28f6, 0x2071, 0x0100, 0x0078, 0x28fe, 0x2071, 0x0200,
- 0x0078, 0x28fe, 0x2079, 0x4f80, 0x2071, 0x0100, 0x7920, 0xa18c,
- 0x000f, 0x70ec, 0xd0c4, 0x00c0, 0x2908, 0x017f, 0x0078, 0x2923,
- 0x810b, 0x810b, 0x810b, 0x810b, 0x007f, 0xd0bc, 0x00c0, 0x2920,
- 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x291c,
- 0xa18d, 0x0f00, 0x0078, 0x2922, 0xa18d, 0x0f00, 0x0078, 0x2922,
- 0xa18d, 0x0800, 0x2104, 0x0e7f, 0x0f7f, 0x007c, 0x0e7e, 0x2001,
- 0x4f01, 0x2004, 0xd0ac, 0x00c0, 0x29a3, 0x68e4, 0xd0ac, 0x0040,
- 0x29a3, 0xa084, 0x0006, 0x00c0, 0x29a3, 0x6014, 0xd0fc, 0x00c0,
- 0x293d, 0x2071, 0x53c0, 0x0078, 0x293f, 0x2071, 0x5440, 0x8007,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xae70, 0x7004, 0xa084,
- 0x000a, 0x00c0, 0x29a3, 0x7108, 0xa194, 0xff00, 0x0040, 0x29a3,
- 0xa18c, 0x00ff, 0x2001, 0x000a, 0xa106, 0x0040, 0x2972, 0x2001,
- 0x000c, 0xa106, 0x0040, 0x2976, 0x2001, 0x0012, 0xa106, 0x0040,
- 0x297a, 0x2001, 0x0014, 0xa106, 0x0040, 0x297e, 0x2001, 0x0019,
- 0xa106, 0x0040, 0x2982, 0x2001, 0x0032, 0xa106, 0x0040, 0x2986,
- 0x0078, 0x298a, 0x2009, 0x000c, 0x0078, 0x298c, 0x2009, 0x0012,
- 0x0078, 0x298c, 0x2009, 0x0014, 0x0078, 0x298c, 0x2009, 0x0019,
- 0x0078, 0x298c, 0x2009, 0x0020, 0x0078, 0x298c, 0x2009, 0x003f,
- 0x0078, 0x298c, 0x2011, 0x0000, 0x2100, 0xa205, 0x700a, 0x2071,
- 0x4f00, 0x7004, 0xd0bc, 0x0040, 0x29a3, 0x6014, 0xd0fc, 0x00c0,
- 0x299e, 0x70ea, 0x2071, 0x4f40, 0x0078, 0x29a1, 0x70ee, 0x2071,
- 0x4f80, 0x701f, 0x000d, 0x0e7f, 0x007c, 0x2001, 0x4f05, 0x2004,
- 0xd0e4, 0x00c0, 0x29b1, 0x7804, 0xa084, 0xff1f, 0xa085, 0x6340,
- 0x7806, 0x007c, 0x0068, 0x29b2, 0x2091, 0x8000, 0x2071, 0x0000,
- 0x007e, 0x7018, 0xd084, 0x00c0, 0x29b9, 0x007f, 0x2071, 0x0010,
- 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002, 0x70db, 0x080f, 0x70df,
- 0x000b, 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x0078,
- 0x29cf, 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0x78a0, 0x708e, 0x7592,
- 0x7496, 0x769a, 0x779e, 0xa594, 0x003f, 0xd4f4, 0x0040, 0x29e6,
- 0xa784, 0x007d, 0x00c0, 0x441d, 0x1078, 0x29b2, 0xa49c, 0x000f,
- 0xa382, 0x0004, 0x0050, 0x29f1, 0xa3a6, 0x0007, 0x00c0, 0x29b2,
- 0x2418, 0x8507, 0xa084, 0x000f, 0x0079, 0x29f6, 0x3071, 0x3162,
- 0x318d, 0x33ff, 0x37e8, 0x3862, 0x3917, 0x39a8, 0x3a96, 0x3b85,
- 0x2a09, 0x2a06, 0x2e42, 0x2f65, 0x37b9, 0x2a06, 0x1078, 0x29b2,
- 0x007c, 0xa006, 0x0078, 0x2a13, 0x7808, 0xc08d, 0x780a, 0xa006,
- 0x7002, 0x704e, 0x7046, 0x70d2, 0x7060, 0xa005, 0x00c0, 0x2b79,
- 0x7064, 0xa084, 0x0007, 0x0079, 0x2a1d, 0x2a25, 0x2a98, 0x2aa1,
- 0x2aac, 0x2ab7, 0x2b5f, 0x2ac2, 0x2a98, 0x7830, 0xd0bc, 0x00c0,
- 0x2a08, 0x71d4, 0xd1bc, 0x00c0, 0x2a08, 0xd1b4, 0x00c0, 0x2a75,
- 0x70a4, 0xa086, 0x0001, 0x0040, 0x2a08, 0x70b4, 0xa06d, 0x6800,
- 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c, 0x7baa, 0x6808, 0xa045,
- 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886, 0x0001, 0x0040, 0x2a4b,
- 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d, 0x6e1c, 0x2001, 0x0010,
- 0x0078, 0x2cd3, 0x7060, 0xa005, 0x00c0, 0x2a08, 0x0c7e, 0x0d7e,
- 0x70b4, 0xa06d, 0x6800, 0xa065, 0xa055, 0x789b, 0x0010, 0x6b0c,
- 0x7baa, 0x6808, 0xa045, 0x6d10, 0x6804, 0xa06d, 0xa05d, 0xa886,
- 0x0001, 0x0040, 0x2a6e, 0x69bc, 0x7daa, 0x79aa, 0x68c0, 0xa04d,
- 0x6e1c, 0x2001, 0x0020, 0x0078, 0x2cd3, 0x1078, 0x43b0, 0x00c0,
- 0x2a08, 0x781b, 0x005b, 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894,
- 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a,
- 0x68bc, 0x7042, 0xc1b4, 0x71d6, 0x70b8, 0xa065, 0x68c0, 0x705a,
- 0x7003, 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c,
- 0x1078, 0x43b0, 0x00c0, 0x2aa0, 0x781b, 0x0047, 0x7003, 0x0004,
- 0x007c, 0x1078, 0x43b0, 0x00c0, 0x2aab, 0x2011, 0x000c, 0x1078,
- 0x2ad2, 0x7003, 0x0004, 0x007c, 0x1078, 0x43b0, 0x00c0, 0x2ab6,
- 0x2011, 0x0006, 0x1078, 0x2ad2, 0x7003, 0x0004, 0x007c, 0x1078,
- 0x43b0, 0x00c0, 0x2ac1, 0x2011, 0x000d, 0x1078, 0x2ad2, 0x7003,
- 0x0004, 0x007c, 0x1078, 0x43b0, 0x00c0, 0x2ad1, 0x2011, 0x0006,
- 0x1078, 0x2ad2, 0x707c, 0x707f, 0x0000, 0x2068, 0x704e, 0x7003,
- 0x0001, 0x007c, 0x7174, 0xc1fc, 0x8107, 0x7882, 0x789b, 0x0010,
- 0xa286, 0x000c, 0x00c0, 0x2ae1, 0x7aaa, 0x2001, 0x0001, 0x0078,
- 0x2af6, 0xa18c, 0x001f, 0xa18d, 0x00c0, 0x79aa, 0xa286, 0x000d,
- 0x0040, 0x2aef, 0x7aaa, 0x2001, 0x0002, 0x0078, 0x2af6, 0x78ab,
- 0x0020, 0x7178, 0x79aa, 0x7aaa, 0x2001, 0x0004, 0x789b, 0x0060,
- 0x78aa, 0x785b, 0x0004, 0x781b, 0x0116, 0x1078, 0x43d3, 0x7083,
- 0x000f, 0x70d4, 0xd0b4, 0x0040, 0x2b12, 0xc0b4, 0x70d6, 0x0c7e,
- 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
- 0x601a, 0x0c7f, 0x007c, 0x7014, 0xa005, 0x00c0, 0x2b21, 0x70d4,
- 0xd0b4, 0x0040, 0x2b22, 0x70b8, 0xac06, 0x00c0, 0x2b22, 0x1078,
- 0x2b01, 0x007c, 0x017e, 0x71a4, 0xa186, 0x0001, 0x0040, 0x2b54,
- 0x0d7e, 0x027e, 0x2100, 0x2011, 0x0001, 0xa212, 0x70b4, 0x2068,
- 0x6800, 0xac06, 0x0040, 0x2b3b, 0x8211, 0x0040, 0x2b52, 0x1078,
- 0x2b56, 0x0078, 0x2b30, 0x0c7e, 0x2100, 0x2011, 0x0001, 0xa212,
- 0x70b4, 0x2068, 0x6800, 0x2060, 0x6008, 0xa084, 0xfbef, 0x600a,
- 0x8211, 0x0040, 0x2b4f, 0x1078, 0x2b56, 0x0078, 0x2b42, 0x70a7,
- 0x0001, 0x0c7f, 0x027f, 0x0d7f, 0x017f, 0x007c, 0xade8, 0x0005,
- 0x70ac, 0xad06, 0x00c0, 0x2b5e, 0x70a8, 0x2068, 0x007c, 0x1078,
- 0x43b0, 0x00c0, 0x2a08, 0x707c, 0x2068, 0x7774, 0x1078, 0x424e,
- 0x2c50, 0x1078, 0x4492, 0x789b, 0x0010, 0x6814, 0xa084, 0x001f,
- 0xc0bd, 0x78aa, 0x6e1c, 0x2041, 0x0001, 0x2001, 0x0004, 0x0078,
- 0x2cd9, 0x1078, 0x43b0, 0x00c0, 0x2a08, 0x789b, 0x0010, 0x7060,
- 0x2068, 0x6f14, 0x70d4, 0xd0b4, 0x0040, 0x2b93, 0xc0b4, 0x70d6,
- 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018,
- 0x8001, 0x601a, 0x0c7f, 0x1078, 0x424e, 0x2c50, 0x1078, 0x4492,
- 0x6824, 0xa005, 0x0040, 0x2ba4, 0xa082, 0x0006, 0x0048, 0x2ba2,
- 0x0078, 0x2ba4, 0x6827, 0x0005, 0x6814, 0xa084, 0x001f, 0xc0bd,
- 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001, 0x2001, 0x0003, 0x0078,
- 0x2cd9, 0xc28d, 0x72d6, 0x72c0, 0xa200, 0xa015, 0x7154, 0x8108,
- 0xa12a, 0x0048, 0x2bbc, 0x71c0, 0x2164, 0x6504, 0x85ff, 0x00c0,
- 0x2bd3, 0x7156, 0x8421, 0x00c0, 0x2bb7, 0x70d4, 0xd08c, 0x0040,
- 0x2bcf, 0x70d0, 0xa005, 0x00c0, 0x2bcf, 0x70d3, 0x000a, 0x007c,
- 0x2200, 0x0078, 0x2bc1, 0x70d4, 0xc08c, 0x70d6, 0x70d3, 0x0000,
- 0x6034, 0xa005, 0x00c0, 0x2bd0, 0x6708, 0xa784, 0x073f, 0x0040,
- 0x2c02, 0xd7d4, 0x00c0, 0x2bd0, 0xa784, 0x0021, 0x00c0, 0x2bd0,
- 0xa784, 0x0002, 0x0040, 0x2bf3, 0xa784, 0x0004, 0x0040, 0x2bd0,
- 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0218, 0x00c0, 0x2bd0, 0xa784,
- 0x0100, 0x0040, 0x2c02, 0x6018, 0xa005, 0x00c0, 0x2bd0, 0xa7bc,
- 0xfeff, 0x670a, 0x2568, 0x6823, 0x0000, 0x6e1c, 0xa684, 0x000e,
- 0x6318, 0x0040, 0x2c13, 0x601c, 0xa302, 0x0048, 0x2c16, 0x0040,
- 0x2c16, 0x0078, 0x2bd0, 0x83ff, 0x00c0, 0x2bd0, 0x2d58, 0x2c50,
- 0x7156, 0xd7bc, 0x00c0, 0x2c1f, 0x7028, 0x6022, 0x603a, 0xc7bc,
- 0x670a, 0x68c0, 0xa065, 0xa04d, 0x6100, 0x2a60, 0x2041, 0x0001,
- 0x6b14, 0xa39c, 0x001f, 0xa39d, 0x00c0, 0xd1fc, 0x0040, 0x2c33,
- 0xd684, 0x0040, 0x2c35, 0xa39c, 0xffbf, 0xd6a4, 0x0040, 0x2c3a,
- 0xa39d, 0x0020, 0xa684, 0x000e, 0x00c0, 0x2c85, 0xc7a5, 0x670a,
- 0x2c00, 0x68c6, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c59, 0x70d4,
- 0xd0b4, 0x00c0, 0x2c59, 0x7000, 0xa082, 0x0002, 0x00c8, 0x2c59,
- 0x7830, 0xd0bc, 0x00c0, 0x2c59, 0x789b, 0x0010, 0x7baa, 0x0078,
- 0x2cd1, 0x8739, 0x77a6, 0x2750, 0x77b0, 0xa7b0, 0x0005, 0x70ac,
- 0xa606, 0x00c0, 0x2c64, 0x76a8, 0x76b2, 0x2c3a, 0x8738, 0x2d3a,
- 0x8738, 0x283a, 0x8738, 0x233a, 0x8738, 0x253a, 0x7830, 0xd0bc,
- 0x0040, 0x2c7c, 0x2091, 0x8000, 0x2091, 0x303d, 0x70d4, 0xa084,
- 0x303d, 0x2091, 0x8000, 0x2090, 0xaad5, 0x0000, 0x0040, 0x2c84,
- 0x8421, 0x2200, 0x00c0, 0x2bb6, 0x007c, 0xd1dc, 0x0040, 0x3e49,
- 0x2029, 0x0020, 0xd69c, 0x00c0, 0x2c92, 0x8528, 0xd68c, 0x00c0,
- 0x2c92, 0x8528, 0x8840, 0x6f14, 0x610c, 0x8108, 0xa18c, 0x00ff,
- 0x70cc, 0xa160, 0x2c64, 0x8cff, 0x0040, 0x2cb1, 0x6014, 0xa706,
- 0x00c0, 0x2c9a, 0x60b8, 0x8001, 0x60ba, 0x00c0, 0x2c95, 0x2a60,
- 0x6008, 0xa085, 0x0100, 0x600a, 0x2200, 0x8421, 0x00c0, 0x2bb6,
- 0x007c, 0x2a60, 0x610e, 0x69be, 0x2c00, 0x68c6, 0x8840, 0x6008,
- 0xc0d5, 0x600a, 0x77a4, 0xa786, 0x0001, 0x00c0, 0x2c59, 0x70d4,
- 0xd0b4, 0x00c0, 0x2c59, 0x7000, 0xa082, 0x0002, 0x00c8, 0x2c59,
- 0x7830, 0xd0bc, 0x00c0, 0x2c59, 0x789b, 0x0010, 0x7baa, 0x7daa,
- 0x79aa, 0x2001, 0x0002, 0x007e, 0x6018, 0x8000, 0x601a, 0x0078,
- 0x2cda, 0x007e, 0x2960, 0x6104, 0x2a60, 0xa184, 0x0018, 0x0040,
- 0x2cf6, 0xa184, 0x0010, 0x0040, 0x2ce9, 0x1078, 0x405e, 0x00c0,
- 0x2d1b, 0xa184, 0x0008, 0x0040, 0x2cf6, 0x69a0, 0xa184, 0x0600,
- 0x00c0, 0x2cf6, 0x1078, 0x3f3e, 0x0078, 0x2d1b, 0x69a0, 0xa184,
- 0x1e00, 0x0040, 0x2d26, 0xa184, 0x0800, 0x0040, 0x2d0f, 0x0c7e,
- 0x2960, 0x6000, 0xa085, 0x2000, 0x6002, 0x6104, 0xa18d, 0x0010,
- 0x6106, 0x0c7f, 0x1078, 0x405e, 0x00c0, 0x2d1b, 0x69a0, 0xa184,
- 0x0200, 0x0040, 0x2d17, 0x1078, 0x3fa1, 0x0078, 0x2d1b, 0xa184,
- 0x0400, 0x00c0, 0x2cf2, 0x69a0, 0xa184, 0x1000, 0x0040, 0x2d26,
- 0x6914, 0xa18c, 0xff00, 0x810f, 0x1078, 0x27e6, 0x027f, 0xa68c,
- 0x00e0, 0xa684, 0x0060, 0x0040, 0x2d33, 0xa086, 0x0060, 0x00c0,
- 0x2d33, 0xa18d, 0x4000, 0xa18d, 0x0104, 0x69b6, 0x789b, 0x0060,
- 0x2800, 0x78aa, 0x6818, 0xc0fd, 0x681a, 0xd6bc, 0x0040, 0x2d4e,
- 0xc0fc, 0x7087, 0x0000, 0xa08a, 0x000d, 0x0050, 0x2d4c, 0xa08a,
- 0x000c, 0x7186, 0x2001, 0x000c, 0x800c, 0x718a, 0x78aa, 0x3518,
- 0x3340, 0x3428, 0x8000, 0x80ac, 0xaf80, 0x002b, 0x20a0, 0x789b,
- 0x0000, 0xad80, 0x000b, 0x2098, 0x53a6, 0x23a8, 0x2898, 0x25a0,
- 0xa286, 0x0020, 0x00c0, 0x2d86, 0x70d4, 0xc0b5, 0x70d6, 0x2c00,
- 0x70ba, 0x2d00, 0x70be, 0x6814, 0xc0fc, 0x8007, 0x7882, 0xa286,
- 0x0002, 0x0040, 0x2dbc, 0x70a4, 0x8000, 0x70a6, 0x74b4, 0xa498,
- 0x0005, 0x70ac, 0xa306, 0x00c0, 0x2d7e, 0x73a8, 0x73b6, 0xa286,
- 0x0010, 0x0040, 0x2a08, 0x0d7f, 0x0c7f, 0x007c, 0x7000, 0xa005,
- 0x00c0, 0x2d64, 0xa286, 0x0002, 0x00c0, 0x2dd6, 0x1078, 0x43b0,
- 0x00c0, 0x2d64, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x2091, 0x8000,
- 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898,
- 0x78d2, 0x78da, 0x2091, 0x8001, 0x7808, 0xc08d, 0x780a, 0x127e,
- 0x0d7e, 0x0c7e, 0x70d4, 0xa084, 0x2700, 0x2090, 0x0c7f, 0x0d7f,
- 0x127f, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003, 0x0002, 0x2d00,
- 0x704e, 0xad80, 0x0009, 0x7046, 0x7830, 0xd0bc, 0x0040, 0x2dc8,
- 0x2091, 0x303d, 0x70d4, 0xa084, 0x303d, 0x2091, 0x8000, 0x2090,
- 0x70a4, 0xa005, 0x00c0, 0x2dcd, 0x007c, 0x8421, 0x0040, 0x2dcc,
- 0x7250, 0x70c0, 0xa200, 0xa015, 0x0078, 0x2bb6, 0xa286, 0x0010,
- 0x00c0, 0x2e07, 0x1078, 0x43b0, 0x00c0, 0x2d64, 0x6814, 0xc0fc,
- 0x8007, 0x7882, 0x781b, 0x005b, 0x68b4, 0x785a, 0x6894, 0x78d6,
- 0x78de, 0x6898, 0x78d2, 0x78da, 0x7808, 0xc08d, 0x780a, 0x70a4,
- 0x8000, 0x70a6, 0x74b4, 0xa490, 0x0005, 0x70ac, 0xa206, 0x00c0,
- 0x2dfa, 0x72a8, 0x72b6, 0x2900, 0x705a, 0x68bc, 0x7042, 0x7003,
- 0x0002, 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0x6bb4,
- 0xa39d, 0x2000, 0x7b5a, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x6b94,
- 0x7bd6, 0x7bde, 0x6e98, 0x7ed2, 0x7eda, 0x781b, 0x005b, 0x2900,
- 0x705a, 0x7202, 0x7808, 0xc08d, 0x780a, 0x2300, 0xa605, 0x0040,
- 0x2e32, 0x70d4, 0xa084, 0x2700, 0xa086, 0x2300, 0x00c0, 0x2e2c,
- 0x2009, 0x0000, 0x0078, 0x2e2e, 0x2009, 0x0001, 0xa284, 0x000f,
- 0x1079, 0x2e38, 0xad80, 0x0009, 0x7046, 0x2d00, 0x704e, 0x007c,
- 0x2e40, 0x493f, 0x493f, 0x492c, 0x493f, 0x2e40, 0x2e40, 0x2e40,
- 0x1078, 0x29b2, 0x7808, 0xa084, 0xfffd, 0x780a, 0x1078, 0x29a5,
- 0x0f7e, 0x2079, 0x4f00, 0x78ac, 0x0f7f, 0xd084, 0x0040, 0x2e6a,
- 0x7064, 0xa086, 0x0001, 0x00c0, 0x2e58, 0x7066, 0x0078, 0x2f41,
- 0x7064, 0xa086, 0x0005, 0x00c0, 0x2e68, 0x707c, 0x2068, 0x681b,
- 0x0004, 0x6817, 0x0000, 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822,
- 0x7067, 0x0000, 0x70a7, 0x0000, 0x70a8, 0x70b2, 0x70b6, 0x1078,
- 0x2b01, 0x157e, 0x2011, 0x0004, 0x7164, 0xa186, 0x0001, 0x0040,
- 0x2e8a, 0xa186, 0x0007, 0x00c0, 0x2e81, 0x701f, 0x0005, 0x0078,
- 0x2e8a, 0x701f, 0x0001, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6,
- 0x0078, 0x2e8c, 0x7067, 0x0000, 0x2001, 0x4f0a, 0x2004, 0xa084,
- 0x00ff, 0xa086, 0x0018, 0x0040, 0x2e9c, 0x7018, 0x7016, 0xa005,
- 0x00c0, 0x2e9c, 0x70a7, 0x0001, 0x067e, 0x1078, 0x45d6, 0x20a9,
- 0x0010, 0x2039, 0x0000, 0x1078, 0x4148, 0xa7b8, 0x0100, 0x00f0,
- 0x2ea3, 0x067f, 0x7000, 0x0079, 0x2ead, 0x2ee7, 0x2ec2, 0x2ec2,
- 0x2eb7, 0x2ee7, 0x2ee7, 0x2ee7, 0x2eb5, 0x1078, 0x29b2, 0x7060,
- 0xa005, 0x0040, 0x2ee7, 0xad06, 0x00c0, 0x2ec2, 0x6800, 0x7062,
- 0x0078, 0x2ed4, 0x6820, 0xd084, 0x00c0, 0x2ed0, 0x6f14, 0x1078,
- 0x424e, 0x6008, 0xc0d4, 0x600a, 0x1078, 0x3e19, 0x0078, 0x2ed4,
- 0x705c, 0x2060, 0x6800, 0x6002, 0xa684, 0x5f00, 0x681e, 0x6818,
- 0xd0fc, 0x0040, 0x2edc, 0x6a1a, 0x6817, 0x0000, 0x682b, 0x0000,
- 0x6820, 0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x2073, 0xb284,
- 0x0400, 0x0040, 0x2eef, 0x2021, 0x96d0, 0x0078, 0x2ef1, 0x2021,
- 0x95c0, 0x1078, 0x2f46, 0xb284, 0x0400, 0x0040, 0x2efb, 0x2021,
- 0x4f98, 0x0078, 0x2efd, 0x2021, 0x4f58, 0x1078, 0x2f46, 0x20a9,
- 0x0101, 0xb284, 0x0400, 0x0040, 0x2f09, 0x2021, 0x95d0, 0x0078,
- 0x2f0b, 0x2021, 0x94c0, 0x1078, 0x2f46, 0x8420, 0x00f0, 0x2f0b,
- 0xb284, 0x0300, 0x0040, 0x2f18, 0x2061, 0x54c0, 0x0078, 0x2f1a,
- 0x2061, 0x74c0, 0x2021, 0x0002, 0x20a9, 0x0100, 0x6110, 0x81ff,
- 0x0040, 0x2f37, 0x6018, 0x017e, 0x007e, 0x2011, 0x4f02, 0x220c,
- 0xa102, 0x2012, 0x007f, 0x017f, 0xa102, 0x0050, 0x2f37, 0x6012,
- 0x00c0, 0x2f37, 0x2011, 0x4f04, 0x2204, 0xc0a5, 0x2012, 0x601b,
- 0x0000, 0xace0, 0x0010, 0x00f0, 0x2f1e, 0x8421, 0x00c0, 0x2f1c,
- 0x157f, 0x7003, 0x0000, 0x704f, 0x0000, 0x007c, 0x047e, 0x2404,
- 0xa005, 0x0040, 0x2f61, 0x2068, 0x6800, 0x007e, 0x6a1a, 0x6817,
- 0x0000, 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820,
- 0xa084, 0x00ff, 0xc09d, 0x6822, 0x1078, 0x2073, 0x007f, 0x0078,
- 0x2f48, 0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050,
- 0x2f6b, 0x1078, 0x29b2, 0x2300, 0x0079, 0x2f6e, 0x2f71, 0x2ffc,
- 0x3019, 0xa282, 0x0002, 0x0040, 0x2f77, 0x1078, 0x29b2, 0x7064,
- 0x7067, 0x0000, 0x7083, 0x0000, 0x0079, 0x2f7e, 0x2f86, 0x2f86,
- 0x2f88, 0x2fc8, 0x3e55, 0x2f86, 0x2fc8, 0x2f86, 0x1078, 0x29b2,
- 0x7774, 0x1078, 0x4148, 0x7774, 0xa7bc, 0x8f00, 0x1078, 0x424e,
- 0x6018, 0xa005, 0x0040, 0x2fbf, 0xd7fc, 0x00c0, 0x2f9b, 0x2021,
- 0x95c0, 0x0078, 0x2f9d, 0x2021, 0x96d0, 0x2009, 0x0005, 0x2011,
- 0x0010, 0x1078, 0x3034, 0x0040, 0x2fbf, 0x157e, 0x20a9, 0x0101,
- 0xd7fc, 0x00c0, 0x2faf, 0x2021, 0x94c0, 0x0078, 0x2fb1, 0x2021,
- 0x95d0, 0x047e, 0x2009, 0x0005, 0x2011, 0x0010, 0x1078, 0x3034,
- 0x047f, 0x0040, 0x2fbe, 0x8420, 0x00f0, 0x2fb1, 0x157f, 0x8738,
- 0xa784, 0x001f, 0x00c0, 0x2f8e, 0x0078, 0x2a0c, 0x0078, 0x2a0c,
- 0x7774, 0x1078, 0x424e, 0x6018, 0xa005, 0x0040, 0x2ffa, 0xd7fc,
- 0x00c0, 0x2fd6, 0x2021, 0x95c0, 0x0078, 0x2fd8, 0x2021, 0x96d0,
- 0x2009, 0x0005, 0x2011, 0x0020, 0x1078, 0x3034, 0x0040, 0x2ffa,
- 0x157e, 0x20a9, 0x0101, 0xd7fc, 0x00c0, 0x2fea, 0x2021, 0x94c0,
- 0x0078, 0x2fec, 0x2021, 0x95d0, 0x047e, 0x2009, 0x0005, 0x2011,
- 0x0020, 0x1078, 0x3034, 0x047f, 0x0040, 0x2ff9, 0x8420, 0x00f0,
- 0x2fec, 0x157f, 0x0078, 0x2a0c, 0x2200, 0x0079, 0x2fff, 0x3002,
- 0x3004, 0x3004, 0x1078, 0x29b2, 0x2009, 0x0012, 0x7064, 0xa086,
- 0x0002, 0x0040, 0x300d, 0x2009, 0x000e, 0x6818, 0xd0fc, 0x0040,
- 0x3012, 0x691a, 0x7067, 0x0000, 0x70d4, 0xc0dd, 0x70d6, 0x0078,
- 0x435d, 0x2200, 0x0079, 0x301c, 0x3021, 0x3004, 0x301f, 0x1078,
- 0x29b2, 0x1078, 0x45d6, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3dc7,
- 0x1078, 0x3e36, 0x6008, 0xa084, 0xfbef, 0x600a, 0x1078, 0x3db8,
- 0x0040, 0x3dc7, 0x0078, 0x2a0c, 0x2404, 0xa005, 0x0040, 0x306d,
- 0x2068, 0x2d04, 0x007e, 0x6814, 0xa706, 0x0040, 0x3043, 0x2d20,
- 0x007f, 0x0078, 0x3035, 0x007f, 0x2022, 0x691a, 0x6817, 0x0000,
- 0x682b, 0x0000, 0x68b4, 0xa084, 0x5f00, 0x681e, 0x6820, 0xa084,
- 0x00ff, 0xa205, 0x6822, 0x1078, 0x2073, 0x2021, 0x4f02, 0x241c,
- 0x8319, 0x2322, 0x6010, 0x8001, 0x6012, 0x00c0, 0x3064, 0x2021,
- 0x4f04, 0x2404, 0xc0a5, 0x2022, 0x6008, 0xa084, 0xf9ef, 0x600a,
- 0x1078, 0x2b22, 0x1078, 0x3e36, 0x007c, 0xa085, 0x0001, 0x0078,
- 0x306c, 0x2300, 0x0079, 0x3074, 0x3079, 0x3077, 0x30f9, 0x1078,
- 0x29b2, 0x78e4, 0xa005, 0x00d0, 0x30af, 0x3208, 0x007e, 0x2001,
- 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x308a, 0xa18c, 0x0300,
- 0x0078, 0x308c, 0xa18c, 0x0400, 0x0040, 0x3092, 0x0018, 0x2a08,
- 0x0078, 0x3094, 0x0028, 0x2a08, 0x2008, 0xa084, 0x0030, 0x00c0,
- 0x309b, 0x0078, 0x37b9, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3099,
- 0x2100, 0xa084, 0x0007, 0x0079, 0x30a5, 0x30d9, 0x30e3, 0x30ce,
- 0x30ad, 0x43a5, 0x43a5, 0x30ad, 0x30ee, 0x1078, 0x29b2, 0x7000,
- 0xa086, 0x0004, 0x00c0, 0x30c9, 0x7064, 0xa086, 0x0002, 0x00c0,
- 0x30bf, 0x2011, 0x0002, 0x2019, 0x0000, 0x0078, 0x2f65, 0x7064,
- 0xa086, 0x0006, 0x0040, 0x30b9, 0x7064, 0xa086, 0x0004, 0x0040,
- 0x30b9, 0x79e4, 0x2001, 0x0003, 0x0078, 0x3443, 0x6818, 0xd0fc,
- 0x0040, 0x30d4, 0x681b, 0x001d, 0x1078, 0x4118, 0x781b, 0x0064,
- 0x007c, 0x6818, 0xd0fc, 0x0040, 0x30df, 0x681b, 0x001d, 0x1078,
- 0x4118, 0x0078, 0x4381, 0x6818, 0xd0fc, 0x0040, 0x30e9, 0x681b,
- 0x001d, 0x1078, 0x4118, 0x781b, 0x00f8, 0x007c, 0x6818, 0xd0fc,
- 0x0040, 0x30f4, 0x681b, 0x001d, 0x1078, 0x4118, 0x781b, 0x00c8,
- 0x007c, 0xa584, 0x000f, 0x00c0, 0x3118, 0x1078, 0x29a5, 0x7000,
- 0x0079, 0x3102, 0x2a0c, 0x310a, 0x310c, 0x3dc7, 0x3dc7, 0x3dc7,
- 0x310a, 0x310a, 0x1078, 0x29b2, 0x1078, 0x3e36, 0x6008, 0xa084,
- 0xfbef, 0x600a, 0x1078, 0x3db8, 0x0040, 0x3dc7, 0x0078, 0x2a0c,
- 0x78e4, 0xa005, 0x00d0, 0x30af, 0x3208, 0x007e, 0x2001, 0x4f04,
- 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3129, 0xa18c, 0x0300, 0x0078,
- 0x312b, 0xa18c, 0x0400, 0x0040, 0x3131, 0x0018, 0x30af, 0x0078,
- 0x3133, 0x0028, 0x30af, 0x2008, 0xa084, 0x0030, 0x00c0, 0x313b,
- 0x781b, 0x005b, 0x007c, 0x78ec, 0xa084, 0x0003, 0x0040, 0x3138,
- 0x2100, 0xa184, 0x0007, 0x0079, 0x3145, 0x3154, 0x3158, 0x314f,
- 0x314d, 0x43a5, 0x43a5, 0x314d, 0x439f, 0x1078, 0x29b2, 0x1078,
- 0x4120, 0x781b, 0x0064, 0x007c, 0x1078, 0x4120, 0x0078, 0x4381,
- 0x1078, 0x4120, 0x781b, 0x00f8, 0x007c, 0x1078, 0x4120, 0x781b,
- 0x00c8, 0x007c, 0x2300, 0x0079, 0x3165, 0x316a, 0x3168, 0x316c,
- 0x1078, 0x29b2, 0x0078, 0x39a8, 0x681b, 0x0016, 0x78a3, 0x0000,
- 0x79e4, 0xa184, 0x0030, 0x0040, 0x39a8, 0x78ec, 0xa084, 0x0003,
- 0x0040, 0x39a8, 0xa184, 0x0100, 0x0040, 0x3170, 0xa184, 0x0007,
- 0x0079, 0x3182, 0x318a, 0x3158, 0x30ce, 0x435d, 0x43a5, 0x43a5,
- 0x435d, 0x439f, 0x1078, 0x4369, 0x007c, 0xa282, 0x0005, 0x0050,
- 0x3193, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3196, 0x3199, 0x33c9,
- 0x33d4, 0x2200, 0x0079, 0x319c, 0x31b6, 0x31a3, 0x31b6, 0x31a1,
- 0x33ac, 0x1078, 0x29b2, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
- 0xa082, 0x0020, 0x0048, 0x4107, 0xa08a, 0x0004, 0x00c8, 0x4107,
- 0x0079, 0x31b2, 0x4107, 0x4107, 0x4107, 0x40b1, 0x789b, 0x0018,
- 0x79a8, 0xa184, 0x0080, 0x0040, 0x31c7, 0x0078, 0x4107, 0x7000,
- 0xa005, 0x00c0, 0x31bd, 0x2011, 0x0004, 0x0078, 0x3b93, 0xa184,
- 0x00ff, 0xa08a, 0x0010, 0x00c8, 0x4107, 0x0079, 0x31cf, 0x31e1,
- 0x31df, 0x31f6, 0x31fa, 0x32cd, 0x4107, 0x4107, 0x32cf, 0x4107,
- 0x4107, 0x33a8, 0x33a8, 0x4107, 0x4107, 0x4107, 0x33aa, 0x1078,
- 0x29b2, 0xd6e4, 0x0040, 0x31ec, 0x2001, 0x0300, 0x8000, 0x8000,
- 0x783a, 0x781b, 0x00c3, 0x007c, 0x6818, 0xd0fc, 0x0040, 0x31f4,
- 0x681b, 0x001d, 0x0078, 0x31e4, 0x0078, 0x435d, 0x681b, 0x001d,
- 0x0078, 0x4111, 0x6920, 0x6922, 0xa684, 0x1800, 0x00c0, 0x325f,
- 0x6820, 0xd084, 0x00c0, 0x3265, 0x6818, 0xa086, 0x0008, 0x00c0,
- 0x320b, 0x681b, 0x0000, 0xd6d4, 0x0040, 0x32ca, 0xd6bc, 0x0040,
- 0x324b, 0x7087, 0x0000, 0x6818, 0xa084, 0x003f, 0xa08a, 0x000d,
- 0x0050, 0x324b, 0xa08a, 0x000c, 0x7186, 0x2001, 0x000c, 0x800c,
- 0x718a, 0x789b, 0x0061, 0x78aa, 0x157e, 0x137e, 0x147e, 0x017e,
- 0x3208, 0xa18c, 0x0300, 0x0040, 0x323d, 0x007e, 0x2001, 0x4f04,
- 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3239, 0x20a1, 0x012b, 0x0078,
- 0x323f, 0x20a1, 0x022b, 0x0078, 0x323f, 0x20a1, 0x012b, 0x017f,
- 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6,
- 0x147f, 0x137f, 0x157f, 0x6038, 0xa005, 0x00c0, 0x325a, 0x681c,
- 0xa084, 0x000e, 0x0040, 0x4111, 0x1078, 0x4127, 0x782b, 0x3008,
- 0x0078, 0x325c, 0x8001, 0x603a, 0x781b, 0x0067, 0x007c, 0xd6e4,
- 0x0040, 0x3265, 0x781b, 0x0079, 0x007c, 0xa684, 0x0060, 0x0040,
- 0x32c7, 0xd6dc, 0x0040, 0x32c7, 0xd6fc, 0x00c0, 0x3271, 0x0078,
- 0x3288, 0xc6fc, 0x7e5a, 0x6eb6, 0x7adc, 0x79d8, 0x78d0, 0x801b,
- 0x00c8, 0x327b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
- 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae,
- 0xd6f4, 0x0040, 0x328e, 0xc6f4, 0x7e5a, 0x6eb6, 0x7000, 0xa086,
- 0x0003, 0x00c0, 0x329c, 0x007e, 0x1078, 0x45d6, 0x1078, 0x493f,
- 0x007f, 0x781b, 0x0076, 0x007c, 0xa006, 0x1078, 0x4a44, 0x6ab0,
- 0x69ac, 0x6c98, 0x6b94, 0x2200, 0xa105, 0x0040, 0x32ab, 0x2200,
- 0xa422, 0x2100, 0xa31b, 0x6caa, 0x7cd2, 0x7cda, 0x6ba6, 0x7bd6,
- 0x7bde, 0x2300, 0xa405, 0x00c0, 0x32bb, 0xc6f5, 0x7e5a, 0x6eb6,
- 0x781b, 0x0076, 0x007c, 0x781b, 0x0076, 0x2200, 0xa115, 0x00c0,
- 0x32c4, 0x1078, 0x493f, 0x007c, 0x1078, 0x4977, 0x007c, 0x781b,
- 0x0079, 0x007c, 0x781b, 0x0067, 0x007c, 0x1078, 0x29b2, 0x0078,
- 0x331b, 0x6920, 0xd1c4, 0x0040, 0x32e4, 0xc1c4, 0x6922, 0x0c7e,
- 0x7058, 0x2060, 0x6000, 0xc0e4, 0x6002, 0x6004, 0xa084, 0xfff5,
- 0x6006, 0x0c7f, 0x0078, 0x330f, 0xd1cc, 0x0040, 0x330f, 0xc1cc,
- 0x6922, 0x0c7e, 0x7058, 0x2060, 0x6000, 0xc0ec, 0x6002, 0x6004,
- 0xc0a4, 0x6006, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x330f,
- 0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x330f, 0x789b,
- 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
- 0x330c, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58,
- 0xd6d4, 0x00c0, 0x3316, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
- 0x007c, 0x0078, 0x410c, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007,
- 0x00c0, 0x3329, 0x6820, 0xa084, 0x0100, 0x0040, 0x3319, 0x2009,
- 0x0008, 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001,
- 0x00c0, 0x3345, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040,
- 0x333d, 0x0048, 0x333d, 0x0078, 0x333f, 0x0078, 0x32d1, 0x24a8,
- 0x7aa8, 0x00f0, 0x333f, 0x0078, 0x332b, 0xa284, 0x00f0, 0xa086,
- 0x0020, 0x00c0, 0x3399, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040,
- 0x3355, 0x0048, 0x3355, 0x0078, 0x3396, 0xa286, 0x0023, 0x0040,
- 0x3319, 0x681c, 0xa084, 0xfff1, 0x681e, 0x7e58, 0xa684, 0xfff1,
- 0xc0a5, 0x2030, 0x7e5a, 0x6008, 0xc0a5, 0x600a, 0x0c7e, 0x7058,
- 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd1a4, 0x0040, 0x3376,
- 0x1078, 0x424a, 0x1078, 0x405e, 0x0078, 0x3384, 0x0c7e, 0x7058,
- 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xd19c, 0x0040, 0x330f,
- 0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x330f, 0x789b,
- 0x0060, 0x2800, 0x78aa, 0xc695, 0x7e5a, 0xd6d4, 0x00c0, 0x3393,
- 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7aa8, 0x0078,
- 0x332b, 0x8318, 0x2300, 0xa102, 0x0040, 0x33a2, 0x0048, 0x33a2,
- 0x0078, 0x332b, 0xa284, 0x0080, 0x00c0, 0x4111, 0x0078, 0x410c,
- 0x0078, 0x4111, 0x0078, 0x4107, 0x7058, 0xa04d, 0x789b, 0x0018,
- 0x78a8, 0xa084, 0x00ff, 0xa08e, 0x0001, 0x0040, 0x33b9, 0x1078,
- 0x29b2, 0x7aa8, 0xa294, 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a,
- 0x0004, 0x00c8, 0x4107, 0x0079, 0x33c5, 0x4107, 0x3e8f, 0x4107,
- 0x4006, 0xa282, 0x0000, 0x00c0, 0x33cf, 0x1078, 0x29b2, 0x1078,
- 0x4118, 0x781b, 0x0078, 0x007c, 0xa282, 0x0003, 0x00c0, 0x33da,
- 0x1078, 0x29b2, 0xd4fc, 0x00c0, 0x33fa, 0x7064, 0xa005, 0x0040,
- 0x33e3, 0x1078, 0x29b2, 0x6f14, 0x7776, 0xa7bc, 0x8f00, 0x1078,
- 0x424e, 0x6008, 0xa085, 0x0021, 0x600a, 0x8738, 0xa784, 0x001f,
- 0x00c0, 0x33e7, 0x1078, 0x411c, 0x7067, 0x0002, 0x701f, 0x0009,
- 0x0078, 0x33fc, 0x1078, 0x412b, 0x781b, 0x0078, 0x007c, 0xa282,
- 0x0004, 0x0050, 0x3405, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3408,
- 0x340b, 0x35cb, 0x360e, 0xa286, 0x0003, 0x0040, 0x3443, 0x7200,
- 0x7cd8, 0x7ddc, 0x7fd0, 0x71d4, 0xd1bc, 0x00c0, 0x343b, 0xd1b4,
- 0x0040, 0x343b, 0x7868, 0xa084, 0x00ff, 0x00c0, 0x343b, 0xa282,
- 0x0002, 0x00c8, 0x343b, 0x0d7e, 0x783b, 0x8300, 0x781b, 0x004c,
- 0x70bc, 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898,
- 0x78d2, 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x2001,
- 0x0000, 0x0078, 0x3447, 0x783b, 0x1300, 0x781b, 0x004a, 0x2001,
- 0x0000, 0x0078, 0x3447, 0x7200, 0x7cd8, 0x7ddc, 0x7fd0, 0x704a,
- 0x68a0, 0xd0ec, 0x0040, 0x344f, 0x6008, 0xc08d, 0x600a, 0xa284,
- 0x000f, 0x0079, 0x3453, 0x35ab, 0x3460, 0x345d, 0x3711, 0x379d,
- 0x2a0c, 0x345b, 0x345b, 0x1078, 0x29b2, 0x6008, 0xc0d4, 0x600a,
- 0xd6e4, 0x0040, 0x3468, 0x7048, 0xa086, 0x0014, 0x00c0, 0x3488,
- 0x1078, 0x45d6, 0x2009, 0x0000, 0x6818, 0xd0fc, 0x0040, 0x3471,
- 0x7048, 0xa086, 0x0014, 0x0040, 0x3482, 0x6818, 0xa086, 0x0008,
- 0x00c0, 0x3563, 0x7858, 0xd09c, 0x0040, 0x3563, 0x6820, 0xd0ac,
- 0x0040, 0x3563, 0x681b, 0x0014, 0x2009, 0x0002, 0x0078, 0x34c7,
- 0x7868, 0xa08c, 0x00ff, 0x0040, 0x34c7, 0xa186, 0x0008, 0x00c0,
- 0x349e, 0x6008, 0xc0a4, 0x600a, 0x1078, 0x3db8, 0x0040, 0x34c7,
- 0x1078, 0x3e36, 0x1078, 0x45d6, 0x0078, 0x34af, 0xa186, 0x0028,
- 0x00c0, 0x34c7, 0x6018, 0xa005, 0x0040, 0x3491, 0x8001, 0x0040,
- 0x3491, 0x8001, 0x0040, 0x3491, 0x601e, 0x0078, 0x3491, 0x6820,
- 0xd084, 0x0040, 0x2a0c, 0xc084, 0x6822, 0x1078, 0x2b13, 0x705c,
- 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f, 0x6004, 0x6802, 0xa005,
- 0x2d00, 0x00c0, 0x34c4, 0x6002, 0x6006, 0x0078, 0x2a0c, 0x017e,
- 0x81ff, 0x00c0, 0x3511, 0x7000, 0xa086, 0x0030, 0x0040, 0x3511,
- 0x71d4, 0xd1bc, 0x00c0, 0x3511, 0xd1b4, 0x00c0, 0x34f8, 0x7060,
- 0xa005, 0x00c0, 0x3511, 0x70a4, 0xa086, 0x0001, 0x0040, 0x3511,
- 0x7003, 0x0000, 0x047e, 0x057e, 0x077e, 0x067e, 0x0c7e, 0x0d7e,
- 0x1078, 0x2a35, 0x0d7f, 0x0c7f, 0x067f, 0x077f, 0x057f, 0x047f,
- 0x71d4, 0xd1b4, 0x00c0, 0x3511, 0x7003, 0x0040, 0x0078, 0x3511,
- 0x1078, 0x43b0, 0x00c0, 0x3511, 0x781b, 0x005b, 0x0d7e, 0x70bc,
- 0xa06d, 0x68b4, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2,
- 0x78da, 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x7808, 0xc08d, 0x780a,
- 0x0d7f, 0x1078, 0x3648, 0x017f, 0x81ff, 0x0040, 0x3563, 0xa684,
- 0xdf00, 0x681e, 0x682b, 0x0000, 0x6f14, 0xa186, 0x0002, 0x00c0,
- 0x3564, 0x6818, 0xa086, 0x0014, 0x00c0, 0x352d, 0x2008, 0xd6e4,
- 0x0040, 0x352d, 0x7868, 0xa08c, 0x00ff, 0x1078, 0x2b01, 0x1078,
- 0x2b22, 0x6820, 0xd0dc, 0x00c0, 0x3564, 0x8717, 0xa294, 0x000f,
- 0x8213, 0x8213, 0x8213, 0xb284, 0x0300, 0x0040, 0x3543, 0xa290,
- 0x53c0, 0x0078, 0x3545, 0xa290, 0x5440, 0xa290, 0x0000, 0x221c,
- 0xd3c4, 0x00c0, 0x354d, 0x0078, 0x3553, 0x8210, 0x2204, 0xa085,
- 0x0018, 0x2012, 0x8211, 0xd3d4, 0x0040, 0x355e, 0x68a0, 0xd0c4,
- 0x00c0, 0x355e, 0x1078, 0x36c2, 0x0078, 0x2a0c, 0x6008, 0xc08d,
- 0x600a, 0x0078, 0x3564, 0x692a, 0x6916, 0x6818, 0xd0fc, 0x0040,
- 0x356b, 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x6410, 0x84ff,
- 0x0040, 0x3580, 0x2009, 0x4f02, 0x2104, 0x8001, 0x200a, 0x8421,
- 0x6412, 0x00c0, 0x3580, 0x2021, 0x4f04, 0x2404, 0xc0a5, 0x2022,
- 0x6018, 0xa005, 0x0040, 0x3588, 0x8001, 0x601a, 0x00c0, 0x358b,
- 0x6008, 0xc0a4, 0x600a, 0x6820, 0xd084, 0x00c0, 0x3597, 0x6800,
- 0xa005, 0x00c0, 0x3594, 0x6002, 0x6006, 0x0078, 0x359b, 0x705c,
- 0x2060, 0x6800, 0x6002, 0x2061, 0x4f00, 0x6887, 0x0103, 0x2d08,
- 0x206b, 0x0000, 0x6068, 0xa005, 0x616a, 0x0040, 0x35aa, 0x2d02,
- 0x0078, 0x35ab, 0x616e, 0x7200, 0xa286, 0x0030, 0x0040, 0x35bb,
- 0xa286, 0x0040, 0x00c0, 0x2a0c, 0x7003, 0x0002, 0x704c, 0x2068,
- 0x68c4, 0x2060, 0x007c, 0x7003, 0x0002, 0x70bc, 0xa06d, 0x68bc,
- 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a, 0x2d00, 0x704e, 0xad80,
- 0x0009, 0x7046, 0x007c, 0xa282, 0x0004, 0x0048, 0x35d1, 0x1078,
- 0x29b2, 0x2200, 0x0079, 0x35d4, 0x35d8, 0x35e9, 0x35f6, 0x35e9,
- 0xa586, 0x1300, 0x0040, 0x35e9, 0xa586, 0x8300, 0x00c0, 0x35cf,
- 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008, 0xa084, 0xfbef,
- 0x600a, 0x7000, 0xa086, 0x0005, 0x0040, 0x35f3, 0x1078, 0x4118,
- 0x781b, 0x0078, 0x007c, 0x781b, 0x0079, 0x007c, 0x7890, 0x8007,
- 0x8001, 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c,
- 0x00ff, 0xa186, 0x0003, 0x0040, 0x360b, 0xa186, 0x0000, 0x0040,
- 0x360b, 0x0078, 0x4107, 0x781b, 0x0079, 0x007c, 0x6820, 0xc095,
- 0x6822, 0x82ff, 0x00c0, 0x3618, 0x1078, 0x4118, 0x0078, 0x361f,
- 0x8211, 0x0040, 0x361d, 0x1078, 0x29b2, 0x1078, 0x412b, 0x781b,
- 0x0078, 0x007c, 0x1078, 0x43d3, 0x7830, 0xa084, 0x00c0, 0x00c0,
- 0x3645, 0x017e, 0x3208, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec,
- 0x007f, 0x0040, 0x3637, 0xa18c, 0x0300, 0x0078, 0x3639, 0xa18c,
- 0x0400, 0x017f, 0x0040, 0x3640, 0x0018, 0x3645, 0x0078, 0x3642,
- 0x0028, 0x3645, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c,
- 0xa684, 0x0060, 0x00c0, 0x3652, 0x682f, 0x0000, 0x6833, 0x0000,
- 0x0078, 0x36c1, 0xd6dc, 0x00c0, 0x366a, 0x68b4, 0xd0dc, 0x00c0,
- 0x366a, 0x6998, 0x6a94, 0x692e, 0x6a32, 0x7048, 0xa005, 0x00c0,
- 0x3667, 0x2200, 0xa105, 0x0040, 0x45d6, 0x704b, 0x0015, 0x0078,
- 0x45d6, 0x007c, 0xd6ac, 0x0040, 0x3690, 0xd6f4, 0x0040, 0x3676,
- 0x682f, 0x0000, 0x6833, 0x0000, 0x0078, 0x45d6, 0x68b4, 0xa084,
- 0x4000, 0xa635, 0xd6f4, 0x00c0, 0x3670, 0x7048, 0xa005, 0x00c0,
- 0x3683, 0x704b, 0x0015, 0xd6dc, 0x00c0, 0x368c, 0x68b4, 0xd0dc,
- 0x0040, 0x368c, 0x6ca8, 0x6da4, 0x6c2e, 0x6d32, 0x0078, 0x45d6,
- 0xd6f4, 0x0040, 0x3699, 0x682f, 0x0000, 0x6833, 0x0000, 0x0078,
- 0x45d6, 0x68b4, 0xa084, 0x4800, 0xa635, 0xd6f4, 0x00c0, 0x3693,
- 0x7048, 0xa005, 0x00c0, 0x36a6, 0x704b, 0x0015, 0x2408, 0x2510,
- 0x2700, 0x80fb, 0x00c8, 0x36ad, 0x8000, 0xa084, 0x003f, 0xa108,
- 0xa291, 0x0000, 0x692e, 0x6a32, 0x2100, 0xa205, 0x00c0, 0x36ba,
- 0x0078, 0x45d6, 0x7000, 0xa086, 0x0006, 0x0040, 0x36c1, 0x0078,
- 0x45d6, 0x007c, 0x6946, 0x6008, 0xc0cd, 0xd3cc, 0x0040, 0x36c9,
- 0xc08d, 0x600a, 0x6818, 0x683a, 0x681b, 0x0006, 0x688f, 0x0000,
- 0x6893, 0x0000, 0x6a30, 0x692c, 0x6a3e, 0x6942, 0x682f, 0x0003,
- 0x6833, 0x0000, 0x6837, 0x0020, 0x6897, 0x0000, 0x689b, 0x0020,
- 0x7000, 0x0079, 0x36e3, 0x2a0c, 0x36f5, 0x36ed, 0x36eb, 0x36eb,
- 0x36eb, 0x36eb, 0x36eb, 0x1078, 0x29b2, 0x6820, 0xd084, 0x00c0,
- 0x36f5, 0x1078, 0x3e19, 0x0078, 0x36fb, 0x705c, 0x2c50, 0x2060,
- 0x6800, 0x6002, 0x2a60, 0x3208, 0xa18c, 0x0300, 0x0040, 0x3704,
- 0x2021, 0x4f58, 0x0078, 0x3706, 0x2021, 0x4f98, 0x2404, 0xa005,
- 0x0040, 0x370d, 0x2020, 0x0078, 0x3706, 0x2d22, 0x206b, 0x0000,
- 0x007c, 0x1078, 0x3e20, 0x1078, 0x3e36, 0x6008, 0xc0cc, 0x600a,
- 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x6938, 0x691a, 0x6944,
- 0x6916, 0x3208, 0xa18c, 0x0300, 0x0040, 0x372a, 0x2009, 0x0000,
- 0x0078, 0x372c, 0x2009, 0x0001, 0x1078, 0x4a81, 0xd6dc, 0x0040,
- 0x3734, 0x691c, 0xc1ed, 0x691e, 0x6818, 0xd0fc, 0x0040, 0x3743,
- 0x7868, 0xa08c, 0x00ff, 0x0040, 0x3741, 0x681b, 0x001e, 0x0078,
- 0x3743, 0x681b, 0x0000, 0xb284, 0x0300, 0x00c0, 0x374b, 0x2021,
- 0x4f98, 0x0078, 0x374d, 0x2021, 0x4f58, 0x6800, 0x2022, 0x6a3c,
- 0x6940, 0x6a32, 0x692e, 0x68c0, 0x2060, 0x6000, 0xd0a4, 0x0040,
- 0x378d, 0x2041, 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x0d7e,
- 0x0f7e, 0x157e, 0x147e, 0x2079, 0x4f00, 0x1078, 0x1e46, 0x147f,
- 0x157f, 0x0f7f, 0x70cc, 0x2010, 0x2009, 0x0101, 0x027e, 0x2204,
- 0xa06d, 0x0040, 0x377d, 0x6814, 0xa706, 0x0040, 0x377a, 0x6800,
- 0x0078, 0x3770, 0x6820, 0xc0d5, 0x6822, 0x027f, 0x8210, 0x8109,
- 0x00c0, 0x376e, 0x0d7f, 0x7067, 0x0003, 0x707f, 0x0000, 0x7776,
- 0x7083, 0x000f, 0x71d4, 0xc1dc, 0x71d6, 0x6818, 0xa086, 0x0002,
- 0x00c0, 0x3799, 0x6817, 0x0000, 0x682b, 0x0000, 0x681c, 0xc0ec,
- 0x681e, 0x1078, 0x2073, 0x0078, 0x2a0c, 0x7cd8, 0x7ddc, 0x7fd0,
- 0x1078, 0x3648, 0x682b, 0x0000, 0x789b, 0x000e, 0x6f14, 0x1078,
- 0x43d7, 0xa08c, 0x00ff, 0x6916, 0x6818, 0xd0fc, 0x0040, 0x37b2,
- 0x7048, 0x681a, 0xa68c, 0xdf00, 0x691e, 0x7067, 0x0000, 0x0078,
- 0x2a0c, 0x7000, 0xa005, 0x00c0, 0x37bf, 0x0078, 0x2a0c, 0xa006,
- 0x1078, 0x45d6, 0x6920, 0xd1ac, 0x00c0, 0x37c8, 0x681b, 0x0014,
- 0xa68c, 0xdf00, 0x691e, 0x682b, 0x0000, 0x6820, 0xa084, 0x00ff,
- 0x6822, 0x7000, 0x0079, 0x37d4, 0x2a0c, 0x37de, 0x37de, 0x37e1,
- 0x37e1, 0x37e1, 0x37dc, 0x37dc, 0x1078, 0x29b2, 0x6818, 0x0078,
- 0x3443, 0x6008, 0xc0a4, 0x600a, 0x6817, 0x0000, 0x0078, 0x3dde,
- 0x2300, 0x0079, 0x37eb, 0x37ee, 0x37f0, 0x3860, 0x1078, 0x29b2,
- 0xd6fc, 0x00c0, 0x3847, 0x7000, 0xa00d, 0x0079, 0x37f7, 0x2a0c,
- 0x3801, 0x3801, 0x3831, 0x3801, 0x3844, 0x37ff, 0x37ff, 0x1078,
- 0x29b2, 0xa684, 0x0060, 0x0040, 0x3831, 0xa086, 0x0060, 0x00c0,
- 0x382e, 0xc6ac, 0xc6f4, 0xc6ed, 0x7e5a, 0x6eb6, 0x681c, 0xc0ac,
- 0x681e, 0xa186, 0x0002, 0x0040, 0x3820, 0x1078, 0x45d6, 0x69ac,
- 0x68b0, 0xa115, 0x0040, 0x3820, 0x1078, 0x4977, 0x0078, 0x3822,
- 0x1078, 0x493f, 0x781b, 0x0079, 0x71d4, 0xd1b4, 0x00c0, 0x2a08,
- 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c, 0xd6ec, 0x0040,
- 0x380b, 0x6818, 0xd0fc, 0x0040, 0x3844, 0xd6f4, 0x00c0, 0x383e,
- 0x681b, 0x0015, 0x781b, 0x0079, 0x0078, 0x2a08, 0x681b, 0x0007,
- 0x682f, 0x0000, 0x6833, 0x0000, 0x1078, 0x4369, 0x007c, 0xc6fc,
- 0x7e5a, 0x7adc, 0x79d8, 0x78d0, 0x801b, 0x00c8, 0x3850, 0x8000,
- 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x6b98, 0x2100, 0xa302,
- 0x68b2, 0x6b94, 0x2200, 0xa303, 0x68ae, 0x781b, 0x0079, 0x007c,
- 0x1078, 0x29b2, 0x2300, 0x0079, 0x3865, 0x386a, 0x388f, 0x38ef,
- 0x1078, 0x29b2, 0x7000, 0x0079, 0x386d, 0x3875, 0x3877, 0x3880,
- 0x3875, 0x3875, 0x3875, 0x3875, 0x3875, 0x1078, 0x29b2, 0x69ac,
- 0x68b0, 0xa115, 0x0040, 0x3880, 0x1078, 0x4977, 0x0078, 0x3882,
- 0x1078, 0x493f, 0x681c, 0xc0b4, 0x681e, 0x70d4, 0xd0b4, 0x00c0,
- 0x2a08, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c, 0xd6fc,
- 0x00c0, 0x38df, 0x7000, 0xa00d, 0x0079, 0x3896, 0x2a0c, 0x38a6,
- 0x38a0, 0x38d6, 0x38a6, 0x38dc, 0x389e, 0x389e, 0x1078, 0x29b2,
- 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da, 0xa684, 0x0060,
- 0x0040, 0x38d6, 0xa086, 0x0060, 0x00c0, 0x38d3, 0xa6b4, 0xbfbf,
- 0xc6ed, 0x7e5a, 0x6eb6, 0xa186, 0x0002, 0x0040, 0x38c2, 0x1078,
- 0x45d6, 0x69ac, 0x68b0, 0xa115, 0x0040, 0x38c2, 0x1078, 0x4977,
- 0x0078, 0x38c4, 0x1078, 0x493f, 0x781b, 0x0079, 0x681c, 0xc0b4,
- 0x681e, 0x71d4, 0xd1b4, 0x00c0, 0x2a08, 0x70a4, 0xa086, 0x0001,
- 0x00c0, 0x2a52, 0x007c, 0xd6ec, 0x0040, 0x38b0, 0x6818, 0xd0fc,
- 0x0040, 0x38dc, 0x681b, 0x0007, 0x781b, 0x00f9, 0x007c, 0xc6fc,
- 0x7e5a, 0x7adc, 0x79d8, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94,
- 0x2200, 0xa303, 0x68ae, 0x79d2, 0x781b, 0x0079, 0x007c, 0xd6dc,
- 0x0040, 0x38f8, 0x782b, 0x3009, 0x781b, 0x0079, 0x0078, 0x2a08,
- 0x7884, 0xc0ac, 0x7886, 0x78e4, 0xa084, 0x0008, 0x00c0, 0x390b,
- 0xa484, 0x0200, 0x0040, 0x3905, 0xc6f5, 0xc6dd, 0x7e5a, 0x781b,
- 0x0079, 0x0078, 0x2a08, 0x6820, 0xc095, 0x6822, 0x1078, 0x42e2,
- 0xc6dd, 0x1078, 0x4118, 0x781b, 0x0078, 0x0078, 0x2a08, 0x2300,
- 0x0079, 0x391a, 0x391d, 0x391f, 0x3921, 0x1078, 0x29b2, 0x0078,
- 0x4111, 0xd6d4, 0x00c0, 0x395c, 0x79e4, 0xd1ac, 0x0040, 0x392f,
- 0x78ec, 0xa084, 0x0003, 0x0040, 0x392f, 0x782b, 0x3009, 0x789b,
- 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb, 0x785a, 0x79e4, 0xd1ac,
- 0x0040, 0x393f, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x3958, 0x2001,
- 0x4f04, 0x2004, 0xd0e4, 0x00c0, 0x3954, 0x6820, 0xd0c4, 0x0040,
- 0x3954, 0x0c7e, 0x7058, 0x2060, 0x6004, 0xc09d, 0x6006, 0x6008,
- 0xa084, 0x00ff, 0x600a, 0x0c7f, 0x2001, 0x0014, 0x0078, 0x3443,
- 0xa184, 0x0007, 0x0079, 0x3992, 0x7a90, 0xa294, 0x0007, 0x789b,
- 0x0060, 0x79a8, 0x81ff, 0x0040, 0x3990, 0x789b, 0x0010, 0x7ba8,
- 0xa384, 0x0001, 0x00c0, 0x3983, 0x7ba8, 0x7ba8, 0xa386, 0x0001,
- 0x00c0, 0x3976, 0x2009, 0xfff7, 0x0078, 0x397c, 0xa386, 0x0003,
- 0x00c0, 0x3983, 0x2009, 0xffef, 0x0c7e, 0x7058, 0x2060, 0x6004,
- 0xa104, 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684,
- 0xfffb, 0x785a, 0x782b, 0x3009, 0x6920, 0xa18c, 0xfcff, 0x6922,
- 0x0078, 0x435d, 0x30d9, 0x30e3, 0x399c, 0x39a2, 0x399a, 0x399a,
- 0x435d, 0x435d, 0x1078, 0x29b2, 0x6920, 0xa18c, 0xfcff, 0x6922,
- 0x0078, 0x4363, 0x6920, 0xa18c, 0xfcff, 0x6922, 0x0078, 0x435d,
- 0x79e4, 0xa184, 0x0030, 0x0040, 0x39b2, 0x78ec, 0xa084, 0x0003,
- 0x00c0, 0x39e6, 0x7000, 0xa086, 0x0004, 0x00c0, 0x39cc, 0x7064,
- 0xa086, 0x0002, 0x00c0, 0x39c2, 0x2011, 0x0002, 0x2019, 0x0000,
- 0x0078, 0x2f65, 0x7064, 0xa086, 0x0006, 0x0040, 0x39bc, 0x7064,
- 0xa086, 0x0004, 0x0040, 0x39bc, 0x7000, 0xa086, 0x0000, 0x0040,
- 0x2a08, 0x6920, 0xa184, 0x0420, 0x0040, 0x39db, 0xc1d4, 0x6922,
- 0x6818, 0x0078, 0x3443, 0x6818, 0xa08e, 0x0002, 0x0040, 0x39e4,
- 0xc0fd, 0x681a, 0x2001, 0x0014, 0x0078, 0x3443, 0xa184, 0x0007,
- 0x0079, 0x39ea, 0x435d, 0x435d, 0x39f2, 0x435d, 0x43a5, 0x43a5,
- 0x435d, 0x435d, 0xd6bc, 0x0040, 0x3a34, 0x7184, 0x81ff, 0x0040,
- 0x3a34, 0xa182, 0x000d, 0x00d0, 0x3a01, 0x7087, 0x0000, 0x0078,
- 0x3a06, 0xa182, 0x000c, 0x7086, 0x2009, 0x000c, 0x789b, 0x0061,
- 0x79aa, 0x157e, 0x137e, 0x147e, 0x7088, 0x8114, 0xa210, 0x728a,
- 0xa080, 0x000b, 0xad00, 0x2098, 0xb284, 0x0300, 0x0040, 0x3a28,
- 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x3a24,
- 0x20a1, 0x012b, 0x0078, 0x3a2a, 0x20a1, 0x022b, 0x0078, 0x3a2a,
- 0x20a1, 0x012b, 0x789b, 0x0000, 0x8108, 0x81ac, 0x53a6, 0x147f,
- 0x137f, 0x157f, 0x0078, 0x4363, 0xd6d4, 0x00c0, 0x3a88, 0x6820,
- 0xd084, 0x0040, 0x4363, 0xa68c, 0x0060, 0xa684, 0x0060, 0x0040,
- 0x3a46, 0xa086, 0x0060, 0x00c0, 0x3a46, 0xc1f5, 0xc194, 0x795a,
- 0x69b6, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061, 0x6818,
- 0xc0fd, 0x681a, 0x78aa, 0x8008, 0x810c, 0x0040, 0x3e4f, 0xa18c,
- 0x00f8, 0x00c0, 0x3e4f, 0x157e, 0x137e, 0x147e, 0x017e, 0x3208,
- 0xa18c, 0x0300, 0x0040, 0x3a74, 0x007e, 0x2001, 0x4f04, 0x2004,
- 0xd0ec, 0x007f, 0x0040, 0x3a70, 0x20a1, 0x012b, 0x0078, 0x3a76,
- 0x20a1, 0x022b, 0x0078, 0x3a76, 0x20a1, 0x012b, 0x017f, 0x789b,
- 0x0000, 0x8000, 0x80ac, 0xad80, 0x000b, 0x2098, 0x53a6, 0x147f,
- 0x137f, 0x157f, 0x6814, 0xc0fc, 0x8007, 0x7882, 0x0078, 0x4363,
- 0x6818, 0xd0fc, 0x0040, 0x3a8e, 0x681b, 0x0008, 0x6820, 0xc0ad,
- 0x6822, 0x1078, 0x4120, 0x781b, 0x00ea, 0x007c, 0x2300, 0x0079,
- 0x3a99, 0x3a9e, 0x3b76, 0x3a9c, 0x1078, 0x29b2, 0x7cd8, 0x7ddc,
- 0x7fd0, 0x82ff, 0x00c0, 0x3ac7, 0x7200, 0xa286, 0x0003, 0x0040,
- 0x3410, 0x71d4, 0xd1bc, 0x00c0, 0x3aca, 0xd1b4, 0x0040, 0x3aca,
- 0x0d7e, 0x783b, 0x8800, 0x781b, 0x004c, 0x70bc, 0xa06d, 0x68b4,
- 0xc0a5, 0x785a, 0x6894, 0x78d6, 0x78de, 0x6898, 0x78d2, 0x78da,
- 0xc1b4, 0x71d6, 0x7003, 0x0030, 0x0d7f, 0x0078, 0x3ace, 0x7200,
- 0x0078, 0x3ace, 0x783b, 0x1800, 0x781b, 0x004a, 0xa284, 0x000f,
- 0x0079, 0x3ad2, 0x3b61, 0x3b10, 0x3adc, 0x343f, 0x3ada, 0x3b61,
- 0x3ada, 0x3ada, 0x1078, 0x29b2, 0x681c, 0xd0ec, 0x0040, 0x3ae3,
- 0x6008, 0xc08d, 0x600a, 0x6920, 0xc185, 0x6922, 0x6800, 0x6006,
- 0xa005, 0x00c0, 0x3aec, 0x6002, 0x6008, 0xc0d4, 0x600a, 0x681c,
- 0xa084, 0x000e, 0x00c0, 0x3b00, 0xb284, 0x0300, 0x0040, 0x3afc,
- 0x2009, 0x95c0, 0x0078, 0x3b05, 0x2009, 0x96d0, 0x0078, 0x3b05,
- 0x7030, 0x68ba, 0x7140, 0x70cc, 0xa108, 0x2104, 0x6802, 0x2d0a,
- 0x715e, 0xd6dc, 0x00c0, 0x3b10, 0xc6fc, 0x6eb6, 0x0078, 0x3b61,
- 0x6eb6, 0xa684, 0x0060, 0x00c0, 0x3b1a, 0xa684, 0x7fff, 0x68b6,
- 0x0078, 0x3b61, 0xd6dc, 0x00c0, 0x3b28, 0xa684, 0x7fff, 0x68b6,
- 0x6894, 0x68a6, 0x6898, 0x68aa, 0x1078, 0x45d6, 0x0078, 0x3b61,
- 0xd6ac, 0x0040, 0x3b34, 0xa006, 0x1078, 0x45d6, 0x2408, 0x2510,
- 0x69aa, 0x6aa6, 0x0078, 0x3b44, 0x2408, 0x2510, 0x2700, 0x801b,
- 0x00c8, 0x3b3b, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
- 0x69aa, 0x6aa6, 0x1078, 0x45d6, 0xd6fc, 0x0040, 0x3b61, 0xa684,
- 0x7fff, 0x68b6, 0x2510, 0x2408, 0xd6ac, 0x00c0, 0x3b59, 0x2700,
- 0x801b, 0x00c8, 0x3b54, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291,
- 0x0000, 0x6b98, 0x2100, 0xa302, 0x68b2, 0x6b94, 0x2200, 0xa303,
- 0x68ae, 0x7000, 0xa086, 0x0030, 0x00c0, 0x2a0c, 0x7003, 0x0002,
- 0x70bc, 0xa06d, 0x68bc, 0x7042, 0x70b8, 0xa065, 0x68c0, 0x705a,
- 0x2d00, 0x704e, 0xad80, 0x0009, 0x7046, 0x007c, 0xa586, 0x8800,
- 0x00c0, 0x3b83, 0x7003, 0x0000, 0x6018, 0x8001, 0x601a, 0x6008,
- 0xa084, 0xfbef, 0x600a, 0x0078, 0x4111, 0x7047, 0x0000, 0xa282,
- 0x0006, 0x0050, 0x3b8d, 0x1078, 0x29b2, 0x2300, 0x0079, 0x3b90,
- 0x3b93, 0x3ba5, 0x3bb1, 0x2200, 0x0079, 0x3b96, 0x3b9c, 0x4111,
- 0x3b9e, 0x3b9c, 0x3beb, 0x3c40, 0x1078, 0x29b2, 0x7a80, 0xa294,
- 0x0f00, 0x1078, 0x3cca, 0x0078, 0x4107, 0x1078, 0x3bc2, 0x0079,
- 0x3ba9, 0x4111, 0x3baf, 0x3baf, 0x3beb, 0x3baf, 0x4111, 0x1078,
- 0x29b2, 0x1078, 0x3bc2, 0x0079, 0x3bb5, 0x3bbd, 0x3bbb, 0x3bbb,
- 0x3bbd, 0x3bbb, 0x3bbd, 0x1078, 0x29b2, 0x1078, 0x412b, 0x781b,
- 0x0078, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bd3, 0x1078,
- 0x3e36, 0x0078, 0x3bcd, 0x1078, 0x45d6, 0x6008, 0xa084, 0xfbef,
- 0x600a, 0x0078, 0x3bd8, 0x7000, 0xa086, 0x0003, 0x0040, 0x3bcb,
- 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3be2, 0x2001, 0x96e0,
- 0x0078, 0x3be4, 0x2001, 0x9712, 0x2068, 0x704e, 0xad80, 0x0009,
- 0x7046, 0x2200, 0x007c, 0x7000, 0xa086, 0x0002, 0x00c0, 0x3bfd,
- 0x70d4, 0xc0b5, 0x70d6, 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078,
- 0x3c02, 0x1078, 0x45d6, 0x0078, 0x3c02, 0x7000, 0xa086, 0x0003,
- 0x0040, 0x3bf9, 0x7003, 0x0001, 0x7a80, 0xa294, 0x0f00, 0x789b,
- 0x0018, 0x7ca8, 0xa484, 0x001f, 0xa215, 0x2069, 0x95c0, 0xb284,
- 0x0300, 0x00c0, 0x3c16, 0xc2fd, 0x2069, 0x96d0, 0x2d04, 0x2d08,
- 0x715e, 0xa06d, 0x0040, 0x3c23, 0x6814, 0xa206, 0x0040, 0x3c25,
- 0x6800, 0x0078, 0x3c17, 0x1078, 0x3cca, 0x6eb4, 0x7e5a, 0x6920,
- 0xa184, 0x0c00, 0x0040, 0x3cf4, 0x7064, 0xa086, 0x0006, 0x00c0,
- 0x3c37, 0x7074, 0xa206, 0x00c0, 0x3c37, 0x7066, 0x707e, 0x681b,
- 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x4120, 0x0078, 0x3cf4,
- 0x7200, 0xa286, 0x0002, 0x00c0, 0x3c52, 0x70d4, 0xc0b5, 0x70d6,
- 0x2c00, 0x70ba, 0x2d00, 0x70be, 0x0078, 0x3c56, 0x1078, 0x45d6,
- 0x0078, 0x3c56, 0xa286, 0x0003, 0x0040, 0x3c4e, 0x7003, 0x0001,
- 0x7a80, 0xa294, 0x0f00, 0x789b, 0x0018, 0x7ca8, 0xa484, 0x001f,
- 0xa215, 0xb284, 0x0300, 0x00c0, 0x3c66, 0xc2fd, 0x79a8, 0x79a8,
- 0xa18c, 0x00ff, 0x2118, 0x70cc, 0xa168, 0x2d04, 0x2d08, 0x715e,
- 0xa06d, 0x0040, 0x3c7a, 0x6814, 0xa206, 0x0040, 0x3ca3, 0x6800,
- 0x0078, 0x3c6e, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3c84,
- 0x2001, 0x96e0, 0x0078, 0x3c86, 0x2001, 0x9712, 0x2068, 0x704e,
- 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3c8b,
- 0x157f, 0xb284, 0x0300, 0x0040, 0x3c98, 0xc2fc, 0x0078, 0x3c99,
- 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823,
- 0x0800, 0x6827, 0x0003, 0x6eb4, 0x6920, 0xa184, 0x0c00, 0x0040,
- 0x3cf4, 0xd0dc, 0x0040, 0x3cbf, 0x7064, 0xa086, 0x0004, 0x00c0,
- 0x3cbb, 0x7074, 0xa206, 0x00c0, 0x3cbb, 0x7078, 0xa306, 0x00c0,
- 0x3cbb, 0x7066, 0x707e, 0x1078, 0x4127, 0x0078, 0x3cf4, 0x681b,
- 0x0005, 0xc1ad, 0xc1d4, 0x6922, 0x1078, 0x4120, 0x707f, 0x0000,
- 0x0078, 0x3cf4, 0x7003, 0x0005, 0xb284, 0x0300, 0x0040, 0x3cd4,
- 0x2001, 0x96e0, 0x0078, 0x3cd6, 0x2001, 0x9712, 0x2068, 0x704e,
- 0x157e, 0x20a9, 0x0032, 0x2003, 0x0000, 0x8000, 0x00f0, 0x3cdb,
- 0x157f, 0xb284, 0x0300, 0x0040, 0x3ce8, 0xc2fc, 0x0078, 0x3ce9,
- 0xc2fd, 0x6a16, 0xad80, 0x0009, 0x7046, 0x68b7, 0x0700, 0x6823,
- 0x0800, 0x6827, 0x0003, 0x007c, 0xc6ec, 0xa6ac, 0x0060, 0x0040,
- 0x3d46, 0x6b98, 0x6c94, 0x69ac, 0x68b0, 0xa105, 0x00c0, 0x3d21,
- 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa586, 0x0060, 0x0040, 0x3d4b,
- 0xd6f4, 0x00c0, 0x3d0c, 0xc6ed, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009,
- 0x0079, 0xd69c, 0x0040, 0x3d19, 0x2009, 0x0078, 0x2019, 0x0000,
- 0x2320, 0x791a, 0xd6ec, 0x0040, 0x3d56, 0x1078, 0x493f, 0x0078,
- 0x3d56, 0x68b0, 0xa31a, 0x2100, 0xa423, 0x2400, 0xa305, 0x0040,
- 0x3d4d, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0x68b0, 0xd6f4, 0x00c0,
- 0x3d32, 0xc6ed, 0xc6f4, 0x7e5a, 0x2011, 0x0079, 0xd69c, 0x0040,
- 0x3d3e, 0x2011, 0x0078, 0x2019, 0x0000, 0x2320, 0x7a1a, 0xd6ec,
- 0x0040, 0x3d56, 0x1078, 0x4977, 0x0078, 0x3d56, 0x2019, 0x0000,
- 0x2320, 0x0078, 0x3d4d, 0xa6b4, 0xb7ff, 0x7e5a, 0x2009, 0x0079,
- 0xd69c, 0x0040, 0x3d55, 0x2009, 0x0078, 0x791a, 0x68c0, 0x705a,
- 0x2d00, 0x704e, 0x68c4, 0x2060, 0x71d4, 0x2001, 0x4f01, 0x2004,
- 0xd0c4, 0x00c0, 0x3dab, 0x70d8, 0xa02d, 0x0040, 0x3d84, 0xd1bc,
- 0x0040, 0x3d9e, 0x7a80, 0xa294, 0x0f00, 0x70dc, 0xa206, 0x0040,
- 0x3d75, 0x78e0, 0xa504, 0x00c0, 0x3dab, 0x70da, 0xc1bc, 0x71d6,
- 0x0078, 0x3dab, 0x2031, 0x0001, 0x852c, 0x0048, 0x3d83, 0x8633,
- 0x8210, 0x0078, 0x3d7c, 0x007c, 0x7de0, 0xa594, 0xff00, 0x0040,
- 0x3d91, 0x2011, 0x0008, 0x852f, 0x1078, 0x3d7a, 0x8637, 0x0078,
- 0x3d93, 0x1078, 0x3d7a, 0x8217, 0x7880, 0xa084, 0x0f00, 0xa206,
- 0x0040, 0x3dab, 0x72de, 0x76da, 0x0078, 0x3dab, 0x7a80, 0xa294,
- 0x0f00, 0x70dc, 0xa236, 0x0040, 0x3d9b, 0x78e0, 0xa534, 0x0040,
- 0x3d9b, 0xc1bd, 0x71d6, 0xd1b4, 0x00c0, 0x2a08, 0x2300, 0xa405,
- 0x0040, 0x2a08, 0x70a4, 0xa086, 0x0001, 0x00c0, 0x2a52, 0x007c,
- 0x6020, 0xa005, 0x0040, 0x3dc6, 0x8001, 0x6022, 0x6008, 0xa085,
- 0x0008, 0x600a, 0x700f, 0x0100, 0x702c, 0x6026, 0x007c, 0xa006,
- 0x1078, 0x45d6, 0x7000, 0xa086, 0x0002, 0x0040, 0x3dd4, 0x7064,
- 0xa086, 0x0005, 0x00c0, 0x3dde, 0x682b, 0x0000, 0x6817, 0x0000,
- 0x681b, 0x0001, 0x6823, 0x0040, 0x681f, 0x0100, 0x7000, 0xa084,
- 0x000f, 0x0079, 0x3de3, 0x2a0c, 0x3df3, 0x3ded, 0x3e15, 0x3dfd,
- 0x2a0c, 0x3deb, 0x3deb, 0x1078, 0x29b2, 0x1078, 0x3e20, 0x1078,
- 0x3e19, 0x0078, 0x3df9, 0x1078, 0x3e20, 0x705c, 0x2060, 0x6800,
- 0x6002, 0x1078, 0x2073, 0x0078, 0x2a0c, 0x7064, 0x7067, 0x0000,
- 0x7083, 0x0000, 0x0079, 0x3e04, 0x3e11, 0x3e11, 0x3e0c, 0x3e0c,
- 0x3e0c, 0x3e11, 0x3e0c, 0x3e11, 0x77d4, 0xc7dd, 0x77d6, 0x0079,
- 0x2f7e, 0x7067, 0x0000, 0x0078, 0x2a0c, 0x681b, 0x0000, 0x0078,
- 0x3711, 0x6800, 0xa005, 0x00c0, 0x3e1e, 0x6002, 0x6006, 0x007c,
- 0x6410, 0x84ff, 0x0040, 0x3e32, 0x2009, 0x4f02, 0x2104, 0x8001,
- 0x200a, 0x8421, 0x6412, 0x00c0, 0x3e32, 0x2021, 0x4f04, 0x2404,
- 0xc0a5, 0x2022, 0x6008, 0xc0a4, 0x600a, 0x007c, 0x6018, 0xa005,
- 0x0040, 0x3e3c, 0x8001, 0x601a, 0x007c, 0x1078, 0x43d3, 0x681b,
- 0x0018, 0x0078, 0x3e7d, 0x1078, 0x43d3, 0x681b, 0x0019, 0x0078,
- 0x3e7d, 0x1078, 0x43d3, 0x681b, 0x001a, 0x0078, 0x3e7d, 0x1078,
- 0x43d3, 0x681b, 0x0003, 0x0078, 0x3e7d, 0x7774, 0x1078, 0x424e,
- 0x7178, 0xa18c, 0x00ff, 0x3210, 0xa294, 0x0300, 0x0040, 0x3e64,
- 0xa1e8, 0x94c0, 0x0078, 0x3e66, 0xa1e8, 0x95d0, 0x2d04, 0x2d08,
- 0x2068, 0xa005, 0x00c0, 0x3e6f, 0x707e, 0x0078, 0x2a0c, 0x6814,
- 0x7274, 0xa206, 0x0040, 0x3e77, 0x6800, 0x0078, 0x3e67, 0x6800,
- 0x200a, 0x681b, 0x0005, 0x707f, 0x0000, 0x1078, 0x3e20, 0x6820,
- 0xd084, 0x00c0, 0x3e85, 0x1078, 0x3e19, 0x1078, 0x3e36, 0x681f,
- 0x0000, 0x6823, 0x0020, 0x1078, 0x2073, 0x0078, 0x2a0c, 0xa282,
- 0x0003, 0x00c0, 0x4107, 0x7da8, 0xa5ac, 0x00ff, 0x7e5a, 0x7ea8,
- 0xa6b4, 0x00ff, 0x6920, 0xc1bd, 0x6922, 0xd1c4, 0x0040, 0x3eea,
- 0xc1c4, 0x6922, 0xa6b4, 0x00ff, 0x0040, 0x3ed7, 0xa682, 0x000c,
- 0x0048, 0x3eae, 0x0040, 0x3eae, 0x2031, 0x000c, 0x2500, 0xa086,
- 0x000a, 0x0040, 0x3eb5, 0x852b, 0x852b, 0x1078, 0x41e0, 0x0040,
- 0x3ebd, 0x1078, 0x3fbc, 0x0078, 0x3ee0, 0x1078, 0x419b, 0x0c7e,
- 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3ff2, 0x0c7f,
- 0x6920, 0xc1c5, 0x6922, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
- 0x3ed4, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x0c7e,
- 0x2960, 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x3ff2, 0x0c7f,
- 0x7e58, 0xd6d4, 0x00c0, 0x3ee7, 0x781b, 0x0067, 0x007c, 0x781b,
- 0x0079, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6100, 0xd1e4, 0x0040,
- 0x3f33, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000c, 0x0048,
- 0x3efd, 0x0040, 0x3efd, 0x2011, 0x000c, 0x2600, 0xa202, 0x00c8,
- 0x3f02, 0x2230, 0x6208, 0xa294, 0x00ff, 0x2001, 0x4f05, 0x2004,
- 0xd0e4, 0x00c0, 0x3f17, 0x78ec, 0xd0e4, 0x0040, 0x3f17, 0xa282,
- 0x000a, 0x00c8, 0x3f1d, 0x2011, 0x000a, 0x0078, 0x3f1d, 0xa282,
- 0x000c, 0x00c8, 0x3f1d, 0x2011, 0x000c, 0x2200, 0xa502, 0x00c8,
- 0x3f22, 0x2228, 0x1078, 0x419f, 0x2500, 0xa086, 0x000a, 0x0040,
- 0x3f2b, 0x852b, 0x852b, 0x1078, 0x41e0, 0x0040, 0x3f33, 0x1078,
- 0x3fbc, 0x0078, 0x3f37, 0x1078, 0x419b, 0x1078, 0x3ff2, 0x7858,
- 0xc095, 0x785a, 0x0c7f, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x2960,
- 0x6000, 0xd0e4, 0x00c0, 0x3f58, 0xd0b4, 0x00c0, 0x3f52, 0x6010,
- 0xa084, 0x000f, 0x00c0, 0x3f52, 0x6104, 0xa18c, 0xfff5, 0x6106,
- 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078, 0x3f83,
- 0x68a0, 0xd0cc, 0x00c0, 0x3f52, 0x6208, 0xa294, 0x00ff, 0x2001,
- 0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x3f71, 0x78ec, 0xd0e4, 0x0040,
- 0x3f71, 0xa282, 0x000b, 0x00c8, 0x3f71, 0x2011, 0x000a, 0x0078,
- 0x3f77, 0xa282, 0x000c, 0x00c8, 0x3f77, 0x2011, 0x000c, 0x6308,
- 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000c, 0x0048, 0x3f83, 0x0040,
- 0x3f83, 0x2019, 0x000c, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
- 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820, 0xc0c5, 0x6822,
- 0x70d4, 0xd0b4, 0x0040, 0x3f9f, 0xc0b4, 0x70d6, 0x70b8, 0xa065,
- 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f,
- 0x007c, 0x0c7e, 0x2960, 0x6104, 0xa18c, 0xfff5, 0x6106, 0x2011,
- 0x0032, 0x2019, 0x0000, 0x0078, 0x3fad, 0x78ab, 0x0001, 0x78ab,
- 0x0003, 0x78ab, 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x6820,
- 0xc0c5, 0x6822, 0x0c7f, 0x007c, 0x0c7e, 0x7158, 0x2160, 0x2018,
- 0xa08c, 0x0020, 0x0040, 0x3fc5, 0xc0ac, 0x2008, 0xa084, 0xfff0,
- 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4, 0xa084,
- 0xfff0, 0xa18c, 0x000f, 0xa105, 0xc0f4, 0xa39c, 0x0020, 0x0040,
- 0x3fdb, 0xa085, 0x4000, 0xc0fc, 0xd0b4, 0x00c0, 0x3fe0, 0xc0fd,
- 0x78a6, 0x6016, 0x788a, 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004,
- 0xa084, 0x00ff, 0xa605, 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006,
- 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x6018, 0x789a, 0x78a4,
- 0xa084, 0xfff0, 0x78a6, 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886,
- 0x600c, 0xa084, 0x00ff, 0x600e, 0x0c7f, 0x007c, 0xa282, 0x0002,
- 0x00c0, 0x4107, 0x7aa8, 0x6920, 0xc1bd, 0x6922, 0xd1cc, 0x0040,
- 0x4041, 0xc1cc, 0x6922, 0xa294, 0x00ff, 0xa282, 0x0002, 0x00c8,
- 0x4107, 0x1078, 0x4094, 0x1078, 0x3ff2, 0xa980, 0x0001, 0x200c,
- 0x1078, 0x424a, 0x1078, 0x3f3e, 0x88ff, 0x0040, 0x4037, 0x789b,
- 0x0060, 0x2800, 0x78aa, 0x7e58, 0xc695, 0x7e5a, 0xd6d4, 0x00c0,
- 0x4034, 0x781b, 0x0064, 0x007c, 0x781b, 0x0078, 0x007c, 0x7e58,
- 0xd6d4, 0x00c0, 0x403e, 0x781b, 0x0067, 0x007c, 0x781b, 0x0079,
- 0x007c, 0xa282, 0x0002, 0x00c8, 0x4049, 0xa284, 0x0001, 0x0040,
- 0x4052, 0x7158, 0xa188, 0x0000, 0x210c, 0xd1ec, 0x00c0, 0x4052,
- 0x2011, 0x0000, 0x1078, 0x417c, 0x1078, 0x4094, 0x1078, 0x3ff2,
- 0x7858, 0xc095, 0x785a, 0x781b, 0x0078, 0x007c, 0x0c7e, 0x027e,
- 0x2960, 0x6000, 0x2011, 0x0001, 0xd0ec, 0x00c0, 0x4075, 0xd0bc,
- 0x00c0, 0x4073, 0x6014, 0xd0b4, 0x00c0, 0x4073, 0xc1a4, 0x6106,
- 0xa006, 0x0078, 0x4091, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab,
- 0x0002, 0x78ab, 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x70d4, 0xd0b4,
- 0x0040, 0x408d, 0xc0b4, 0x70d6, 0x70b8, 0xa065, 0x6008, 0xa084,
- 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x6820, 0xa085, 0x0200,
- 0x6822, 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7058, 0x2060, 0x82ff,
- 0x0040, 0x409c, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a,
- 0x78a4, 0xa084, 0xffbf, 0xa205, 0xc0fc, 0xd0b4, 0x00c0, 0x40a9,
- 0xc0fd, 0x78a6, 0x6016, 0x788a, 0x6004, 0xc0a4, 0x6006, 0x0c7f,
- 0x007c, 0x007e, 0x7000, 0xa086, 0x0003, 0x0040, 0x40ba, 0x007f,
- 0x0078, 0x40bd, 0x007f, 0x0078, 0x4104, 0xd6ac, 0x0040, 0x4104,
- 0x7888, 0xa084, 0x0040, 0x0040, 0x4104, 0x7bb8, 0xa384, 0x003f,
- 0x831b, 0x00c8, 0x40cc, 0x8000, 0xa005, 0x0040, 0x40e1, 0x831b,
- 0x00c8, 0x40d5, 0x8001, 0x0040, 0x4101, 0xd6f4, 0x0040, 0x40e1,
- 0x78b8, 0x801b, 0x00c8, 0x40dd, 0x8000, 0xa084, 0x003f, 0x00c0,
- 0x4101, 0xc6f4, 0x7e5a, 0x79d8, 0x7adc, 0x2001, 0x0001, 0xa108,
- 0x00c8, 0x40ec, 0xa291, 0x0000, 0x79d2, 0x79da, 0x7ad6, 0x7ade,
- 0x1078, 0x4a44, 0x781b, 0x0076, 0xb284, 0x0300, 0x0040, 0x40fc,
- 0x2001, 0x0000, 0x0078, 0x40fe, 0x2001, 0x0001, 0x1078, 0x48ce,
- 0x007c, 0x781b, 0x0076, 0x007c, 0x781b, 0x0079, 0x007c, 0x1078,
- 0x412f, 0x781b, 0x0078, 0x007c, 0x1078, 0x4118, 0x781b, 0x0078,
- 0x007c, 0x6827, 0x0002, 0x1078, 0x4120, 0x781b, 0x0078, 0x007c,
- 0x2001, 0x0005, 0x0078, 0x4131, 0x2001, 0x000c, 0x0078, 0x4131,
- 0x6820, 0xc0d5, 0x6822, 0x2001, 0x0006, 0x0078, 0x4131, 0x2001,
- 0x000d, 0x0078, 0x4131, 0x2001, 0x0009, 0x0078, 0x4131, 0x2001,
- 0x0007, 0x789b, 0x007e, 0x78aa, 0xc69d, 0x7e5a, 0x70d4, 0xd0b4,
- 0x0040, 0x4147, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008,
- 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c,
- 0x077e, 0x873f, 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0x017e,
- 0xb28c, 0x0300, 0x0040, 0x4158, 0xa0e0, 0x53c0, 0x0078, 0x415a,
- 0xa0e0, 0x5440, 0x017f, 0xa7b8, 0x0020, 0x7f9a, 0x79a4, 0xa184,
- 0x000f, 0x0040, 0x416a, 0xa184, 0xfff0, 0x78a6, 0x6012, 0x6004,
- 0xc09d, 0x6006, 0x8738, 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040,
- 0x0040, 0x417a, 0xa184, 0xffbf, 0xc0fd, 0x78a6, 0x6016, 0x6004,
- 0xc0a5, 0x6006, 0x077f, 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001,
- 0x78ab, 0x0002, 0x78ab, 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab,
- 0x0004, 0x70d4, 0xd0b4, 0x0040, 0x419a, 0xc0b4, 0x70d6, 0x0c7e,
- 0x70b8, 0xa065, 0x6008, 0xa084, 0xfbef, 0x600a, 0x6018, 0x8001,
- 0x601a, 0x0c7f, 0x007c, 0x2031, 0x0000, 0x2029, 0x0032, 0x789b,
- 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab, 0x0001, 0x7daa,
- 0x7eaa, 0x789b, 0x0060, 0x78ab, 0x0005, 0x70d4, 0xd0b4, 0x0040,
- 0x41be, 0xc0b4, 0x70d6, 0x0c7e, 0x70b8, 0xa065, 0x6008, 0xa084,
- 0xfbef, 0x600a, 0x6018, 0x8001, 0x601a, 0x0c7f, 0x007c, 0x157e,
- 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003, 0xa080, 0x0020, 0x789a,
- 0x79a4, 0xa18c, 0xfff0, 0x2021, 0x4233, 0x2019, 0x0011, 0x20a9,
- 0x000e, 0x2011, 0x0032, 0x2404, 0xa084, 0xfff0, 0xa106, 0x0040,
- 0x41de, 0x8420, 0x2300, 0xa210, 0x00f0, 0x41d3, 0x157f, 0x007c,
- 0x157e, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x4211, 0x2021,
- 0x4241, 0x20a9, 0x0009, 0x2011, 0x0028, 0xa582, 0x0019, 0x0040,
- 0x4227, 0x0048, 0x4227, 0x8420, 0x95a9, 0x2011, 0x0032, 0xa582,
- 0x0032, 0x0040, 0x4227, 0x0048, 0x4227, 0x8420, 0x95a9, 0x2019,
- 0x000a, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x4227, 0x0048,
- 0x4227, 0x8420, 0x2300, 0xa210, 0x00f0, 0x4203, 0x157f, 0x0078,
- 0x4225, 0x2021, 0x4233, 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011,
- 0x0032, 0x2200, 0xa502, 0x0040, 0x4227, 0x0048, 0x4227, 0x8420,
- 0x2300, 0xa210, 0x00f0, 0x4219, 0x157f, 0xa006, 0x007c, 0x157f,
- 0xa582, 0x0064, 0x00c8, 0x4230, 0x7808, 0xa085, 0x0070, 0x780a,
- 0x2404, 0xa005, 0x007c, 0x1209, 0x3002, 0x3202, 0x4203, 0x4403,
- 0x5404, 0x5604, 0x6605, 0x6805, 0x7806, 0x7a06, 0x0c07, 0x0c07,
- 0x0e07, 0x10e1, 0x330a, 0x5805, 0x5a05, 0x6a06, 0x6c06, 0x7c07,
- 0x7e07, 0x0e00, 0x789b, 0x0010, 0xa046, 0x007c, 0xa784, 0x0f00,
- 0x800b, 0xa784, 0x001f, 0x8003, 0x8003, 0x8003, 0x8003, 0xa105,
- 0xd7fc, 0x0040, 0x425f, 0xa0e0, 0x74c0, 0x0078, 0x4261, 0xa0e0,
- 0x54c0, 0x007c, 0x0e7e, 0x0f7e, 0xd084, 0x0040, 0x426f, 0x2079,
- 0x0100, 0x2009, 0x4f80, 0x2071, 0x4f80, 0x0078, 0x427f, 0x2009,
- 0x4f40, 0x2071, 0x4f40, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x0040,
- 0x427d, 0x2079, 0x0100, 0x0078, 0x427f, 0x2079, 0x0200, 0x2091,
- 0x8000, 0x2104, 0xa084, 0x000f, 0x0079, 0x4286, 0x4290, 0x4290,
- 0x4290, 0x4290, 0x4290, 0x4290, 0x428e, 0x428e, 0x1078, 0x29b2,
- 0x69b4, 0xc1f5, 0xa18c, 0xff9f, 0x69b6, 0xa005, 0x0040, 0x42df,
- 0x7858, 0xa084, 0xff9f, 0xa085, 0x6000, 0x785a, 0x7828, 0xa086,
- 0x1814, 0x00c0, 0x42df, 0x784b, 0x0004, 0x7848, 0xa084, 0x0004,
- 0x00c0, 0x42a5, 0x784b, 0x0008, 0x7848, 0xa084, 0x0008, 0x00c0,
- 0x42ac, 0x7830, 0xd0bc, 0x00c0, 0x42df, 0x007e, 0x2001, 0x4f04,
- 0x2004, 0xd0ec, 0x007f, 0x0040, 0x42c1, 0xb284, 0x0300, 0x0078,
- 0x42c3, 0xb284, 0x0400, 0x0040, 0x42c9, 0x0018, 0x42df, 0x0078,
- 0x42cb, 0x0028, 0x42df, 0x79e4, 0xa184, 0x0030, 0x0040, 0x42df,
- 0x78ec, 0xa084, 0x0003, 0x0040, 0x42df, 0x681c, 0xd0ac, 0x00c0,
- 0x42dd, 0x1078, 0x4369, 0x0078, 0x42df, 0x781b, 0x00f9, 0x0f7f,
- 0x0e7f, 0x007c, 0x0c7e, 0x2001, 0x4f01, 0x2004, 0xd0ac, 0x00c0,
- 0x435b, 0x6814, 0x8007, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003,
- 0xb28c, 0x0300, 0x0040, 0x42f8, 0xa0e0, 0x53c0, 0x0078, 0x42fa,
- 0xa0e0, 0x5440, 0x6004, 0xa084, 0x000a, 0x00c0, 0x435b, 0x6108,
- 0xa194, 0xff00, 0x0040, 0x435b, 0xa18c, 0x00ff, 0x2001, 0x000a,
- 0xa106, 0x0040, 0x4326, 0x2001, 0x000c, 0xa106, 0x0040, 0x432a,
- 0x2001, 0x0012, 0xa106, 0x0040, 0x432e, 0x2001, 0x0014, 0xa106,
- 0x0040, 0x4332, 0x2001, 0x0019, 0xa106, 0x0040, 0x4336, 0x2001,
- 0x0032, 0xa106, 0x0040, 0x433a, 0x0078, 0x433e, 0x2009, 0x000c,
- 0x0078, 0x4340, 0x2009, 0x0012, 0x0078, 0x4340, 0x2009, 0x0014,
- 0x0078, 0x4340, 0x2009, 0x0019, 0x0078, 0x4340, 0x2009, 0x0020,
- 0x0078, 0x4340, 0x2009, 0x003f, 0x0078, 0x4340, 0x2011, 0x0000,
- 0x2100, 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x2061,
- 0x4f00, 0x6004, 0xd0bc, 0x0040, 0x435b, 0x6814, 0xd0fc, 0x00c0,
- 0x4356, 0x60ea, 0x2061, 0x4f40, 0x0078, 0x4359, 0x60ee, 0x2061,
- 0x4f80, 0x601f, 0x800f, 0x0c7f, 0x007c, 0x781b, 0x0079, 0x007c,
- 0x781b, 0x0078, 0x007c, 0x781b, 0x0067, 0x007c, 0x781b, 0x0064,
- 0x007c, 0x2009, 0x4f19, 0x210c, 0xa186, 0x0000, 0x0040, 0x437b,
- 0xa186, 0x0001, 0x0040, 0x437e, 0x701f, 0x000b, 0x7067, 0x0001,
- 0x781b, 0x0047, 0x007c, 0x781b, 0x00f0, 0x007c, 0x701f, 0x000a,
- 0x007c, 0x2009, 0x4f19, 0x210c, 0xa186, 0x0000, 0x0040, 0x4396,
- 0xa186, 0x0001, 0x0040, 0x4393, 0x701f, 0x000b, 0x7067, 0x0001,
- 0x781b, 0x0047, 0x007c, 0x701f, 0x000a, 0x007c, 0x781b, 0x00ef,
- 0x007c, 0x781b, 0x00f9, 0x007c, 0x781b, 0x00f8, 0x007c, 0x781b,
- 0x00c9, 0x007c, 0x781b, 0x00c8, 0x007c, 0x6818, 0xd0fc, 0x0040,
- 0x43ab, 0x681b, 0x001d, 0x7067, 0x0001, 0x781b, 0x0047, 0x007c,
- 0x7830, 0xa084, 0x00c0, 0x00c0, 0x43d2, 0x7808, 0xc08c, 0x780a,
- 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x00c0,
- 0x43cf, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x00c0, 0x43cd, 0x7804,
- 0xa084, 0xff1f, 0xa085, 0x00e0, 0x7806, 0xa006, 0x007c, 0x7808,
- 0xc08d, 0x780a, 0x007c, 0x7808, 0xc08d, 0x780a, 0x007c, 0x7830,
- 0xa084, 0x0040, 0x00c0, 0x43d7, 0x2001, 0x4f04, 0x2004, 0xd0ec,
- 0x0040, 0x43e6, 0xb284, 0x0300, 0x0078, 0x43e8, 0xb284, 0x0400,
- 0x0040, 0x43ee, 0x0098, 0x43f2, 0x0078, 0x43f0, 0x00a8, 0x43f2,
- 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0005, 0x0005,
- 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040, 0x4415, 0x007e,
- 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f, 0x0040, 0x440b, 0xb284,
- 0x0300, 0x0078, 0x440d, 0xb284, 0x0400, 0x0040, 0x4413, 0x0098,
- 0x440f, 0x0078, 0x4415, 0x00a8, 0x4413, 0x78ac, 0x007e, 0x7808,
- 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0xa784, 0x0001, 0x00c0,
- 0x37b9, 0xa784, 0x0070, 0x0040, 0x442d, 0x0c7e, 0x2d60, 0x2f68,
- 0x1078, 0x2926, 0x2d78, 0x2c68, 0x0c7f, 0xa784, 0x0008, 0x0040,
- 0x443a, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003, 0x0040, 0x37b9,
- 0x0078, 0x435d, 0xa784, 0x0004, 0x0040, 0x4469, 0x78b8, 0xa084,
- 0x4001, 0x0040, 0x4469, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
- 0x0040, 0x37b9, 0x78e4, 0xa084, 0x0007, 0xa086, 0x0001, 0x00c0,
- 0x4469, 0x78c0, 0xa685, 0x4800, 0x2030, 0x7e5a, 0x781b, 0x00f9,
- 0x007c, 0x784b, 0x0008, 0x6818, 0xd0fc, 0x0040, 0x4466, 0x681b,
- 0x0015, 0xd6f4, 0x0040, 0x4466, 0x681b, 0x0007, 0x1078, 0x4369,
- 0x007c, 0x681b, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681e, 0x682f,
- 0x0000, 0x6833, 0x0000, 0x784b, 0x0008, 0x78ec, 0xa084, 0x0003,
- 0x0040, 0x30af, 0x007e, 0x2001, 0x4f04, 0x2004, 0xd0ec, 0x007f,
- 0x0040, 0x4486, 0xb284, 0x0300, 0x0078, 0x4488, 0xb284, 0x0400,
- 0x0040, 0x448e, 0x0018, 0x2a08, 0x0078, 0x4490, 0x0028, 0x2a08,
- 0x0078, 0x410c, 0x6b14, 0x8307, 0xa084, 0x000f, 0x8003, 0x8003,
- 0x8003, 0xd3fc, 0x0040, 0x44a0, 0xa080, 0x5440, 0x0078, 0x44a2,
- 0xa080, 0x53c0, 0x2060, 0x2048, 0x705a, 0x2a60, 0x007c, 0x0020,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000,
- 0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9848, 0x0014, 0x0014,
- 0x9914, 0x98fd, 0x0014, 0x0014, 0x0080, 0x00ff, 0x0100, 0x0402,
- 0x2008, 0xf880, 0x0018, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014,
- 0x2500, 0x0013, 0x2500, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
- 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010, 0x0010,
- 0x0010, 0xa200, 0x3806, 0x7102, 0x805f, 0x9481, 0x8839, 0x20c4,
- 0x0864, 0xa856, 0x3008, 0x28c1, 0x9d1b, 0xa201, 0x300c, 0x2847,
- 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a, 0xa808, 0x28e2,
- 0x9ccb, 0xa8f3, 0x0864, 0xa844, 0x300c, 0xa801, 0x3008, 0x28e1,
- 0x9ccb, 0x2021, 0xa81d, 0xa205, 0x870c, 0xd8de, 0x64a0, 0x6de0,
- 0x6fc0, 0x63a4, 0x6c80, 0x0212, 0xa205, 0x883d, 0x7942, 0x8020,
- 0xa4a1, 0x882b, 0x1814, 0x883b, 0x80df, 0x94a1, 0x7027, 0x85f2,
- 0xa737, 0xa532, 0xf003, 0x8576, 0x8677, 0xa816, 0x883e, 0xa814,
- 0x2001, 0xa812, 0xa204, 0x64c0, 0x6de0, 0x67a0, 0x6fc0, 0x7942,
- 0x8020, 0xa4a1, 0x1814, 0x80df, 0x94a1, 0x883b, 0x7023, 0x8576,
- 0x8677, 0xa802, 0x7861, 0x883e, 0x206b, 0x28c1, 0x9d1b, 0x2044,
- 0x2103, 0x20a2, 0x2081, 0xa8c3, 0xa207, 0x0904, 0xa20e, 0xa809,
- 0xa203, 0x8000, 0x85a4, 0x1872, 0x879a, 0x883c, 0x1fe2, 0xf601,
- 0xa208, 0x856e, 0x866f, 0x7161, 0x0014, 0x0704, 0x3008, 0x9ccb,
- 0x0014, 0xa202, 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf844,
- 0x856e, 0x883f, 0x08e6, 0xa8f5, 0xf861, 0xa8ea, 0xf801, 0x0014,
- 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2, 0x1de2, 0x0014,
- 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0, 0x1fe6, 0x0014,
- 0x3008, 0x8000, 0x284a, 0x1011, 0xa8fc, 0x3008, 0x9d33, 0x8000,
- 0xa000, 0x2802, 0x1011, 0xa8fd, 0x9d39, 0xa8bd, 0x3008, 0x9d33,
- 0x283b, 0x1011, 0xa8fd, 0xa209, 0x7102, 0x805f, 0x9481, 0x0017,
- 0x300c, 0xa209, 0x8000, 0x85a4, 0x1de2, 0xa209, 0xdac1, 0x0014,
- 0x0210, 0xa801, 0x0014, 0x26e0, 0x873a, 0xfaa3, 0x19f2, 0x26e0,
- 0x18f2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x3806, 0x0210, 0x9d25,
- 0x0704, 0xa206, 0x6865, 0x817e, 0x842a, 0x1dc1, 0x8823, 0x0016,
- 0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a, 0xf021,
- 0x3008, 0x84a8, 0x11d6, 0x7042, 0x20dd, 0x0011, 0x20d4, 0x8822,
- 0x0016, 0x7944, 0x8421, 0xa020, 0xa532, 0x84a1, 0x0016, 0x7944,
- 0x8421, 0xa0df, 0x9532, 0x84a1, 0x0016, 0x0000, 0x127e, 0x70d4,
- 0xa084, 0x4600, 0x8004, 0x2090, 0x7204, 0x7008, 0xc09c, 0xa205,
- 0x00c0, 0x4602, 0x720c, 0x82ff, 0x0040, 0x45ed, 0x8aff, 0x00c0,
- 0x4602, 0x7200, 0xd284, 0x00c0, 0x4602, 0x7804, 0xd0cc, 0x0040,
- 0x45f3, 0x1078, 0x4acc, 0x7023, 0x0000, 0x7027, 0x0000, 0x7000,
- 0xd084, 0x0040, 0x45fd, 0x7007, 0x0004, 0x7003, 0x0008, 0x127f,
- 0x2000, 0x007c, 0x7000, 0xa084, 0x0003, 0x7002, 0xc69c, 0xd084,
- 0x0040, 0x465b, 0x7108, 0x0005, 0x7008, 0xa106, 0x00c0, 0x460a,
- 0xa184, 0x0003, 0x0040, 0x468c, 0xa184, 0x01e0, 0x00c0, 0x468c,
- 0xd1f4, 0x00c0, 0x460a, 0xa184, 0x3000, 0xa086, 0x1000, 0x0040,
- 0x460a, 0x2001, 0x4f05, 0x2004, 0xd0e4, 0x0040, 0x4637, 0x2011,
- 0x0180, 0x710c, 0x8211, 0x0040, 0x4645, 0x7008, 0xd0f4, 0x00c0,
- 0x460a, 0x700c, 0xa106, 0x0040, 0x462a, 0x0078, 0x4627, 0x2011,
- 0x0180, 0x710c, 0x8211, 0x0040, 0x4645, 0x7008, 0xd0f4, 0x00c0,
- 0x460a, 0x700c, 0xa106, 0x0040, 0x463a, 0x7007, 0x0012, 0x7108,
- 0x0005, 0x7008, 0xa106, 0x00c0, 0x4647, 0xa184, 0x0003, 0x0040,
- 0x468c, 0xd194, 0x0040, 0x4647, 0xd1f4, 0x0040, 0x468c, 0x7007,
- 0x0002, 0x0078, 0x460a, 0x7108, 0xd1fc, 0x0040, 0x4666, 0x1078,
- 0x47ed, 0x8aff, 0x0040, 0x45dc, 0x0078, 0x465b, 0x700c, 0xa08c,
- 0x03ff, 0x0040, 0x4691, 0x7004, 0xd084, 0x0040, 0x4683, 0x7014,
- 0xa005, 0x00c0, 0x467f, 0x7010, 0x7310, 0xa306, 0x00c0, 0x4673,
- 0x2300, 0xa005, 0x0040, 0x4683, 0xa102, 0x00c8, 0x465b, 0x7007,
- 0x0010, 0x0078, 0x468c, 0x8aff, 0x0040, 0x4691, 0x1078, 0x49f2,
- 0x00c0, 0x4686, 0x0040, 0x465b, 0x1078, 0x4738, 0x127f, 0x2000,
- 0x007c, 0x7204, 0x7108, 0xc19c, 0x8103, 0x00c8, 0x46a0, 0x7007,
- 0x0002, 0x0078, 0x4691, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c,
- 0xa205, 0x00c0, 0x468c, 0x7023, 0x0000, 0x7027, 0x0000, 0x7003,
- 0x0008, 0x007e, 0x2001, 0x4f01, 0x2004, 0xd0cc, 0x0040, 0x46b2,
- 0x1078, 0x4acc, 0x007f, 0x127f, 0x2000, 0x007c, 0x6428, 0x84ff,
- 0x0040, 0x46e2, 0x2c70, 0x7004, 0xa0bc, 0x000f, 0xa7b8, 0x46f2,
- 0x273c, 0x87fb, 0x00c0, 0x46d0, 0x0048, 0x46c8, 0x1078, 0x29b2,
- 0x609c, 0xa075, 0x0040, 0x46e2, 0x0078, 0x46bb, 0x2039, 0x46e7,
- 0x2704, 0xae68, 0x6808, 0xa630, 0x680c, 0xa529, 0x8421, 0x0040,
- 0x46e2, 0x8738, 0x2704, 0xa005, 0x00c0, 0x46d1, 0x709c, 0xa075,
- 0x00c0, 0x46bb, 0x007c, 0x0000, 0x0005, 0x0009, 0x000d, 0x0011,
- 0x0015, 0x0019, 0x001d, 0x0000, 0x0003, 0x0009, 0x000f, 0x0015,
- 0x001b, 0x0000, 0x0000, 0x46e7, 0x46e4, 0x0000, 0x0000, 0x8000,
- 0x0000, 0x46e7, 0x0000, 0x46ef, 0x46ec, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x46ef, 0x0000, 0x46ea, 0x46ea, 0x0000, 0x0000, 0x8000,
- 0x0000, 0x46ea, 0x0000, 0x46f0, 0x46f0, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x46f0, 0x2079, 0x4f00, 0x2071, 0x0010, 0x7007, 0x000a,
- 0x7007, 0x0002, 0x7003, 0x0001, 0x7810, 0xd0ec, 0x0040, 0x4726,
- 0x2009, 0x0001, 0x2071, 0x0020, 0x0078, 0x472a, 0x2009, 0x0002,
- 0x2071, 0x0050, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000,
- 0x8109, 0x0040, 0x4737, 0x2071, 0x0020, 0x0078, 0x472a, 0x007c,
- 0x7004, 0x8004, 0x00c8, 0x47c1, 0x7108, 0x7008, 0xa106, 0x00c0,
- 0x473c, 0xa184, 0x01e0, 0x0040, 0x4749, 0x1078, 0x4830, 0x0078,
- 0x47e9, 0x7007, 0x0012, 0x2019, 0x0000, 0x7108, 0x7008, 0xa106,
- 0x00c0, 0x474d, 0xa184, 0x01e0, 0x0040, 0x475a, 0x1078, 0x4830,
- 0x0078, 0x47e9, 0x7810, 0xd0ec, 0x0040, 0x4774, 0x2001, 0x04fd,
- 0x2004, 0xa086, 0x0003, 0x00c0, 0x4778, 0xa184, 0x4000, 0x0040,
- 0x477c, 0xa382, 0x0003, 0x00c8, 0x477c, 0xa184, 0x0004, 0x0040,
- 0x474d, 0x8318, 0x0078, 0x474d, 0x7814, 0xd0ec, 0x00c0, 0x477c,
- 0xa184, 0x4000, 0x00c0, 0x474d, 0xa19c, 0x300c, 0xa386, 0x2004,
- 0x0040, 0x4799, 0xa386, 0x0008, 0x0040, 0x47a4, 0x7004, 0xd084,
- 0x00c0, 0x4795, 0x7108, 0x7008, 0xa106, 0x00c0, 0x478a, 0xa184,
- 0x0003, 0x0040, 0x4795, 0x0078, 0x4830, 0xa386, 0x200c, 0x00c0,
- 0x474d, 0x7200, 0x8204, 0x0048, 0x47a4, 0x730c, 0xa384, 0x03ff,
- 0x0040, 0x47a4, 0x1078, 0x29b2, 0x7108, 0x7008, 0xa106, 0x00c0,
- 0x47a4, 0xa184, 0x01e0, 0x0040, 0x47b1, 0x1078, 0x4830, 0x0078,
- 0x47e9, 0x7007, 0x0012, 0x7000, 0xd084, 0x00c0, 0x47c1, 0x7310,
- 0x7014, 0xa305, 0x0040, 0x47c1, 0x710c, 0xa184, 0x03ff, 0x00c0,
- 0x4738, 0x7108, 0x7008, 0xa106, 0x00c0, 0x47c1, 0xa184, 0x01e0,
- 0x0040, 0x47ce, 0x1078, 0x4830, 0x0078, 0x47e9, 0x7007, 0x0012,
- 0x7007, 0x0008, 0x7004, 0xd09c, 0x00c0, 0x47d2, 0x7108, 0x7008,
- 0xa106, 0x00c0, 0x47d6, 0xa184, 0x01e0, 0x0040, 0x47e3, 0x1078,
- 0x4830, 0x0078, 0x47e9, 0x7007, 0x0012, 0x7108, 0x8103, 0x0048,
- 0x47d6, 0x7003, 0x0008, 0x007c, 0x7108, 0xa184, 0x01e0, 0x00c0,
- 0x4830, 0x7108, 0xa184, 0x01e0, 0x00c0, 0x4830, 0xa184, 0x0007,
- 0x0079, 0x47fa, 0x4804, 0x4814, 0x4802, 0x4814, 0x4802, 0x4872,
- 0x4802, 0x4870, 0x1078, 0x29b2, 0x7004, 0xa084, 0x0010, 0xc08d,
- 0x7006, 0x8aff, 0x00c0, 0x480f, 0x2049, 0x0000, 0x007c, 0x1078,
- 0x49f2, 0x00c0, 0x480f, 0x007c, 0x7004, 0xa084, 0x0010, 0xc08d,
- 0x7006, 0x7004, 0xd084, 0x00c0, 0x4828, 0x7108, 0x7008, 0xa106,
- 0x00c0, 0x481d, 0xa184, 0x0003, 0x0040, 0x4828, 0x0078, 0x4830,
- 0x8aff, 0x0040, 0x482f, 0x1078, 0x49f2, 0x00c0, 0x482b, 0x007c,
- 0x7007, 0x0012, 0x7108, 0x00e0, 0x4833, 0x2091, 0x6000, 0x00e0,
- 0x4837, 0x2091, 0x6000, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004,
- 0xd09c, 0x00c0, 0x483f, 0x7007, 0x0012, 0x7108, 0xd1fc, 0x00c0,
- 0x4843, 0x7003, 0x0000, 0x7000, 0xa005, 0x00c0, 0x4857, 0x7004,
- 0xa005, 0x00c0, 0x4857, 0x700c, 0xa005, 0x0040, 0x4859, 0x0078,
- 0x483b, 0x2049, 0x0000, 0xb284, 0x0100, 0x0040, 0x4863, 0x2001,
- 0x0000, 0x0078, 0x4865, 0x2001, 0x0001, 0x1078, 0x4262, 0x681b,
- 0x0002, 0x2051, 0x0000, 0x007c, 0x1078, 0x29b2, 0x1078, 0x29b2,
- 0x1078, 0x48b9, 0x7210, 0x7114, 0x700c, 0xa09c, 0x03ff, 0x2800,
- 0xa300, 0xa211, 0xa189, 0x0000, 0x1078, 0x48b9, 0x2704, 0x2c58,
- 0xac60, 0x6308, 0x2200, 0xa322, 0x630c, 0x2100, 0xa31b, 0x2400,
- 0xa305, 0x0040, 0x4895, 0x00c8, 0x4895, 0x8412, 0x8210, 0x830a,
- 0xa189, 0x0000, 0x2b60, 0x0078, 0x487c, 0x2b60, 0x8a07, 0x007e,
- 0x6004, 0xd09c, 0x0040, 0x48a0, 0xa7ba, 0x46ec, 0x0078, 0x48a2,
- 0xa7ba, 0x46e4, 0x007f, 0xa73d, 0x2c00, 0x6886, 0x6f8a, 0x6c92,
- 0x6b8e, 0x7108, 0x7008, 0xa106, 0x00c0, 0x48a9, 0xa184, 0x01e0,
- 0x0040, 0x48b4, 0x1078, 0x4830, 0x7007, 0x0012, 0x1078, 0x4738,
- 0x007c, 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x48cd, 0x6000,
- 0xa064, 0x00c0, 0x48c4, 0x2d60, 0x6004, 0xa084, 0x000f, 0xa080,
- 0x4702, 0x203c, 0x87fb, 0x1040, 0x29b2, 0x007c, 0x127e, 0x0d7e,
- 0x70d4, 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x6884, 0x2060,
- 0x6888, 0x6b8c, 0x6c90, 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff,
- 0x007e, 0x6804, 0xa084, 0x0008, 0x007f, 0x0040, 0x48eb, 0xa0b8,
- 0x46ec, 0x0078, 0x48ed, 0xa0b8, 0x46e4, 0xb284, 0x0100, 0x0040,
- 0x48f4, 0x7e20, 0x0078, 0x48f5, 0x7e24, 0xa6b5, 0x000c, 0x681c,
- 0xd0b4, 0x0040, 0x48fc, 0xc685, 0x2400, 0xa305, 0x0040, 0x4925,
- 0x2c58, 0x2704, 0x6104, 0xac60, 0x6000, 0xa400, 0x701a, 0x6004,
- 0xa301, 0x701e, 0xd19c, 0x0040, 0x4915, 0x6010, 0xa081, 0x0000,
- 0x7022, 0x6014, 0xa081, 0x0000, 0x7026, 0x6208, 0x2400, 0xa202,
- 0x7012, 0x620c, 0x2300, 0xa203, 0x7016, 0x7602, 0x7007, 0x0001,
- 0x2b60, 0x1078, 0x4a1c, 0x0078, 0x4927, 0x1078, 0x49f2, 0x00c0,
- 0x4925, 0x127f, 0x2000, 0x007c, 0x127e, 0x0d7e, 0x70d4, 0xa084,
- 0x4600, 0x8004, 0x2090, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xd094,
- 0x00c0, 0x4936, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c, 0x127e,
- 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x007e, 0x2090, 0x007f,
- 0x0d7f, 0x7e20, 0xb284, 0x0100, 0x00c0, 0x494f, 0x7e24, 0xa6b5,
- 0x000c, 0x681c, 0xd0ac, 0x00c0, 0x495a, 0xc685, 0x7003, 0x0000,
- 0x7007, 0x0004, 0x6828, 0x2050, 0x2d60, 0x6004, 0xa0bc, 0x000f,
- 0xa7b8, 0x46f2, 0x273c, 0x87fb, 0x00c0, 0x4970, 0x0048, 0x496a,
- 0x1078, 0x29b2, 0x689c, 0xa065, 0x0040, 0x4974, 0x0078, 0x495d,
- 0x1078, 0x49f2, 0x00c0, 0x4970, 0x127f, 0x2000, 0x007c, 0x127e,
- 0x007e, 0x017e, 0x0d7e, 0x70d4, 0xa084, 0x4600, 0x8004, 0x007e,
- 0x2090, 0x007f, 0x7e20, 0xb284, 0x0100, 0x00c0, 0x4988, 0x7e24,
- 0x0d7f, 0x037f, 0x047f, 0xa6b5, 0x000c, 0x681c, 0xd0b4, 0x0040,
- 0x4996, 0xc685, 0x7003, 0x0000, 0x7007, 0x0004, 0x2049, 0x4977,
- 0x6828, 0xa055, 0x0d7e, 0x0040, 0x49ee, 0x2d70, 0x2e60, 0x7004,
- 0xa0bc, 0x000f, 0xa7b8, 0x46f2, 0x273c, 0x87fb, 0x00c0, 0x49b3,
- 0x0048, 0x49ac, 0x1078, 0x29b2, 0x709c, 0xa075, 0x2060, 0x0040,
- 0x49ee, 0x0078, 0x499f, 0x2704, 0xae68, 0x6808, 0xa422, 0x680c,
- 0xa31b, 0x0048, 0x49cc, 0x8a51, 0x00c0, 0x49c0, 0x1078, 0x29b2,
- 0x8738, 0x2704, 0xa005, 0x00c0, 0x49b4, 0x709c, 0xa075, 0x2060,
- 0x0040, 0x49ee, 0x0078, 0x499f, 0x8422, 0x8420, 0x831a, 0xa399,
- 0x0000, 0x6908, 0x2400, 0xa122, 0x690c, 0x2300, 0xa11b, 0x00c8,
- 0x49db, 0x1078, 0x29b2, 0xb284, 0x0100, 0x0040, 0x49e9, 0x2001,
- 0x4f04, 0x2004, 0xd0ec, 0x00c0, 0x49e9, 0x2071, 0x0050, 0x0078,
- 0x49eb, 0x2071, 0x0020, 0x0d7f, 0x0078, 0x48fc, 0x0d7f, 0x127f,
- 0x2000, 0x007c, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040,
- 0x49fb, 0xa006, 0x007c, 0xa084, 0x0003, 0xa086, 0x0003, 0x00c0,
- 0x4a02, 0x007c, 0x2704, 0xac78, 0x7800, 0x701a, 0x7804, 0x701e,
- 0x7808, 0x7012, 0x780c, 0x7016, 0x6004, 0xd09c, 0x0040, 0x4a14,
- 0x7810, 0x7022, 0x7814, 0x7026, 0x7602, 0x7004, 0xa084, 0x0010,
- 0xc085, 0x7006, 0x2079, 0x4f00, 0x8738, 0x8a51, 0x0040, 0x4a40,
- 0x2704, 0xa005, 0x00c0, 0x4a32, 0x609c, 0xa005, 0x0040, 0x4a41,
- 0x2060, 0x6004, 0xa084, 0x000f, 0xa080, 0x46f2, 0x203c, 0x87fb,
- 0x1040, 0x29b2, 0x7008, 0x007e, 0xa084, 0x01e0, 0x007f, 0x0040,
- 0x4a3c, 0xa006, 0x0078, 0x4a41, 0xa084, 0x0003, 0xa086, 0x0003,
- 0x007c, 0x2051, 0x0000, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x70d4,
- 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x087f, 0x7108, 0xa184,
- 0x0003, 0x00c0, 0x4a59, 0x6828, 0xa005, 0x0040, 0x4a69, 0x0078,
- 0x4602, 0x7108, 0xd1fc, 0x0040, 0x4a61, 0x1078, 0x47ed, 0x0078,
- 0x4a4e, 0x7007, 0x0010, 0x7108, 0xd1fc, 0x0040, 0x4a63, 0x1078,
- 0x47ed, 0x7008, 0xa086, 0x0008, 0x00c0, 0x4a4e, 0x7000, 0xa005,
- 0x00c0, 0x4a4e, 0x7003, 0x0000, 0x2049, 0x0000, 0x007e, 0x7804,
- 0xd0cc, 0x0040, 0x4a7d, 0x1078, 0x4acc, 0x007f, 0x127f, 0x2000,
- 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0c7e, 0x0d7e, 0x70d4,
- 0xa084, 0x4600, 0x8004, 0x2090, 0x0d7f, 0x2049, 0x4a81, 0xad80,
- 0x0011, 0x20a0, 0xb284, 0x0100, 0x0040, 0x4aa4, 0x2001, 0x4f04,
- 0x2004, 0xd0ec, 0x0040, 0x4aa0, 0x2099, 0x0031, 0x0078, 0x4aa6,
- 0x2099, 0x0032, 0x0078, 0x4aa6, 0x2099, 0x0031, 0x700c, 0xa084,
- 0x03ff, 0x682a, 0x7007, 0x0008, 0x7007, 0x0002, 0x7003, 0x0001,
- 0x0040, 0x4ab5, 0x8000, 0x80ac, 0x53a5, 0x700c, 0xa084, 0x03ff,
- 0x0040, 0x4ac1, 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0,
- 0x4abc, 0x0c7f, 0x2049, 0x0000, 0x7003, 0x0000, 0x157f, 0x137f,
- 0x147f, 0x127f, 0x2000, 0x007c, 0x6814, 0xd0fc, 0x0040, 0x4b11,
- 0x7000, 0xd084, 0x0040, 0x4b11, 0x7e24, 0xa6b5, 0x0004, 0x7007,
- 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x4ad9, 0x7118, 0x017e,
- 0x711c, 0x017e, 0x7120, 0x017e, 0x7124, 0x017e, 0xa00e, 0x711a,
- 0x701f, 0x3fff, 0x7122, 0x7126, 0x7013, 0x0004, 0x7116, 0x7602,
- 0x7007, 0x0001, 0x2001, 0xffff, 0x2009, 0x0031, 0x200a, 0x200a,
- 0x7108, 0x7008, 0xa106, 0x00c0, 0x4af8, 0xd1fc, 0x0040, 0x4af8,
- 0x027f, 0x7226, 0x027f, 0x7222, 0x027f, 0x721e, 0x027f, 0x721a,
- 0x7007, 0x0002, 0x7008, 0xa086, 0x0008, 0x0040, 0x4b11, 0x0078,
- 0x4830, 0x7007, 0x0004, 0x7003, 0x0000, 0x007c, 0x2091, 0x8000,
- 0x2091, 0x6000, 0x78ac, 0xa005, 0x00c0, 0x4b2d, 0x7974, 0x70d0,
- 0xa106, 0x00c0, 0x4b2d, 0x781c, 0xa005, 0x0040, 0x4b2d, 0x781f,
- 0x0000, 0x0068, 0x4b2d, 0x2091, 0x4080, 0x7830, 0x8001, 0x7832,
- 0x00c0, 0x4bb5, 0x7834, 0x7832, 0x7810, 0xd0ec, 0x00c0, 0x4bae,
- 0x2061, 0x74c0, 0x2069, 0x4f80, 0xc7fd, 0x68d0, 0xa005, 0x0040,
- 0x4b47, 0x8001, 0x68d2, 0x00c0, 0x4b47, 0x1078, 0x4d83, 0x6800,
- 0xa084, 0x000f, 0x0040, 0x4b5c, 0xa086, 0x0001, 0x0040, 0x4b5c,
- 0x6844, 0xa00d, 0x0040, 0x4b5c, 0x2104, 0xa005, 0x0040, 0x4b5c,
- 0x8001, 0x200a, 0x0040, 0x4cf6, 0x6814, 0xa005, 0x0040, 0x4b81,
- 0x8001, 0x6816, 0x00c0, 0x4b81, 0x68a7, 0x0001, 0x0f7e, 0xd7fc,
- 0x00c0, 0x4b76, 0x7810, 0xd0ec, 0x0040, 0x4b72, 0x2079, 0x0100,
- 0x0078, 0x4b78, 0x2079, 0x0200, 0x0078, 0x4b78, 0x2079, 0x0100,
- 0x1078, 0x43d3, 0x0f7f, 0x6864, 0xa005, 0x0040, 0x4b81, 0x1078,
- 0x266f, 0x6880, 0xa005, 0x0040, 0x4b8e, 0x8001, 0x6882, 0x00c0,
- 0x4b8e, 0x6867, 0x0000, 0x68d4, 0xc0dd, 0x68d6, 0x68d4, 0xd0fc,
- 0x0040, 0x4bab, 0xc0fc, 0x68d6, 0x20a9, 0x0200, 0x6034, 0xa005,
- 0x0040, 0x4ba7, 0x8001, 0x6036, 0x68d4, 0xc0fd, 0x68d6, 0x00c0,
- 0x4ba7, 0x6010, 0xa005, 0x0040, 0x4ba7, 0x1078, 0x266f, 0xace0,
- 0x0010, 0x00f0, 0x4b96, 0xd7fc, 0x0040, 0x4bb5, 0x2061, 0x54c0,
- 0x2069, 0x4f40, 0xc7fc, 0x0078, 0x4b3d, 0x1078, 0x4bf1, 0x7838,
- 0x8001, 0x783a, 0x00c0, 0x4bd7, 0x783c, 0x783a, 0x2061, 0x54c0,
- 0x2069, 0x4f40, 0xc7fc, 0x680c, 0xa005, 0x0040, 0x4bc9, 0x1078,
- 0x4c5b, 0xd7fc, 0x00c0, 0x4bd7, 0x7810, 0xd0ec, 0x00c0, 0x4bd7,
- 0x2061, 0x74c0, 0x2069, 0x4f80, 0xc7fd, 0x0078, 0x4bc3, 0x7814,
- 0xd0e4, 0x00c0, 0x4bdb, 0x7810, 0xd0cc, 0x0040, 0x4bee, 0xd0ac,
- 0x00c0, 0x4be7, 0xd0a4, 0x0040, 0x4bee, 0xc0ad, 0x7812, 0x2091,
- 0x8001, 0x0068, 0x4bed, 0x1078, 0x23dc, 0x007c, 0x2091, 0x8001,
- 0x007c, 0x7840, 0x8001, 0x7842, 0x00c0, 0x4c5a, 0x7844, 0x7842,
- 0x2069, 0x4f40, 0xc7fc, 0x7810, 0x2079, 0x0200, 0xd0ec, 0x0040,
- 0x4c03, 0x2079, 0x0100, 0x68d8, 0xa005, 0x0040, 0x4c0f, 0x7de0,
- 0xa504, 0x00c0, 0x4c0f, 0x68da, 0x68d4, 0xc0bc, 0x68d6, 0x2079,
- 0x4f00, 0x6810, 0xa005, 0x00c0, 0x4c17, 0x2001, 0x0101, 0x8001,
- 0x6812, 0xd7fc, 0x0040, 0x4c20, 0xa080, 0x95d0, 0x0078, 0x4c22,
- 0xa080, 0x94c0, 0x2040, 0x2004, 0xa065, 0x0040, 0x4c4c, 0x6024,
- 0xa005, 0x0040, 0x4c48, 0x8001, 0x6026, 0x00c0, 0x4c48, 0x6800,
- 0xa005, 0x0040, 0x4c3b, 0x684c, 0xac06, 0x00c0, 0x4c3b, 0x1078,
- 0x4cf6, 0x0078, 0x4c4c, 0x6864, 0xa005, 0x0040, 0x4c43, 0x6027,
- 0x0001, 0x0078, 0x4c48, 0x1078, 0x4ca9, 0x2804, 0x0078, 0x4c24,
- 0x6000, 0x2c40, 0x0078, 0x4c24, 0xd7fc, 0x00c0, 0x4c5a, 0x7810,
- 0xd0ec, 0x00c0, 0x4c5a, 0x2069, 0x4f80, 0xc7fd, 0x2079, 0x0100,
- 0x0078, 0x4c03, 0x007c, 0x2009, 0x0000, 0x20a9, 0x0200, 0x6008,
- 0xd09c, 0x0040, 0x4c95, 0x6024, 0xa005, 0x0040, 0x4c6b, 0x8001,
- 0x6026, 0x0078, 0x4c93, 0x6008, 0xc09c, 0xd084, 0x00c0, 0x4c73,
- 0xd0ac, 0x0040, 0x4c8d, 0x600a, 0x6004, 0xa005, 0x0040, 0x4c95,
- 0x0d7e, 0x0c7e, 0x017e, 0x2068, 0x6010, 0x8001, 0x6012, 0x1078,
- 0x3e19, 0x2d00, 0x2c68, 0x2060, 0x1078, 0x1ea2, 0x1078, 0x2064,
- 0x017f, 0x0c7f, 0x0d7f, 0x0078, 0x4c95, 0xc0bd, 0x600a, 0xa18d,
- 0x0001, 0x0078, 0x4c95, 0xa18d, 0x0100, 0xace0, 0x0010, 0x00f0,
- 0x4c5f, 0xa184, 0x0001, 0x0040, 0x4ca4, 0xa18c, 0xfffe, 0x690e,
- 0x1078, 0x266f, 0x0078, 0x4ca5, 0x690e, 0x007c, 0x00c0, 0x4ca5,
- 0x786c, 0x2c00, 0x687e, 0x6714, 0x6f76, 0x6017, 0x0000, 0x602b,
- 0x0000, 0x601b, 0x0006, 0x60b4, 0xa084, 0x3f00, 0x601e, 0x6020,
- 0xa084, 0x00ff, 0xa085, 0x0060, 0x6022, 0x6000, 0x2042, 0x1078,
- 0x1e2b, 0x6818, 0xa005, 0x0040, 0x4cc7, 0x8001, 0x681a, 0x6808,
- 0xc0a4, 0x680a, 0x6810, 0x7908, 0x8109, 0x790a, 0x8001, 0x00d0,
- 0x4cd3, 0x1078, 0x29b2, 0x6812, 0x00c0, 0x4cd9, 0x7910, 0xc1a5,
- 0x7912, 0x602f, 0x0000, 0x6033, 0x0000, 0x2c68, 0x1078, 0x2073,
- 0xd7fc, 0x00c0, 0x4ce7, 0x2069, 0x4f40, 0x0078, 0x4ce9, 0x2069,
- 0x4f80, 0x6910, 0xa184, 0x0100, 0x2001, 0x0006, 0x00c0, 0x4cf3,
- 0x697a, 0x2001, 0x0004, 0x1078, 0x2663, 0x007c, 0x0d7e, 0x694c,
- 0x2160, 0xd7fc, 0x00c0, 0x4d08, 0x7810, 0xd0ec, 0x0040, 0x4d04,
- 0x2069, 0x0100, 0x0078, 0x4d0a, 0x2069, 0x0200, 0x0078, 0x4d0a,
- 0x2069, 0x0100, 0x1078, 0x2926, 0x601b, 0x0006, 0x6858, 0xa084,
- 0x3f00, 0x601e, 0x6020, 0xa084, 0x00ff, 0xa085, 0x0048, 0x6022,
- 0x602f, 0x0000, 0x6033, 0x0000, 0x6808, 0xa084, 0xfffd, 0x680a,
- 0x6830, 0xd0b4, 0x0040, 0x4d3c, 0x684b, 0x0004, 0x20a9, 0x0014,
- 0x6848, 0xd094, 0x0040, 0x4d2e, 0x00f0, 0x4d28, 0x684b, 0x0009,
- 0x20a9, 0x0014, 0x6848, 0xd084, 0x0040, 0x4d38, 0x00f0, 0x4d32,
- 0x20a9, 0x00fa, 0x00f0, 0x4d3a, 0x681b, 0x0047, 0x0d7f, 0x6867,
- 0x0007, 0x007c, 0x2079, 0x4f00, 0x1078, 0x4d76, 0x1078, 0x4d5c,
- 0x1078, 0x4d69, 0x2009, 0x0002, 0x2069, 0x4f80, 0x680f, 0x0000,
- 0x6813, 0x0000, 0x6817, 0x0000, 0x8109, 0x0040, 0x4d5b, 0x2069,
- 0x4f40, 0x0078, 0x4d4e, 0x007c, 0x7810, 0xd0ec, 0x0040, 0x4d64,
- 0x2019, 0x00cc, 0x0078, 0x4d66, 0x2019, 0x007b, 0x7b3a, 0x7b3e,
- 0x007c, 0x7814, 0xd0e4, 0x00c0, 0x4d71, 0x2019, 0x0040, 0x0078,
- 0x4d73, 0x2019, 0x0026, 0x7b42, 0x7b46, 0x007c, 0x7814, 0xd0e4,
- 0x00c0, 0x4d7e, 0x2019, 0x3f94, 0x0078, 0x4d80, 0x2019, 0x2624,
- 0x7b32, 0x7b36, 0x007c, 0x6a50, 0xa285, 0x0000, 0x0040, 0x4daf,
- 0x6954, 0x6bc0, 0xa300, 0x0c7e, 0x2164, 0x6304, 0x83ff, 0x00c0,
- 0x4d9b, 0x8211, 0x0040, 0x4d9f, 0x8108, 0xa11a, 0x0048, 0x4d8c,
- 0x69c0, 0x0078, 0x4d8c, 0x68d3, 0x000a, 0x0c7f, 0x007c, 0x6950,
- 0x6ac0, 0x2264, 0x602b, 0x0000, 0x602f, 0x0000, 0x6008, 0xc0b5,
- 0x600a, 0x8210, 0x8109, 0x00c0, 0x4da1, 0x6952, 0x0c7f, 0x007c,
- 0x00e0, 0x4db0, 0x2091, 0x6000, 0x00e0, 0x4db4, 0x2091, 0x6000,
- 0x70ec, 0xd0dc, 0x00c0, 0x4dc1, 0xd0d4, 0x0040, 0x4dea, 0x0078,
- 0x4ded, 0x2008, 0x7810, 0xd0ec, 0x0040, 0x4dd4, 0xd1c4, 0x00c0,
- 0x4e0e, 0x7814, 0xc0c5, 0x7816, 0x7810, 0xc0f5, 0x7812, 0xd0ec,
- 0x0040, 0x4e0a, 0x0078, 0x4e06, 0xae8e, 0x0100, 0x0040, 0x4de1,
- 0x7814, 0xc0f5, 0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4e0a, 0x0078,
- 0x4e06, 0x7814, 0xc0fd, 0xc0c5, 0x7816, 0xd0d4, 0x00c0, 0x4e0a,
- 0x0078, 0x4e06, 0xd0e4, 0x0040, 0x4e0c, 0x00e0, 0x4ded, 0x2091,
- 0x6000, 0x2009, 0x000c, 0x00e0, 0x4df3, 0x2091, 0x6000, 0x8109,
- 0x00c0, 0x4df3, 0x70e4, 0xa084, 0x01ff, 0xa086, 0x01ff, 0x00c0,
- 0x4e04, 0x70ec, 0x0078, 0x4dc1, 0x1078, 0x4e0f, 0x7804, 0xd08c,
- 0x0040, 0x4e0c, 0x681f, 0x000c, 0x70a0, 0x70a2, 0x007c, 0x7910,
- 0xd1ec, 0x0040, 0x4e19, 0x7814, 0xc0c4, 0xc1f4, 0x7912, 0x0078,
- 0x4e2b, 0xae8e, 0x0100, 0x0040, 0x4e25, 0x7814, 0xc0f4, 0xd0fc,
- 0x00c0, 0x4e2b, 0xc0c4, 0x0078, 0x4e2b, 0x7814, 0xc0fc, 0xd0f4,
- 0x00c0, 0x4e2b, 0xc0c4, 0x7816, 0x007c, 0x14e3
-};
-#ifdef UNIQUE_FW_NAME
-static unsigned short fw1280ei_length01 = 0x3e2e;
-#else
-static unsigned short risc_code_length01 = 0x3e2e;
-#endif
-
diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
index df09820e891..351b56ced92 100644
--- a/drivers/scsi/qla1280.c
+++ b/drivers/scsi/qla1280.c
@@ -348,6 +348,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
#include <asm/io.h>
#include <asm/irq.h>
@@ -384,11 +385,7 @@
#define MEMORY_MAPPED_IO 1
#endif
-#define UNIQUE_FW_NAME
#include "qla1280.h"
-#include "ql12160_fw.h" /* ISP RISC codes */
-#include "ql1280_fw.h"
-#include "ql1040_fw.h"
#ifndef BITS_PER_LONG
#error "BITS_PER_LONG not defined!"
@@ -541,10 +538,7 @@ __setup("qla1280=", qla1280_setup);
struct qla_boards {
unsigned char name[9]; /* Board ID String */
int numPorts; /* Number of SCSI ports */
- unsigned short *fwcode; /* pointer to FW array */
- unsigned short *fwlen; /* number of words in array */
- unsigned short *fwstart; /* start address for F/W */
- unsigned char *fwver; /* Ptr to F/W version array */
+ char *fwname; /* firmware name */
};
/* NOTE: the last argument in each entry is used to index ql1280_board_tbl */
@@ -567,19 +561,13 @@ MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl);
static struct qla_boards ql1280_board_tbl[] = {
/* Name , Number of ports, FW details */
- {"QLA12160", 2, &fw12160i_code01[0], &fw12160i_length01,
- &fw12160i_addr01, &fw12160i_version_str[0]},
- {"QLA1040", 1, &risc_code01[0], &risc_code_length01,
- &risc_code_addr01, &firmware_version[0]},
- {"QLA1080", 1, &fw1280ei_code01[0], &fw1280ei_length01,
- &fw1280ei_addr01, &fw1280ei_version_str[0]},
- {"QLA1240", 2, &fw1280ei_code01[0], &fw1280ei_length01,
- &fw1280ei_addr01, &fw1280ei_version_str[0]},
- {"QLA1280", 2, &fw1280ei_code01[0], &fw1280ei_length01,
- &fw1280ei_addr01, &fw1280ei_version_str[0]},
- {"QLA10160", 1, &fw12160i_code01[0], &fw12160i_length01,
- &fw12160i_addr01, &fw12160i_version_str[0]},
- {" ", 0}
+ {"QLA12160", 2, "qlogic/12160.bin"},
+ {"QLA1040", 1, "qlogic/1040.bin"},
+ {"QLA1080", 1, "qlogic/1280.bin"},
+ {"QLA1240", 2, "qlogic/1280.bin"},
+ {"QLA1280", 2, "qlogic/1280.bin"},
+ {"QLA10160", 1, "qlogic/12160.bin"},
+ {" ", 0, " "},
};
static int qla1280_verbose = 1;
@@ -704,7 +692,7 @@ qla1280_info(struct Scsi_Host *host)
sprintf (bp,
"QLogic %s PCI to SCSI Host Adapter\n"
" Firmware version: %2d.%02d.%02d, Driver version %s",
- &bdp->name[0], bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
+ &bdp->name[0], ha->fwver1, ha->fwver2, ha->fwver3,
QLA1280_VERSION);
return bp;
}
@@ -1648,36 +1636,60 @@ qla1280_chip_diag(struct scsi_qla_host *ha)
static int
qla1280_load_firmware_pio(struct scsi_qla_host *ha)
{
- uint16_t risc_address, *risc_code_address, risc_code_size;
+ const struct firmware *fw;
+ const __le16 *fw_data;
+ uint16_t risc_address, risc_code_size;
uint16_t mb[MAILBOX_REGISTER_COUNT], i;
int err;
+ err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
+ &ha->pdev->dev);
+ if (err) {
+ printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ ql1280_board_tbl[ha->devnum].fwname, err);
+ return err;
+ }
+ if ((fw->size % 2) || (fw->size < 6)) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, ql1280_board_tbl[ha->devnum].fwname);
+ err = -EINVAL;
+ goto out;
+ }
+ ha->fwver1 = fw->data[0];
+ ha->fwver2 = fw->data[1];
+ ha->fwver3 = fw->data[2];
+ fw_data = (const __le16 *)&fw->data[0];
+ ha->fwstart = __le16_to_cpu(fw_data[2]);
+
/* Load RISC code. */
- risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
- risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
- risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
+ risc_address = ha->fwstart;
+ fw_data = (const __le16 *)&fw->data[4];
+ risc_code_size = (fw->size - 6) / 2;
for (i = 0; i < risc_code_size; i++) {
mb[0] = MBC_WRITE_RAM_WORD;
mb[1] = risc_address + i;
- mb[2] = risc_code_address[i];
+ mb[2] = __le16_to_cpu(fw_data[i]);
err = qla1280_mailbox_command(ha, BIT_0 | BIT_1 | BIT_2, mb);
if (err) {
printk(KERN_ERR "scsi(%li): Failed to load firmware\n",
ha->host_no);
- return err;
+ goto out;
}
}
-
- return 0;
+out:
+ release_firmware(fw);
+ return err;
}
#define DUMP_IT_BACK 0 /* for debug of RISC loading */
static int
qla1280_load_firmware_dma(struct scsi_qla_host *ha)
{
- uint16_t risc_address, *risc_code_address, risc_code_size;
+ const struct firmware *fw;
+ const __le16 *fw_data;
+ uint16_t risc_address, risc_code_size;
uint16_t mb[MAILBOX_REGISTER_COUNT], cnt;
int err = 0, num, i;
#if DUMP_IT_BACK
@@ -1689,10 +1701,29 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
return -ENOMEM;
#endif
+ err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
+ &ha->pdev->dev);
+ if (err) {
+ printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ ql1280_board_tbl[ha->devnum].fwname, err);
+ return err;
+ }
+ if ((fw->size % 2) || (fw->size < 6)) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, ql1280_board_tbl[ha->devnum].fwname);
+ err = -EINVAL;
+ goto out;
+ }
+ ha->fwver1 = fw->data[0];
+ ha->fwver2 = fw->data[1];
+ ha->fwver3 = fw->data[2];
+ fw_data = (const __le16 *)&fw->data[0];
+ ha->fwstart = __le16_to_cpu(fw_data[2]);
+
/* Load RISC code. */
- risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
- risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
- risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
+ risc_address = ha->fwstart;
+ fw_data = (const __le16 *)&fw->data[4];
+ risc_code_size = (fw->size - 6) / 2;
dprintk(1, "%s: DMA RISC code (%i) words\n",
__func__, risc_code_size);
@@ -1708,10 +1739,9 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
dprintk(2, "qla1280_setup_chip: loading risc @ =(0x%p),"
"%d,%d(0x%x)\n",
- risc_code_address, cnt, num, risc_address);
+ fw_data, cnt, num, risc_address);
for(i = 0; i < cnt; i++)
- ((__le16 *)ha->request_ring)[i] =
- cpu_to_le16(risc_code_address[i]);
+ ((__le16 *)ha->request_ring)[i] = fw_data[i];
mb[0] = MBC_LOAD_RAM;
mb[1] = risc_address;
@@ -1763,7 +1793,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
#endif
risc_address += cnt;
risc_code_size = risc_code_size - cnt;
- risc_code_address = risc_code_address + cnt;
+ fw_data = fw_data + cnt;
num++;
}
@@ -1771,6 +1801,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
#if DUMP_IT_BACK
pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
#endif
+ release_firmware(fw);
return err;
}
@@ -1786,7 +1817,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
/* Verify checksum of loaded RISC code. */
mb[0] = MBC_VERIFY_CHECKSUM;
/* mb[1] = ql12_risc_code_addr01; */
- mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+ mb[1] = ha->fwstart;
err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
if (err) {
printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", ha->host_no);
@@ -1796,7 +1827,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
/* Start firmware execution. */
dprintk(1, "%s: start firmware running.\n", __func__);
mb[0] = MBC_EXECUTE_FIRMWARE;
- mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
+ mb[1] = ha->fwstart;
err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
if (err) {
printk(KERN_ERR "scsi(%li): Failed to start firmware\n",
@@ -4450,6 +4481,9 @@ module_exit(qla1280_exit);
MODULE_AUTHOR("Qlogic & Jes Sorensen");
MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE("qlogic/1040.bin");
+MODULE_FIRMWARE("qlogic/1280.bin");
+MODULE_FIRMWARE("qlogic/12160.bin");
MODULE_VERSION(QLA1280_VERSION);
/*
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index ff2c363ead2..d7c44b8d2b4 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -1069,6 +1069,12 @@ struct scsi_qla_host {
struct nvram nvram;
int nvram_valid;
+
+ /* Firmware Info */
+ unsigned short fwstart; /* start address for F/W */
+ unsigned char fwver1; /* F/W version first char */
+ unsigned char fwver2; /* F/W version second char */
+ unsigned char fwver3; /* F/W version third char */
};
#endif /* _QLA1280_H */
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 33a3c13fd89..b09993a0657 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -96,7 +96,9 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return 0;
- /* Read NVRAM data from cache. */
+ if (IS_NOCACHE_VPD_TYPE(ha))
+ ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_nvram << 2,
+ ha->nvram_size);
return memory_read_from_buffer(buf, count, &off, ha->nvram,
ha->nvram_size);
}
@@ -111,7 +113,8 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
struct qla_hw_data *ha = vha->hw;
uint16_t cnt;
- if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size)
+ if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->nvram_size ||
+ !ha->isp_ops->write_nvram)
return 0;
/* Checksum NVRAM. */
@@ -137,12 +140,21 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj,
*iter = chksum;
}
+ if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "HBA not online, failing NVRAM update.\n");
+ return -EAGAIN;
+ }
+
/* Write NVRAM. */
ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->nvram_base, count);
ha->isp_ops->read_nvram(vha, (uint8_t *)ha->nvram, ha->nvram_base,
count);
+ /* NVRAM settings take effect immediately. */
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ qla2x00_wait_for_chip_reset(vha);
return (count);
}
@@ -244,12 +256,6 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
if (ha->optrom_state != QLA_SWAITING)
break;
- if (start & 0xfff) {
- qla_printk(KERN_WARNING, ha,
- "Invalid start region 0x%x/0x%x.\n", start, size);
- return -EINVAL;
- }
-
ha->optrom_region_start = start;
ha->optrom_region_size = start + size > ha->optrom_size ?
ha->optrom_size - start : size;
@@ -303,8 +309,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
else if (start == (ha->flt_region_boot * 4) ||
start == (ha->flt_region_fw * 4))
valid = 1;
- else if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) &&
- start == (ha->flt_region_vpd_nvram * 4))
+ else if (IS_QLA25XX(ha) || IS_QLA81XX(ha))
valid = 1;
if (!valid) {
qla_printk(KERN_WARNING, ha,
@@ -337,6 +342,12 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj,
if (ha->optrom_state != QLA_SWRITING)
break;
+ if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "HBA not online, failing flash update.\n");
+ return -EAGAIN;
+ }
+
DEBUG2(qla_printk(KERN_INFO, ha,
"Writing flash region -- 0x%x/0x%x.\n",
ha->optrom_region_start, ha->optrom_region_size));
@@ -371,7 +382,9 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj,
if (!capable(CAP_SYS_ADMIN))
return 0;
- /* Read NVRAM data from cache. */
+ if (IS_NOCACHE_VPD_TYPE(ha))
+ ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
+ ha->vpd_size);
return memory_read_from_buffer(buf, count, &off, ha->vpd, ha->vpd_size);
}
@@ -383,14 +396,35 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj,
struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
struct device, kobj)));
struct qla_hw_data *ha = vha->hw;
+ uint8_t *tmp_data;
- if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size)
+ if (!capable(CAP_SYS_ADMIN) || off != 0 || count != ha->vpd_size ||
+ !ha->isp_ops->write_nvram)
return 0;
+ if (qla2x00_wait_for_hba_online(vha) != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "HBA not online, failing VPD update.\n");
+ return -EAGAIN;
+ }
+
/* Write NVRAM. */
ha->isp_ops->write_nvram(vha, (uint8_t *)buf, ha->vpd_base, count);
ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd, ha->vpd_base, count);
+ /* Update flash version information for 4Gb & above. */
+ if (!IS_FWI2_CAPABLE(ha))
+ goto done;
+
+ tmp_data = vmalloc(256);
+ if (!tmp_data) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to allocate memory for VPD information update.\n");
+ goto done;
+ }
+ ha->isp_ops->get_flash_version(vha, tmp_data);
+ vfree(tmp_data);
+done:
return count;
}
@@ -465,6 +499,199 @@ static struct bin_attribute sysfs_sfp_attr = {
.read = qla2x00_sysfs_read_sfp,
};
+static ssize_t
+qla2x00_sysfs_write_reset(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+ struct qla_hw_data *ha = vha->hw;
+ int type;
+
+ if (off != 0)
+ return 0;
+
+ type = simple_strtol(buf, NULL, 10);
+ switch (type) {
+ case 0x2025c:
+ qla_printk(KERN_INFO, ha,
+ "Issuing ISP reset on (%ld).\n", vha->host_no);
+
+ scsi_block_requests(vha->host);
+ set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
+ qla2xxx_wake_dpc(vha);
+ qla2x00_wait_for_chip_reset(vha);
+ scsi_unblock_requests(vha->host);
+ break;
+ case 0x2025d:
+ if (!IS_QLA81XX(ha))
+ break;
+
+ qla_printk(KERN_INFO, ha,
+ "Issuing MPI reset on (%ld).\n", vha->host_no);
+
+ /* Make sure FC side is not in reset */
+ qla2x00_wait_for_hba_online(vha);
+
+ /* Issue MPI reset */
+ scsi_block_requests(vha->host);
+ if (qla81xx_restart_mpi_firmware(vha) != QLA_SUCCESS)
+ qla_printk(KERN_WARNING, ha,
+ "MPI reset failed on (%ld).\n", vha->host_no);
+ scsi_unblock_requests(vha->host);
+ break;
+ }
+ return count;
+}
+
+static struct bin_attribute sysfs_reset_attr = {
+ .attr = {
+ .name = "reset",
+ .mode = S_IWUSR,
+ },
+ .size = 0,
+ .write = qla2x00_sysfs_write_reset,
+};
+
+static ssize_t
+qla2x00_sysfs_write_edc(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+ struct qla_hw_data *ha = vha->hw;
+ uint16_t dev, adr, opt, len;
+ int rval;
+
+ ha->edc_data_len = 0;
+
+ if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8)
+ return 0;
+
+ if (!ha->edc_data) {
+ ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+ &ha->edc_data_dma);
+ if (!ha->edc_data) {
+ DEBUG2(qla_printk(KERN_INFO, ha,
+ "Unable to allocate memory for EDC write.\n"));
+ return 0;
+ }
+ }
+
+ dev = le16_to_cpup((void *)&buf[0]);
+ adr = le16_to_cpup((void *)&buf[2]);
+ opt = le16_to_cpup((void *)&buf[4]);
+ len = le16_to_cpup((void *)&buf[6]);
+
+ if (!(opt & BIT_0))
+ if (len == 0 || len > DMA_POOL_SIZE || len > count - 8)
+ return -EINVAL;
+
+ memcpy(ha->edc_data, &buf[8], len);
+
+ rval = qla2x00_write_edc(vha, dev, adr, ha->edc_data_dma,
+ ha->edc_data, len, opt);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(qla_printk(KERN_INFO, ha,
+ "Unable to write EDC (%x) %02x:%02x:%04x:%02x:%02x.\n",
+ rval, dev, adr, opt, len, *buf));
+ return 0;
+ }
+
+ return count;
+}
+
+static struct bin_attribute sysfs_edc_attr = {
+ .attr = {
+ .name = "edc",
+ .mode = S_IWUSR,
+ },
+ .size = 0,
+ .write = qla2x00_sysfs_write_edc,
+};
+
+static ssize_t
+qla2x00_sysfs_write_edc_status(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+ struct qla_hw_data *ha = vha->hw;
+ uint16_t dev, adr, opt, len;
+ int rval;
+
+ ha->edc_data_len = 0;
+
+ if (!capable(CAP_SYS_ADMIN) || off != 0 || count < 8)
+ return 0;
+
+ if (!ha->edc_data) {
+ ha->edc_data = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+ &ha->edc_data_dma);
+ if (!ha->edc_data) {
+ DEBUG2(qla_printk(KERN_INFO, ha,
+ "Unable to allocate memory for EDC status.\n"));
+ return 0;
+ }
+ }
+
+ dev = le16_to_cpup((void *)&buf[0]);
+ adr = le16_to_cpup((void *)&buf[2]);
+ opt = le16_to_cpup((void *)&buf[4]);
+ len = le16_to_cpup((void *)&buf[6]);
+
+ if (!(opt & BIT_0))
+ if (len == 0 || len > DMA_POOL_SIZE)
+ return -EINVAL;
+
+ memset(ha->edc_data, 0, len);
+ rval = qla2x00_read_edc(vha, dev, adr, ha->edc_data_dma,
+ ha->edc_data, len, opt);
+ if (rval != QLA_SUCCESS) {
+ DEBUG2(qla_printk(KERN_INFO, ha,
+ "Unable to write EDC status (%x) %02x:%02x:%04x:%02x.\n",
+ rval, dev, adr, opt, len));
+ return 0;
+ }
+
+ ha->edc_data_len = len;
+
+ return count;
+}
+
+static ssize_t
+qla2x00_sysfs_read_edc_status(struct kobject *kobj,
+ struct bin_attribute *bin_attr,
+ char *buf, loff_t off, size_t count)
+{
+ struct scsi_qla_host *vha = shost_priv(dev_to_shost(container_of(kobj,
+ struct device, kobj)));
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!capable(CAP_SYS_ADMIN) || off != 0 || count == 0)
+ return 0;
+
+ if (!ha->edc_data || ha->edc_data_len == 0 || ha->edc_data_len > count)
+ return -EINVAL;
+
+ memcpy(buf, ha->edc_data, ha->edc_data_len);
+
+ return ha->edc_data_len;
+}
+
+static struct bin_attribute sysfs_edc_status_attr = {
+ .attr = {
+ .name = "edc_status",
+ .mode = S_IRUSR | S_IWUSR,
+ },
+ .size = 0,
+ .write = qla2x00_sysfs_write_edc_status,
+ .read = qla2x00_sysfs_read_edc_status,
+};
+
static struct sysfs_entry {
char *name;
struct bin_attribute *attr;
@@ -476,6 +703,9 @@ static struct sysfs_entry {
{ "optrom_ctl", &sysfs_optrom_ctl_attr, },
{ "vpd", &sysfs_vpd_attr, 1 },
{ "sfp", &sysfs_sfp_attr, 1 },
+ { "reset", &sysfs_reset_attr, },
+ { "edc", &sysfs_edc_attr, 2 },
+ { "edc_status", &sysfs_edc_status_attr, 2 },
{ NULL },
};
@@ -489,6 +719,8 @@ qla2x00_alloc_sysfs_attr(scsi_qla_host_t *vha)
for (iter = bin_file_entries; iter->name; iter++) {
if (iter->is4GBp_only && !IS_FWI2_CAPABLE(vha->hw))
continue;
+ if (iter->is4GBp_only == 2 && !IS_QLA25XX(vha->hw))
+ continue;
ret = sysfs_create_bin_file(&host->shost_gendev.kobj,
iter->attr);
@@ -509,6 +741,8 @@ qla2x00_free_sysfs_attr(scsi_qla_host_t *vha)
for (iter = bin_file_entries; iter->name; iter++) {
if (iter->is4GBp_only && !IS_FWI2_CAPABLE(ha))
continue;
+ if (iter->is4GBp_only == 2 && !IS_QLA25XX(ha))
+ continue;
sysfs_remove_bin_file(&host->shost_gendev.kobj,
iter->attr);
@@ -825,9 +1059,33 @@ qla2x00_mpi_version_show(struct device *dev, struct device_attribute *attr,
if (!IS_QLA81XX(ha))
return snprintf(buf, PAGE_SIZE, "\n");
- return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x (%x)\n",
+ return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d (%x)\n",
ha->mpi_version[0], ha->mpi_version[1], ha->mpi_version[2],
- ha->mpi_version[3], ha->mpi_capabilities);
+ ha->mpi_capabilities);
+}
+
+static ssize_t
+qla2x00_phy_version_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+
+ if (!IS_QLA81XX(ha))
+ return snprintf(buf, PAGE_SIZE, "\n");
+
+ return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d\n",
+ ha->phy_version[0], ha->phy_version[1], ha->phy_version[2]);
+}
+
+static ssize_t
+qla2x00_flash_block_size_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ scsi_qla_host_t *vha = shost_priv(class_to_shost(dev));
+ struct qla_hw_data *ha = vha->hw;
+
+ return snprintf(buf, PAGE_SIZE, "0x%x\n", ha->fdt_block_size);
}
static DEVICE_ATTR(driver_version, S_IRUGO, qla2x00_drvr_version_show, NULL);
@@ -855,6 +1113,9 @@ static DEVICE_ATTR(optrom_fw_version, S_IRUGO, qla2x00_optrom_fw_version_show,
static DEVICE_ATTR(total_isp_aborts, S_IRUGO, qla2x00_total_isp_aborts_show,
NULL);
static DEVICE_ATTR(mpi_version, S_IRUGO, qla2x00_mpi_version_show, NULL);
+static DEVICE_ATTR(phy_version, S_IRUGO, qla2x00_phy_version_show, NULL);
+static DEVICE_ATTR(flash_block_size, S_IRUGO, qla2x00_flash_block_size_show,
+ NULL);
struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_driver_version,
@@ -875,6 +1136,8 @@ struct device_attribute *qla2x00_host_attrs[] = {
&dev_attr_optrom_fw_version,
&dev_attr_total_isp_aborts,
&dev_attr_mpi_version,
+ &dev_attr_phy_version,
+ &dev_attr_flash_block_size,
NULL,
};
@@ -1019,7 +1282,10 @@ qla2x00_dev_loss_tmo_callbk(struct fc_rport *rport)
if (!fcport)
return;
- qla2x00_abort_fcport_cmds(fcport);
+ if (unlikely(pci_channel_offline(fcport->vha->hw->pdev)))
+ qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
+ else
+ qla2x00_abort_fcport_cmds(fcport);
/*
* Transport has effectively 'deleted' the rport, clear
@@ -1039,16 +1305,18 @@ qla2x00_terminate_rport_io(struct fc_rport *rport)
if (!fcport)
return;
+ if (unlikely(pci_channel_offline(fcport->vha->hw->pdev))) {
+ qla2x00_abort_all_cmds(fcport->vha, DID_NO_CONNECT << 16);
+ return;
+ }
/*
* At this point all fcport's software-states are cleared. Perform any
* final cleanup of firmware resources (PCBs and XCBs).
*/
- if (fcport->loop_id != FC_NO_LOOP_ID) {
+ if (fcport->loop_id != FC_NO_LOOP_ID)
fcport->vha->hw->isp_ops->fabric_logout(fcport->vha,
fcport->loop_id, fcport->d_id.b.domain,
fcport->d_id.b.area, fcport->d_id.b.al_pa);
- fcport->loop_id = FC_NO_LOOP_ID;
- }
qla2x00_abort_fcport_cmds(fcport);
}
@@ -1265,13 +1533,6 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
test_bit(FCPORT_UPDATE_NEEDED, &vha->dpc_flags))
msleep(1000);
- if (ha->mqenable) {
- if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
- qla_printk(KERN_WARNING, ha,
- "Queue delete failed.\n");
- vha->req_ques[0] = ha->req_q_map[0]->id;
- }
-
qla24xx_disable_vp(vha);
fc_remove_host(vha->host);
@@ -1293,6 +1554,12 @@ qla24xx_vport_delete(struct fc_vport *fc_vport)
vha->host_no, vha->vp_idx, vha));
}
+ if (ha->mqenable) {
+ if (qla25xx_delete_queues(vha, 0) != QLA_SUCCESS)
+ qla_printk(KERN_WARNING, ha,
+ "Queue delete failed.\n");
+ }
+
scsi_host_put(vha->host);
qla_printk(KERN_INFO, ha, "vport %d deleted\n", id);
return 0;
diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
index 023ee77fb02..714ee67567e 100644
--- a/drivers/scsi/qla2xxx/qla_def.h
+++ b/drivers/scsi/qla2xxx/qla_def.h
@@ -176,8 +176,7 @@
/* ISP request and response entry counts (37-65535) */
#define REQUEST_ENTRY_CNT_2100 128 /* Number of request entries. */
#define REQUEST_ENTRY_CNT_2200 2048 /* Number of request entries. */
-#define REQUEST_ENTRY_CNT_2XXX_EXT_MEM 4096 /* Number of request entries. */
-#define REQUEST_ENTRY_CNT_24XX 4096 /* Number of request entries. */
+#define REQUEST_ENTRY_CNT_24XX 2048 /* Number of request entries. */
#define RESPONSE_ENTRY_CNT_2100 64 /* Number of response entries.*/
#define RESPONSE_ENTRY_CNT_2300 512 /* Number of response entries.*/
@@ -201,20 +200,7 @@ typedef struct srb {
/*
* SRB flag definitions
*/
-#define SRB_TIMEOUT BIT_0 /* Command timed out */
-#define SRB_DMA_VALID BIT_1 /* Command sent to ISP */
-#define SRB_WATCHDOG BIT_2 /* Command on watchdog list */
-#define SRB_ABORT_PENDING BIT_3 /* Command abort sent to device */
-
-#define SRB_ABORTED BIT_4 /* Command aborted command already */
-#define SRB_RETRY BIT_5 /* Command needs retrying */
-#define SRB_GOT_SENSE BIT_6 /* Command has sense data */
-#define SRB_FAILOVER BIT_7 /* Command in failover state */
-
-#define SRB_BUSY BIT_8 /* Command is in busy retry state */
-#define SRB_FO_CANCEL BIT_9 /* Command don't need to do failover */
-#define SRB_IOCTL BIT_10 /* IOCTL command. */
-#define SRB_TAPE BIT_11 /* FCP2 (Tape) command. */
+#define SRB_DMA_VALID BIT_0 /* Command sent to ISP */
/*
* ISP I/O Register Set structure definitions.
@@ -372,10 +358,10 @@ struct device_reg_2xxx {
};
struct device_reg_25xxmq {
- volatile uint32_t req_q_in;
- volatile uint32_t req_q_out;
- volatile uint32_t rsp_q_in;
- volatile uint32_t rsp_q_out;
+ uint32_t req_q_in;
+ uint32_t req_q_out;
+ uint32_t rsp_q_in;
+ uint32_t rsp_q_out;
};
typedef union {
@@ -620,6 +606,7 @@ typedef struct {
#define MBC_GET_TIMEOUT_PARAMS 0x22 /* Get FW timeouts. */
#define MBC_TRACE_CONTROL 0x27 /* Trace control command. */
#define MBC_GEN_SYSTEM_ERROR 0x2a /* Generate System Error. */
+#define MBC_WRITE_SFP 0x30 /* Write SFP Data. */
#define MBC_READ_SFP 0x31 /* Read SFP Data. */
#define MBC_SET_TIMEOUT_PARAMS 0x32 /* Set FW timeouts. */
#define MBC_MID_INITIALIZE_FIRMWARE 0x48 /* MID Initialize firmware. */
@@ -1570,39 +1557,13 @@ typedef struct fc_port {
#define FCS_DEVICE_DEAD 2
#define FCS_DEVICE_LOST 3
#define FCS_ONLINE 4
-#define FCS_NOT_SUPPORTED 5
-#define FCS_FAILOVER 6
-#define FCS_FAILOVER_FAILED 7
/*
* FC port flags.
*/
#define FCF_FABRIC_DEVICE BIT_0
#define FCF_LOGIN_NEEDED BIT_1
-#define FCF_FO_MASKED BIT_2
-#define FCF_FAILOVER_NEEDED BIT_3
-#define FCF_RESET_NEEDED BIT_4
-#define FCF_PERSISTENT_BOUND BIT_5
-#define FCF_TAPE_PRESENT BIT_6
-#define FCF_FARP_DONE BIT_7
-#define FCF_FARP_FAILED BIT_8
-#define FCF_FARP_REPLY_NEEDED BIT_9
-#define FCF_AUTH_REQ BIT_10
-#define FCF_SEND_AUTH_REQ BIT_11
-#define FCF_RECEIVE_AUTH_REQ BIT_12
-#define FCF_AUTH_SUCCESS BIT_13
-#define FCF_RLC_SUPPORT BIT_14
-#define FCF_CONFIG BIT_15 /* Needed? */
-#define FCF_RESCAN_NEEDED BIT_16
-#define FCF_XP_DEVICE BIT_17
-#define FCF_MSA_DEVICE BIT_18
-#define FCF_EVA_DEVICE BIT_19
-#define FCF_MSA_PORT_ACTIVE BIT_20
-#define FCF_FAILBACK_DISABLE BIT_21
-#define FCF_FAILOVER_DISABLE BIT_22
-#define FCF_DSXXX_DEVICE BIT_23
-#define FCF_AA_EVA_DEVICE BIT_24
-#define FCF_AA_MSA_DEVICE BIT_25
+#define FCF_TAPE_PRESENT BIT_2
/* No loop ID flag. */
#define FC_NO_LOOP_ID 0x1000
@@ -2102,9 +2063,6 @@ struct isp_operations {
int (*get_flash_version) (struct scsi_qla_host *, void *);
int (*start_scsi) (srb_t *);
- void (*wrt_req_reg) (struct qla_hw_data *, uint16_t, uint16_t);
- void (*wrt_rsp_reg) (struct qla_hw_data *, uint16_t, uint16_t);
- uint16_t (*rd_req_reg) (struct qla_hw_data *, uint16_t);
};
/* MSI-X Support *************************************************************/
@@ -2135,6 +2093,7 @@ struct qla_msix_entry {
/* Work events. */
enum qla_work_type {
QLA_EVT_AEN,
+ QLA_EVT_IDC_ACK,
};
@@ -2149,6 +2108,10 @@ struct qla_work_evt {
enum fc_host_event_code code;
u32 data;
} aen;
+ struct {
+#define QLA_IDC_ACK_REGS 7
+ uint16_t mb[QLA_IDC_ACK_REGS];
+ } idc_ack;
} u;
};
@@ -2195,6 +2158,8 @@ struct rsp_que {
dma_addr_t dma;
response_t *ring;
response_t *ring_ptr;
+ uint32_t __iomem *rsp_q_in; /* FWI2-capable only. */
+ uint32_t __iomem *rsp_q_out;
uint16_t ring_index;
uint16_t out_ptr;
uint16_t length;
@@ -2212,6 +2177,8 @@ struct req_que {
dma_addr_t dma;
request_t *ring;
request_t *ring_ptr;
+ uint32_t __iomem *req_q_in; /* FWI2-capable only. */
+ uint32_t __iomem *req_q_out;
uint16_t ring_index;
uint16_t in_ptr;
uint16_t cnt;
@@ -2251,10 +2218,10 @@ struct qla_hw_data {
uint32_t msix_enabled :1;
uint32_t disable_serdes :1;
uint32_t gpsc_supported :1;
- uint32_t vsan_enabled :1;
uint32_t npiv_supported :1;
uint32_t fce_enabled :1;
- uint32_t hw_event_marker_found:1;
+ uint32_t fac_supported :1;
+ uint32_t chip_reset_done :1;
} flags;
/* This spinlock is used to protect "io transactions", you must
@@ -2272,7 +2239,7 @@ struct qla_hw_data {
#define MIN_IOBASE_LEN 0x100
/* Multi queue data structs */
- device_reg_t *mqiobase;
+ device_reg_t __iomem *mqiobase;
uint16_t msix_count;
uint8_t mqenable;
struct req_que **req_q_map;
@@ -2295,7 +2262,6 @@ struct qla_hw_data {
uint16_t max_loop_id;
uint16_t fb_rev;
- uint16_t max_public_loop_ids;
uint16_t min_external_loopid; /* First external loop Id */
#define PORT_SPEED_UNKNOWN 0xFFFF
@@ -2376,6 +2342,8 @@ struct qla_hw_data {
IS_QLA25XX(ha) || IS_QLA81XX(ha))
#define IS_NOPOLLING_TYPE(ha) ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && \
(ha)->flags.msix_enabled)
+#define IS_FAC_REQUIRED(ha) (IS_QLA81XX(ha))
+#define IS_NOCACHE_VPD_TYPE(ha) (IS_QLA81XX(ha))
#define IS_IIDMA_CAPABLE(ha) ((ha)->device_type & DT_IIDMA)
#define IS_FWI2_CAPABLE(ha) ((ha)->device_type & DT_FWI2)
@@ -2420,6 +2388,10 @@ struct qla_hw_data {
void *sfp_data;
dma_addr_t sfp_data_dma;
+ uint8_t *edc_data;
+ dma_addr_t edc_data_dma;
+ uint16_t edc_data_len;
+
struct task_struct *dpc_thread;
uint8_t dpc_active; /* DPC routine is active */
@@ -2434,6 +2406,8 @@ struct qla_hw_data {
dma_addr_t init_cb_dma;
init_cb_t *init_cb;
int init_cb_size;
+ dma_addr_t ex_init_cb_dma;
+ struct ex_init_cb_81xx *ex_init_cb;
/* These are used by mailbox operations. */
volatile uint16_t mailbox_out[MAILBOX_REGISTER_COUNT];
@@ -2448,15 +2422,6 @@ struct qla_hw_data {
struct completion mbx_cmd_comp; /* Serialize mbx access */
struct completion mbx_intr_comp; /* Used for completion notification */
- uint32_t mbx_flags;
-#define MBX_IN_PROGRESS BIT_0
-#define MBX_BUSY BIT_1 /* Got the Access */
-#define MBX_SLEEPING_ON_SEM BIT_2
-#define MBX_POLLING_FOR_COMP BIT_3
-#define MBX_COMPLETED BIT_4
-#define MBX_TIMEDOUT BIT_5
-#define MBX_ACCESS_TIMEDOUT BIT_6
-
/* Basic firmware related information. */
uint16_t fw_major_version;
uint16_t fw_minor_version;
@@ -2468,13 +2433,15 @@ struct qla_hw_data {
#define RISC_START_ADDRESS_2100 0x1000
#define RISC_START_ADDRESS_2300 0x800
#define RISC_START_ADDRESS_2400 0x100000
+ uint16_t fw_xcb_count;
uint16_t fw_options[16]; /* slots: 1,2,3,10,11 */
uint8_t fw_seriallink_options[4];
uint16_t fw_seriallink_options24[4];
- uint8_t mpi_version[4];
+ uint8_t mpi_version[3];
uint32_t mpi_capabilities;
+ uint8_t phy_version[3];
/* Firmware dump information. */
struct qla2xxx_fw_dump *fw_dump;
@@ -2540,6 +2507,8 @@ struct qla_hw_data {
uint32_t flt_region_boot;
uint32_t flt_region_fw;
uint32_t flt_region_vpd_nvram;
+ uint32_t flt_region_vpd;
+ uint32_t flt_region_nvram;
uint32_t flt_region_npiv_conf;
/* Needed for BEACON */
@@ -2608,36 +2577,19 @@ typedef struct scsi_qla_host {
#define LOOP_RESYNC_ACTIVE 5
#define LOCAL_LOOP_UPDATE 6 /* Perform a local loop update. */
#define RSCN_UPDATE 7 /* Perform an RSCN update. */
-#define MAILBOX_RETRY 8
-#define ISP_RESET_NEEDED 9 /* Initiate a ISP reset. */
-#define FAILOVER_EVENT_NEEDED 10
-#define FAILOVER_EVENT 11
-#define FAILOVER_NEEDED 12
-#define SCSI_RESTART_NEEDED 13 /* Processes SCSI retry queue. */
-#define PORT_RESTART_NEEDED 14 /* Processes Retry queue. */
-#define RESTART_QUEUES_NEEDED 15 /* Restarts the Lun queue. */
-#define ABORT_QUEUES_NEEDED 16
-#define RELOGIN_NEEDED 17
-#define LOGIN_RETRY_NEEDED 18 /* Initiate required fabric logins. */
-#define REGISTER_FC4_NEEDED 19 /* SNS FC4 registration required. */
-#define ISP_ABORT_RETRY 20 /* ISP aborted. */
-#define FCPORT_RESCAN_NEEDED 21 /* IO descriptor processing needed */
-#define IODESC_PROCESS_NEEDED 22 /* IO descriptor processing needed */
-#define IOCTL_ERROR_RECOVERY 23
-#define LOOP_RESET_NEEDED 24
-#define BEACON_BLINK_NEEDED 25
-#define REGISTER_FDMI_NEEDED 26
-#define FCPORT_UPDATE_NEEDED 27
-#define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */
-#define UNLOADING 29
-#define NPIV_CONFIG_NEEDED 30
+#define RELOGIN_NEEDED 8
+#define REGISTER_FC4_NEEDED 9 /* SNS FC4 registration required. */
+#define ISP_ABORT_RETRY 10 /* ISP aborted. */
+#define BEACON_BLINK_NEEDED 11
+#define REGISTER_FDMI_NEEDED 12
+#define FCPORT_UPDATE_NEEDED 13
+#define VP_DPC_NEEDED 14 /* wake up for VP dpc handling */
+#define UNLOADING 15
+#define NPIV_CONFIG_NEEDED 16
uint32_t device_flags;
-#define DFLG_LOCAL_DEVICES BIT_0
-#define DFLG_RETRY_LOCAL_DEVICES BIT_1
-#define DFLG_FABRIC_DEVICES BIT_2
-#define SWITCH_FOUND BIT_3
-#define DFLG_NO_CABLE BIT_4
+#define SWITCH_FOUND BIT_0
+#define DFLG_NO_CABLE BIT_1
srb_t *status_srb; /* Status continuation entry. */
@@ -2750,10 +2702,5 @@ typedef struct scsi_qla_host {
#include "qla_inline.h"
#define CMD_SP(Cmnd) ((Cmnd)->SCp.ptr)
-#define CMD_COMPL_STATUS(Cmnd) ((Cmnd)->SCp.this_residual)
-#define CMD_RESID_LEN(Cmnd) ((Cmnd)->SCp.buffers_residual)
-#define CMD_SCSI_STATUS(Cmnd) ((Cmnd)->SCp.Status)
-#define CMD_ACTUAL_SNSLEN(Cmnd) ((Cmnd)->SCp.Message)
-#define CMD_ENTRY_STATUS(Cmnd) ((Cmnd)->SCp.have_data_in)
#endif
diff --git a/drivers/scsi/qla2xxx/qla_devtbl.h b/drivers/scsi/qla2xxx/qla_devtbl.h
index d78d35e681a..d6ea69df7c5 100644
--- a/drivers/scsi/qla2xxx/qla_devtbl.h
+++ b/drivers/scsi/qla2xxx/qla_devtbl.h
@@ -72,7 +72,7 @@ static char *qla2x00_model_name[QLA_MODEL_NAMES*2] = {
"QLA2462", "Sun PCI-X 2.0 to 4Gb FC, Dual Channel", /* 0x141 */
"QLE2460", "Sun PCI-Express to 2Gb FC, Single Channel", /* 0x142 */
"QLE2462", "Sun PCI-Express to 4Gb FC, Single Channel", /* 0x143 */
- "QEM2462" "Server I/O Module 4Gb FC, Dual Channel", /* 0x144 */
+ "QEM2462", "Server I/O Module 4Gb FC, Dual Channel", /* 0x144 */
"QLE2440", "PCI-Express to 4Gb FC, Single Channel", /* 0x145 */
"QLE2464", "PCI-Express to 4Gb FC, Quad Channel", /* 0x146 */
"QLA2440", "PCI-X 2.0 to 4Gb FC, Single Channel", /* 0x147 */
diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c
index c66036da7d2..3a9a6ca4226 100644
--- a/drivers/scsi/qla2xxx/qla_dfs.c
+++ b/drivers/scsi/qla2xxx/qla_dfs.c
@@ -71,7 +71,7 @@ qla2x00_dfs_fce_open(struct inode *inode, struct file *file)
mutex_unlock(&ha->fce_mutex);
out:
- return single_open(file, qla2x00_dfs_fce_show, ha);
+ return single_open(file, qla2x00_dfs_fce_show, vha);
}
static int
@@ -145,7 +145,7 @@ create_dir:
atomic_inc(&qla2x00_dfs_root_count);
create_nodes:
- ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, ha,
+ ha->dfs_fce = debugfs_create_file("fce", S_IRUSR, ha->dfs_dir, vha,
&dfs_fce_ops);
if (!ha->dfs_fce) {
qla_printk(KERN_NOTICE, ha,
diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h
index 7abb045a041..96ccb9642ba 100644
--- a/drivers/scsi/qla2xxx/qla_fw.h
+++ b/drivers/scsi/qla2xxx/qla_fw.h
@@ -1402,6 +1402,23 @@ struct access_chip_rsp_84xx {
#define MBA_IDC_NOTIFY 0x8101
#define MBA_IDC_TIME_EXT 0x8102
+#define MBC_IDC_ACK 0x101
+#define MBC_RESTART_MPI_FW 0x3d
+#define MBC_FLASH_ACCESS_CTRL 0x3e /* Control flash access. */
+
+/* Flash access control option field bit definitions */
+#define FAC_OPT_FORCE_SEMAPHORE BIT_15
+#define FAC_OPT_REQUESTOR_ID BIT_14
+#define FAC_OPT_CMD_SUBCODE 0xff
+
+/* Flash access control command subcodes */
+#define FAC_OPT_CMD_WRITE_PROTECT 0x00
+#define FAC_OPT_CMD_WRITE_ENABLE 0x01
+#define FAC_OPT_CMD_ERASE_SECTOR 0x02
+#define FAC_OPT_CMD_LOCK_SEMAPHORE 0x03
+#define FAC_OPT_CMD_UNLOCK_SEMAPHORE 0x04
+#define FAC_OPT_CMD_GET_SECTOR_SIZE 0x05
+
struct nvram_81xx {
/* NVRAM header. */
uint8_t id[4];
@@ -1438,7 +1455,17 @@ struct nvram_81xx {
uint16_t reserved_6[24];
/* Offset 128. */
- uint16_t reserved_7[64];
+ uint16_t ex_version;
+ uint8_t prio_fcf_matching_flags;
+ uint8_t reserved_6_1[3];
+ uint16_t pri_fcf_vlan_id;
+ uint8_t pri_fcf_fabric_name[8];
+ uint16_t reserved_6_2[7];
+ uint8_t spma_mac_addr[6];
+ uint16_t reserved_6_3[14];
+
+ /* Offset 192. */
+ uint16_t reserved_7[32];
/*
* BIT 0 = Enable spinup delay
@@ -1662,6 +1689,17 @@ struct mid_init_cb_81xx {
struct mid_conf_entry_24xx entries[MAX_MULTI_ID_FABRIC];
};
+struct ex_init_cb_81xx {
+ uint16_t ex_version;
+ uint8_t prio_fcf_matching_flags;
+ uint8_t reserved_1[3];
+ uint16_t pri_fcf_vlan_id;
+ uint8_t pri_fcf_fabric_name[8];
+ uint16_t reserved_2[7];
+ uint8_t spma_mac_addr[6];
+ uint16_t reserved_3[14];
+};
+
#define FARX_ACCESS_FLASH_CONF_81XX 0x7FFD0000
#define FARX_ACCESS_FLASH_DATA_81XX 0x7F800000
@@ -1670,6 +1708,10 @@ struct mid_init_cb_81xx {
#define FA_RISC_CODE_ADDR_81 0xA0000
#define FA_FW_AREA_ADDR_81 0xC0000
#define FA_VPD_NVRAM_ADDR_81 0xD0000
+#define FA_VPD0_ADDR_81 0xD0000
+#define FA_VPD1_ADDR_81 0xD0400
+#define FA_NVRAM0_ADDR_81 0xD0080
+#define FA_NVRAM1_ADDR_81 0xD0480
#define FA_FEATURE_ADDR_81 0xD4000
#define FA_FLASH_DESCR_ADDR_81 0xD8000
#define FA_FLASH_LAYOUT_ADDR_81 0xD8400
diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
index a336b4bc81a..528913f6bed 100644
--- a/drivers/scsi/qla2xxx/qla_gbl.h
+++ b/drivers/scsi/qla2xxx/qla_gbl.h
@@ -72,6 +72,8 @@ extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
fc_host_event_code, u32);
+extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);
+extern int qla81xx_restart_mpi_firmware(scsi_qla_host_t *);
extern void qla2x00_abort_fcport_cmds(fc_port_t *);
extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
@@ -81,7 +83,7 @@ extern void qla2x00_relogin(struct scsi_qla_host *);
/*
* Global Functions in qla_mid.c source file.
*/
-extern struct scsi_host_template qla24xx_driver_template;
+extern struct scsi_host_template qla2xxx_driver_template;
extern struct scsi_transport_template *qla2xxx_transport_vport_template;
extern void qla2x00_timer(scsi_qla_host_t *);
extern void qla2x00_start_timer(scsi_qla_host_t *, void *, unsigned long);
@@ -109,6 +111,7 @@ extern void qla2x00_mark_all_devices_lost(scsi_qla_host_t *, int);
extern struct fw_blob *qla2x00_request_firmware(scsi_qla_host_t *);
extern int qla2x00_wait_for_hba_online(scsi_qla_host_t *);
+extern int qla2x00_wait_for_chip_reset(scsi_qla_host_t *);
extern void qla2xxx_wake_dpc(struct scsi_qla_host *);
extern void qla2x00_alert_all_vps(struct rsp_que *, uint16_t *);
@@ -143,8 +146,8 @@ extern int
qla2x00_execute_fw(scsi_qla_host_t *, uint32_t);
extern void
-qla2x00_get_fw_version(scsi_qla_host_t *, uint16_t *,
- uint16_t *, uint16_t *, uint16_t *, uint32_t *, uint8_t *, uint32_t *);
+qla2x00_get_fw_version(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *,
+ uint16_t *, uint32_t *, uint8_t *, uint32_t *, uint8_t *);
extern int
qla2x00_get_fw_options(scsi_qla_host_t *, uint16_t *);
@@ -262,10 +265,29 @@ extern int
qla2x00_read_sfp(scsi_qla_host_t *, dma_addr_t, uint16_t, uint16_t, uint16_t);
extern int
+qla2x00_read_edc(scsi_qla_host_t *, uint16_t, uint16_t, dma_addr_t,
+ uint8_t *, uint16_t, uint16_t);
+
+extern int
+qla2x00_write_edc(scsi_qla_host_t *, uint16_t, uint16_t, dma_addr_t,
+ uint8_t *, uint16_t, uint16_t);
+
+extern int
qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);
extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);
+extern int qla81xx_idc_ack(scsi_qla_host_t *, uint16_t *);
+
+extern int
+qla81xx_fac_get_sector_size(scsi_qla_host_t *, uint32_t *);
+
+extern int
+qla81xx_fac_do_write_enable(scsi_qla_host_t *, int);
+
+extern int
+qla81xx_fac_erase_sector(scsi_qla_host_t *, uint32_t, uint32_t);
+
/*
* Global Function Prototypes in qla_isr.c source file.
*/
@@ -376,10 +398,8 @@ extern int qla2x00_dfs_remove(scsi_qla_host_t *);
/* Globa function prototypes for multi-q */
extern int qla25xx_request_irq(struct rsp_que *);
-extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *,
- uint8_t);
-extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *,
- uint8_t);
+extern int qla25xx_init_req_que(struct scsi_qla_host *, struct req_que *);
+extern int qla25xx_init_rsp_que(struct scsi_qla_host *, struct rsp_que *);
extern int qla25xx_create_req_que(struct qla_hw_data *, uint16_t, uint8_t,
uint16_t, uint8_t, uint8_t);
extern int qla25xx_create_rsp_que(struct qla_hw_data *, uint16_t, uint8_t,
diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
index f6368a1d302..bd7dd84c064 100644
--- a/drivers/scsi/qla2xxx/qla_init.c
+++ b/drivers/scsi/qla2xxx/qla_init.c
@@ -20,7 +20,6 @@
* QLogic ISP2x00 Hardware Support Function Prototypes.
*/
static int qla2x00_isp_firmware(scsi_qla_host_t *);
-static void qla2x00_resize_request_q(scsi_qla_host_t *);
static int qla2x00_setup_chip(scsi_qla_host_t *);
static int qla2x00_init_rings(scsi_qla_host_t *);
static int qla2x00_fw_ready(scsi_qla_host_t *);
@@ -61,8 +60,10 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
int rval;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
+
/* Clear adapter flags. */
vha->flags.online = 0;
+ ha->flags.chip_reset_done = 0;
vha->flags.reset_active = 0;
atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
atomic_set(&vha->loop_state, LOOP_DOWN);
@@ -70,7 +71,6 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
vha->dpc_flags = 0;
vha->flags.management_server_logged_in = 0;
vha->marker_needed = 0;
- ha->mbx_flags = 0;
ha->isp_abort_cnt = 0;
ha->beacon_blink_led = 0;
set_bit(REGISTER_FDMI_NEEDED, &vha->dpc_flags);
@@ -131,6 +131,7 @@ qla2x00_initialize_adapter(scsi_qla_host_t *vha)
}
}
rval = qla2x00_init_rings(vha);
+ ha->flags.chip_reset_done = 1;
return (rval);
}
@@ -512,7 +513,6 @@ qla2x00_reset_chip(scsi_qla_host_t *vha)
static inline void
qla24xx_reset_risc(scsi_qla_host_t *vha)
{
- int hw_evt = 0;
unsigned long flags = 0;
struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
@@ -542,8 +542,6 @@ qla24xx_reset_risc(scsi_qla_host_t *vha)
d2 = (uint32_t) RD_REG_WORD(&reg->mailbox0);
barrier();
}
- if (cnt == 0)
- hw_evt = 1;
/* Wait for soft-reset to complete. */
d2 = RD_REG_DWORD(&reg->ctrl_status);
@@ -816,7 +814,7 @@ qla2x00_alloc_fw_dump(scsi_qla_host_t *vha)
qla_printk(KERN_INFO, ha, "Allocated (%d KB) for FCE...\n",
FCE_SIZE / 1024);
- fce_size = sizeof(struct qla2xxx_fce_chain) + EFT_SIZE;
+ fce_size = sizeof(struct qla2xxx_fce_chain) + FCE_SIZE;
ha->flags.fce_enabled = 1;
ha->fce_dma = tc_dma;
ha->fce = tc;
@@ -894,62 +892,6 @@ cont_alloc:
}
/**
- * qla2x00_resize_request_q() - Resize request queue given available ISP memory.
- * @ha: HA context
- *
- * Returns 0 on success.
- */
-static void
-qla2x00_resize_request_q(scsi_qla_host_t *vha)
-{
- int rval;
- uint16_t fw_iocb_cnt = 0;
- uint16_t request_q_length = REQUEST_ENTRY_CNT_2XXX_EXT_MEM;
- dma_addr_t request_dma;
- request_t *request_ring;
- struct qla_hw_data *ha = vha->hw;
- struct req_que *req = ha->req_q_map[0];
-
- /* Valid only on recent ISPs. */
- if (IS_QLA2100(ha) || IS_QLA2200(ha))
- return;
-
- /* Retrieve IOCB counts available to the firmware. */
- rval = qla2x00_get_resource_cnts(vha, NULL, NULL, NULL, &fw_iocb_cnt,
- &ha->max_npiv_vports);
- if (rval)
- return;
- /* No point in continuing if current settings are sufficient. */
- if (fw_iocb_cnt < 1024)
- return;
- if (req->length >= request_q_length)
- return;
-
- /* Attempt to claim larger area for request queue. */
- request_ring = dma_alloc_coherent(&ha->pdev->dev,
- (request_q_length + 1) * sizeof(request_t), &request_dma,
- GFP_KERNEL);
- if (request_ring == NULL)
- return;
-
- /* Resize successful, report extensions. */
- qla_printk(KERN_INFO, ha, "Extended memory detected (%d KB)...\n",
- (ha->fw_memory_size + 1) / 1024);
- qla_printk(KERN_INFO, ha, "Resizing request queue depth "
- "(%d -> %d)...\n", req->length, request_q_length);
-
- /* Clear old allocations. */
- dma_free_coherent(&ha->pdev->dev,
- (req->length + 1) * sizeof(request_t), req->ring,
- req->dma);
-
- /* Begin using larger queue. */
- req->length = request_q_length;
- req->ring = request_ring;
- req->dma = request_dma;
-}
-
-/**
* qla2x00_setup_chip() - Load and start RISC firmware.
* @ha: HA context
*
@@ -963,6 +905,7 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
struct qla_hw_data *ha = vha->hw;
struct device_reg_2xxx __iomem *reg = &ha->iobase->isp;
unsigned long flags;
+ uint16_t fw_major_version;
if (!IS_FWI2_CAPABLE(ha) && !IS_QLA2100(ha) && !IS_QLA2200(ha)) {
/* Disable SRAM, Instruction RAM and GP RAM parity. */
@@ -986,13 +929,15 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
rval = qla2x00_execute_fw(vha, srisc_address);
/* Retrieve firmware information. */
- if (rval == QLA_SUCCESS && ha->fw_major_version == 0) {
+ if (rval == QLA_SUCCESS) {
+ fw_major_version = ha->fw_major_version;
qla2x00_get_fw_version(vha,
&ha->fw_major_version,
&ha->fw_minor_version,
&ha->fw_subminor_version,
&ha->fw_attributes, &ha->fw_memory_size,
- ha->mpi_version, &ha->mpi_capabilities);
+ ha->mpi_version, &ha->mpi_capabilities,
+ ha->phy_version);
ha->flags.npiv_supported = 0;
if (IS_QLA2XXX_MIDTYPE(ha) &&
(ha->fw_attributes & BIT_2)) {
@@ -1003,9 +948,11 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
ha->max_npiv_vports =
MIN_MULTI_ID_FABRIC - 1;
}
- qla2x00_resize_request_q(vha);
+ qla2x00_get_resource_cnts(vha, NULL,
+ &ha->fw_xcb_count, NULL, NULL,
+ &ha->max_npiv_vports);
- if (ql2xallocfwdump)
+ if (!fw_major_version && ql2xallocfwdump)
qla2x00_alloc_fw_dump(vha);
}
} else {
@@ -1028,6 +975,21 @@ qla2x00_setup_chip(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->hardware_lock, flags);
}
+ if (rval == QLA_SUCCESS && IS_FAC_REQUIRED(ha)) {
+ uint32_t size;
+
+ rval = qla81xx_fac_get_sector_size(vha, &size);
+ if (rval == QLA_SUCCESS) {
+ ha->flags.fac_supported = 1;
+ ha->fdt_block_size = size << 2;
+ } else {
+ qla_printk(KERN_ERR, ha,
+ "Unsupported FAC firmware (%d.%02d.%02d).\n",
+ ha->fw_major_version, ha->fw_minor_version,
+ ha->fw_subminor_version);
+ }
+ }
+
if (rval) {
DEBUG2_3(printk("scsi(%ld): Setup chip **** FAILED ****.\n",
vha->host_no));
@@ -1226,9 +1188,8 @@ qla24xx_config_rings(struct scsi_qla_host *vha)
icb->firmware_options_2 |=
__constant_cpu_to_le32(BIT_18);
- icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_22);
+ icb->firmware_options_2 &= __constant_cpu_to_le32(~BIT_22);
icb->firmware_options_2 |= __constant_cpu_to_le32(BIT_23);
- ha->rsp_q_map[0]->options = icb->firmware_options_2;
WRT_REG_DWORD(&reg->isp25mq.req_q_in, 0);
WRT_REG_DWORD(&reg->isp25mq.req_q_out, 0);
@@ -1309,10 +1270,17 @@ qla2x00_init_rings(scsi_qla_host_t *vha)
DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no));
- if (ha->flags.npiv_supported)
+ if (ha->flags.npiv_supported) {
+ if (ha->operating_mode == LOOP)
+ ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1;
mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports);
+ }
- mid_init_cb->options = __constant_cpu_to_le16(BIT_1);
+ if (IS_FWI2_CAPABLE(ha)) {
+ mid_init_cb->options = __constant_cpu_to_le16(BIT_1);
+ mid_init_cb->init_cb.execution_throttle =
+ cpu_to_le16(ha->fw_xcb_count);
+ }
rval = qla2x00_init_firmware(vha, ha->init_cb_size);
if (rval) {
@@ -1986,7 +1954,6 @@ qla2x00_alloc_fcport(scsi_qla_host_t *vha, gfp_t flags)
fcport->port_type = FCT_UNKNOWN;
fcport->loop_id = FC_NO_LOOP_ID;
atomic_set(&fcport->state, FCS_UNCONFIGURED);
- fcport->flags = FCF_RLC_SUPPORT;
fcport->supported_classes = FC_COS_UNSPECIFIED;
return fcport;
@@ -2168,7 +2135,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
vha->host_no, fcport->loop_id));
atomic_set(&fcport->state, FCS_DEVICE_LOST);
- fcport->flags &= ~FCF_FARP_DONE;
}
}
@@ -2225,8 +2191,7 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
WWN_SIZE))
continue;
- fcport->flags &= ~(FCF_FABRIC_DEVICE |
- FCF_PERSISTENT_BOUND);
+ fcport->flags &= ~FCF_FABRIC_DEVICE;
fcport->loop_id = new_fcport->loop_id;
fcport->port_type = new_fcport->port_type;
fcport->d_id.b24 = new_fcport->d_id.b24;
@@ -2239,7 +2204,6 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
if (!found) {
/* New device, add to fcports list. */
- new_fcport->flags &= ~FCF_PERSISTENT_BOUND;
if (vha->vp_idx) {
new_fcport->vha = vha;
new_fcport->vp_idx = vha->vp_idx;
@@ -2272,11 +2236,6 @@ cleanup_allocation:
"rval=%x\n", vha->host_no, rval));
}
- if (found_devs) {
- vha->device_flags |= DFLG_LOCAL_DEVICES;
- vha->device_flags &= ~DFLG_RETRY_LOCAL_DEVICES;
- }
-
return (rval);
}
@@ -2611,6 +2570,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
port_id_t wrap, nxt_d_id;
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev);
+ struct scsi_qla_host *tvp;
rval = QLA_SUCCESS;
@@ -2710,7 +2670,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
/* Bypass virtual ports of the same host. */
found = 0;
if (ha->num_vhosts) {
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (new_fcport->d_id.b24 == vp->d_id.b24) {
found = 1;
break;
@@ -2761,7 +2721,6 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
fcport->loop_id = FC_NO_LOOP_ID;
fcport->flags |= (FCF_FABRIC_DEVICE |
FCF_LOGIN_NEEDED);
- fcport->flags &= ~FCF_PERSISTENT_BOUND;
break;
}
@@ -2804,9 +2763,6 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha,
kfree(swl);
kfree(new_fcport);
- if (!list_empty(new_fcports))
- vha->device_flags |= DFLG_FABRIC_DEVICES;
-
return (rval);
}
@@ -2833,6 +2789,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
uint16_t first_loop_id;
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *vp;
+ struct scsi_qla_host *tvp;
rval = QLA_SUCCESS;
@@ -2857,7 +2814,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev)
/* Check for loop ID being already in use. */
found = 0;
fcport = NULL;
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
list_for_each_entry(fcport, &vp->vp_fcports, list) {
if (fcport->loop_id == dev->loop_id &&
fcport != dev) {
@@ -2988,7 +2945,6 @@ qla2x00_device_resync(scsi_qla_host_t *vha)
0, 0);
}
}
- fcport->flags &= ~FCF_FARP_DONE;
}
}
return (rval);
@@ -3292,10 +3248,12 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
uint8_t status = 0;
struct qla_hw_data *ha = vha->hw;
struct scsi_qla_host *vp;
+ struct scsi_qla_host *tvp;
struct req_que *req = ha->req_q_map[0];
if (vha->flags.online) {
vha->flags.online = 0;
+ ha->flags.chip_reset_done = 0;
clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
ha->qla_stats.total_isp_aborts++;
@@ -3307,7 +3265,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
if (atomic_read(&vha->loop_state) != LOOP_DOWN) {
atomic_set(&vha->loop_state, LOOP_DOWN);
qla2x00_mark_all_devices_lost(vha, 0);
- list_for_each_entry(vp, &ha->vp_list, list)
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list)
qla2x00_mark_all_devices_lost(vp, 0);
} else {
if (!atomic_read(&vha->loop_down_timer))
@@ -3404,7 +3362,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
DEBUG(printk(KERN_INFO
"qla2x00_abort_isp(%ld): succeeded.\n",
vha->host_no));
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx)
qla2x00_vp_abort_isp(vp);
}
@@ -3429,7 +3387,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha)
static int
qla2x00_restart_isp(scsi_qla_host_t *vha)
{
- uint8_t status = 0;
+ int status = 0;
uint32_t wait_time;
struct qla_hw_data *ha = vha->hw;
struct req_que *req = ha->req_q_map[0];
@@ -3445,6 +3403,7 @@ qla2x00_restart_isp(scsi_qla_host_t *vha)
if (!status && !(status = qla2x00_init_rings(vha))) {
clear_bit(RESET_MARKER_NEEDED, &vha->dpc_flags);
+ ha->flags.chip_reset_done = 1;
/* Initialize the queues in use */
qla25xx_init_queues(ha);
@@ -3493,7 +3452,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
rsp = ha->rsp_q_map[i];
if (rsp) {
rsp->options &= ~BIT_0;
- ret = qla25xx_init_rsp_que(base_vha, rsp, rsp->options);
+ ret = qla25xx_init_rsp_que(base_vha, rsp);
if (ret != QLA_SUCCESS)
DEBUG2_17(printk(KERN_WARNING
"%s Rsp que:%d init failed\n", __func__,
@@ -3507,7 +3466,7 @@ qla25xx_init_queues(struct qla_hw_data *ha)
if (req) {
/* Clear outstanding commands array. */
req->options &= ~BIT_0;
- ret = qla25xx_init_req_que(base_vha, req, req->options);
+ ret = qla25xx_init_req_que(base_vha, req);
if (ret != QLA_SUCCESS)
DEBUG2_17(printk(KERN_WARNING
"%s Req que:%d init failed\n", __func__,
@@ -4332,23 +4291,17 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
/* Determine NVRAM starting address. */
ha->nvram_size = sizeof(struct nvram_81xx);
- ha->nvram_base = FA_NVRAM_FUNC0_ADDR;
ha->vpd_size = FA_NVRAM_VPD_SIZE;
- ha->vpd_base = FA_NVRAM_VPD0_ADDR;
- if (PCI_FUNC(ha->pdev->devfn) & 1) {
- ha->nvram_base = FA_NVRAM_FUNC1_ADDR;
- ha->vpd_base = FA_NVRAM_VPD1_ADDR;
- }
/* Get VPD data into cache */
ha->vpd = ha->nvram + VPD_OFFSET;
- ha->isp_ops->read_nvram(vha, (uint8_t *)ha->vpd,
- ha->nvram_base - FA_NVRAM_FUNC0_ADDR, FA_NVRAM_VPD_SIZE * 4);
+ ha->isp_ops->read_optrom(vha, ha->vpd, ha->flt_region_vpd << 2,
+ ha->vpd_size);
/* Get NVRAM data into cache and calculate checksum. */
- dptr = (uint32_t *)nv;
- ha->isp_ops->read_nvram(vha, (uint8_t *)dptr, ha->nvram_base,
+ ha->isp_ops->read_optrom(vha, ha->nvram, ha->flt_region_nvram << 2,
ha->nvram_size);
+ dptr = (uint32_t *)nv;
for (cnt = 0, chksum = 0; cnt < ha->nvram_size >> 2; cnt++)
chksum += le32_to_cpu(*dptr++);
@@ -4446,6 +4399,9 @@ qla81xx_nvram_config(scsi_qla_host_t *vha)
icb->enode_mac[5] = 0x06 + PCI_FUNC(ha->pdev->devfn);
}
+ /* Use extended-initialization control block. */
+ memcpy(ha->ex_init_cb, &nv->ex_version, sizeof(*ha->ex_init_cb));
+
/*
* Setup driver NVRAM options.
*/
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 2258152b1f4..a8abbb95730 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -776,7 +776,7 @@ qla24xx_start_scsi(srb_t *sp)
req_cnt = qla24xx_calc_iocbs(tot_dsds);
if (req->cnt < (req_cnt + 2)) {
- cnt = ha->isp_ops->rd_req_reg(ha, req->id);
+ cnt = RD_REG_DWORD_RELAXED(req->req_q_out);
if (req->ring_index < cnt)
req->cnt = cnt - req->ring_index;
@@ -836,7 +836,8 @@ qla24xx_start_scsi(srb_t *sp)
sp->flags |= SRB_DMA_VALID;
/* Set chip new ring index. */
- ha->isp_ops->wrt_req_reg(ha, req->id, req->ring_index);
+ WRT_REG_DWORD(req->req_q_in, req->ring_index);
+ RD_REG_DWORD_RELAXED(&ha->iobase->isp24.hccr);
/* Manage unprocessed RIO/ZIO commands in response queue. */
if (vha->flags.process_response_queue &&
@@ -854,35 +855,3 @@ queuing_error:
return QLA_FUNCTION_FAILED;
}
-
-uint16_t
-qla24xx_rd_req_reg(struct qla_hw_data *ha, uint16_t id)
-{
- device_reg_t __iomem *reg = (void *) ha->iobase;
- return RD_REG_DWORD_RELAXED(&reg->isp24.req_q_out);
-}
-
-uint16_t
-qla25xx_rd_req_reg(struct qla_hw_data *ha, uint16_t id)
-{
- device_reg_t __iomem *reg = (void *) ha->mqiobase + QLA_QUE_PAGE * id;
- return RD_REG_DWORD_RELAXED(&reg->isp25mq.req_q_out);
-}
-
-void
-qla24xx_wrt_req_reg(struct qla_hw_data *ha, uint16_t id, uint16_t index)
-{
- device_reg_t __iomem *reg = (void *) ha->iobase;
- WRT_REG_DWORD(&reg->isp24.req_q_in, index);
- RD_REG_DWORD_RELAXED(&reg->isp24.req_q_in);
-}
-
-void
-qla25xx_wrt_req_reg(struct qla_hw_data *ha, uint16_t id, uint16_t index)
-{
- device_reg_t __iomem *reg = (void *) ha->mqiobase + QLA_QUE_PAGE * id;
- struct device_reg_2xxx __iomem *ioreg = &ha->iobase->isp;
- WRT_REG_DWORD(&reg->isp25mq.req_q_in, index);
- RD_REG_DWORD(&ioreg->hccr); /* PCI posting */
-}
-
diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
index e28ad81baf1..d04981848e5 100644
--- a/drivers/scsi/qla2xxx/qla_isr.c
+++ b/drivers/scsi/qla2xxx/qla_isr.c
@@ -266,6 +266,40 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
}
}
+static void
+qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
+{
+ static char *event[] =
+ { "Complete", "Request Notification", "Time Extension" };
+ int rval;
+ struct device_reg_24xx __iomem *reg24 = &vha->hw->iobase->isp24;
+ uint16_t __iomem *wptr;
+ uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];
+
+ /* Seed data -- mailbox1 -> mailbox7. */
+ wptr = (uint16_t __iomem *)&reg24->mailbox1;
+ for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
+ mb[cnt] = RD_REG_WORD(wptr);
+
+ DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
+ "%04x %04x %04x %04x %04x %04x %04x.\n", vha->host_no,
+ event[aen & 0xff],
+ mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]));
+
+ /* Acknowledgement needed? [Notify && non-zero timeout]. */
+ timeout = (descr >> 8) & 0xf;
+ if (aen != MBA_IDC_NOTIFY || !timeout)
+ return;
+
+ DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
+ "ACK timeout=%d.\n", vha->host_no, event[aen & 0xff], timeout));
+
+ rval = qla2x00_post_idc_ack_work(vha, mb);
+ if (rval != QLA_SUCCESS)
+ qla_printk(KERN_WARNING, vha->hw,
+ "IDC failed to post ACK.\n");
+}
+
/**
* qla2x00_async_event() - Process aynchronous events.
* @ha: SCSI driver HA context
@@ -714,21 +748,9 @@ skip_rio:
"%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
break;
case MBA_IDC_COMPLETE:
- DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
- "Complete -- %04x %04x %04x\n", vha->host_no, mb[1], mb[2],
- mb[3]));
- break;
case MBA_IDC_NOTIFY:
- DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
- "Request Notification -- %04x %04x %04x\n", vha->host_no,
- mb[1], mb[2], mb[3]));
- /**** Mailbox registers 4 - 7 valid!!! */
- break;
case MBA_IDC_TIME_EXT:
- DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
- "Time Extension -- %04x %04x %04x\n", vha->host_no, mb[1],
- mb[2], mb[3]));
- /**** Mailbox registers 4 - 7 valid!!! */
+ qla81xx_idc_event(vha, mb[0], mb[1]);
break;
}
@@ -830,9 +852,6 @@ qla2x00_process_completed_request(struct scsi_qla_host *vha,
/* Free outstanding command slot. */
req->outstanding_cmds[index] = NULL;
- CMD_COMPL_STATUS(sp->cmd) = 0L;
- CMD_SCSI_STATUS(sp->cmd) = 0L;
-
/* Save ISP completion status */
sp->cmd->result = DID_OK << 16;
@@ -933,7 +952,6 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
if (sense_len >= SCSI_SENSE_BUFFERSIZE)
sense_len = SCSI_SENSE_BUFFERSIZE;
- CMD_ACTUAL_SNSLEN(cp) = sense_len;
sp->request_sense_length = sense_len;
sp->request_sense_ptr = cp->sense_buffer;
if (sp->request_sense_length > 32)
@@ -951,8 +969,7 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len)
cp->device->channel, cp->device->id, cp->device->lun, cp,
cp->serial_number));
if (sense_len)
- DEBUG5(qla2x00_dump_buffer(cp->sense_buffer,
- CMD_ACTUAL_SNSLEN(cp)));
+ DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, sense_len));
}
/**
@@ -1021,9 +1038,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
}
lscsi_status = scsi_status & STATUS_MASK;
- CMD_ENTRY_STATUS(cp) = sts->entry_status;
- CMD_COMPL_STATUS(cp) = comp_status;
- CMD_SCSI_STATUS(cp) = scsi_status;
fcport = sp->fcport;
@@ -1082,7 +1096,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (scsi_status & (SS_RESIDUAL_UNDER | SS_RESIDUAL_OVER)) {
resid = resid_len;
scsi_set_resid(cp, resid);
- CMD_RESID_LEN(cp) = resid;
if (!lscsi_status &&
((unsigned)(scsi_bufflen(cp) - resid) <
@@ -1138,7 +1151,6 @@ qla2x00_status_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, void *pkt)
if (scsi_status & SS_RESIDUAL_UNDER) {
scsi_set_resid(cp, resid);
- CMD_RESID_LEN(cp) = resid;
} else {
DEBUG2(printk(KERN_INFO
"scsi(%ld:%d:%d) UNDERRUN status detected "
@@ -1477,7 +1489,6 @@ qla24xx_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
void
qla24xx_process_response_queue(struct rsp_que *rsp)
{
- struct qla_hw_data *ha = rsp->hw;
struct sts_entry_24xx *pkt;
struct scsi_qla_host *vha;
@@ -1531,7 +1542,7 @@ qla24xx_process_response_queue(struct rsp_que *rsp)
}
/* Adjust ring index */
- ha->isp_ops->wrt_rsp_reg(ha, rsp->id, rsp->ring_index);
+ WRT_REG_DWORD(rsp->rsp_q_out, rsp->ring_index);
}
static void
@@ -1707,7 +1718,6 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
struct qla_hw_data *ha;
struct rsp_que *rsp;
struct device_reg_24xx __iomem *reg;
- uint16_t msix_disabled_hccr = 0;
rsp = (struct rsp_que *) dev_id;
if (!rsp) {
@@ -1720,17 +1730,8 @@ qla25xx_msix_rsp_q(int irq, void *dev_id)
spin_lock_irq(&ha->hardware_lock);
- msix_disabled_hccr = rsp->options;
- if (!rsp->id)
- msix_disabled_hccr &= __constant_cpu_to_le32(BIT_22);
- else
- msix_disabled_hccr &= __constant_cpu_to_le32(BIT_6);
-
qla24xx_process_response_queue(rsp);
- if (!msix_disabled_hccr)
- WRT_REG_DWORD(&reg->hccr, HCCRX_CLR_RISC_INT);
-
spin_unlock_irq(&ha->hardware_lock);
return IRQ_HANDLED;
@@ -2017,7 +2018,7 @@ skip_msix:
skip_msi:
ret = request_irq(ha->pdev->irq, ha->isp_ops->intr_handler,
- IRQF_DISABLED|IRQF_SHARED, QLA2XXX_DRIVER_NAME, rsp);
+ IRQF_SHARED, QLA2XXX_DRIVER_NAME, rsp);
if (ret) {
qla_printk(KERN_WARNING, ha,
"Failed to reserve interrupt %d already in use.\n",
@@ -2105,18 +2106,3 @@ int qla25xx_request_irq(struct rsp_que *rsp)
msix->rsp = rsp;
return ret;
}
-
-void
-qla25xx_wrt_rsp_reg(struct qla_hw_data *ha, uint16_t id, uint16_t index)
-{
- device_reg_t __iomem *reg = (void *) ha->mqiobase + QLA_QUE_PAGE * id;
- WRT_REG_DWORD(&reg->isp25mq.rsp_q_out, index);
-}
-
-void
-qla24xx_wrt_rsp_reg(struct qla_hw_data *ha, uint16_t id, uint16_t index)
-{
- device_reg_t __iomem *reg = (void *) ha->iobase;
- WRT_REG_DWORD(&reg->isp24.rsp_q_out, index);
-}
-
diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
index f94ffbb98e9..e67c1660bf4 100644
--- a/drivers/scsi/qla2xxx/qla_mbx.c
+++ b/drivers/scsi/qla2xxx/qla_mbx.c
@@ -45,6 +45,9 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
+ if (ha->pdev->error_state > pci_channel_io_frozen)
+ return QLA_FUNCTION_TIMEOUT;
+
reg = ha->iobase;
io_lock_on = base_vha->flags.init_done;
@@ -408,7 +411,7 @@ qla2x00_execute_fw(scsi_qla_host_t *vha, uint32_t risc_addr)
void
qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
uint16_t *subminor, uint16_t *attributes, uint32_t *memory, uint8_t *mpi,
- uint32_t *mpi_caps)
+ uint32_t *mpi_caps, uint8_t *phy)
{
int rval;
mbx_cmd_t mc;
@@ -420,7 +423,7 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
mcp->out_mb = MBX_0;
mcp->in_mb = MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
if (IS_QLA81XX(vha->hw))
- mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10;
+ mcp->in_mb |= MBX_13|MBX_12|MBX_11|MBX_10|MBX_9|MBX_8;
mcp->flags = 0;
mcp->tov = MBX_TOV_SECONDS;
rval = qla2x00_mailbox_command(vha, mcp);
@@ -435,11 +438,13 @@ qla2x00_get_fw_version(scsi_qla_host_t *vha, uint16_t *major, uint16_t *minor,
else
*memory = (mcp->mb[5] << 16) | mcp->mb[4];
if (IS_QLA81XX(vha->hw)) {
- mpi[0] = mcp->mb[10] >> 8;
- mpi[1] = mcp->mb[10] & 0xff;
- mpi[2] = mcp->mb[11] >> 8;
- mpi[3] = mcp->mb[11] & 0xff;
+ mpi[0] = mcp->mb[10] & 0xff;
+ mpi[1] = mcp->mb[11] >> 8;
+ mpi[2] = mcp->mb[11] & 0xff;
*mpi_caps = (mcp->mb[12] << 16) | mcp->mb[13];
+ phy[0] = mcp->mb[8] & 0xff;
+ phy[1] = mcp->mb[9] >> 8;
+ phy[2] = mcp->mb[9] & 0xff;
}
if (rval != QLA_SUCCESS) {
@@ -1043,14 +1048,22 @@ qla2x00_init_firmware(scsi_qla_host_t *vha, uint16_t size)
else
mcp->mb[0] = MBC_INITIALIZE_FIRMWARE;
+ mcp->mb[1] = 0;
mcp->mb[2] = MSW(ha->init_cb_dma);
mcp->mb[3] = LSW(ha->init_cb_dma);
- mcp->mb[4] = 0;
- mcp->mb[5] = 0;
mcp->mb[6] = MSW(MSD(ha->init_cb_dma));
mcp->mb[7] = LSW(MSD(ha->init_cb_dma));
- mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_0;
- mcp->in_mb = MBX_5|MBX_4|MBX_0;
+ mcp->out_mb = MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ if (IS_QLA81XX(ha) && ha->ex_init_cb->ex_version) {
+ mcp->mb[1] = BIT_0;
+ mcp->mb[10] = MSW(ha->ex_init_cb_dma);
+ mcp->mb[11] = LSW(ha->ex_init_cb_dma);
+ mcp->mb[12] = MSW(MSD(ha->ex_init_cb_dma));
+ mcp->mb[13] = LSW(MSD(ha->ex_init_cb_dma));
+ mcp->mb[14] = sizeof(*ha->ex_init_cb);
+ mcp->out_mb |= MBX_14|MBX_13|MBX_12|MBX_11|MBX_10;
+ }
+ mcp->in_mb = MBX_0;
mcp->buf_size = size;
mcp->flags = MBX_DMA_OUT;
mcp->tov = MBX_TOV_SECONDS;
@@ -1187,10 +1200,6 @@ qla2x00_get_port_database(scsi_qla_host_t *vha, fc_port_t *fcport, uint8_t opt)
fcport->d_id.b.al_pa = pd->port_id[2];
fcport->d_id.b.rsvd_1 = 0;
- /* Check for device require authentication. */
- pd->common_features & BIT_5 ? (fcport->flags |= FCF_AUTH_REQ) :
- (fcport->flags &= ~FCF_AUTH_REQ);
-
/* If not target must be initiator or unknown type. */
if ((pd->prli_svc_param_word_3[0] & BIT_4) == 0)
fcport->port_type = FCT_INITIATOR;
@@ -2685,6 +2694,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
uint16_t stat = le16_to_cpu(rptid_entry->vp_idx);
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *vp;
+ scsi_qla_host_t *tvp;
if (rptid_entry->entry_status != 0)
return;
@@ -2710,7 +2720,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha,
if (MSB(stat) == 1)
return;
- list_for_each_entry(vp, &ha->vp_list, list)
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list)
if (vp_idx == vp->vp_idx)
break;
if (!vp)
@@ -3090,8 +3100,7 @@ verify_done:
}
int
-qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
- uint8_t options)
+qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req)
{
int rval;
unsigned long flags;
@@ -3101,7 +3110,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
struct qla_hw_data *ha = vha->hw;
mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
- mcp->mb[1] = options;
+ mcp->mb[1] = req->options;
mcp->mb[2] = MSW(LSD(req->dma));
mcp->mb[3] = LSW(LSD(req->dma));
mcp->mb[6] = MSW(MSD(req->dma));
@@ -3128,7 +3137,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
mcp->tov = 60;
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (!(options & BIT_0)) {
+ if (!(req->options & BIT_0)) {
WRT_REG_DWORD(&reg->req_q_in, 0);
WRT_REG_DWORD(&reg->req_q_out, 0);
}
@@ -3142,8 +3151,7 @@ qla25xx_init_req_que(struct scsi_qla_host *vha, struct req_que *req,
}
int
-qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
- uint8_t options)
+qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
{
int rval;
unsigned long flags;
@@ -3153,7 +3161,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
struct qla_hw_data *ha = vha->hw;
mcp->mb[0] = MBC_INITIALIZE_MULTIQ;
- mcp->mb[1] = options;
+ mcp->mb[1] = rsp->options;
mcp->mb[2] = MSW(LSD(rsp->dma));
mcp->mb[3] = LSW(LSD(rsp->dma));
mcp->mb[6] = MSW(MSD(rsp->dma));
@@ -3178,7 +3186,7 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
mcp->tov = 60;
spin_lock_irqsave(&ha->hardware_lock, flags);
- if (!(options & BIT_0)) {
+ if (!(rsp->options & BIT_0)) {
WRT_REG_DWORD(&reg->rsp_q_out, 0);
WRT_REG_DWORD(&reg->rsp_q_in, 0);
}
@@ -3193,3 +3201,230 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp,
return rval;
}
+int
+qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+ mcp->mb[0] = MBC_IDC_ACK;
+ memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
+ mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
+ vha->host_no, rval, mcp->mb[0]));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ }
+
+ return rval;
+}
+
+int
+qla81xx_fac_get_sector_size(scsi_qla_host_t *vha, uint32_t *sector_size)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA81XX(vha->hw))
+ return QLA_FUNCTION_FAILED;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+ mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
+ mcp->mb[1] = FAC_OPT_CMD_GET_SECTOR_SIZE;
+ mcp->out_mb = MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
+ __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ *sector_size = mcp->mb[1];
+ }
+
+ return rval;
+}
+
+int
+qla81xx_fac_do_write_enable(scsi_qla_host_t *vha, int enable)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA81XX(vha->hw))
+ return QLA_FUNCTION_FAILED;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+ mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
+ mcp->mb[1] = enable ? FAC_OPT_CMD_WRITE_ENABLE :
+ FAC_OPT_CMD_WRITE_PROTECT;
+ mcp->out_mb = MBX_1|MBX_0;
+ mcp->in_mb = MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x.\n",
+ __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ }
+
+ return rval;
+}
+
+int
+qla81xx_fac_erase_sector(scsi_qla_host_t *vha, uint32_t start, uint32_t finish)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ if (!IS_QLA81XX(vha->hw))
+ return QLA_FUNCTION_FAILED;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+ mcp->mb[0] = MBC_FLASH_ACCESS_CTRL;
+ mcp->mb[1] = FAC_OPT_CMD_ERASE_SECTOR;
+ mcp->mb[2] = LSW(start);
+ mcp->mb[3] = MSW(start);
+ mcp->mb[4] = LSW(finish);
+ mcp->mb[5] = MSW(finish);
+ mcp->out_mb = MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_2|MBX_1|MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x mb[1]=%x "
+ "mb[2]=%x.\n", __func__, vha->host_no, rval, mcp->mb[0],
+ mcp->mb[1], mcp->mb[2]));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ }
+
+ return rval;
+}
+
+int
+qla81xx_restart_mpi_firmware(scsi_qla_host_t *vha)
+{
+ int rval = 0;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+ mcp->mb[0] = MBC_RESTART_MPI_FW;
+ mcp->out_mb = MBX_0;
+ mcp->in_mb = MBX_0|MBX_1;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=0x%x mb[1]=0x%x.\n",
+ __func__, vha->host_no, rval, mcp->mb[0], mcp->mb[1]));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ }
+
+ return rval;
+}
+
+int
+qla2x00_read_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
+ dma_addr_t sfp_dma, uint8_t *sfp, uint16_t len, uint16_t opt)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+ mcp->mb[0] = MBC_READ_SFP;
+ mcp->mb[1] = dev;
+ mcp->mb[2] = MSW(sfp_dma);
+ mcp->mb[3] = LSW(sfp_dma);
+ mcp->mb[6] = MSW(MSD(sfp_dma));
+ mcp->mb[7] = LSW(MSD(sfp_dma));
+ mcp->mb[8] = len;
+ mcp->mb[9] = adr;
+ mcp->mb[10] = opt;
+ mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (opt & BIT_0)
+ if (sfp)
+ *sfp = mcp->mb[8];
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
+ vha->host_no, rval, mcp->mb[0]));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no));
+ }
+
+ return rval;
+}
+
+int
+qla2x00_write_edc(scsi_qla_host_t *vha, uint16_t dev, uint16_t adr,
+ dma_addr_t sfp_dma, uint8_t *sfp, uint16_t len, uint16_t opt)
+{
+ int rval;
+ mbx_cmd_t mc;
+ mbx_cmd_t *mcp = &mc;
+
+ DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));
+
+ if (opt & BIT_0)
+ if (sfp)
+ len = *sfp;
+
+ mcp->mb[0] = MBC_WRITE_SFP;
+ mcp->mb[1] = dev;
+ mcp->mb[2] = MSW(sfp_dma);
+ mcp->mb[3] = LSW(sfp_dma);
+ mcp->mb[6] = MSW(MSD(sfp_dma));
+ mcp->mb[7] = LSW(MSD(sfp_dma));
+ mcp->mb[8] = len;
+ mcp->mb[9] = adr;
+ mcp->mb[10] = opt;
+ mcp->out_mb = MBX_10|MBX_9|MBX_8|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0;
+ mcp->in_mb = MBX_0;
+ mcp->tov = MBX_TOV_SECONDS;
+ mcp->flags = 0;
+ rval = qla2x00_mailbox_command(vha, mcp);
+
+ if (rval != QLA_SUCCESS) {
+ DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
+ vha->host_no, rval, mcp->mb[0]));
+ } else {
+ DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
+ }
+
+ return rval;
+}
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index f53179c4642..51716c7e300 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -69,9 +69,10 @@ static scsi_qla_host_t *
qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name)
{
scsi_qla_host_t *vha;
+ struct scsi_qla_host *tvha;
/* Locate matching device in database. */
- list_for_each_entry(vha, &ha->vp_list, list) {
+ list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) {
if (!memcmp(port_name, vha->port_name, WWN_SIZE))
return vha;
}
@@ -194,11 +195,11 @@ qla24xx_configure_vp(scsi_qla_host_t *vha)
void
qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
{
- scsi_qla_host_t *vha;
+ scsi_qla_host_t *vha, *tvha;
struct qla_hw_data *ha = rsp->hw;
int i = 0;
- list_for_each_entry(vha, &ha->vp_list, list) {
+ list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) {
if (vha->vp_idx) {
switch (mb[0]) {
case MBA_LIP_OCCURRED:
@@ -300,6 +301,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
int ret;
struct qla_hw_data *ha = vha->hw;
scsi_qla_host_t *vp;
+ struct scsi_qla_host *tvp;
if (vha->vp_idx)
return;
@@ -308,7 +310,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
clear_bit(VP_DPC_NEEDED, &vha->dpc_flags);
- list_for_each_entry(vp, &ha->vp_list, list) {
+ list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx)
ret = qla2x00_do_dpc_vp(vp);
}
@@ -357,7 +359,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
scsi_qla_host_t *base_vha = shost_priv(fc_vport->shost);
struct qla_hw_data *ha = base_vha->hw;
scsi_qla_host_t *vha;
- struct scsi_host_template *sht = &qla24xx_driver_template;
+ struct scsi_host_template *sht = &qla2xxx_driver_template;
struct Scsi_Host *host;
vha = qla2x00_create_host(sht, ha);
@@ -396,7 +398,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
qla2x00_start_timer(vha, qla2x00_timer, WATCH_INTERVAL);
- memset(vha->req_ques, 0, sizeof(vha->req_ques) * QLA_MAX_HOST_QUES);
+ memset(vha->req_ques, 0, sizeof(vha->req_ques));
vha->req_ques[0] = ha->req_q_map[0]->id;
host->can_queue = ha->req_q_map[0]->length + 128;
host->this_id = 255;
@@ -471,7 +473,7 @@ qla25xx_delete_req_que(struct scsi_qla_host *vha, struct req_que *req)
if (req) {
req->options |= BIT_0;
- ret = qla25xx_init_req_que(vha, req, req->options);
+ ret = qla25xx_init_req_que(vha, req);
}
if (ret == QLA_SUCCESS)
qla25xx_free_req_que(vha, req);
@@ -486,7 +488,7 @@ qla25xx_delete_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
if (rsp) {
rsp->options |= BIT_0;
- ret = qla25xx_init_rsp_que(vha, rsp, rsp->options);
+ ret = qla25xx_init_rsp_que(vha, rsp);
}
if (ret == QLA_SUCCESS)
qla25xx_free_rsp_que(vha, rsp);
@@ -502,7 +504,7 @@ int qla25xx_update_req_que(struct scsi_qla_host *vha, uint8_t que, uint8_t qos)
req->options |= BIT_3;
req->qos = qos;
- ret = qla25xx_init_req_que(vha, req, req->options);
+ ret = qla25xx_init_req_que(vha, req);
if (ret != QLA_SUCCESS)
DEBUG2_17(printk(KERN_WARNING "%s failed\n", __func__));
/* restore options bit */
@@ -582,6 +584,7 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
struct req_que *req = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
uint16_t que_id = 0;
+ device_reg_t __iomem *reg;
req = kzalloc(sizeof(struct req_que), GFP_KERNEL);
if (req == NULL) {
@@ -629,10 +632,13 @@ qla25xx_create_req_que(struct qla_hw_data *ha, uint16_t options,
req->ring_index = 0;
req->cnt = req->length;
req->id = que_id;
+ reg = ISP_QUE_REG(ha, que_id);
+ req->req_q_in = &reg->isp25mq.req_q_in;
+ req->req_q_out = &reg->isp25mq.req_q_out;
req->max_q_depth = ha->req_q_map[0]->max_q_depth;
mutex_unlock(&ha->vport_lock);
- ret = qla25xx_init_req_que(base_vha, req, options);
+ ret = qla25xx_init_req_que(base_vha, req);
if (ret != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
mutex_lock(&ha->vport_lock);
@@ -656,7 +662,8 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
int ret = 0;
struct rsp_que *rsp = NULL;
struct scsi_qla_host *base_vha = pci_get_drvdata(ha->pdev);
- uint16_t que_id = 0;;
+ uint16_t que_id = 0;
+ device_reg_t __iomem *reg;
rsp = kzalloc(sizeof(struct rsp_que), GFP_KERNEL);
if (rsp == NULL) {
@@ -704,13 +711,16 @@ qla25xx_create_rsp_que(struct qla_hw_data *ha, uint16_t options,
rsp->ring_ptr = rsp->ring;
rsp->ring_index = 0;
rsp->id = que_id;
+ reg = ISP_QUE_REG(ha, que_id);
+ rsp->rsp_q_in = &reg->isp25mq.rsp_q_in;
+ rsp->rsp_q_out = &reg->isp25mq.rsp_q_out;
mutex_unlock(&ha->vport_lock);
ret = qla25xx_request_irq(rsp);
if (ret)
goto que_failed;
- ret = qla25xx_init_rsp_que(base_vha, rsp, options);
+ ret = qla25xx_init_rsp_que(base_vha, rsp);
if (ret != QLA_SUCCESS) {
qla_printk(KERN_WARNING, ha, "%s failed\n", __func__);
mutex_lock(&ha->vport_lock);
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index c11f872d3e1..efe29924e05 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -104,9 +104,7 @@ static int qla2xxx_slave_alloc(struct scsi_device *);
static int qla2xxx_scan_finished(struct Scsi_Host *, unsigned long time);
static void qla2xxx_scan_start(struct Scsi_Host *);
static void qla2xxx_slave_destroy(struct scsi_device *);
-static int qla2x00_queuecommand(struct scsi_cmnd *cmd,
- void (*fn)(struct scsi_cmnd *));
-static int qla24xx_queuecommand(struct scsi_cmnd *cmd,
+static int qla2xxx_queuecommand(struct scsi_cmnd *cmd,
void (*fn)(struct scsi_cmnd *));
static int qla2xxx_eh_abort(struct scsi_cmnd *);
static int qla2xxx_eh_device_reset(struct scsi_cmnd *);
@@ -117,42 +115,10 @@ static int qla2xxx_eh_host_reset(struct scsi_cmnd *);
static int qla2x00_change_queue_depth(struct scsi_device *, int);
static int qla2x00_change_queue_type(struct scsi_device *, int);
-static struct scsi_host_template qla2x00_driver_template = {
+struct scsi_host_template qla2xxx_driver_template = {
.module = THIS_MODULE,
.name = QLA2XXX_DRIVER_NAME,
- .queuecommand = qla2x00_queuecommand,
-
- .eh_abort_handler = qla2xxx_eh_abort,
- .eh_device_reset_handler = qla2xxx_eh_device_reset,
- .eh_target_reset_handler = qla2xxx_eh_target_reset,
- .eh_bus_reset_handler = qla2xxx_eh_bus_reset,
- .eh_host_reset_handler = qla2xxx_eh_host_reset,
-
- .slave_configure = qla2xxx_slave_configure,
-
- .slave_alloc = qla2xxx_slave_alloc,
- .slave_destroy = qla2xxx_slave_destroy,
- .scan_finished = qla2xxx_scan_finished,
- .scan_start = qla2xxx_scan_start,
- .change_queue_depth = qla2x00_change_queue_depth,
- .change_queue_type = qla2x00_change_queue_type,
- .this_id = -1,
- .cmd_per_lun = 3,
- .use_clustering = ENABLE_CLUSTERING,
- .sg_tablesize = SG_ALL,
-
- /*
- * The RISC allows for each command to transfer (2^32-1) bytes of data,
- * which equates to 0x800000 sectors.
- */
- .max_sectors = 0xFFFF,
- .shost_attrs = qla2x00_host_attrs,
-};
-
-struct scsi_host_template qla24xx_driver_template = {
- .module = THIS_MODULE,
- .name = QLA2XXX_DRIVER_NAME,
- .queuecommand = qla24xx_queuecommand,
+ .queuecommand = qla2xxx_queuecommand,
.eh_abort_handler = qla2xxx_eh_abort,
.eh_device_reset_handler = qla2xxx_eh_device_reset,
@@ -430,73 +396,7 @@ qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
}
static int
-qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
-{
- scsi_qla_host_t *vha = shost_priv(cmd->device->host);
- fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
- struct fc_rport *rport = starget_to_rport(scsi_target(cmd->device));
- struct qla_hw_data *ha = vha->hw;
- srb_t *sp;
- int rval;
-
- if (unlikely(pci_channel_offline(ha->pdev))) {
- cmd->result = DID_REQUEUE << 16;
- goto qc_fail_command;
- }
-
- rval = fc_remote_port_chkready(rport);
- if (rval) {
- cmd->result = rval;
- goto qc_fail_command;
- }
-
- /* Close window on fcport/rport state-transitioning. */
- if (fcport->drport)
- goto qc_target_busy;
-
- if (atomic_read(&fcport->state) != FCS_ONLINE) {
- if (atomic_read(&fcport->state) == FCS_DEVICE_DEAD ||
- atomic_read(&vha->loop_state) == LOOP_DEAD) {
- cmd->result = DID_NO_CONNECT << 16;
- goto qc_fail_command;
- }
- goto qc_target_busy;
- }
-
- spin_unlock_irq(vha->host->host_lock);
-
- sp = qla2x00_get_new_sp(vha, fcport, cmd, done);
- if (!sp)
- goto qc_host_busy_lock;
-
- rval = ha->isp_ops->start_scsi(sp);
- if (rval != QLA_SUCCESS)
- goto qc_host_busy_free_sp;
-
- spin_lock_irq(vha->host->host_lock);
-
- return 0;
-
-qc_host_busy_free_sp:
- qla2x00_sp_free_dma(sp);
- mempool_free(sp, ha->srb_mempool);
-
-qc_host_busy_lock:
- spin_lock_irq(vha->host->host_lock);
- return SCSI_MLQUEUE_HOST_BUSY;
-
-qc_target_busy:
- return SCSI_MLQUEUE_TARGET_BUSY;
-
-qc_fail_command:
- done(cmd);
-
- return 0;
-}
-
-
-static int
-qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+qla2xxx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
{
scsi_qla_host_t *vha = shost_priv(cmd->device->host);
fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@@ -507,7 +407,10 @@ qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
int rval;
if (unlikely(pci_channel_offline(ha->pdev))) {
- cmd->result = DID_REQUEUE << 16;
+ if (ha->pdev->error_state == pci_channel_io_frozen)
+ cmd->result = DID_REQUEUE << 16;
+ else
+ cmd->result = DID_NO_CONNECT << 16;
goto qc24_fail_command;
}
@@ -635,6 +538,34 @@ qla2x00_wait_for_hba_online(scsi_qla_host_t *vha)
return (return_status);
}
+int
+qla2x00_wait_for_chip_reset(scsi_qla_host_t *vha)
+{
+ int return_status;
+ unsigned long wait_reset;
+ struct qla_hw_data *ha = vha->hw;
+ scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
+
+ wait_reset = jiffies + (MAX_LOOP_TIMEOUT * HZ);
+ while (((test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags)) ||
+ test_bit(ABORT_ISP_ACTIVE, &base_vha->dpc_flags) ||
+ test_bit(ISP_ABORT_RETRY, &base_vha->dpc_flags) ||
+ ha->dpc_active) && time_before(jiffies, wait_reset)) {
+
+ msleep(1000);
+
+ if (!test_bit(ISP_ABORT_NEEDED, &base_vha->dpc_flags) &&
+ ha->flags.chip_reset_done)
+ break;
+ }
+ if (ha->flags.chip_reset_done)
+ return_status = QLA_SUCCESS;
+ else
+ return_status = QLA_FUNCTION_FAILED;
+
+ return return_status;
+}
+
/*
* qla2x00_wait_for_loop_ready
* Wait for MAX_LOOP_TIMEOUT(5 min) value for loop
@@ -1163,7 +1094,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *vha, int res)
continue;
for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
sp = req->outstanding_cmds[cnt];
- if (sp && sp->fcport->vha == vha) {
+ if (sp) {
req->outstanding_cmds[cnt] = NULL;
sp->cmd->result = res;
qla2x00_sp_compl(ha, sp);
@@ -1351,9 +1282,6 @@ static struct isp_operations qla2100_isp_ops = {
.write_optrom = qla2x00_write_optrom_data,
.get_flash_version = qla2x00_get_flash_version,
.start_scsi = qla2x00_start_scsi,
- .wrt_req_reg = NULL,
- .wrt_rsp_reg = NULL,
- .rd_req_reg = NULL,
};
static struct isp_operations qla2300_isp_ops = {
@@ -1389,9 +1317,6 @@ static struct isp_operations qla2300_isp_ops = {
.write_optrom = qla2x00_write_optrom_data,
.get_flash_version = qla2x00_get_flash_version,
.start_scsi = qla2x00_start_scsi,
- .wrt_req_reg = NULL,
- .wrt_rsp_reg = NULL,
- .rd_req_reg = NULL,
};
static struct isp_operations qla24xx_isp_ops = {
@@ -1427,9 +1352,6 @@ static struct isp_operations qla24xx_isp_ops = {
.write_optrom = qla24xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
.start_scsi = qla24xx_start_scsi,
- .wrt_req_reg = qla24xx_wrt_req_reg,
- .wrt_rsp_reg = qla24xx_wrt_rsp_reg,
- .rd_req_reg = qla24xx_rd_req_reg,
};
static struct isp_operations qla25xx_isp_ops = {
@@ -1465,9 +1387,6 @@ static struct isp_operations qla25xx_isp_ops = {
.write_optrom = qla24xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
.start_scsi = qla24xx_start_scsi,
- .wrt_req_reg = qla24xx_wrt_req_reg,
- .wrt_rsp_reg = qla24xx_wrt_rsp_reg,
- .rd_req_reg = qla24xx_rd_req_reg,
};
static struct isp_operations qla81xx_isp_ops = {
@@ -1493,8 +1412,8 @@ static struct isp_operations qla81xx_isp_ops = {
.build_iocbs = NULL,
.prep_ms_iocb = qla24xx_prep_ms_iocb,
.prep_ms_fdmi_iocb = qla24xx_prep_ms_fdmi_iocb,
- .read_nvram = qla25xx_read_nvram_data,
- .write_nvram = qla25xx_write_nvram_data,
+ .read_nvram = NULL,
+ .write_nvram = NULL,
.fw_dump = qla81xx_fw_dump,
.beacon_on = qla24xx_beacon_on,
.beacon_off = qla24xx_beacon_off,
@@ -1503,9 +1422,6 @@ static struct isp_operations qla81xx_isp_ops = {
.write_optrom = qla24xx_write_optrom_data,
.get_flash_version = qla24xx_get_flash_version,
.start_scsi = qla24xx_start_scsi,
- .wrt_req_reg = qla24xx_wrt_req_reg,
- .wrt_rsp_reg = qla24xx_wrt_rsp_reg,
- .rd_req_reg = qla24xx_rd_req_reg,
};
static inline void
@@ -1727,7 +1643,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
struct rsp_que *rsp = NULL;
bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO);
- sht = &qla2x00_driver_template;
+ sht = &qla2xxx_driver_template;
if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8432 ||
@@ -1736,7 +1652,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2532 ||
pdev->device == PCI_DEVICE_ID_QLOGIC_ISP8001) {
bars = pci_select_bars(pdev, IORESOURCE_MEM);
- sht = &qla24xx_driver_template;
mem_only = 1;
}
@@ -1927,10 +1842,16 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
ha->rsp_q_map[0] = rsp;
ha->req_q_map[0] = req;
+ /* FWI2-capable only. */
+ req->req_q_in = &ha->iobase->isp24.req_q_in;
+ req->req_q_out = &ha->iobase->isp24.req_q_out;
+ rsp->rsp_q_in = &ha->iobase->isp24.rsp_q_in;
+ rsp->rsp_q_out = &ha->iobase->isp24.rsp_q_out;
if (ha->mqenable) {
- ha->isp_ops->wrt_req_reg = qla25xx_wrt_req_reg;
- ha->isp_ops->wrt_rsp_reg = qla25xx_wrt_rsp_reg;
- ha->isp_ops->rd_req_reg = qla25xx_rd_req_reg;
+ req->req_q_in = &ha->mqiobase->isp25mq.req_q_in;
+ req->req_q_out = &ha->mqiobase->isp25mq.req_q_out;
+ rsp->rsp_q_in = &ha->mqiobase->isp25mq.rsp_q_in;
+ rsp->rsp_q_out = &ha->mqiobase->isp25mq.rsp_q_out;
}
if (qla2x00_initialize_adapter(base_vha)) {
@@ -2000,6 +1921,16 @@ probe_init_failed:
ha->max_queues = 0;
probe_failed:
+ if (base_vha->timer_active)
+ qla2x00_stop_timer(base_vha);
+ base_vha->flags.online = 0;
+ if (ha->dpc_thread) {
+ struct task_struct *t = ha->dpc_thread;
+
+ ha->dpc_thread = NULL;
+ kthread_stop(t);
+ }
+
qla2x00_free_device(base_vha);
scsi_host_put(base_vha->host);
@@ -2033,10 +1964,30 @@ qla2x00_remove_one(struct pci_dev *pdev)
set_bit(UNLOADING, &base_vha->dpc_flags);
+ qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
+
qla2x00_dfs_remove(base_vha);
qla84xx_put_chip(base_vha);
+ /* Disable timer */
+ if (base_vha->timer_active)
+ qla2x00_stop_timer(base_vha);
+
+ base_vha->flags.online = 0;
+
+ /* Kill the kernel thread for this host */
+ if (ha->dpc_thread) {
+ struct task_struct *t = ha->dpc_thread;
+
+ /*
+ * qla2xxx_wake_dpc checks for ->dpc_thread
+ * so we need to zero it out.
+ */
+ ha->dpc_thread = NULL;
+ kthread_stop(t);
+ }
+
qla2x00_free_sysfs_attr(base_vha);
fc_remove_host(base_vha->host);
@@ -2065,25 +2016,6 @@ static void
qla2x00_free_device(scsi_qla_host_t *vha)
{
struct qla_hw_data *ha = vha->hw;
- qla2x00_abort_all_cmds(vha, DID_NO_CONNECT << 16);
-
- /* Disable timer */
- if (vha->timer_active)
- qla2x00_stop_timer(vha);
-
- vha->flags.online = 0;
-
- /* Kill the kernel thread for this host */
- if (ha->dpc_thread) {
- struct task_struct *t = ha->dpc_thread;
-
- /*
- * qla2xxx_wake_dpc checks for ->dpc_thread
- * so we need to zero it out.
- */
- ha->dpc_thread = NULL;
- kthread_stop(t);
- }
if (ha->flags.fce_enabled)
qla2x00_disable_fce_trace(vha, NULL, NULL);
@@ -2222,10 +2154,6 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
{
char name[16];
- ha->init_cb_size = sizeof(init_cb_t);
- if (IS_QLA2XXX_MIDTYPE(ha))
- ha->init_cb_size = sizeof(struct mid_init_cb_24xx);
-
ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size,
&ha->init_cb_dma, GFP_KERNEL);
if (!ha->init_cb)
@@ -2317,9 +2245,19 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len,
} else
ha->npiv_info = NULL;
+ /* Get consistent memory allocated for EX-INIT-CB. */
+ if (IS_QLA81XX(ha)) {
+ ha->ex_init_cb = dma_pool_alloc(ha->s_dma_pool, GFP_KERNEL,
+ &ha->ex_init_cb_dma);
+ if (!ha->ex_init_cb)
+ goto fail_ex_init_cb;
+ }
+
INIT_LIST_HEAD(&ha->vp_list);
return 1;
+fail_ex_init_cb:
+ kfree(ha->npiv_info);
fail_npiv_info:
dma_free_coherent(&ha->pdev->dev, ((*rsp)->length + 1) *
sizeof(response_t), (*rsp)->ring, (*rsp)->dma);
@@ -2402,18 +2340,22 @@ qla2x00_mem_free(struct qla_hw_data *ha)
if (ha->sfp_data)
dma_pool_free(ha->s_dma_pool, ha->sfp_data, ha->sfp_data_dma);
+ if (ha->edc_data)
+ dma_pool_free(ha->s_dma_pool, ha->edc_data, ha->edc_data_dma);
+
if (ha->ms_iocb)
dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma);
+ if (ha->ex_init_cb)
+ dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma);
+
if (ha->s_dma_pool)
dma_pool_destroy(ha->s_dma_pool);
-
if (ha->gid_list)
dma_free_coherent(&ha->pdev->dev, GID_LIST_SIZE, ha->gid_list,
ha->gid_list_dma);
-
if (ha->init_cb)
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
ha->init_cb, ha->init_cb_dma);
@@ -2432,6 +2374,8 @@ qla2x00_mem_free(struct qla_hw_data *ha)
ha->ms_iocb_dma = 0;
ha->init_cb = NULL;
ha->init_cb_dma = 0;
+ ha->ex_init_cb = NULL;
+ ha->ex_init_cb_dma = 0;
ha->s_dma_pool = NULL;
@@ -2522,6 +2466,19 @@ qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
return qla2x00_post_work(vha, e, 1);
}
+int
+qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
+{
+ struct qla_work_evt *e;
+
+ e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK, 1);
+ if (!e)
+ return QLA_FUNCTION_FAILED;
+
+ memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
+ return qla2x00_post_work(vha, e, 1);
+}
+
static void
qla2x00_do_work(struct scsi_qla_host *vha)
{
@@ -2539,6 +2496,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
fc_host_post_event(vha->host, fc_get_event_number(),
e->u.aen.code, e->u.aen.data);
break;
+ case QLA_EVT_IDC_ACK:
+ qla81xx_idc_ack(vha, e->u.idc_ack.mb);
+ break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
@@ -2552,7 +2512,7 @@ qla2x00_do_work(struct scsi_qla_host *vha)
void qla2x00_relogin(struct scsi_qla_host *vha)
{
fc_port_t *fcport;
- uint8_t status;
+ int status;
uint16_t next_loopid = 0;
struct qla_hw_data *ha = vha->hw;
@@ -2902,19 +2862,11 @@ qla2x00_timer(scsi_qla_host_t *vha)
spin_unlock_irqrestore(&ha->hardware_lock,
cpu_flags);
}
- set_bit(ABORT_QUEUES_NEEDED, &vha->dpc_flags);
start_dpc++;
}
/* if the loop has been down for 4 minutes, reinit adapter */
if (atomic_dec_and_test(&vha->loop_down_timer) != 0) {
- DEBUG(printk("scsi(%ld): Loop down exceed 4 mins - "
- "restarting queues.\n",
- vha->host_no));
-
- set_bit(RESTART_QUEUES_NEEDED, &vha->dpc_flags);
- start_dpc++;
-
if (!(vha->device_flags & DFLG_NO_CABLE) &&
!vha->vp_idx) {
DEBUG(printk("scsi(%ld): Loop down - "
@@ -3041,6 +2993,8 @@ qla2x00_release_firmware(void)
static pci_ers_result_t
qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
{
+ scsi_qla_host_t *base_vha = pci_get_drvdata(pdev);
+
switch (state) {
case pci_channel_io_normal:
return PCI_ERS_RESULT_CAN_RECOVER;
@@ -3048,7 +3002,7 @@ qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state)
pci_disable_device(pdev);
return PCI_ERS_RESULT_NEED_RESET;
case pci_channel_io_perm_failure:
- qla2x00_remove_one(pdev);
+ qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
return PCI_ERS_RESULT_DISCONNECT;
}
return PCI_ERS_RESULT_NEED_RESET;
diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c
index 9c3b694c049..152ecfc26cd 100644
--- a/drivers/scsi/qla2xxx/qla_sup.c
+++ b/drivers/scsi/qla2xxx/qla_sup.c
@@ -612,8 +612,8 @@ qla2xxx_find_flt_start(scsi_qla_host_t *vha, uint32_t *start)
/* Good data. Use specified location. */
loc = locations[1];
- *start = le16_to_cpu(fltl->start_hi) << 16 |
- le16_to_cpu(fltl->start_lo);
+ *start = (le16_to_cpu(fltl->start_hi) << 16 |
+ le16_to_cpu(fltl->start_lo)) >> 2;
end:
DEBUG2(qla_printk(KERN_DEBUG, ha, "FLTL[%s] = 0x%x.\n", loc, *start));
return QLA_SUCCESS;
@@ -629,6 +629,14 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
{ FA_BOOT_CODE_ADDR, FA_BOOT_CODE_ADDR, FA_BOOT_CODE_ADDR_81 };
const uint32_t def_vpd_nvram[] =
{ FA_VPD_NVRAM_ADDR, FA_VPD_NVRAM_ADDR, FA_VPD_NVRAM_ADDR_81 };
+ const uint32_t def_vpd0[] =
+ { 0, 0, FA_VPD0_ADDR_81 };
+ const uint32_t def_vpd1[] =
+ { 0, 0, FA_VPD1_ADDR_81 };
+ const uint32_t def_nvram0[] =
+ { 0, 0, FA_NVRAM0_ADDR_81 };
+ const uint32_t def_nvram1[] =
+ { 0, 0, FA_NVRAM1_ADDR_81 };
const uint32_t def_fdt[] =
{ FA_FLASH_DESCR_ADDR_24, FA_FLASH_DESCR_ADDR,
FA_FLASH_DESCR_ADDR_81 };
@@ -684,7 +692,7 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
"end=0x%x size=0x%x.\n", le32_to_cpu(region->code), start,
le32_to_cpu(region->end) >> 2, le32_to_cpu(region->size)));
- switch (le32_to_cpu(region->code)) {
+ switch (le32_to_cpu(region->code) & 0xff) {
case FLT_REG_FW:
ha->flt_region_fw = start;
break;
@@ -693,6 +701,20 @@ qla2xxx_get_flt_info(scsi_qla_host_t *vha, uint32_t flt_addr)
break;
case FLT_REG_VPD_0:
ha->flt_region_vpd_nvram = start;
+ if (!(PCI_FUNC(ha->pdev->devfn) & 1))
+ ha->flt_region_vpd = start;
+ break;
+ case FLT_REG_VPD_1:
+ if (PCI_FUNC(ha->pdev->devfn) & 1)
+ ha->flt_region_vpd = start;
+ break;
+ case FLT_REG_NVRAM_0:
+ if (!(PCI_FUNC(ha->pdev->devfn) & 1))
+ ha->flt_region_nvram = start;
+ break;
+ case FLT_REG_NVRAM_1:
+ if (PCI_FUNC(ha->pdev->devfn) & 1)
+ ha->flt_region_nvram = start;
break;
case FLT_REG_FDT:
ha->flt_region_fdt = start;
@@ -722,13 +744,18 @@ no_flash_data:
ha->flt_region_fw = def_fw[def];
ha->flt_region_boot = def_boot[def];
ha->flt_region_vpd_nvram = def_vpd_nvram[def];
+ ha->flt_region_vpd = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
+ def_vpd0[def]: def_vpd1[def];
+ ha->flt_region_nvram = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
+ def_nvram0[def]: def_nvram1[def];
ha->flt_region_fdt = def_fdt[def];
ha->flt_region_npiv_conf = !(PCI_FUNC(ha->pdev->devfn) & 1) ?
def_npiv_conf0[def]: def_npiv_conf1[def];
done:
DEBUG2(qla_printk(KERN_DEBUG, ha, "FLT[%s]: boot=0x%x fw=0x%x "
- "vpd_nvram=0x%x fdt=0x%x flt=0x%x npiv=0x%x.\n", loc,
- ha->flt_region_boot, ha->flt_region_fw, ha->flt_region_vpd_nvram,
+ "vpd_nvram=0x%x vpd=0x%x nvram=0x%x fdt=0x%x flt=0x%x "
+ "npiv=0x%x.\n", loc, ha->flt_region_boot, ha->flt_region_fw,
+ ha->flt_region_vpd_nvram, ha->flt_region_vpd, ha->flt_region_nvram,
ha->flt_region_fdt, ha->flt_region_flt, ha->flt_region_npiv_conf));
}
@@ -931,31 +958,41 @@ done:
ha->npiv_info = NULL;
}
-static void
-qla24xx_unprotect_flash(struct qla_hw_data *ha)
+static int
+qla24xx_unprotect_flash(scsi_qla_host_t *vha)
{
+ struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ if (ha->flags.fac_supported)
+ return qla81xx_fac_do_write_enable(vha, 1);
+
/* Enable flash write. */
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) | CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
if (!ha->fdt_wrt_disable)
- return;
+ goto done;
/* Disable flash write-protection, first clear SR protection bit */
qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
/* Then write zero again to clear remaining SR bits.*/
qla24xx_write_flash_dword(ha, flash_conf_addr(ha, 0x101), 0);
+done:
+ return QLA_SUCCESS;
}
-static void
-qla24xx_protect_flash(struct qla_hw_data *ha)
+static int
+qla24xx_protect_flash(scsi_qla_host_t *vha)
{
uint32_t cnt;
+ struct qla_hw_data *ha = vha->hw;
struct device_reg_24xx __iomem *reg = &ha->iobase->isp24;
+ if (ha->flags.fac_supported)
+ return qla81xx_fac_do_write_enable(vha, 0);
+
if (!ha->fdt_wrt_disable)
goto skip_wrt_protect;
@@ -973,6 +1010,26 @@ skip_wrt_protect:
WRT_REG_DWORD(&reg->ctrl_status,
RD_REG_DWORD(&reg->ctrl_status) & ~CSRX_FLASH_ENABLE);
RD_REG_DWORD(&reg->ctrl_status); /* PCI Posting. */
+
+ return QLA_SUCCESS;
+}
+
+static int
+qla24xx_erase_sector(scsi_qla_host_t *vha, uint32_t fdata)
+{
+ struct qla_hw_data *ha = vha->hw;
+ uint32_t start, finish;
+
+ if (ha->flags.fac_supported) {
+ start = fdata >> 2;
+ finish = start + (ha->fdt_block_size >> 2) - 1;
+ return qla81xx_fac_erase_sector(vha, flash_data_addr(ha,
+ start), flash_data_addr(ha, finish));
+ }
+
+ return qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
+ (fdata & 0xff00) | ((fdata << 16) & 0xff0000) |
+ ((fdata >> 16) & 0xff));
}
static int
@@ -987,8 +1044,6 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
void *optrom = NULL;
struct qla_hw_data *ha = vha->hw;
- ret = QLA_SUCCESS;
-
/* Prepare burst-capable write on supported ISPs. */
if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && !(faddr & 0xfff) &&
dwords > OPTROM_BURST_DWORDS) {
@@ -1004,7 +1059,12 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
rest_addr = (ha->fdt_block_size >> 2) - 1;
sec_mask = ~rest_addr;
- qla24xx_unprotect_flash(ha);
+ ret = qla24xx_unprotect_flash(vha);
+ if (ret != QLA_SUCCESS) {
+ qla_printk(KERN_WARNING, ha,
+ "Unable to unprotect flash for update.\n");
+ goto done;
+ }
for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) {
fdata = (faddr & sec_mask) << 2;
@@ -1017,9 +1077,7 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
ha->fdt_unprotect_sec_cmd,
(fdata & 0xff00) | ((fdata << 16) &
0xff0000) | ((fdata >> 16) & 0xff));
- ret = qla24xx_write_flash_dword(ha, ha->fdt_erase_cmd,
- (fdata & 0xff00) |((fdata << 16) &
- 0xff0000) | ((fdata >> 16) & 0xff));
+ ret = qla24xx_erase_sector(vha, fdata);
if (ret != QLA_SUCCESS) {
DEBUG9(qla_printk("Unable to erase sector: "
"address=%x.\n", faddr));
@@ -1073,8 +1131,11 @@ qla24xx_write_flash_data(scsi_qla_host_t *vha, uint32_t *dwptr, uint32_t faddr,
0xff0000) | ((fdata >> 16) & 0xff));
}
- qla24xx_protect_flash(ha);
-
+ ret = qla24xx_protect_flash(vha);
+ if (ret != QLA_SUCCESS)
+ qla_printk(KERN_WARNING, ha,
+ "Unable to protect flash after update.\n");
+done:
if (optrom)
dma_free_coherent(&ha->pdev->dev,
OPTROM_BURST_SIZE, optrom, optrom_dma);
@@ -1915,7 +1976,7 @@ qla2x00_resume_hba(struct scsi_qla_host *vha)
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
qla2xxx_wake_dpc(vha);
- qla2x00_wait_for_hba_online(vha);
+ qla2x00_wait_for_chip_reset(vha);
scsi_unblock_requests(vha->host);
}
@@ -2206,11 +2267,7 @@ qla24xx_write_optrom_data(struct scsi_qla_host *vha, uint8_t *buf,
rval = qla24xx_write_flash_data(vha, (uint32_t *)buf, offset >> 2,
length >> 2);
- /* Resume HBA -- RISC reset needed. */
clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags);
- set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
- qla2xxx_wake_dpc(vha);
- qla2x00_wait_for_hba_online(vha);
scsi_unblock_requests(vha->host);
return rval;
@@ -2518,7 +2575,7 @@ qla24xx_get_flash_version(scsi_qla_host_t *vha, void *mbuf)
dcode = mbuf;
/* Begin with first PCI expansion ROM header. */
- pcihdr = ha->flt_region_boot;
+ pcihdr = ha->flt_region_boot << 2;
last_image = 1;
do {
/* Verify PCI expansion ROM header. */
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index cfa4c11a479..19d1afc3a34 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -7,9 +7,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "8.03.00-k2"
+#define QLA2XXX_VERSION "8.03.01-k1"
#define QLA_DRIVER_MAJOR_VER 8
#define QLA_DRIVER_MINOR_VER 3
-#define QLA_DRIVER_PATCH_VER 0
+#define QLA_DRIVER_PATCH_VER 1
#define QLA_DRIVER_BETA_VER 0
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c
index 69d6ad862b6..fa34b92850a 100644
--- a/drivers/scsi/qlogicpti.c
+++ b/drivers/scsi/qlogicpti.c
@@ -28,6 +28,7 @@
#include <linux/dma-mapping.h>
#include <linux/of.h>
#include <linux/of_device.h>
+#include <linux/firmware.h>
#include <asm/byteorder.h>
@@ -53,8 +54,6 @@
#define DEFAULT_LOOP_COUNT 10000
-#include "qlogicpti_asm.c"
-
static struct qlogicpti *qptichain = NULL;
static DEFINE_SPINLOCK(qptichain_lock);
@@ -465,16 +464,32 @@ static int qlogicpti_reset_hardware(struct Scsi_Host *host)
static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
{
+ const struct firmware *fw;
+ const char fwname[] = "qlogic/isp1000.bin";
+ const __le16 *fw_data;
struct Scsi_Host *host = qpti->qhost;
unsigned short csum = 0;
unsigned short param[6];
- unsigned short *risc_code, risc_code_addr, risc_code_length;
+ unsigned short risc_code_addr, risc_code_length;
+ int err;
unsigned long flags;
int i, timeout;
- risc_code = &sbus_risc_code01[0];
+ err = request_firmware(&fw, fwname, &qpti->op->dev);
+ if (err) {
+ printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
+ fwname, err);
+ return err;
+ }
+ if (fw->size % 2) {
+ printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
+ fw->size, fwname);
+ err = -EINVAL;
+ goto outfirm;
+ }
+ fw_data = (const __le16 *)&fw->data[0];
risc_code_addr = 0x1000; /* all f/w modules load at 0x1000 */
- risc_code_length = sbus_risc_code_length01;
+ risc_code_length = fw->size / 2;
spin_lock_irqsave(host->host_lock, flags);
@@ -482,12 +497,12 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
* afterwards via the mailbox commands.
*/
for (i = 0; i < risc_code_length; i++)
- csum += risc_code[i];
+ csum += __le16_to_cpu(fw_data[i]);
if (csum) {
- spin_unlock_irqrestore(host->host_lock, flags);
printk(KERN_EMERG "qlogicpti%d: Aieee, firmware checksum failed!",
qpti->qpti_id);
- return 1;
+ err = 1;
+ goto out;
}
sbus_writew(SBUS_CTRL_RESET, qpti->qregs + SBUS_CTRL);
sbus_writew((DMA_CTRL_CCLEAR | DMA_CTRL_CIRQ), qpti->qregs + CMD_DMA_CTRL);
@@ -496,9 +511,9 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
while (--timeout && (sbus_readw(qpti->qregs + SBUS_CTRL) & SBUS_CTRL_RESET))
udelay(20);
if (!timeout) {
- spin_unlock_irqrestore(host->host_lock, flags);
printk(KERN_EMERG "qlogicpti%d: Cannot reset the ISP.", qpti->qpti_id);
- return 1;
+ err = 1;
+ goto out;
}
sbus_writew(HCCTRL_RESET, qpti->qregs + HCCTRL);
@@ -536,21 +551,21 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
if (qlogicpti_mbox_command(qpti, param, 1)) {
printk(KERN_EMERG "qlogicpti%d: Cannot stop firmware for reload.\n",
qpti->qpti_id);
- spin_unlock_irqrestore(host->host_lock, flags);
- return 1;
+ err = 1;
+ goto out;
}
/* Load it up.. */
for (i = 0; i < risc_code_length; i++) {
param[0] = MBOX_WRITE_RAM_WORD;
param[1] = risc_code_addr + i;
- param[2] = risc_code[i];
+ param[2] = __le16_to_cpu(fw_data[i]);
if (qlogicpti_mbox_command(qpti, param, 1) ||
param[0] != MBOX_COMMAND_COMPLETE) {
printk("qlogicpti%d: Firmware dload failed, I'm bolixed!\n",
qpti->qpti_id);
- spin_unlock_irqrestore(host->host_lock, flags);
- return 1;
+ err = 1;
+ goto out;
}
}
@@ -569,8 +584,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: New firmware csum failure!\n",
qpti->qpti_id);
- spin_unlock_irqrestore(host->host_lock, flags);
- return 1;
+ err = 1;
+ goto out;
}
/* Start using newly downloaded firmware. */
@@ -583,8 +598,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: AboutFirmware cmd fails.\n",
qpti->qpti_id);
- spin_unlock_irqrestore(host->host_lock, flags);
- return 1;
+ err = 1;
+ goto out;
}
/* Snag the major and minor revisions from the result. */
@@ -599,8 +614,8 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
(param[0] != MBOX_COMMAND_COMPLETE)) {
printk(KERN_EMERG "qlogicpti%d: could not set clock rate.\n",
qpti->qpti_id);
- spin_unlock_irqrestore(host->host_lock, flags);
- return 1;
+ err = 1;
+ goto out;
}
if (qpti->is_pti != 0) {
@@ -616,8 +631,11 @@ static int __devinit qlogicpti_load_firmware(struct qlogicpti *qpti)
qlogicpti_mbox_command(qpti, param, 1);
}
+out:
spin_unlock_irqrestore(host->host_lock, flags);
- return 0;
+outfirm:
+ release_firmware(fw);
+ return err;
}
static int qlogicpti_verify_tmon(struct qlogicpti *qpti)
@@ -1458,6 +1476,7 @@ MODULE_DESCRIPTION("QlogicISP SBUS driver");
MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
MODULE_LICENSE("GPL");
MODULE_VERSION("2.1");
+MODULE_FIRMWARE("qlogic/isp1000.bin");
module_init(qpti_init);
module_exit(qpti_exit);
diff --git a/drivers/scsi/qlogicpti_asm.c b/drivers/scsi/qlogicpti_asm.c
deleted file mode 100644
index 19aa84f4601..00000000000
--- a/drivers/scsi/qlogicpti_asm.c
+++ /dev/null
@@ -1,1160 +0,0 @@
-/* Version 1.31.00 ISP1000 Initiator RISC firmware */
-unsigned short sbus_risc_code01[] __devinitdata = {
- 0x0078, 0x1030, 0x0000, 0x2419, 0x0000, 0x12ff, 0x2043, 0x4f50,
- 0x5952, 0x4947, 0x4854, 0x2031, 0x3939, 0x312c, 0x3139, 0x3932,
- 0x2c31, 0x3939, 0x332c, 0x3139, 0x3934, 0x2051, 0x4c4f, 0x4749,
- 0x4320, 0x434f, 0x5250, 0x4f52, 0x4154, 0x494f, 0x4e00, 0x2049,
- 0x5350, 0x3130, 0x3030, 0x2046, 0x6972, 0x6d77, 0x6172, 0x6520,
- 0x2056, 0x6572, 0x7369, 0x6f6e, 0x2030, 0x312e, 0x3331, 0x2020,
- 0x20b9, 0x1212, 0x20c1, 0x0008, 0x2071, 0x0010, 0x70c3, 0x0004,
- 0x20c9, 0x3fff, 0x2089, 0x10c8, 0x70c7, 0x4953, 0x70cb, 0x5020,
- 0x70cf, 0x2020, 0x70d3, 0x0001, 0x3f00, 0x70d6, 0x2031, 0x0030,
- 0x2079, 0x3500, 0x7863, 0x0000, 0x2fa0, 0x2009, 0x0327, 0x2011,
- 0x0000, 0x20a9, 0x0040, 0x42a4, 0x8109, 0x00c0, 0x1051, 0x789b,
- 0x0101, 0x780b, 0x0002, 0x780f, 0x0002, 0x784f, 0x0bb8, 0x2069,
- 0x3540, 0x00a8, 0x106a, 0x681b, 0x003c, 0x2009, 0x1313, 0x21b8,
- 0x0078, 0x106c, 0x681b, 0x0028, 0x6807, 0x0007, 0x680b, 0x00fa,
- 0x680f, 0x0008, 0x6813, 0x0005, 0x681f, 0x0000, 0x6823, 0x0006,
- 0x6817, 0x0008, 0x6827, 0x0000, 0x2069, 0x3600, 0x2011, 0x0020,
- 0x2009, 0x0010, 0x680b, 0x0c19, 0x680f, 0x0019, 0x6803, 0xdd00,
- 0x6807, 0x001a, 0x6a1a, 0x2d00, 0xa0e8, 0x0008, 0xa290, 0x0004,
- 0x8109, 0x00c0, 0x1082, 0x2069, 0x3680, 0x20a9, 0x0080, 0x6837,
- 0x0000, 0x680b, 0x0040, 0x6817, 0x0100, 0x681f, 0x0064, 0xade8,
- 0x0010, 0x0070, 0x10a5, 0x0078, 0x1097, 0x1078, 0x1a38, 0x1078,
- 0x2f3a, 0x1078, 0x1681, 0x1078, 0x33ba, 0x3200, 0xa085, 0x000d,
- 0x2090, 0x70c3, 0x0000, 0x0090, 0x10bc, 0x70c0, 0xa086, 0x0002,
- 0x00c0, 0x10bc, 0x1078, 0x11ba, 0x1078, 0x10ec, 0x1078, 0x1817,
- 0x1078, 0x19a8, 0x1078, 0x327d, 0x1078, 0x177d, 0x0078, 0x10bc,
- 0x10d0, 0x10d2, 0x1bc3, 0x1bc3, 0x2f98, 0x2f98, 0x1bc3, 0x1bc3,
- 0x0078, 0x10d0, 0x0078, 0x10d2, 0x0078, 0x10d4, 0x0078, 0x10d6,
- 0x7008, 0x800c, 0x00c8, 0x10e7, 0x7007, 0x0002, 0xa08c, 0x000c,
- 0x00c0, 0x10e8, 0x8004, 0x8004, 0x00c8, 0x10e7, 0x087a, 0x097a,
- 0x70c3, 0x4002, 0x0078, 0x11bd, 0x7814, 0xa005, 0x00c0, 0x10f4,
- 0x0010, 0x1130, 0x0078, 0x112f, 0x2009, 0x3568, 0x2104, 0xa005,
- 0x00c0, 0x112f, 0x7814, 0xa086, 0x0001, 0x00c0, 0x1101, 0x1078,
- 0x1536, 0x7817, 0x0000, 0x2009, 0x356f, 0x2104, 0xa065, 0x0040,
- 0x111d, 0x2009, 0x356a, 0x211c, 0x8108, 0x2114, 0x8108, 0x2104,
- 0xa210, 0xa399, 0x0000, 0x2009, 0x001c, 0x6083, 0x0103, 0x1078,
- 0x1611, 0x00c0, 0x1129, 0x1078, 0x1678, 0x2009, 0x356f, 0x200b,
- 0x0000, 0x2009, 0x3569, 0x2104, 0x200b, 0x0000, 0xa005, 0x0040,
- 0x112d, 0x2001, 0x4005, 0x0078, 0x11bc, 0x0078, 0x11ba, 0x007c,
- 0x2061, 0x0000, 0x6018, 0xa084, 0x0001, 0x0040, 0x1138, 0x007c,
- 0x70c3, 0x0000, 0x70c7, 0x0000, 0x70cb, 0x0000, 0x70cf, 0x0000,
- 0x70c0, 0xa0bc, 0xffc0, 0x00c0, 0x1188, 0x2038, 0x0079, 0x1148,
- 0x11ba, 0x1205, 0x11d3, 0x1205, 0x1256, 0x1256, 0x11ca, 0x1590,
- 0x1261, 0x11c6, 0x11d7, 0x11d9, 0x11db, 0x11dd, 0x1595, 0x11c6,
- 0x1267, 0x1283, 0x1544, 0x158a, 0x11df, 0x146b, 0x148d, 0x14a7,
- 0x14d0, 0x1424, 0x1432, 0x1446, 0x145a, 0x12ef, 0x11c6, 0x129f,
- 0x12a6, 0x12ab, 0x12b0, 0x12b6, 0x12bb, 0x12c0, 0x12c5, 0x12ca,
- 0x12ce, 0x12e3, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x12fb,
- 0x1304, 0x1313, 0x1339, 0x1343, 0x134a, 0x1370, 0x137f, 0x138e,
- 0x13a0, 0x1409, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x1419,
- 0xa0bc, 0xffa0, 0x00c0, 0x11c6, 0x2038, 0xa084, 0x001f, 0x0079,
- 0x1191, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6,
- 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6,
- 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6, 0x11c6,
- 0x11c6, 0x11c6, 0x11c6, 0x15ed, 0x15f7, 0x15fb, 0x1609, 0x11c6,
- 0x11c6, 0x72ca, 0x71c6, 0x2001, 0x4006, 0x0078, 0x11bc, 0x73ce,
- 0x72ca, 0x71c6, 0x2001, 0x4000, 0x70c2, 0x2061, 0x0000, 0x601b,
- 0x0001, 0x2091, 0x5000, 0x2091, 0x4080, 0x007c, 0x70c3, 0x4001,
- 0x0078, 0x11bd, 0x2099, 0x0041, 0x20a1, 0x0041, 0x20a9, 0x0005,
- 0x53a3, 0x0078, 0x11ba, 0x70c4, 0x70c3, 0x0004, 0x007a, 0x0078,
- 0x11ba, 0x0078, 0x11ba, 0x0078, 0x11ba, 0x0078, 0x11ba, 0x2091,
- 0x8000, 0x70c3, 0x0000, 0x70c7, 0x4953, 0x70cb, 0x5020, 0x70cf,
- 0x2020, 0x70d3, 0x0001, 0x3f00, 0x70d6, 0x2079, 0x0000, 0x781b,
- 0x0001, 0x2031, 0x0030, 0x2059, 0x1000, 0x2029, 0x0457, 0x2051,
- 0x0470, 0x2061, 0x0472, 0x20b9, 0xffff, 0x20c1, 0x0000, 0x2091,
- 0x5000, 0x2091, 0x4080, 0x0078, 0x0455, 0x71d0, 0x72c8, 0x73cc,
- 0x70c4, 0x20a0, 0x2098, 0x2031, 0x0030, 0x81ff, 0x0040, 0x11ba,
- 0x7007, 0x0004, 0x731a, 0x721e, 0x2051, 0x0012, 0x2049, 0x1234,
- 0x2041, 0x11ba, 0x7003, 0x0002, 0xa786, 0x0001, 0x00c0, 0x1226,
- 0x2049, 0x1242, 0x2041, 0x124e, 0x7003, 0x0003, 0x7017, 0x0000,
- 0x810b, 0x7112, 0x00c8, 0x122e, 0x7017, 0x0001, 0x7007, 0x0001,
- 0xa786, 0x0001, 0x0040, 0x1242, 0x700c, 0xa084, 0x007f, 0x8004,
- 0x2009, 0x0020, 0xa102, 0x0942, 0x094a, 0x20a8, 0x26a0, 0x53a6,
- 0x0078, 0x10d8, 0x700c, 0xa084, 0x007f, 0x0040, 0x1242, 0x80ac,
- 0x0048, 0x1242, 0x2698, 0x53a5, 0x0078, 0x10d8, 0x700c, 0xa084,
- 0x007f, 0x80ac, 0x2698, 0x53a5, 0x0078, 0x11ba, 0x71c4, 0x70c8,
- 0x2114, 0xa79e, 0x0004, 0x00c0, 0x125e, 0x200a, 0x72ca, 0x0078,
- 0x11b9, 0x70c7, 0x0001, 0x70cb, 0x001f, 0x0078, 0x11ba, 0x70c4,
- 0x72c8, 0x73cc, 0x74d0, 0x70c6, 0x72ca, 0x73ce, 0x74d2, 0xa005,
- 0x0040, 0x127d, 0x8001, 0x7872, 0x7a7a, 0x7b7e, 0x7c76, 0x7898,
- 0xa084, 0xfffc, 0x789a, 0x0078, 0x1281, 0x7898, 0xa085, 0x0001,
- 0x789a, 0x0078, 0x11ba, 0x70c4, 0x72c8, 0x73cc, 0x74d4, 0x70c6,
- 0x72ca, 0x73ce, 0x74d6, 0xa005, 0x0040, 0x1299, 0x8001, 0x7886,
- 0x7a8e, 0x7b92, 0x7c8a, 0x7898, 0xa084, 0xfcff, 0x789a, 0x0078,
- 0x129d, 0x7898, 0xa085, 0x0100, 0x789a, 0x0078, 0x11ba, 0x2009,
- 0x3559, 0x210c, 0x2011, 0x0410, 0x0078, 0x11b8, 0x2009, 0x3541,
- 0x210c, 0x0078, 0x11b9, 0x2009, 0x3542, 0x210c, 0x0078, 0x11b9,
- 0x2061, 0x3540, 0x610c, 0x6210, 0x0078, 0x11b8, 0x2009, 0x3545,
- 0x210c, 0x0078, 0x11b9, 0x2009, 0x3546, 0x210c, 0x0078, 0x11b9,
- 0x2009, 0x3547, 0x210c, 0x0078, 0x11b9, 0x2009, 0x3548, 0x210c,
- 0x0078, 0x11b9, 0x7908, 0x7a0c, 0x0078, 0x11b8, 0x71c4, 0x8107,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8, 0x3600, 0x6a00,
- 0x6804, 0xa084, 0x0008, 0x0040, 0x12e0, 0x6b08, 0x0078, 0x12e1,
- 0x6b0c, 0x0078, 0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000,
- 0x6b1c, 0x6a14, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b7, 0x77c4,
- 0x1078, 0x1692, 0x2091, 0x8000, 0x6908, 0x6a18, 0x6b10, 0x2091,
- 0x8001, 0x0078, 0x11b7, 0x71c4, 0xa182, 0x0010, 0x00c8, 0x11b2,
- 0x1078, 0x1abc, 0x0078, 0x11b7, 0x71c4, 0xa182, 0x0010, 0x00c8,
- 0x11b2, 0x2011, 0x3541, 0x2204, 0x007e, 0x2112, 0x1078, 0x1a75,
- 0x017f, 0x0078, 0x11b9, 0x71c4, 0x2011, 0x1331, 0x20a9, 0x0008,
- 0x2204, 0xa106, 0x0040, 0x1323, 0x8210, 0x0070, 0x1321, 0x0078,
- 0x1318, 0x0078, 0x11b2, 0xa292, 0x1331, 0x027e, 0x2011, 0x3542,
- 0x2204, 0x2112, 0x017f, 0x007e, 0x1078, 0x1a81, 0x017f, 0x0078,
- 0x11b9, 0x03e8, 0x00fa, 0x01f4, 0x02ee, 0x0064, 0x0019, 0x0032,
- 0x004b, 0x2061, 0x3540, 0x610c, 0x6210, 0x70c4, 0x600e, 0x70c8,
- 0x6012, 0x0078, 0x11b8, 0x2061, 0x3540, 0x6114, 0x70c4, 0x6016,
- 0x0078, 0x11b9, 0x71c4, 0x2011, 0x0004, 0x2019, 0x1212, 0xa186,
- 0x0028, 0x0040, 0x1363, 0x2011, 0x0005, 0x2019, 0x1212, 0xa186,
- 0x0032, 0x0040, 0x1363, 0x2011, 0x0006, 0x2019, 0x1313, 0xa186,
- 0x003c, 0x00c0, 0x11b2, 0x2061, 0x3540, 0x6018, 0x007e, 0x611a,
- 0x23b8, 0x1078, 0x1a92, 0x1078, 0x33ba, 0x017f, 0x0078, 0x11b9,
- 0x71c4, 0xa184, 0xffcf, 0x00c0, 0x11b2, 0x2011, 0x3547, 0x2204,
- 0x2112, 0x007e, 0x1078, 0x1ab4, 0x017f, 0x0078, 0x11b9, 0x71c4,
- 0xa182, 0x0010, 0x00c8, 0x11b2, 0x2011, 0x3548, 0x2204, 0x007e,
- 0x2112, 0x1078, 0x1aa3, 0x017f, 0x0078, 0x11b9, 0x71c4, 0x72c8,
- 0xa184, 0xfffd, 0x00c0, 0x11b1, 0xa284, 0xfffd, 0x00c0, 0x11b1,
- 0x2100, 0x7908, 0x780a, 0x2200, 0x7a0c, 0x780e, 0x0078, 0x11b8,
- 0x71c4, 0x8107, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa0e8,
- 0x3600, 0x2019, 0x0000, 0x72c8, 0x6800, 0x007e, 0xa226, 0x0040,
- 0x13cf, 0x6a02, 0xa484, 0x2000, 0x0040, 0x13b8, 0xa39d, 0x0010,
- 0xa484, 0x1000, 0x0040, 0x13be, 0xa39d, 0x0008, 0xa484, 0x4000,
- 0x0040, 0x13cf, 0x810f, 0xa284, 0x4000, 0x0040, 0x13cb, 0x1078,
- 0x1ad6, 0x0078, 0x13cf, 0x1078, 0x1ac8, 0x0078, 0x13cf, 0x72cc,
- 0x82ff, 0x0040, 0x1401, 0x6808, 0xa206, 0x0040, 0x1401, 0xa2a4,
- 0x00ff, 0x2061, 0x3540, 0x6118, 0xa186, 0x0028, 0x0040, 0x13e8,
- 0xa186, 0x0032, 0x0040, 0x13ee, 0xa186, 0x003c, 0x0040, 0x13f4,
- 0xa482, 0x0064, 0x0048, 0x13fe, 0x0078, 0x13f8, 0xa482, 0x0050,
- 0x0048, 0x13fe, 0x0078, 0x13f8, 0xa482, 0x0043, 0x0048, 0x13fe,
- 0x71c4, 0x71c6, 0x027f, 0x72ca, 0x0078, 0x11b3, 0x6a0a, 0xa39d,
- 0x000a, 0x6804, 0xa305, 0x6806, 0x027f, 0x6b0c, 0x71c4, 0x0078,
- 0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000, 0x6a14, 0x6b1c,
- 0x2091, 0x8001, 0x70c8, 0x6816, 0x70cc, 0x681e, 0x2708, 0x0078,
- 0x11b7, 0x71c4, 0x72c8, 0x73cc, 0xa182, 0x0010, 0x00c8, 0x11b2,
- 0x1078, 0x1ae4, 0x0078, 0x11b7, 0x77c4, 0x1078, 0x1692, 0x2091,
- 0x8000, 0x6a08, 0xa295, 0x0002, 0x6a0a, 0x2091, 0x8001, 0x2708,
- 0x0078, 0x11b8, 0x77c4, 0x1078, 0x1692, 0x2091, 0x8000, 0x6a08,
- 0xa294, 0xfff9, 0x6a0a, 0x6804, 0xa005, 0x0040, 0x1441, 0x1078,
- 0x1a19, 0x2091, 0x8001, 0x2708, 0x0078, 0x11b8, 0x77c4, 0x1078,
- 0x1692, 0x2091, 0x8000, 0x6a08, 0xa295, 0x0004, 0x6a0a, 0x6804,
- 0xa005, 0x0040, 0x1455, 0x1078, 0x1a19, 0x2091, 0x8001, 0x2708,
- 0x0078, 0x11b8, 0x77c4, 0x2041, 0x0001, 0x2049, 0x0005, 0x2051,
- 0x0020, 0x2091, 0x8000, 0x1078, 0x169f, 0x2091, 0x8001, 0x2708,
- 0x6a08, 0x0078, 0x11b8, 0x77c4, 0x72c8, 0x73cc, 0x77c6, 0x72ca,
- 0x73ce, 0x1078, 0x1718, 0x00c0, 0x1489, 0x6818, 0xa005, 0x0040,
- 0x1483, 0x2708, 0x1078, 0x1af4, 0x00c0, 0x1483, 0x7817, 0xffff,
- 0x2091, 0x8001, 0x007c, 0x2091, 0x8001, 0x2001, 0x4005, 0x0078,
- 0x11bc, 0x2091, 0x8001, 0x0078, 0x11ba, 0x77c4, 0x77c6, 0x2041,
- 0x0021, 0x2049, 0x0005, 0x2051, 0x0020, 0x2091, 0x8000, 0x1078,
- 0x169f, 0x2061, 0x3540, 0x60a3, 0x0003, 0x67b6, 0x60a7, 0x0000,
- 0x7817, 0xffff, 0x2091, 0x8001, 0x1078, 0x1a19, 0x007c, 0x77c8,
- 0x77ca, 0x77c4, 0x77c6, 0xa7bc, 0xff00, 0x2091, 0x8000, 0x2061,
- 0x3540, 0x60a3, 0x0002, 0x60a7, 0x0000, 0x67b6, 0x7817, 0xffff,
- 0x1078, 0x1a19, 0x2091, 0x8001, 0x2041, 0x0021, 0x2049, 0x0004,
- 0x2051, 0x0010, 0x2091, 0x8000, 0x1078, 0x169f, 0x70c8, 0x6836,
- 0x8738, 0xa784, 0x0007, 0x00c0, 0x14c4, 0x2091, 0x8001, 0x007c,
- 0x7898, 0xa084, 0x0003, 0x00c0, 0x14f4, 0x2039, 0x0000, 0x2041,
- 0x0021, 0x2049, 0x0004, 0x2051, 0x0008, 0x1078, 0x1692, 0x2091,
- 0x8000, 0x6808, 0xa80d, 0x690a, 0x2091, 0x8001, 0x8738, 0xa784,
- 0x0007, 0x00c0, 0x14dd, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f,
- 0xa784, 0x0f00, 0x00c0, 0x14dd, 0x2091, 0x8000, 0x2069, 0x0100,
- 0x6830, 0xa084, 0x0040, 0x0040, 0x151d, 0x684b, 0x0004, 0x20a9,
- 0x0014, 0x6848, 0xa084, 0x0004, 0x0040, 0x150a, 0x0070, 0x150a,
- 0x0078, 0x1501, 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084,
- 0x0001, 0x0040, 0x1517, 0x0070, 0x1517, 0x0078, 0x150e, 0x20a9,
- 0x00fa, 0x0070, 0x151d, 0x0078, 0x1519, 0x2079, 0x3500, 0x7817,
- 0x0001, 0x2061, 0x3540, 0x60a3, 0x0001, 0x60a7, 0x0000, 0x60c3,
- 0x000f, 0x7898, 0xa085, 0x0002, 0x789a, 0x6808, 0xa084, 0xfffd,
- 0x680a, 0x681b, 0x0046, 0x2091, 0x8001, 0x007c, 0x7898, 0xa084,
- 0xfffd, 0x789a, 0xa084, 0x0001, 0x00c0, 0x1540, 0x1078, 0x1760,
- 0x71c4, 0x71c6, 0x794a, 0x007c, 0x74c4, 0x73c8, 0x72cc, 0x74c6,
- 0x73ca, 0x72ce, 0x2079, 0x3500, 0x2009, 0x0040, 0x1078, 0x166f,
- 0x0040, 0x1586, 0x1078, 0x163f, 0x0040, 0x155a, 0x1078, 0x1678,
- 0x0078, 0x1586, 0x6010, 0x2091, 0x8001, 0x7817, 0xffff, 0x2009,
- 0x3568, 0x200b, 0x0005, 0x8108, 0x200b, 0x0000, 0x8108, 0x230a,
- 0x8108, 0x220a, 0x8108, 0x240a, 0x8108, 0x200a, 0x8108, 0x200b,
- 0x0000, 0x8108, 0x2c0a, 0xa02e, 0x2530, 0x0e7e, 0x1078, 0x2f13,
- 0x0e7f, 0x6592, 0x65a2, 0x6696, 0x66a6, 0x60ab, 0x0000, 0x60af,
- 0x0000, 0x2091, 0x8001, 0x1078, 0x1a19, 0x007c, 0x70c3, 0x4005,
- 0x0078, 0x11bd, 0x71c4, 0x70c7, 0x0000, 0x7906, 0x0078, 0x11ba,
- 0x71c4, 0x71c6, 0x2168, 0x0078, 0x1597, 0x2069, 0x1000, 0x690c,
- 0xa016, 0x2d04, 0xa210, 0x8d68, 0x8109, 0x00c0, 0x1599, 0xa285,
- 0x0000, 0x00c0, 0x15a7, 0x70c3, 0x4000, 0x0078, 0x15a9, 0x70c3,
- 0x4003, 0x70ca, 0x0078, 0x11bd, 0x71c4, 0x72c8, 0x73cc, 0x2100,
- 0xa184, 0xfffc, 0x00c0, 0x11c6, 0x2100, 0x0079, 0x15b7, 0x15ce,
- 0x15e3, 0x15e5, 0x15e7, 0x70c3, 0x4003, 0x71ce, 0x72d2, 0x73d6,
- 0x0078, 0x15ca, 0x70c3, 0x4000, 0x70cf, 0x0000, 0x70d3, 0x0000,
- 0x70d7, 0x0000, 0x77c6, 0x71ca, 0x0078, 0x11ba, 0x2031, 0x15e9,
- 0x2624, 0x8630, 0x2412, 0x2204, 0xa446, 0x00c0, 0x15bb, 0xa484,
- 0xffff, 0x00c0, 0x15d0, 0x2031, 0x15e9, 0x8210, 0x8319, 0xa384,
- 0xffff, 0x00c0, 0x15d0, 0x0078, 0x15c2, 0x0078, 0x15c2, 0x0078,
- 0x15c2, 0x5555, 0xaaaa, 0xffff, 0x0000, 0x7960, 0x71c6, 0x71c4,
- 0xa182, 0x0003, 0x00c8, 0x11b2, 0x7962, 0x0078, 0x11ba, 0x7960,
- 0x71c6, 0x0078, 0x11ba, 0x7954, 0x71c6, 0x71c4, 0x7956, 0x7958,
- 0x71ca, 0x71c8, 0x795a, 0x795c, 0x71ce, 0x71cc, 0x795e, 0x0078,
- 0x11ba, 0x7954, 0x71c6, 0x7958, 0x71ca, 0x795c, 0x71ce, 0x0078,
- 0x11ba, 0x700c, 0xa084, 0x007f, 0x0040, 0x161d, 0x7007, 0x0004,
- 0x7004, 0xa084, 0x0004, 0x00c0, 0x1618, 0x7017, 0x0000, 0x7112,
- 0x721a, 0x731e, 0x8108, 0x810c, 0x81a9, 0x8c98, 0x20a1, 0x0030,
- 0x6080, 0x20a2, 0x53a6, 0x780c, 0xa085, 0x0000, 0x7002, 0x7007,
- 0x0001, 0x7108, 0x8104, 0x00c8, 0x1631, 0x7007, 0x0002, 0xa184,
- 0x000c, 0x710c, 0xa184, 0x0300, 0x7003, 0x0000, 0x007c, 0x700c,
- 0xa084, 0x007f, 0x0040, 0x164b, 0x7007, 0x0004, 0x7004, 0xa084,
- 0x0004, 0x00c0, 0x1646, 0x7017, 0x0000, 0x7112, 0x721a, 0x731e,
- 0x2099, 0x0030, 0x8108, 0x81ac, 0x780c, 0xa085, 0x0001, 0x7002,
- 0x7007, 0x0001, 0x7008, 0x800c, 0x00c8, 0x165a, 0x7007, 0x0002,
- 0xa08c, 0x000c, 0x00c0, 0x166c, 0x710c, 0xa184, 0x0300, 0x00c0,
- 0x166c, 0x2ca0, 0x53a5, 0xa006, 0x7003, 0x0000, 0x007c, 0x7850,
- 0xa065, 0x0040, 0x1677, 0x2c04, 0x7852, 0x2063, 0x0000, 0x007c,
- 0x0f7e, 0x2079, 0x3500, 0x7850, 0x2062, 0x2c00, 0x7852, 0x0f7f,
- 0x007c, 0x2011, 0x4000, 0x7a52, 0x2019, 0x0410, 0x8319, 0x0040,
- 0x168f, 0xa280, 0x002f, 0x2012, 0x2010, 0x0078, 0x1686, 0x2013,
- 0x0000, 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003,
- 0x8003, 0x8003, 0x8003, 0xa105, 0xa0e8, 0x3680, 0x007c, 0x1078,
- 0x1692, 0x2900, 0x682a, 0x2a00, 0x682e, 0x6808, 0xa084, 0xffef,
- 0xa80d, 0x690a, 0x2009, 0x354f, 0x210c, 0x6804, 0xa005, 0x0040,
- 0x16bc, 0xa116, 0x00c0, 0x16bc, 0x2060, 0x6000, 0x6806, 0x017e,
- 0x200b, 0x0000, 0x0078, 0x16bf, 0x2009, 0x0000, 0x017e, 0x6804,
- 0xa065, 0x0040, 0x16ce, 0x6000, 0x6806, 0x1078, 0x16df, 0x1078,
- 0x17cb, 0x6810, 0x8001, 0x6812, 0x00c0, 0x16bf, 0x017f, 0x6902,
- 0x6906, 0x007c, 0xa065, 0x0040, 0x16de, 0x6098, 0x609b, 0x0000,
- 0x2008, 0x1078, 0x1678, 0x2100, 0x0078, 0x16d2, 0x007c, 0x6003,
- 0x0103, 0x20a9, 0x001c, 0xac80, 0x0004, 0x20a0, 0x2001, 0x0000,
- 0x40a4, 0x6828, 0x6016, 0x682c, 0x601e, 0x007c, 0x0e7e, 0x2071,
- 0x3540, 0x7040, 0xa08c, 0x0080, 0x00c0, 0x16fc, 0xa088, 0x3580,
- 0x2d0a, 0x8000, 0x7042, 0xa006, 0x0e7f, 0x007c, 0x0e7e, 0x2071,
- 0x3540, 0x2009, 0x3580, 0x7240, 0x8221, 0x8211, 0x0048, 0x1716,
- 0x2104, 0x8108, 0xad06, 0x00c0, 0x1705, 0x8119, 0x211e, 0x8108,
- 0x8318, 0x8211, 0x00c8, 0x170e, 0x7442, 0xa006, 0x0e7f, 0x007c,
- 0x1078, 0x1692, 0x2091, 0x8000, 0x6804, 0x781e, 0xa065, 0x0040,
- 0x175f, 0x0078, 0x1729, 0x2c00, 0x781e, 0x6000, 0xa065, 0x0040,
- 0x175f, 0x600c, 0xa306, 0x00c0, 0x1723, 0x6008, 0xa206, 0x00c0,
- 0x1723, 0x2c28, 0x2001, 0x354f, 0x2004, 0xac06, 0x0040, 0x175f,
- 0x6804, 0xac06, 0x00c0, 0x1746, 0x6000, 0x2060, 0x6806, 0xa005,
- 0x00c0, 0x1746, 0x6803, 0x0000, 0x0078, 0x1750, 0x6400, 0x781c,
- 0x2060, 0x6402, 0xa486, 0x0000, 0x00c0, 0x1750, 0x2c00, 0x6802,
- 0x2560, 0x1078, 0x16df, 0x6017, 0x0005, 0x601f, 0x0020, 0x1078,
- 0x17cb, 0x6810, 0x8001, 0x6812, 0x2001, 0xffff, 0xa005, 0x007c,
- 0x2039, 0x0000, 0x2041, 0x0021, 0x2049, 0x0004, 0x2051, 0x0008,
- 0x2091, 0x8000, 0x1078, 0x169f, 0x8738, 0xa784, 0x0007, 0x00c0,
- 0x176a, 0xa7bc, 0xff00, 0x873f, 0x8738, 0x873f, 0xa784, 0x0f00,
- 0x00c0, 0x176a, 0x2091, 0x8001, 0x007c, 0x2061, 0x0000, 0x6018,
- 0xa084, 0x0001, 0x00c0, 0x178a, 0x78ac, 0x78af, 0x0000, 0xa005,
- 0x00c0, 0x178b, 0x007c, 0xa08c, 0xfff0, 0x0040, 0x1791, 0x1078,
- 0x1ba5, 0x0079, 0x1793, 0x17a3, 0x17a5, 0x17ab, 0x17af, 0x17a3,
- 0x17b3, 0x17a3, 0x17a3, 0x17a3, 0x17a3, 0x17b9, 0x17bd, 0x17a3,
- 0x17a3, 0x17a3, 0x17a3, 0x1078, 0x1ba5, 0x1078, 0x1760, 0x2001,
- 0x8001, 0x0078, 0x17c3, 0x2001, 0x8003, 0x0078, 0x17c3, 0x2001,
- 0x8004, 0x0078, 0x17c3, 0x1078, 0x1760, 0x2001, 0x8006, 0x0078,
- 0x17c3, 0x2001, 0x800c, 0x0078, 0x17c3, 0x1078, 0x1760, 0x2001,
- 0x800d, 0x0078, 0x17c3, 0x70c2, 0x2061, 0x0000, 0x601b, 0x0001,
- 0x2091, 0x4080, 0x007c, 0x2c04, 0x6082, 0x2c08, 0x2063, 0x0000,
- 0x7864, 0x8000, 0x7866, 0x7868, 0xa005, 0x796a, 0x0040, 0x17db,
- 0x2c02, 0x0078, 0x17dc, 0x796e, 0x007c, 0x0c7e, 0x2061, 0x3500,
- 0x6883, 0x0103, 0x2d08, 0x206b, 0x0000, 0x6064, 0x8000, 0x6066,
- 0x6068, 0xa005, 0x616a, 0x0040, 0x17f0, 0x2d02, 0x0078, 0x17f1,
- 0x616e, 0x0c7f, 0x007c, 0x1078, 0x1804, 0x0040, 0x1803, 0x0c7e,
- 0x6098, 0xa065, 0x0040, 0x17fe, 0x1078, 0x16d2, 0x0c7f, 0x609b,
- 0x0000, 0x1078, 0x1678, 0x007c, 0x786c, 0xa065, 0x0040, 0x1816,
- 0x2091, 0x8000, 0x7864, 0x8001, 0x7866, 0x2c04, 0x786e, 0xa005,
- 0x00c0, 0x1814, 0x786a, 0x8000, 0x2091, 0x8001, 0x007c, 0x7898,
- 0xa005, 0x00c0, 0x1865, 0x7974, 0x70d0, 0x0005, 0x0005, 0x72d0,
- 0xa206, 0x00c0, 0x181c, 0x2200, 0xa106, 0x00c0, 0x1833, 0x7804,
- 0xa005, 0x0040, 0x1865, 0x7807, 0x0000, 0x0068, 0x1865, 0x2091,
- 0x4080, 0x0078, 0x1865, 0x1078, 0x166f, 0x0040, 0x1865, 0x7a7c,
- 0x7b78, 0x8107, 0x8004, 0x8004, 0xa210, 0xa399, 0x0000, 0x2009,
- 0x0040, 0x1078, 0x163f, 0x0040, 0x185c, 0x1078, 0x1678, 0x7880,
- 0x8000, 0x7882, 0xa086, 0x0002, 0x00c0, 0x1865, 0x2091, 0x8000,
- 0x78af, 0x0002, 0x7883, 0x0000, 0x7898, 0xa085, 0x0003, 0x789a,
- 0x2091, 0x8001, 0x0078, 0x1865, 0x7883, 0x0000, 0x1078, 0x1992,
- 0x6000, 0xa084, 0x0007, 0x0079, 0x1866, 0x007c, 0x186e, 0x187d,
- 0x189d, 0x186e, 0x18af, 0x186e, 0x186e, 0x186e, 0x2039, 0x0400,
- 0x78a8, 0xa705, 0x78aa, 0x6004, 0xa705, 0x6006, 0x1078, 0x18ed,
- 0x6018, 0x78a6, 0x1078, 0x197a, 0x007c, 0x78a8, 0xa084, 0x0100,
- 0x0040, 0x1884, 0x0078, 0x186e, 0x78ab, 0x0000, 0x6000, 0x8007,
- 0xa084, 0x00ff, 0x789e, 0x8001, 0x609b, 0x0000, 0x0040, 0x189a,
- 0x1078, 0x18ed, 0x0040, 0x189a, 0x78a8, 0xa085, 0x0100, 0x78aa,
- 0x0078, 0x189c, 0x1078, 0x1911, 0x007c, 0x78a8, 0xa08c, 0x0e00,
- 0x00c0, 0x18a6, 0xa084, 0x0100, 0x00c0, 0x18a8, 0x0078, 0x186e,
- 0x1078, 0x18ed, 0x00c0, 0x18ae, 0x1078, 0x1911, 0x007c, 0x78a8,
- 0xa084, 0x0100, 0x0040, 0x18b6, 0x0078, 0x186e, 0x78ab, 0x0000,
- 0x6710, 0x20a9, 0x0001, 0x6014, 0xa084, 0x00ff, 0xa005, 0x0040,
- 0x18d3, 0xa7bc, 0xff00, 0x20a9, 0x0008, 0xa08e, 0x0001, 0x0040,
- 0x18d3, 0x2039, 0x0000, 0x20a9, 0x0080, 0xa08e, 0x0002, 0x0040,
- 0x18d3, 0x0078, 0x18ea, 0x1078, 0x1692, 0x2d00, 0x2091, 0x8000,
- 0x682b, 0x0000, 0x682f, 0x0000, 0x6808, 0xa084, 0xffde, 0x680a,
- 0x2d00, 0xa080, 0x0010, 0x2068, 0x2091, 0x8001, 0x0070, 0x18ea,
- 0x0078, 0x18d6, 0x1078, 0x1678, 0x007c, 0x78a0, 0xa06d, 0x00c0,
- 0x18f8, 0x2c00, 0x78a2, 0x78a6, 0x609b, 0x0000, 0x0078, 0x1904,
- 0x2c00, 0x689a, 0x609b, 0x0000, 0x78a2, 0x2d00, 0x6002, 0x78a4,
- 0xad06, 0x00c0, 0x1904, 0x6002, 0x789c, 0x8001, 0x789e, 0x00c0,
- 0x1910, 0x78a8, 0xa084, 0x0000, 0x78aa, 0x78a4, 0x2060, 0xa006,
- 0x007c, 0xa02e, 0x2530, 0x6118, 0xa184, 0x0060, 0x619e, 0x0040,
- 0x191d, 0x0e7e, 0x1078, 0x2f13, 0x0e7f, 0x6592, 0x65a2, 0x6696,
- 0x66a6, 0x60ab, 0x0000, 0x60af, 0x0000, 0x6710, 0x1078, 0x1692,
- 0x2091, 0x8000, 0x6808, 0xa084, 0x0001, 0x0040, 0x193f, 0x2091,
- 0x8001, 0x1078, 0x16df, 0x2091, 0x8000, 0x1078, 0x17cb, 0x2091,
- 0x8001, 0x78a3, 0x0000, 0x78a7, 0x0000, 0x0078, 0x1979, 0x6020,
- 0xa096, 0x0001, 0x00c0, 0x1946, 0x8000, 0x6022, 0x6a10, 0x6814,
- 0x2091, 0x8001, 0xa202, 0x0048, 0x1955, 0x0040, 0x1955, 0x2039,
- 0x0200, 0x1078, 0x197a, 0x0078, 0x1979, 0x2c08, 0x2091, 0x8000,
- 0x6800, 0xa065, 0x0040, 0x195d, 0x6102, 0x6902, 0x00c0, 0x1961,
- 0x6906, 0x2160, 0x6003, 0x0000, 0x6810, 0x8000, 0x6812, 0x2091,
- 0x8001, 0x6808, 0xa08c, 0x0040, 0x0040, 0x1973, 0xa086, 0x0040,
- 0x680a, 0x1078, 0x16ee, 0x1078, 0x1a19, 0x78a7, 0x0000, 0x78a3,
- 0x0000, 0x007c, 0x6004, 0xa705, 0x6006, 0x2091, 0x8000, 0x1078,
- 0x17cb, 0x2091, 0x8001, 0x78a4, 0xa065, 0x0040, 0x198d, 0x6098,
- 0x78a6, 0x609b, 0x0000, 0x0078, 0x197d, 0x78a3, 0x0000, 0x78a7,
- 0x0000, 0x007c, 0x7970, 0x7874, 0x8000, 0xa10a, 0x00c8, 0x1999,
- 0xa006, 0x7876, 0x70d2, 0x7804, 0xa005, 0x0040, 0x19a7, 0x8001,
- 0x7806, 0x00c0, 0x19a7, 0x0068, 0x19a7, 0x2091, 0x4080, 0x007c,
- 0x0068, 0x19c2, 0x2029, 0x0000, 0x786c, 0xa065, 0x0040, 0x19bd,
- 0x1078, 0x19c3, 0x0040, 0x19bd, 0x057e, 0x1078, 0x19d9, 0x057f,
- 0x00c0, 0x19bd, 0x8528, 0x0078, 0x19ac, 0x85ff, 0x0040, 0x19c2,
- 0x2091, 0x4080, 0x007c, 0x7b84, 0x7988, 0x72d4, 0x0005, 0x0005,
- 0x70d4, 0xa206, 0x00c0, 0x19c5, 0x2200, 0xa102, 0x00c0, 0x19d3,
- 0x2300, 0xa005, 0x007c, 0x0048, 0x19d7, 0xa302, 0x007c, 0x8002,
- 0x007c, 0x1078, 0x1a0b, 0x2009, 0x001c, 0x6024, 0xa005, 0x0040,
- 0x19e3, 0x2009, 0x0040, 0x1078, 0x1611, 0x0040, 0x19fc, 0x7894,
- 0x8000, 0x7896, 0xa086, 0x0002, 0x00c0, 0x1a0a, 0x2091, 0x8000,
- 0x78af, 0x0003, 0x7897, 0x0000, 0x7898, 0xa085, 0x0300, 0x789a,
- 0x2091, 0x8001, 0x0078, 0x1a0a, 0x7897, 0x0000, 0x1078, 0x17f3,
- 0x7984, 0x7888, 0x8000, 0xa10a, 0x00c8, 0x1a07, 0xa006, 0x788a,
- 0x70d6, 0xa006, 0x007c, 0x8107, 0x8004, 0x8004, 0x7a90, 0x7b8c,
- 0xa210, 0xa399, 0x0000, 0x007c, 0x2009, 0x3568, 0x2091, 0x8000,
- 0x200a, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540, 0x2091, 0x8000,
- 0x2104, 0xa086, 0x0000, 0x00c0, 0x1a34, 0x2009, 0x3512, 0x2104,
- 0xa005, 0x00c0, 0x1a34, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x1a34,
- 0x0018, 0x1a34, 0x781b, 0x0044, 0x2091, 0x8001, 0x0f7f, 0x007c,
- 0x127e, 0x2091, 0x2300, 0x2071, 0x3540, 0x2079, 0x0100, 0x2019,
- 0x2dd8, 0x20a1, 0x012b, 0x2304, 0xa005, 0x0040, 0x1a50, 0x789a,
- 0x8318, 0x23ac, 0x8318, 0x2398, 0x53a6, 0x3318, 0x0078, 0x1a43,
- 0x789b, 0x0020, 0x20a9, 0x0010, 0x78af, 0x0000, 0x78af, 0x0220,
- 0x0070, 0x1a5c, 0x0078, 0x1a54, 0x7003, 0x0000, 0x1078, 0x1b5b,
- 0x7004, 0xa084, 0x000f, 0xa085, 0x6280, 0x7806, 0x780f, 0x9200,
- 0x7843, 0x00d8, 0x7853, 0x0080, 0x780b, 0x0038, 0x7047, 0x357f,
- 0x7043, 0x0000, 0x127f, 0x2000, 0x007c, 0xa18c, 0x000f, 0x2011,
- 0x0101, 0x2204, 0xa084, 0xfff0, 0xa105, 0x2012, 0x1078, 0x1b5b,
- 0x007c, 0x2011, 0x0101, 0x20a9, 0x0009, 0x810b, 0x0070, 0x1a8a,
- 0x0078, 0x1a85, 0xa18c, 0x0e00, 0x2204, 0xa084, 0xf1ff, 0xa105,
- 0x2012, 0x007c, 0x2009, 0x0101, 0x20a9, 0x0005, 0x8213, 0x0070,
- 0x1a9b, 0x0078, 0x1a96, 0xa294, 0x00e0, 0x2104, 0xa084, 0xff1f,
- 0xa205, 0x200a, 0x007c, 0x2011, 0x0101, 0x20a9, 0x000c, 0x810b,
- 0x0070, 0x1aac, 0x0078, 0x1aa7, 0xa18c, 0xf000, 0x2204, 0xa084,
- 0x0fff, 0xa105, 0x2012, 0x007c, 0x2011, 0x0102, 0x2204, 0xa084,
- 0xffcf, 0xa105, 0x2012, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020,
- 0x0c7e, 0x2061, 0x0100, 0x609a, 0x62ac, 0x63ac, 0x0c7f, 0x007c,
- 0x8103, 0x8003, 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a,
- 0x60a4, 0xa084, 0xffdf, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003,
- 0xa080, 0x0022, 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0xa085,
- 0x0020, 0x60ae, 0x0c7f, 0x007c, 0x8103, 0x8003, 0xa080, 0x0020,
- 0x0c7e, 0x2061, 0x0100, 0x609a, 0x60a4, 0x62ae, 0x2010, 0x60a4,
- 0x63ae, 0x2018, 0x0c7f, 0x007c, 0x2091, 0x8000, 0x0c7e, 0x0e7e,
- 0x6818, 0xa005, 0x0040, 0x1b39, 0x2061, 0x3f80, 0x1078, 0x1b41,
- 0x0040, 0x1b27, 0x20a9, 0x0000, 0x2061, 0x3e80, 0x0c7e, 0x1078,
- 0x1b41, 0x0040, 0x1b13, 0x0c7f, 0x8c60, 0x0070, 0x1b11, 0x0078,
- 0x1b06, 0x0078, 0x1b39, 0x007f, 0xa082, 0x3e80, 0x2071, 0x3540,
- 0x70ba, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6, 0x60a7, 0x0000,
- 0x2001, 0x0004, 0x70a2, 0x1078, 0x1a14, 0x0078, 0x1b35, 0x2071,
- 0x3540, 0x601c, 0xa085, 0x0800, 0x601e, 0x71b6, 0x60a7, 0x0000,
- 0x2001, 0x0006, 0x70a2, 0x1078, 0x1a14, 0x2001, 0x0000, 0x0078,
- 0x1b3b, 0x2001, 0x0001, 0x2091, 0x8001, 0xa005, 0x0e7f, 0x0c7f,
- 0x007c, 0x2c04, 0xa005, 0x0040, 0x1b58, 0x2060, 0x600c, 0xa306,
- 0x00c0, 0x1b55, 0x6008, 0xa206, 0x00c0, 0x1b55, 0x6010, 0xa106,
- 0x00c0, 0x1b55, 0xa006, 0x0078, 0x1b5a, 0x6000, 0x0078, 0x1b42,
- 0xa085, 0x0001, 0x007c, 0x2011, 0x3541, 0x220c, 0xa18c, 0x000f,
- 0x2011, 0x013b, 0x2204, 0xa084, 0x0100, 0x0040, 0x1b6a, 0x2021,
- 0xff80, 0x2122, 0x007c, 0x0e7e, 0x68e4, 0xa08c, 0x0020, 0x0040,
- 0x1ba3, 0xa084, 0x0006, 0x00c0, 0x1ba3, 0x6010, 0x8007, 0xa084,
- 0x000f, 0x8003, 0x8003, 0x8003, 0xa0f0, 0x3600, 0x7004, 0xa084,
- 0x000a, 0x00c0, 0x1ba3, 0x7108, 0xa194, 0xff00, 0x0040, 0x1ba3,
- 0xa18c, 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, 0x1b96, 0x2001,
- 0x0032, 0xa106, 0x0040, 0x1b9a, 0x0078, 0x1b9e, 0x2009, 0x0020,
- 0x0078, 0x1ba0, 0x2009, 0x003f, 0x0078, 0x1ba0, 0x2011, 0x0000,
- 0x2100, 0xa205, 0x700a, 0x0e7f, 0x007c, 0x0068, 0x1ba5, 0x007e,
- 0x2071, 0x0000, 0x7018, 0xa084, 0x0001, 0x00c0, 0x1baa, 0x007f,
- 0x2e08, 0x2071, 0x0010, 0x70ca, 0x007f, 0x70c6, 0x70c3, 0x8002,
- 0x2071, 0x0000, 0x701b, 0x0001, 0x2091, 0x4080, 0x007f, 0x2070,
- 0x007f, 0x0078, 0x1bc1, 0x107e, 0x007e, 0x127e, 0x2091, 0x2300,
- 0x7f3c, 0x7e58, 0x7c30, 0x7d38, 0xa594, 0x003f, 0xa484, 0x4000,
- 0x0040, 0x1bd8, 0xa784, 0x007c, 0x00c0, 0x2d9c, 0x1078, 0x1ba5,
- 0xa49c, 0x000f, 0xa382, 0x0004, 0x0050, 0x1be0, 0x1078, 0x1ba5,
- 0x8507, 0xa084, 0x000f, 0x0079, 0x1be5, 0x1fea, 0x209a, 0x20c0,
- 0x22e6, 0x256b, 0x25b3, 0x25ea, 0x2665, 0x26bf, 0x2744, 0x1c0b,
- 0x1bf5, 0x1e53, 0x1f1d, 0x254a, 0x1bf5, 0x1078, 0x1ba5, 0x0018,
- 0x1bc8, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c, 0x7003,
- 0x0000, 0x703f, 0x0000, 0x7030, 0xa005, 0x0040, 0x1c09, 0x7033,
- 0x0000, 0x0018, 0x1bc8, 0x705c, 0xa005, 0x00c0, 0x1cb6, 0x70a0,
- 0xa084, 0x0007, 0x0079, 0x1c14, 0x1cd6, 0x1c1c, 0x1c2a, 0x1c4b,
- 0x1c71, 0x1c9d, 0x1c9b, 0x1c1c, 0x7808, 0xa084, 0xfffd, 0x780a,
- 0x2009, 0x0046, 0x1078, 0x2412, 0x00c0, 0x1c28, 0x7003, 0x0004,
- 0x0078, 0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c49, 0x70b4, 0x8007,
- 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0x78ab, 0x000c, 0x789b,
- 0x0060, 0x78ab, 0x0001, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078,
- 0x2410, 0x00c0, 0x1c49, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033,
- 0x3570, 0x0078, 0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c6f, 0x71b4,
- 0x8107, 0x789b, 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, 0x0007,
- 0xa18d, 0x00c0, 0x79aa, 0x78ab, 0x0006, 0x789b, 0x0060, 0x78ab,
- 0x0002, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078, 0x2410, 0x00c0,
- 0x1c6f, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033, 0x3570, 0x0078,
- 0x1bf7, 0x1078, 0x2d5e, 0x00c0, 0x1c99, 0x71b4, 0x8107, 0x789b,
- 0x007e, 0x78aa, 0x789b, 0x0010, 0xa18c, 0x0007, 0xa18d, 0x00c0,
- 0x79aa, 0x78ab, 0x0020, 0x71b8, 0x79aa, 0x78ab, 0x000d, 0x789b,
- 0x0060, 0x78ab, 0x0004, 0x785b, 0x0004, 0x2009, 0x00f7, 0x1078,
- 0x2410, 0x00c0, 0x1c99, 0x7003, 0x0004, 0x70c3, 0x000f, 0x7033,
- 0x3570, 0x0078, 0x1bf7, 0x0078, 0x1c4b, 0x1078, 0x2d5e, 0x00c0,
- 0x1bf7, 0x70bc, 0x2068, 0x789b, 0x0010, 0x6f10, 0x1078, 0x2ca1,
- 0x2c50, 0x6810, 0xa084, 0x0007, 0xa085, 0x0080, 0x78aa, 0x6e18,
- 0x2041, 0x0001, 0x2001, 0x0004, 0x0078, 0x1dde, 0x1078, 0x2d5e,
- 0x00c0, 0x1bf7, 0x789b, 0x0010, 0x705c, 0x2068, 0x6f10, 0x1078,
- 0x2ca1, 0x2c50, 0x6008, 0xa085, 0x0010, 0x600a, 0x6810, 0xa084,
- 0x0007, 0xa085, 0x0080, 0x78aa, 0x2031, 0x0020, 0x2041, 0x0001,
- 0x1078, 0x2dc5, 0x2001, 0x0003, 0x0078, 0x1dc9, 0x0018, 0x1bc8,
- 0x7440, 0xa485, 0x0000, 0x0040, 0x1cf0, 0xa080, 0x3580, 0x2030,
- 0x7144, 0x8108, 0xa12a, 0x0048, 0x1ce7, 0x2009, 0x3580, 0x2164,
- 0x6504, 0x85ff, 0x00c0, 0x1cfd, 0x8421, 0x00c0, 0x1ce1, 0x7146,
- 0x7003, 0x0000, 0x703f, 0x0000, 0x0078, 0x1bf7, 0x7640, 0xa6b0,
- 0x3580, 0x7144, 0x2600, 0x0078, 0x1cec, 0x7146, 0x2568, 0x2558,
- 0x753e, 0x2c50, 0x6034, 0xa085, 0x0000, 0x00c0, 0x1cfa, 0x6708,
- 0x7736, 0xa784, 0x013f, 0x0040, 0x1d2f, 0xa784, 0x0021, 0x00c0,
- 0x1cfa, 0xa784, 0x0002, 0x0040, 0x1d1c, 0xa784, 0x0004, 0x0040,
- 0x1cfa, 0xa7bc, 0xfffb, 0x670a, 0xa784, 0x0008, 0x00c0, 0x1cfa,
- 0xa784, 0x0010, 0x00c0, 0x1cfa, 0xa784, 0x0100, 0x0040, 0x1d2f,
- 0x6018, 0xa005, 0x00c0, 0x1cfa, 0xa7bc, 0xfeff, 0x670a, 0x681f,
- 0x0000, 0x6e18, 0xa684, 0x000e, 0x6118, 0x0040, 0x1d3f, 0x601c,
- 0xa102, 0x0048, 0x1d42, 0x0040, 0x1d42, 0x0078, 0x1cf6, 0x81ff,
- 0x00c0, 0x1cf6, 0xa784, 0x0080, 0x00c0, 0x1d48, 0x700c, 0x6022,
- 0xa7bc, 0xff7f, 0x670a, 0x6b10, 0x8307, 0xa084, 0x000f, 0x8003,
- 0x8003, 0x8003, 0xa080, 0x3600, 0x2060, 0x2048, 0x704a, 0x6000,
- 0x704e, 0x6004, 0x7052, 0x2a60, 0x0018, 0x1bc8, 0x789b, 0x0010,
- 0xa046, 0x1078, 0x2d5e, 0x00c0, 0x1bf7, 0x6b10, 0xa39c, 0x0007,
- 0xa39d, 0x00c0, 0x704c, 0xa084, 0x8000, 0x0040, 0x1d73, 0xa684,
- 0x0001, 0x0040, 0x1d75, 0xa39c, 0xffbf, 0xa684, 0x0010, 0x0040,
- 0x1d7b, 0xa39d, 0x0020, 0x7baa, 0x8840, 0xa684, 0x000e, 0x00c0,
- 0x1d86, 0xa7bd, 0x0010, 0x670a, 0x0078, 0x1dc7, 0x714c, 0xa18c,
- 0x0800, 0x0040, 0x2902, 0x2011, 0x0021, 0x8004, 0x8004, 0x0048,
- 0x1d9d, 0x2011, 0x0022, 0x8004, 0x0048, 0x1d9d, 0x2011, 0x0020,
- 0x8004, 0x0048, 0x1d9d, 0x0040, 0x1dc7, 0x7aaa, 0x8840, 0x1078,
- 0x2d77, 0x6a10, 0x610c, 0x8108, 0xa18c, 0x00ff, 0xa1e0, 0x3e80,
- 0x2c64, 0x8cff, 0x0040, 0x1dbe, 0x6010, 0xa206, 0x00c0, 0x1da8,
- 0x60b4, 0x8001, 0x60b6, 0x00c0, 0x1da3, 0x0c7e, 0x2a60, 0x6008,
- 0xa085, 0x0100, 0x600a, 0x0c7f, 0x0078, 0x1cd6, 0x1078, 0x2d5e,
- 0x00c0, 0x1bf7, 0x2a60, 0x610e, 0x79aa, 0x8840, 0x712e, 0x2001,
- 0x0001, 0x007e, 0x7150, 0xa184, 0x0018, 0x0040, 0x1ddd, 0xa184,
- 0x0010, 0x0040, 0x1dd7, 0x1078, 0x2acc, 0x00c0, 0x1ddd, 0xa184,
- 0x0008, 0x0040, 0x1ddd, 0x1078, 0x29e6, 0x007f, 0x7002, 0xa68c,
- 0x0060, 0x88ff, 0x0040, 0x1de6, 0xa18d, 0x0004, 0x795a, 0x69b2,
- 0x789b, 0x0060, 0x2800, 0x78aa, 0x789b, 0x0061, 0x6814, 0xa085,
- 0x8000, 0x6816, 0x78aa, 0x157e, 0x137e, 0x147e, 0x20a1, 0x012c,
- 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000a, 0x2098, 0x53a6,
- 0x147f, 0x137f, 0x157f, 0x6810, 0x8007, 0x789b, 0x007e, 0x78aa,
- 0x6d90, 0x7dd6, 0x7dde, 0x6e94, 0x7ed2, 0x7eda, 0x7830, 0xa084,
- 0x00c0, 0x00c0, 0x1e15, 0x0098, 0x1e1d, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x1078, 0x2d77, 0x0078, 0x1bff, 0x7200, 0xa284, 0x0007,
- 0xa086, 0x0001, 0x00c0, 0x1e2a, 0x781b, 0x0049, 0x1078, 0x2d77,
- 0x0078, 0x1e3b, 0x6ab0, 0xa295, 0x2000, 0x7a5a, 0x781b, 0x0049,
- 0x1078, 0x2d77, 0x7200, 0x2500, 0xa605, 0x0040, 0x1e3b, 0xa284,
- 0x0007, 0x1079, 0x1e49, 0xad80, 0x0008, 0x7032, 0xa284, 0x0007,
- 0xa086, 0x0001, 0x00c0, 0x1e47, 0x6018, 0x8000, 0x601a, 0x0078,
- 0x1bf7, 0x1e51, 0x30f0, 0x30f0, 0x30df, 0x30f0, 0x1e51, 0x1e51,
- 0x1e51, 0x1078, 0x1ba5, 0x7808, 0xa084, 0xfffd, 0x780a, 0x0f7e,
- 0x2079, 0x3500, 0x7898, 0x0f7f, 0xa084, 0x0001, 0x0040, 0x1e79,
- 0x70a0, 0xa086, 0x0001, 0x00c0, 0x1e68, 0x70a2, 0x0078, 0x1f01,
- 0x70a0, 0xa086, 0x0005, 0x00c0, 0x1e77, 0x70bc, 0x2068, 0x6817,
- 0x0004, 0x6813, 0x0000, 0x681c, 0xa085, 0x0008, 0x681e, 0x70a3,
- 0x0000, 0x157e, 0x2011, 0x0004, 0x71a0, 0xa186, 0x0001, 0x0040,
- 0x1e9b, 0xa186, 0x0007, 0x00c0, 0x1e8b, 0x2009, 0x352b, 0x200b,
- 0x0005, 0x0078, 0x1e9b, 0x2009, 0x3513, 0x2104, 0x2009, 0x3512,
- 0x200a, 0x2009, 0x352b, 0x200b, 0x0001, 0x70a3, 0x0000, 0x70a7,
- 0x0001, 0x0078, 0x1e9d, 0x70a3, 0x0000, 0x1078, 0x2ec7, 0x20a9,
- 0x0010, 0x2039, 0x0000, 0x1078, 0x2ba6, 0xa7b8, 0x0100, 0x0070,
- 0x1eab, 0x0078, 0x1ea3, 0x7000, 0x2020, 0x0079, 0x1eaf, 0x1edd,
- 0x1ec6, 0x1ec6, 0x1eb9, 0x1edd, 0x1edd, 0x1eb7, 0x1eb7, 0x1078,
- 0x1ba5, 0x2021, 0x3557, 0x2404, 0xa005, 0x0040, 0x1ec6, 0xad06,
- 0x00c0, 0x1ec6, 0x6800, 0x2022, 0x0078, 0x1ed6, 0x681c, 0xa084,
- 0x0001, 0x00c0, 0x1ed2, 0x6f10, 0x1078, 0x2ca1, 0x1078, 0x28d9,
- 0x0078, 0x1ed6, 0x7054, 0x2060, 0x6800, 0x6002, 0x6a16, 0x681c,
- 0xa085, 0x0008, 0x681e, 0x1078, 0x17dd, 0x2021, 0x3f80, 0x1078,
- 0x1f07, 0x2021, 0x3557, 0x1078, 0x1f07, 0x20a9, 0x0000, 0x2021,
- 0x3e80, 0x1078, 0x1f07, 0x8420, 0x0070, 0x1ef0, 0x0078, 0x1ee9,
- 0x20a9, 0x0080, 0x2061, 0x3680, 0x6018, 0x6110, 0xa102, 0x6012,
- 0x601b, 0x0000, 0xace0, 0x0010, 0x0070, 0x1f00, 0x0078, 0x1ef4,
- 0x157f, 0x7003, 0x0000, 0x703f, 0x0000, 0x0078, 0x1bf7, 0x047e,
- 0x2404, 0xa005, 0x0040, 0x1f19, 0x2068, 0x6800, 0x007e, 0x6a16,
- 0x681c, 0xa085, 0x0008, 0x681e, 0x1078, 0x17dd, 0x007f, 0x0078,
- 0x1f09, 0x047f, 0x2023, 0x0000, 0x007c, 0xa282, 0x0003, 0x0050,
- 0x1f23, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x1f26, 0x1f29, 0x1f9c,
- 0x1faa, 0xa282, 0x0002, 0x0040, 0x1f2f, 0x1078, 0x1ba5, 0x70a0,
- 0x70a3, 0x0000, 0x70c3, 0x0000, 0x0079, 0x1f36, 0x1f3e, 0x1f3e,
- 0x1f40, 0x1f74, 0x2908, 0x1f3e, 0x1f74, 0x1f3e, 0x1078, 0x1ba5,
- 0x77b4, 0x1078, 0x2ba6, 0x77b4, 0xa7bc, 0x0f00, 0x1078, 0x2ca1,
- 0x6018, 0xa005, 0x0040, 0x1f6b, 0x2021, 0x3f80, 0x2009, 0x0004,
- 0x2011, 0x0010, 0x1078, 0x1fc5, 0x0040, 0x1f6b, 0x157e, 0x20a9,
- 0x0000, 0x2021, 0x3e80, 0x047e, 0x2009, 0x0004, 0x2011, 0x0010,
- 0x1078, 0x1fc5, 0x047f, 0x0040, 0x1f6a, 0x8420, 0x0070, 0x1f6a,
- 0x0078, 0x1f5b, 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, 0x1f46,
- 0x0078, 0x1bff, 0x0078, 0x1bff, 0x77b4, 0x1078, 0x2ca1, 0x6018,
- 0xa005, 0x0040, 0x1f9a, 0x2021, 0x3f80, 0x2009, 0x0005, 0x2011,
- 0x0020, 0x1078, 0x1fc5, 0x0040, 0x1f9a, 0x157e, 0x20a9, 0x0000,
- 0x2021, 0x3e80, 0x047e, 0x2009, 0x0005, 0x2011, 0x0020, 0x1078,
- 0x1fc5, 0x047f, 0x0040, 0x1f99, 0x8420, 0x0070, 0x1f99, 0x0078,
- 0x1f8a, 0x157f, 0x0078, 0x1bff, 0x2200, 0x0079, 0x1f9f, 0x1fa2,
- 0x1fa4, 0x1fa4, 0x1078, 0x1ba5, 0x70a3, 0x0000, 0x70a7, 0x0001,
- 0x0078, 0x1bf7, 0x2200, 0x0079, 0x1fad, 0x1fb2, 0x1fa4, 0x1fb0,
- 0x1078, 0x1ba5, 0x1078, 0x241f, 0x7000, 0xa086, 0x0001, 0x00c0,
- 0x28af, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef, 0x600a, 0x1078,
- 0x28a2, 0x0040, 0x28af, 0x0078, 0x1cd6, 0x2404, 0xa005, 0x0040,
- 0x1fe6, 0x2068, 0x2d04, 0x007e, 0x6810, 0xa706, 0x0040, 0x1fd4,
- 0x2d20, 0x007f, 0x0078, 0x1fc6, 0x007f, 0x2022, 0x6916, 0x681c,
- 0xa205, 0x681e, 0x1078, 0x17dd, 0x6010, 0x8001, 0x6012, 0x6008,
- 0xa084, 0xffef, 0x600a, 0x1078, 0x28ef, 0x007c, 0xa085, 0x0001,
- 0x0078, 0x1fe5, 0x2300, 0x0079, 0x1fed, 0x1ff2, 0x1ff0, 0x2035,
- 0x1078, 0x1ba5, 0x78e4, 0xa005, 0x00d0, 0x2015, 0x0018, 0x2015,
- 0x2008, 0xa084, 0x0030, 0x00c0, 0x2001, 0x781b, 0x0049, 0x0078,
- 0x1bf7, 0x78ec, 0xa084, 0x0003, 0x0040, 0x1ffd, 0x2100, 0xa084,
- 0x0007, 0x0079, 0x200b, 0x2023, 0x2029, 0x201d, 0x2013, 0x2d58,
- 0x2d58, 0x2013, 0x202f, 0x1078, 0x1ba5, 0x7000, 0xa005, 0x0040,
- 0x1bff, 0x2001, 0x0003, 0x0078, 0x22fa, 0x1078, 0x2b89, 0x781b,
- 0x0055, 0x0078, 0x1bf7, 0x1078, 0x2b89, 0x781b, 0x00dc, 0x0078,
- 0x1bf7, 0x1078, 0x2b89, 0x781b, 0x00e3, 0x0078, 0x1bf7, 0x1078,
- 0x2b89, 0x781b, 0x009d, 0x0078, 0x1bf7, 0xa584, 0x000f, 0x00c0,
- 0x205f, 0x1078, 0x241f, 0x7000, 0x0079, 0x203e, 0x2046, 0x2053,
- 0x2046, 0x28af, 0x2048, 0x28af, 0x2046, 0x2046, 0x1078, 0x1ba5,
- 0x71a0, 0x70a3, 0x0000, 0xa186, 0x0004, 0x00c0, 0x2051, 0x0078,
- 0x2908, 0x0078, 0x28af, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x1078, 0x28a2, 0x0040, 0x28af, 0x0078, 0x1cd6, 0x78e4,
- 0xa005, 0x00d0, 0x2015, 0x0018, 0x2015, 0x2008, 0xa084, 0x0030,
- 0x00c0, 0x206e, 0x781b, 0x0049, 0x0078, 0x1bf7, 0x78ec, 0xa084,
- 0x0003, 0x0040, 0x206a, 0x2100, 0xa184, 0x0007, 0x0079, 0x2078,
- 0x2088, 0x208e, 0x2082, 0x2080, 0x2d58, 0x2d58, 0x2080, 0x2d50,
- 0x1078, 0x1ba5, 0x1078, 0x2b91, 0x781b, 0x0055, 0x0078, 0x1bf7,
- 0x1078, 0x2b91, 0x781b, 0x00dc, 0x0078, 0x1bf7, 0x1078, 0x2b91,
- 0x781b, 0x00e3, 0x0078, 0x1bf7, 0x1078, 0x2b91, 0x781b, 0x009d,
- 0x0078, 0x1bf7, 0x2300, 0x0079, 0x209d, 0x20a2, 0x20a0, 0x20a4,
- 0x1078, 0x1ba5, 0x0078, 0x2665, 0x6817, 0x0008, 0x78a3, 0x0000,
- 0x79e4, 0xa184, 0x0030, 0x0040, 0x2665, 0x78ec, 0xa084, 0x0003,
- 0x0040, 0x2665, 0xa184, 0x0007, 0x0079, 0x20b6, 0x2023, 0x2029,
- 0x201d, 0x2d30, 0x2d58, 0x2d58, 0x20be, 0x2d50, 0x1078, 0x1ba5,
- 0xa282, 0x0005, 0x0050, 0x20c6, 0x1078, 0x1ba5, 0x2300, 0x0079,
- 0x20c9, 0x20cc, 0x22ce, 0x22da, 0x2200, 0x0079, 0x20cf, 0x20d4,
- 0x20d6, 0x20e9, 0x20d4, 0x22b3, 0x1078, 0x1ba5, 0x789b, 0x0018,
- 0x78a8, 0xa084, 0x00ff, 0xa082, 0x0020, 0x0048, 0x2b6a, 0xa08a,
- 0x0004, 0x00c8, 0x2b6a, 0x0079, 0x20e5, 0x2b6a, 0x2b6a, 0x2b6a,
- 0x2b0c, 0x789b, 0x0018, 0x79a8, 0xa184, 0x0080, 0x0040, 0x20fe,
- 0xa184, 0x0018, 0x0040, 0x20fa, 0x0078, 0x2b6a, 0x7000, 0xa005,
- 0x00c0, 0x20f4, 0x2011, 0x0003, 0x0078, 0x2752, 0xa184, 0x00ff,
- 0xa08a, 0x0010, 0x00c8, 0x2b6a, 0x0079, 0x2106, 0x2118, 0x2116,
- 0x212e, 0x2130, 0x21c2, 0x2b6a, 0x2b6a, 0x21c4, 0x2b6a, 0x2b6a,
- 0x22af, 0x22af, 0x2b6a, 0x2b6a, 0x2b6a, 0x22b1, 0x1078, 0x1ba5,
- 0xa684, 0x1000, 0x0040, 0x2125, 0x2001, 0x0300, 0x8000, 0x8000,
- 0x783a, 0x781b, 0x009a, 0x0078, 0x1bf7, 0x6814, 0xa084, 0x8000,
- 0x0040, 0x212c, 0x6817, 0x0003, 0x0078, 0x2d30, 0x1078, 0x1ba5,
- 0x691c, 0x691e, 0xa684, 0x1800, 0x00c0, 0x214a, 0x681c, 0xa084,
- 0x0001, 0x00c0, 0x2152, 0x6814, 0xa086, 0x0008, 0x00c0, 0x2142,
- 0x6817, 0x0000, 0xa684, 0x0400, 0x0040, 0x21be, 0x781b, 0x0058,
- 0x0078, 0x1bf7, 0xa684, 0x1000, 0x0040, 0x2152, 0x781b, 0x0058,
- 0x0078, 0x1bf7, 0xa684, 0x0060, 0x0040, 0x21ba, 0xa684, 0x0800,
- 0x0040, 0x21ba, 0xa684, 0x8000, 0x00c0, 0x2160, 0x0078, 0x217a,
- 0xa6b4, 0x7fff, 0x7e5a, 0x6eb2, 0x789b, 0x0074, 0x7aac, 0x79ac,
- 0x78ac, 0x801b, 0x00c8, 0x216d, 0x8000, 0xa084, 0x003f, 0xa108,
- 0xa291, 0x0000, 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200,
- 0xa303, 0x68aa, 0xa684, 0x4000, 0x0040, 0x2182, 0xa6b4, 0xbfff,
- 0x7e5a, 0x6eb2, 0x7000, 0xa086, 0x0003, 0x00c0, 0x218f, 0x1078,
- 0x2f3a, 0x1078, 0x30df, 0x781b, 0x0067, 0x0078, 0x1bf7, 0xa006,
- 0x1078, 0x3194, 0x6aac, 0x69a8, 0x6c94, 0x6b90, 0x2200, 0xa105,
- 0x0040, 0x219e, 0x2200, 0xa422, 0x2100, 0xa31b, 0x7cd2, 0x7bd6,
- 0x2300, 0xa405, 0x00c0, 0x21ac, 0xa6b5, 0x4000, 0x7e5a, 0x6eb2,
- 0x781b, 0x0067, 0x0078, 0x1bf7, 0x781b, 0x0067, 0x2200, 0xa115,
- 0x00c0, 0x21b6, 0x1078, 0x30f0, 0x0078, 0x1bf7, 0x1078, 0x311d,
- 0x0078, 0x1bf7, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x781b, 0x0058,
- 0x0078, 0x1bf7, 0x1078, 0x1ba5, 0x0078, 0x2221, 0x691c, 0xa184,
- 0x0100, 0x0040, 0x21dc, 0xa18c, 0xfeff, 0x691e, 0x0c7e, 0x7048,
- 0x2060, 0x6000, 0xa084, 0xefff, 0x6002, 0x6004, 0xa084, 0xfff5,
- 0x6006, 0x0c7f, 0x0078, 0x2210, 0xa184, 0x0200, 0x0040, 0x2210,
- 0xa18c, 0xfdff, 0x691e, 0x0c7e, 0x7048, 0x2060, 0x6000, 0xa084,
- 0xdfff, 0x6002, 0x6004, 0xa084, 0xffef, 0x6006, 0x2008, 0x2c48,
- 0x0c7f, 0xa184, 0x0008, 0x0040, 0x2210, 0x1078, 0x2c9d, 0x1078,
- 0x29e6, 0x88ff, 0x0040, 0x2210, 0x789b, 0x0060, 0x2800, 0x78aa,
- 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x220c,
- 0x781b, 0x0055, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7,
- 0x7e58, 0xa684, 0x0400, 0x00c0, 0x2219, 0x781b, 0x0058, 0x0078,
- 0x1bf7, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x0078, 0x2b70, 0x0078,
- 0x2b70, 0x2019, 0x0000, 0x7990, 0xa18c, 0x0007, 0x0040, 0x221f,
- 0x789b, 0x0010, 0x78a8, 0xa094, 0x00ff, 0xa286, 0x0001, 0x00c0,
- 0x2244, 0x2300, 0x7ca8, 0xa400, 0x2018, 0xa102, 0x0040, 0x223c,
- 0x0048, 0x223c, 0x0078, 0x223e, 0x0078, 0x21c6, 0x24a8, 0x7aa8,
- 0x00f0, 0x223e, 0x0078, 0x222a, 0xa284, 0x00f0, 0xa086, 0x0020,
- 0x00c0, 0x22a0, 0x8318, 0x8318, 0x2300, 0xa102, 0x0040, 0x2254,
- 0x0048, 0x2254, 0x0078, 0x229d, 0xa286, 0x0023, 0x0040, 0x221f,
- 0x6818, 0xa084, 0xfff1, 0x681a, 0x7e58, 0xa684, 0xfff1, 0xa085,
- 0x0010, 0x2030, 0x7e5a, 0x6008, 0xa085, 0x0010, 0x600a, 0x0c7e,
- 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184, 0x0010,
- 0x0040, 0x2278, 0x1078, 0x2c9d, 0x1078, 0x2acc, 0x0078, 0x2287,
- 0x0c7e, 0x7048, 0x2060, 0x6004, 0x2008, 0x2c48, 0x0c7f, 0xa184,
- 0x0008, 0x0040, 0x2210, 0x1078, 0x2c9d, 0x1078, 0x29e6, 0x88ff,
- 0x0040, 0x2210, 0x789b, 0x0060, 0x2800, 0x78aa, 0xa6b5, 0x0004,
- 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2299, 0x781b, 0x0055, 0x0078,
- 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x7aa8, 0x0078, 0x222a,
- 0x8318, 0x2300, 0xa102, 0x0040, 0x22a9, 0x0048, 0x22a9, 0x0078,
- 0x222a, 0xa284, 0x0080, 0x00c0, 0x2b76, 0x0078, 0x2b70, 0x0078,
- 0x2b76, 0x0078, 0x2b6a, 0x789b, 0x0018, 0x78a8, 0xa084, 0x00ff,
- 0xa08e, 0x0001, 0x0040, 0x22be, 0x1078, 0x1ba5, 0x7aa8, 0xa294,
- 0x00ff, 0x78a8, 0xa084, 0x00ff, 0xa08a, 0x0004, 0x00c8, 0x2b6a,
- 0x0079, 0x22ca, 0x2b6a, 0x2939, 0x2b6a, 0x2a67, 0xa282, 0x0000,
- 0x00c0, 0x22d4, 0x1078, 0x1ba5, 0x1078, 0x2b89, 0x781b, 0x0069,
- 0x0078, 0x1bf7, 0xa282, 0x0003, 0x00c0, 0x22e0, 0x1078, 0x1ba5,
- 0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7, 0xa282, 0x0004,
- 0x0050, 0x22ec, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x22ef, 0x22f2,
- 0x23c9, 0x23fa, 0xa286, 0x0003, 0x0040, 0x22f8, 0x1078, 0x1ba5,
- 0x2001, 0x0000, 0x703a, 0x7000, 0xa084, 0x0007, 0x0079, 0x2300,
- 0x2308, 0x230a, 0x230a, 0x2508, 0x2530, 0x24d2, 0x2308, 0x2308,
- 0x1078, 0x1ba5, 0xa684, 0x1000, 0x00c0, 0x2312, 0x1078, 0x2ec7,
- 0x0040, 0x23a3, 0x7868, 0xa08c, 0x00ff, 0x0040, 0x235a, 0xa186,
- 0x0008, 0x00c0, 0x2329, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x1078, 0x28a2, 0x0040, 0x235a, 0x1078, 0x2ec7, 0x0078,
- 0x2341, 0xa186, 0x0028, 0x00c0, 0x235a, 0x1078, 0x2ec7, 0x6008,
- 0xa084, 0xffef, 0x600a, 0x6018, 0xa005, 0x0040, 0x2341, 0x8001,
- 0x601a, 0xa005, 0x0040, 0x2341, 0x8001, 0xa005, 0x0040, 0x2341,
- 0x601e, 0x681c, 0xa084, 0x0001, 0x0040, 0x1bff, 0x681c, 0xa084,
- 0xfffe, 0x681e, 0x7054, 0x0c7e, 0x2060, 0x6800, 0x6002, 0x0c7f,
- 0x6004, 0x6802, 0xa005, 0x2d00, 0x00c0, 0x2357, 0x6002, 0x6006,
- 0x0078, 0x1bff, 0x017e, 0x1078, 0x241f, 0x017f, 0xa684, 0xdf00,
- 0x681a, 0x6827, 0x0000, 0x6f10, 0x81ff, 0x0040, 0x23a3, 0xa186,
- 0x0002, 0x00c0, 0x239b, 0xa684, 0x0800, 0x00c0, 0x2377, 0xa684,
- 0x0060, 0x0040, 0x2377, 0x78d8, 0x7adc, 0x682e, 0x6a2a, 0x8717,
- 0xa294, 0x000f, 0x8213, 0x8213, 0x8213, 0xa290, 0x3600, 0xa290,
- 0x0000, 0x221c, 0xa384, 0x0100, 0x00c0, 0x2388, 0x0078, 0x238e,
- 0x8210, 0x2204, 0xa085, 0x0018, 0x2012, 0x8211, 0xa384, 0x0400,
- 0x0040, 0x239b, 0x689c, 0xa084, 0x0100, 0x00c0, 0x239b, 0x1078,
- 0x2491, 0x0078, 0x1bff, 0xa186, 0x0018, 0x0040, 0x23a3, 0xa186,
- 0x0014, 0x0040, 0x1bff, 0x6912, 0x6814, 0xa084, 0x8000, 0x0040,
- 0x23ab, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x1078, 0x28e0,
- 0x1078, 0x28ef, 0x00c0, 0x23b8, 0x6008, 0xa084, 0xffef, 0x600a,
- 0x681c, 0xa084, 0x0001, 0x00c0, 0x23c1, 0x1078, 0x28d9, 0x0078,
- 0x23c5, 0x7054, 0x2060, 0x6800, 0x6002, 0x1078, 0x17dd, 0x0078,
- 0x1bff, 0xa282, 0x0004, 0x0048, 0x23cf, 0x1078, 0x1ba5, 0x2200,
- 0x0079, 0x23d2, 0x23d6, 0x23d8, 0x23e5, 0x23d8, 0x1078, 0x1ba5,
- 0x7000, 0xa086, 0x0005, 0x0040, 0x23e1, 0x1078, 0x2b89, 0x781b,
- 0x0069, 0x781b, 0x006a, 0x0078, 0x1bf7, 0x7890, 0x8007, 0x8001,
- 0xa084, 0x0007, 0xa080, 0x0018, 0x789a, 0x79a8, 0xa18c, 0x00ff,
- 0xa186, 0x0003, 0x0040, 0x23f6, 0x0078, 0x2b6a, 0x781b, 0x006a,
- 0x0078, 0x1bf7, 0x681c, 0xa085, 0x0004, 0x681e, 0x82ff, 0x00c0,
- 0x2405, 0x1078, 0x2b89, 0x0078, 0x240c, 0x8211, 0x0040, 0x240a,
- 0x1078, 0x1ba5, 0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7,
- 0x1078, 0x2d77, 0x7830, 0xa084, 0x00c0, 0x00c0, 0x241c, 0x0018,
- 0x241c, 0x791a, 0xa006, 0x007c, 0xa085, 0x0001, 0x007c, 0xa684,
- 0x0060, 0x00c0, 0x2429, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078,
- 0x2490, 0xa684, 0x0800, 0x00c0, 0x2438, 0x68b0, 0xa084, 0x4800,
- 0xa635, 0xa684, 0x0800, 0x00c0, 0x2438, 0x1078, 0x2ec7, 0x007c,
- 0xa684, 0x0020, 0x0040, 0x2462, 0x78d0, 0x8003, 0x00c8, 0x2446,
- 0xa006, 0x1078, 0x3194, 0x78d4, 0x1078, 0x31f9, 0xa684, 0x4000,
- 0x0040, 0x2450, 0x682f, 0x0000, 0x682b, 0x0000, 0x0078, 0x2435,
- 0x68b0, 0xa084, 0x4800, 0xa635, 0xa684, 0x4000, 0x00c0, 0x244a,
- 0x7038, 0xa005, 0x00c0, 0x245c, 0x79d8, 0x7adc, 0x692e, 0x6a2a,
- 0x0078, 0x2435, 0xa684, 0x4000, 0x0040, 0x246c, 0x682f, 0x0000,
- 0x682b, 0x0000, 0x0078, 0x2435, 0x68b0, 0xa084, 0x4800, 0xa635,
- 0xa684, 0x4000, 0x00c0, 0x2466, 0x7038, 0xa005, 0x00c0, 0x247a,
- 0x703b, 0x0007, 0x79d8, 0x7adc, 0x78d0, 0x80f3, 0x00c8, 0x2481,
- 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000, 0x692e, 0x6a2a,
- 0x2100, 0xa205, 0x00c0, 0x248e, 0x0078, 0x2435, 0x1078, 0x3194,
- 0x007c, 0xa384, 0x0200, 0x0040, 0x2499, 0x6008, 0xa085, 0x0002,
- 0x600a, 0x6817, 0x0006, 0x6a28, 0x692c, 0x6a3a, 0x693e, 0x682b,
- 0x0300, 0x682f, 0x0000, 0x6833, 0x2000, 0x6893, 0x0000, 0x6897,
- 0x0020, 0x7000, 0x0079, 0x24ac, 0x24b4, 0x24b6, 0x24bf, 0x24b4,
- 0x24b4, 0x24b4, 0x24b4, 0x24b4, 0x1078, 0x1ba5, 0x681c, 0xa084,
- 0x0001, 0x00c0, 0x24bf, 0x1078, 0x28d9, 0x0078, 0x24c5, 0x7054,
- 0x2c50, 0x2060, 0x6800, 0x6002, 0x2a60, 0x2021, 0x3557, 0x2404,
- 0xa005, 0x0040, 0x24ce, 0x2020, 0x0078, 0x24c7, 0x2d22, 0x206b,
- 0x0000, 0x007c, 0x77b4, 0x1078, 0x2ba6, 0xa7bc, 0x0f00, 0x1078,
- 0x2ca1, 0x6018, 0xa005, 0x0040, 0x2501, 0x0d7e, 0x2001, 0x3f90,
- 0x2068, 0x0d7f, 0x2021, 0x3f80, 0x2009, 0x0004, 0x2011, 0x0010,
- 0x1078, 0x1fc5, 0x0040, 0x2501, 0x157e, 0x20a9, 0x0000, 0x2021,
- 0x3e80, 0x047e, 0x2009, 0x0004, 0x2011, 0x0010, 0x1078, 0x1fc5,
- 0x047f, 0x0040, 0x2500, 0x8420, 0x0070, 0x2500, 0x0078, 0x24f1,
- 0x157f, 0x8738, 0xa784, 0x0007, 0x00c0, 0x24d7, 0x0078, 0x1bff,
- 0x1078, 0x28e0, 0x1078, 0x28ef, 0x6827, 0x0000, 0x789b, 0x000e,
- 0x6f10, 0x6813, 0x0002, 0x1078, 0x31ca, 0xa684, 0x0800, 0x0040,
- 0x251d, 0x6918, 0xa18d, 0x2000, 0x691a, 0x6814, 0xa084, 0x8000,
- 0x0040, 0x2524, 0x6817, 0x0000, 0x2021, 0x3557, 0x6800, 0x2022,
- 0x6a38, 0x693c, 0x6a2a, 0x692e, 0x1078, 0x17dd, 0x0078, 0x1bff,
- 0x1078, 0x241f, 0x6827, 0x0000, 0x789b, 0x000e, 0x6f10, 0x1078,
- 0x2d7c, 0xa08c, 0x00ff, 0x6912, 0x6814, 0xa084, 0x8000, 0x0040,
- 0x2543, 0x7038, 0x6816, 0xa68c, 0xdf00, 0x691a, 0x70a3, 0x0000,
- 0x0078, 0x1bff, 0xa006, 0x1078, 0x2ec7, 0x6813, 0x0000, 0x6817,
- 0x0001, 0xa68c, 0xdf00, 0x691a, 0x6827, 0x0000, 0x7000, 0x0079,
- 0x2559, 0x2561, 0x2563, 0x2563, 0x2565, 0x2565, 0x2565, 0x2561,
- 0x2561, 0x1078, 0x1ba5, 0x1078, 0x28ef, 0x6008, 0xa084, 0xffef,
- 0x600a, 0x0078, 0x28ba, 0x2300, 0x0079, 0x256e, 0x2571, 0x2573,
- 0x25b1, 0x1078, 0x1ba5, 0x7000, 0x0079, 0x2576, 0x257e, 0x2580,
- 0x2580, 0x258b, 0x2580, 0x2592, 0x257e, 0x257e, 0x1078, 0x1ba5,
- 0xa684, 0x2000, 0x00c0, 0x258b, 0xa6b5, 0x2000, 0x7e5a, 0x1078,
- 0x30f0, 0x0078, 0x2d30, 0x6814, 0xa084, 0x8000, 0x0040, 0x2592,
- 0x6817, 0x0007, 0x2009, 0x3518, 0x210c, 0xa186, 0x0000, 0x0040,
- 0x25a7, 0xa186, 0x0001, 0x0040, 0x25ab, 0x2009, 0x352b, 0x200b,
- 0x000b, 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, 0x1bf7, 0x781b,
- 0x00dd, 0x0078, 0x1bf7, 0x2009, 0x352b, 0x200b, 0x000a, 0x0078,
- 0x1bf7, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x25b6, 0x25b9, 0x25bb,
- 0x25de, 0x1078, 0x1ba5, 0x7000, 0x0079, 0x25be, 0x25c6, 0x25c8,
- 0x25c8, 0x25d3, 0x25c8, 0x25da, 0x25c6, 0x25c6, 0x1078, 0x1ba5,
- 0xa684, 0x2000, 0x00c0, 0x25d3, 0xa6b5, 0x2000, 0x7e5a, 0x1078,
- 0x30f0, 0x0078, 0x2d30, 0x6814, 0xa084, 0x8000, 0x0040, 0x25da,
- 0x6817, 0x0007, 0x781b, 0x00e4, 0x0078, 0x1bf7, 0x681c, 0xa085,
- 0x0004, 0x681e, 0xa6b5, 0x0800, 0x1078, 0x2b89, 0x781b, 0x0069,
- 0x0078, 0x1bf7, 0x2300, 0x0079, 0x25ed, 0x25f0, 0x25f2, 0x25f4,
- 0x1078, 0x1ba5, 0x1078, 0x1ba5, 0xa684, 0x0400, 0x00c0, 0x2613,
- 0x782b, 0x3009, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
- 0x785a, 0x79e4, 0xa184, 0x0020, 0x0040, 0x260b, 0x78ec, 0xa084,
- 0x0003, 0x00c0, 0x260f, 0x2001, 0x0014, 0x0078, 0x22fa, 0xa184,
- 0x0007, 0x0079, 0x264b, 0x7a90, 0xa294, 0x0007, 0x789b, 0x0060,
- 0x79a8, 0x81ff, 0x0040, 0x2649, 0x789b, 0x0010, 0x7ba8, 0xa384,
- 0x0001, 0x00c0, 0x263a, 0x7ba8, 0x7ba8, 0xa386, 0x0001, 0x00c0,
- 0x262d, 0x2009, 0xfff7, 0x0078, 0x2633, 0xa386, 0x0003, 0x00c0,
- 0x263a, 0x2009, 0xffef, 0x0c7e, 0x7048, 0x2060, 0x6004, 0xa104,
- 0x6006, 0x0c7f, 0x789b, 0x0060, 0x78ab, 0x0000, 0xa684, 0xfffb,
- 0x785a, 0x782b, 0x3009, 0x691c, 0xa18c, 0xfdff, 0xa18c, 0xfeff,
- 0x691e, 0x0078, 0x2d30, 0x2023, 0x2029, 0x2655, 0x265d, 0x2653,
- 0x2653, 0x2653, 0x2d30, 0x1078, 0x1ba5, 0x691c, 0xa18c, 0xfdff,
- 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d38, 0x691c, 0xa18c, 0xfdff,
- 0xa18c, 0xfeff, 0x691e, 0x0078, 0x2d30, 0x79e4, 0xa184, 0x0030,
- 0x0040, 0x266f, 0x78ec, 0xa084, 0x0003, 0x00c0, 0x2677, 0x6814,
- 0xa085, 0x8000, 0x6816, 0x2001, 0x0014, 0x0078, 0x22fa, 0xa184,
- 0x0007, 0x0079, 0x267b, 0x2d30, 0x2d30, 0x2683, 0x2d30, 0x2d58,
- 0x2d58, 0x2d30, 0x2d30, 0xa684, 0x0400, 0x00c0, 0x26b4, 0x681c,
- 0xa084, 0x0001, 0x0040, 0x2d38, 0xa68c, 0x2060, 0xa18c, 0xfffb,
- 0x795a, 0x69b2, 0x789b, 0x0060, 0x78ab, 0x0000, 0x789b, 0x0061,
- 0x6814, 0xa085, 0x8000, 0x6816, 0x78aa, 0x157e, 0x137e, 0x147e,
- 0x20a1, 0x012c, 0x789b, 0x0000, 0x8000, 0x80ac, 0xad80, 0x000a,
- 0x2098, 0x53a6, 0x147f, 0x137f, 0x157f, 0x6810, 0x8007, 0x789b,
- 0x007e, 0x78aa, 0x0078, 0x2d38, 0x6814, 0xa084, 0x8000, 0x0040,
- 0x26bb, 0x6817, 0x0008, 0x781b, 0x00d8, 0x0078, 0x1bf7, 0x2300,
- 0x0079, 0x26c2, 0x26c7, 0x2742, 0x26c5, 0x1078, 0x1ba5, 0x7000,
- 0xa084, 0x0007, 0x0079, 0x26cc, 0x26d4, 0x26d6, 0x26f2, 0x26d4,
- 0x26d4, 0x24d2, 0x26d4, 0x26d4, 0x1078, 0x1ba5, 0x691c, 0xa18d,
- 0x0001, 0x691e, 0x6800, 0x6006, 0xa005, 0x00c0, 0x26e0, 0x6002,
- 0x6818, 0xa084, 0x000e, 0x0040, 0x26ec, 0x7014, 0x68b6, 0x712c,
- 0xa188, 0x3e80, 0x0078, 0x26ee, 0x2009, 0x3f80, 0x2104, 0x6802,
- 0x2d0a, 0x7156, 0x6eb2, 0xa684, 0x0060, 0x0040, 0x2740, 0xa684,
- 0x0800, 0x00c0, 0x2704, 0xa684, 0x7fff, 0x68b2, 0x6890, 0x6894,
- 0x1078, 0x2ec7, 0x0078, 0x2740, 0xa684, 0x0020, 0x0040, 0x2716,
- 0xa006, 0x1078, 0x3194, 0x78d0, 0x8003, 0x00c8, 0x2712, 0x78d4,
- 0x1078, 0x31f9, 0x79d8, 0x7adc, 0x0078, 0x271a, 0x1078, 0x2cae,
- 0x1078, 0x3194, 0xa684, 0x8000, 0x0040, 0x2740, 0xa684, 0x7fff,
- 0x68b2, 0x789b, 0x0074, 0x1078, 0x2d7c, 0x2010, 0x1078, 0x2d7c,
- 0x2008, 0xa684, 0x0020, 0x00c0, 0x2738, 0x1078, 0x2d7c, 0x801b,
- 0x00c8, 0x2733, 0x8000, 0xa084, 0x003f, 0xa108, 0xa291, 0x0000,
- 0x6b94, 0x2100, 0xa302, 0x68ae, 0x6b90, 0x2200, 0xa303, 0x68aa,
- 0x0078, 0x1bff, 0x0078, 0x2b76, 0x7033, 0x0000, 0xa282, 0x0005,
- 0x0050, 0x274c, 0x1078, 0x1ba5, 0x2300, 0x0079, 0x274f, 0x2752,
- 0x275c, 0x277f, 0x2200, 0x0079, 0x2755, 0x275a, 0x2b76, 0x275a,
- 0x27a8, 0x27f9, 0x1078, 0x1ba5, 0x7000, 0xa086, 0x0001, 0x00c0,
- 0x2769, 0x1078, 0x28ef, 0x1078, 0x2ec7, 0x7034, 0x600a, 0x0078,
- 0x276e, 0x7000, 0xa086, 0x0003, 0x0040, 0x2763, 0x7003, 0x0005,
- 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032, 0x2200, 0x0079, 0x2778,
- 0x2b76, 0x277d, 0x27a8, 0x277d, 0x2b76, 0x1078, 0x1ba5, 0x7000,
- 0xa086, 0x0001, 0x00c0, 0x278c, 0x1078, 0x28ef, 0x1078, 0x2ec7,
- 0x7034, 0x600a, 0x0078, 0x2791, 0x7000, 0xa086, 0x0003, 0x0040,
- 0x2786, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e, 0x7032,
- 0x2200, 0x0079, 0x279b, 0x27a2, 0x27a0, 0x27a2, 0x27a0, 0x27a2,
- 0x1078, 0x1ba5, 0x1078, 0x2b99, 0x781b, 0x0069, 0x0078, 0x1bf7,
- 0x7000, 0xa086, 0x0001, 0x00c0, 0x27b5, 0x1078, 0x28ef, 0x1078,
- 0x2ec7, 0x7034, 0x600a, 0x0078, 0x27ba, 0x7000, 0xa086, 0x0003,
- 0x0040, 0x27af, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00, 0x789b,
- 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, 0x2069, 0x3f80, 0x2d04,
- 0x2d08, 0x7156, 0x2068, 0xa005, 0x0040, 0x27d5, 0x6810, 0xa206,
- 0x0040, 0x27ee, 0x6800, 0x0078, 0x27c8, 0x7003, 0x0005, 0x2001,
- 0x3f90, 0x2068, 0x703e, 0x7032, 0x157e, 0x20a9, 0x002f, 0x2003,
- 0x0000, 0x8000, 0x0070, 0x27e6, 0x0078, 0x27df, 0x157f, 0x6a12,
- 0x68b3, 0x0700, 0x681f, 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a,
- 0x681c, 0xa084, 0x0c00, 0x0040, 0x284f, 0x1078, 0x2b91, 0x0078,
- 0x284f, 0x7000, 0xa086, 0x0001, 0x00c0, 0x2806, 0x1078, 0x28ef,
- 0x1078, 0x2ec7, 0x7034, 0x600a, 0x0078, 0x280b, 0x7000, 0xa086,
- 0x0003, 0x0040, 0x2800, 0x7003, 0x0002, 0x7a80, 0xa294, 0x0f00,
- 0x789b, 0x0018, 0x7ca8, 0xa484, 0x0007, 0xa215, 0x79a8, 0x79a8,
- 0xa18c, 0x00ff, 0xa1e8, 0x3e80, 0x2d04, 0x2d08, 0x7156, 0x2068,
- 0xa005, 0x0040, 0x282a, 0x6810, 0xa206, 0x0040, 0x2843, 0x6800,
- 0x0078, 0x281d, 0x7003, 0x0005, 0x2001, 0x3f90, 0x2068, 0x703e,
- 0x7032, 0x157e, 0x20a9, 0x002f, 0x2003, 0x0000, 0x8000, 0x0070,
- 0x283b, 0x0078, 0x2834, 0x157f, 0x6a12, 0x68b3, 0x0700, 0x681f,
- 0x0800, 0x6823, 0x0003, 0x6eb0, 0x7e5a, 0x681c, 0xa084, 0x0c00,
- 0x0040, 0x284f, 0x1078, 0x2b8d, 0x7e58, 0x0078, 0x284f, 0x027e,
- 0x8207, 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600,
- 0x2060, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0xa684, 0x0060,
- 0x0040, 0x2886, 0x6b94, 0x6c90, 0x69a8, 0x68ac, 0xa105, 0x00c0,
- 0x2874, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde, 0xa6b4, 0xb7ff, 0x7e5a,
- 0x1078, 0x30f0, 0x0078, 0x2886, 0x68ac, 0xa31a, 0x2100, 0xa423,
- 0x2400, 0xa305, 0x0040, 0x2886, 0x7bd2, 0x7bda, 0x7cd6, 0x7cde,
- 0x68ac, 0xa6b4, 0xbfff, 0x7e5a, 0x1078, 0x311d, 0x077f, 0x1078,
- 0x2ca1, 0x2009, 0x006a, 0xa684, 0x0008, 0x0040, 0x2891, 0x2009,
- 0x0069, 0xa6b5, 0x2000, 0x7e5a, 0x791a, 0x2d00, 0x703e, 0x8207,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2048,
- 0x0078, 0x1bf7, 0x6020, 0xa005, 0x0040, 0x28ae, 0x8001, 0x6022,
- 0x6008, 0xa085, 0x0008, 0x600a, 0x7010, 0x6026, 0x007c, 0xa006,
- 0x1078, 0x2ec7, 0x6813, 0x0000, 0x6817, 0x0001, 0x681f, 0x0040,
- 0x681b, 0x0100, 0x7000, 0xa084, 0x0007, 0x0079, 0x28bf, 0x28c7,
- 0x28c9, 0x28c9, 0x28d5, 0x28d1, 0x28c7, 0x28c7, 0x28c7, 0x1078,
- 0x1ba5, 0x1078, 0x28e0, 0x1078, 0x28d9, 0x1078, 0x17dd, 0x0078,
- 0x1bff, 0x70a3, 0x0000, 0x0078, 0x1bff, 0x6817, 0x0000, 0x0078,
- 0x2508, 0x6800, 0xa005, 0x00c0, 0x28de, 0x6002, 0x6006, 0x007c,
- 0x6010, 0xa005, 0x0040, 0x28e9, 0x8001, 0x00d0, 0x28e9, 0x1078,
- 0x1ba5, 0x6012, 0x6008, 0xa084, 0xffef, 0x600a, 0x007c, 0x6018,
- 0xa005, 0x0040, 0x28f5, 0x8001, 0x601a, 0x007c, 0x1078, 0x2d77,
- 0x6817, 0x0018, 0x0078, 0x2926, 0x1078, 0x2d77, 0x6817, 0x0019,
- 0x0078, 0x2926, 0x1078, 0x2d77, 0x6817, 0x001a, 0x0078, 0x2926,
- 0x77b4, 0x1078, 0x2ca1, 0x71b8, 0xa18c, 0x00ff, 0xa1e8, 0x3e80,
- 0x2d04, 0x2d08, 0x2068, 0xa005, 0x00c0, 0x2918, 0x0078, 0x1bff,
- 0x6810, 0x72b4, 0xa206, 0x0040, 0x2920, 0x6800, 0x0078, 0x2911,
- 0x6800, 0x200a, 0x6817, 0x0005, 0x70bf, 0x0000, 0x1078, 0x28e0,
- 0x681c, 0xa084, 0x0001, 0x00c0, 0x292f, 0x1078, 0x28d9, 0x1078,
- 0x28ef, 0x681b, 0x0000, 0x681f, 0x0020, 0x1078, 0x17dd, 0x0078,
- 0x1bff, 0xa282, 0x0003, 0x00c0, 0x2b6a, 0x7da8, 0xa5ac, 0x00ff,
- 0x7ea8, 0xa6b4, 0x00ff, 0x691c, 0xa18d, 0x0080, 0x691e, 0xa184,
- 0x0100, 0x0040, 0x2999, 0xa18c, 0xfeff, 0x691e, 0xa6b4, 0x00ff,
- 0x0040, 0x2983, 0xa682, 0x000f, 0x0048, 0x295a, 0x0040, 0x295a,
- 0x2031, 0x000f, 0x852b, 0x852b, 0x1078, 0x2c24, 0x0040, 0x2964,
- 0x1078, 0x2a33, 0x0078, 0x298c, 0x1078, 0x2bdf, 0x0c7e, 0x2960,
- 0x6004, 0xa084, 0xfff5, 0x6006, 0x1078, 0x2a57, 0x0c7f, 0x691c,
- 0xa18d, 0x0100, 0x691e, 0x7e58, 0xa6b5, 0x0004, 0x7e5a, 0xa684,
- 0x0400, 0x00c0, 0x297f, 0x781b, 0x0055, 0x0078, 0x1bf7, 0x781b,
- 0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x2960, 0x6004, 0xa084, 0xfff5,
- 0x6006, 0x1078, 0x2a57, 0x0c7f, 0x7e58, 0xa684, 0x0400, 0x00c0,
- 0x2995, 0x781b, 0x0058, 0x0078, 0x1bf7, 0x781b, 0x006a, 0x0078,
- 0x1bf7, 0x0c7e, 0x7048, 0x2060, 0x6100, 0xa18c, 0x1000, 0x0040,
- 0x29d9, 0x6208, 0x8217, 0xa294, 0x00ff, 0xa282, 0x000f, 0x0048,
- 0x29ad, 0x0040, 0x29ad, 0x2011, 0x000f, 0x2600, 0xa202, 0x00c8,
- 0x29b2, 0x2230, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028,
- 0x00c0, 0x29c2, 0xa282, 0x0019, 0x00c8, 0x29c8, 0x2011, 0x0019,
- 0x0078, 0x29c8, 0xa282, 0x000c, 0x00c8, 0x29c8, 0x2011, 0x000c,
- 0x2200, 0xa502, 0x00c8, 0x29cd, 0x2228, 0x1078, 0x2be3, 0x852b,
- 0x852b, 0x1078, 0x2c24, 0x0040, 0x29d9, 0x1078, 0x2a33, 0x0078,
- 0x29dd, 0x1078, 0x2bdf, 0x1078, 0x2a57, 0x7858, 0xa085, 0x0004,
- 0x785a, 0x0c7f, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x2960,
- 0x6000, 0xa084, 0x1000, 0x00c0, 0x2a01, 0x6010, 0xa084, 0x000f,
- 0x00c0, 0x29fb, 0xa18c, 0x0002, 0x00c0, 0x29fb, 0xa18c, 0xfff5,
- 0x6106, 0x0c7f, 0x007c, 0x2011, 0x0032, 0x2019, 0x0000, 0x0078,
- 0x2a23, 0x6208, 0xa294, 0x00ff, 0x7018, 0xa086, 0x0028, 0x00c0,
- 0x2a11, 0xa282, 0x0019, 0x00c8, 0x2a17, 0x2011, 0x0019, 0x0078,
- 0x2a17, 0xa282, 0x000c, 0x00c8, 0x2a17, 0x2011, 0x000c, 0x6308,
- 0x831f, 0xa39c, 0x00ff, 0xa382, 0x000f, 0x0048, 0x2a23, 0x0040,
- 0x2a23, 0x2019, 0x000f, 0x78ab, 0x0001, 0x78ab, 0x0003, 0x78ab,
- 0x0001, 0x7aaa, 0x7baa, 0xa8c0, 0x0005, 0x681c, 0xa085, 0x0100,
- 0x681e, 0x0c7f, 0x007c, 0x0c7e, 0x7148, 0x2160, 0x2008, 0xa084,
- 0xfff0, 0xa635, 0x7e86, 0x6018, 0x789a, 0x7eae, 0x6612, 0x78a4,
- 0xa084, 0xfff8, 0xa18c, 0x0007, 0xa105, 0x78a6, 0x6016, 0x788a,
- 0xa6b4, 0x000f, 0x8637, 0x8204, 0x8004, 0xa084, 0x00ff, 0xa605,
- 0x600e, 0x6004, 0xa084, 0xfff5, 0x6006, 0x0c7f, 0x007c, 0x0c7e,
- 0x7048, 0x2060, 0x6018, 0x789a, 0x78a4, 0xa084, 0xfff0, 0x78a6,
- 0x6012, 0x7884, 0xa084, 0xfff0, 0x7886, 0x0c7f, 0x007c, 0xa282,
- 0x0002, 0x00c0, 0x2b6a, 0x7aa8, 0x691c, 0xa18d, 0x0080, 0x691e,
- 0xa184, 0x0200, 0x0040, 0x2aac, 0xa18c, 0xfdff, 0x691e, 0xa294,
- 0x00ff, 0xa282, 0x0002, 0x00c8, 0x2b6a, 0x1078, 0x2af3, 0x1078,
- 0x2a57, 0xa980, 0x0001, 0x200c, 0x1078, 0x2c9d, 0x1078, 0x29e6,
- 0x88ff, 0x0040, 0x2a9f, 0x789b, 0x0060, 0x2800, 0x78aa, 0x7e58,
- 0xa6b5, 0x0004, 0x7e5a, 0xa684, 0x0400, 0x00c0, 0x2a9b, 0x781b,
- 0x0055, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x7e58,
- 0xa684, 0x0400, 0x00c0, 0x2aa8, 0x781b, 0x0058, 0x0078, 0x1bf7,
- 0x781b, 0x006a, 0x0078, 0x1bf7, 0xa282, 0x0002, 0x00c8, 0x2ab4,
- 0xa284, 0x0001, 0x0040, 0x2abe, 0x7148, 0xa188, 0x0000, 0x210c,
- 0xa18c, 0x2000, 0x00c0, 0x2abe, 0x2011, 0x0000, 0x1078, 0x2bd1,
- 0x1078, 0x2af3, 0x1078, 0x2a57, 0x7858, 0xa085, 0x0004, 0x785a,
- 0x781b, 0x0069, 0x0078, 0x1bf7, 0x0c7e, 0x027e, 0x2960, 0x6000,
- 0x2011, 0x0001, 0xa084, 0x2000, 0x00c0, 0x2ae3, 0x6014, 0xa084,
- 0x0040, 0x00c0, 0x2ae1, 0xa18c, 0xffef, 0x6106, 0xa006, 0x0078,
- 0x2af0, 0x2011, 0x0000, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
- 0x0003, 0x7aaa, 0xa8c0, 0x0004, 0x681c, 0xa085, 0x0200, 0x681e,
- 0x027f, 0x0c7f, 0x007c, 0x0c7e, 0x7048, 0x2060, 0x82ff, 0x0040,
- 0x2afb, 0x2011, 0x0040, 0x6018, 0xa080, 0x0002, 0x789a, 0x78a4,
- 0xa084, 0xffbf, 0xa205, 0x78a6, 0x6016, 0x788a, 0x6004, 0xa084,
- 0xffef, 0x6006, 0x0c7f, 0x007c, 0x007e, 0x7000, 0xa086, 0x0003,
- 0x0040, 0x2b15, 0x007f, 0x0078, 0x2b18, 0x007f, 0x0078, 0x2b66,
- 0xa684, 0x0020, 0x0040, 0x2b66, 0x7888, 0xa084, 0x0040, 0x0040,
- 0x2b66, 0x78a8, 0x8001, 0x0040, 0x2b25, 0x7bb8, 0xa384, 0x003f,
- 0x831b, 0x00c8, 0x2b2c, 0x8000, 0xa005, 0x0040, 0x2b4d, 0x831b,
- 0x00c8, 0x2b35, 0x8001, 0x0040, 0x2b62, 0xa006, 0x1078, 0x3194,
- 0x78b4, 0x1078, 0x31f9, 0x0078, 0x2b66, 0xa684, 0x4000, 0x0040,
- 0x2b4d, 0x78b8, 0x801b, 0x00c8, 0x2b46, 0x8000, 0xa084, 0x003f,
- 0x00c0, 0x2b62, 0xa6b4, 0xbfff, 0x7e5a, 0x79d8, 0x7adc, 0x2001,
- 0x0001, 0xa108, 0x00c8, 0x2b56, 0xa291, 0x0000, 0x79d2, 0x79da,
- 0x7ad6, 0x7ade, 0x1078, 0x3194, 0x781b, 0x0067, 0x1078, 0x305e,
- 0x0078, 0x1bf7, 0x781b, 0x0067, 0x0078, 0x1bf7, 0x781b, 0x006a,
- 0x0078, 0x1bf7, 0x1078, 0x2b9d, 0x781b, 0x0069, 0x0078, 0x1bf7,
- 0x1078, 0x2b89, 0x781b, 0x0069, 0x0078, 0x1bf7, 0x6823, 0x0002,
- 0x1078, 0x2b91, 0x691c, 0xa18d, 0x0020, 0x691e, 0x6814, 0xa084,
- 0x8000, 0x0040, 0x2b85, 0x6817, 0x0005, 0x781b, 0x0069, 0x0078,
- 0x1bf7, 0x2001, 0x0005, 0x0078, 0x2b9f, 0x2001, 0x000c, 0x0078,
- 0x2b9f, 0x2001, 0x0006, 0x0078, 0x2b9f, 0x2001, 0x000d, 0x0078,
- 0x2b9f, 0x2001, 0x0009, 0x0078, 0x2b9f, 0x2001, 0x0007, 0x789b,
- 0x007f, 0x78aa, 0xa6b5, 0x0008, 0x7e5a, 0x007c, 0x077e, 0x873f,
- 0xa7bc, 0x000f, 0x873b, 0x873b, 0x8703, 0xa0e0, 0x3600, 0xa7b8,
- 0x0020, 0x7f9a, 0x79a4, 0xa184, 0x000f, 0x0040, 0x2bbf, 0xa184,
- 0xfff0, 0x78a6, 0x6012, 0x6004, 0xa085, 0x0008, 0x6006, 0x8738,
- 0x8738, 0x7f9a, 0x79a4, 0xa184, 0x0040, 0x0040, 0x2bcf, 0xa184,
- 0xffbf, 0x78a6, 0x6016, 0x6004, 0xa085, 0x0010, 0x6006, 0x077f,
- 0x007c, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab, 0x0002, 0x78ab,
- 0x0003, 0x7aaa, 0x789b, 0x0060, 0x78ab, 0x0004, 0x007c, 0x2031,
- 0x0000, 0x2029, 0x0032, 0x789b, 0x0010, 0x78ab, 0x0001, 0x78ab,
- 0x0003, 0x78ab, 0x0001, 0x7daa, 0x7eaa, 0x789b, 0x0060, 0x78ab,
- 0x0005, 0x007c, 0x157e, 0x8007, 0xa084, 0x00ff, 0x8003, 0x8003,
- 0xa080, 0x0020, 0x789a, 0x79a4, 0xa18c, 0xfff0, 0x2001, 0x3546,
- 0x2004, 0xa082, 0x0028, 0x0040, 0x2c0d, 0x2021, 0x2c84, 0x2019,
- 0x0014, 0x20a9, 0x000c, 0x0078, 0x2c13, 0x2021, 0x2c90, 0x2019,
- 0x0019, 0x20a9, 0x000d, 0x2011, 0x0064, 0x2404, 0xa084, 0xfff0,
- 0xa106, 0x0040, 0x2c22, 0x8420, 0x2300, 0xa210, 0x0070, 0x2c22,
- 0x0078, 0x2c15, 0x157f, 0x007c, 0x157e, 0x2011, 0x3546, 0x2214,
- 0xa282, 0x0032, 0x0048, 0x2c38, 0x0040, 0x2c3c, 0x2021, 0x2c76,
- 0x2019, 0x0011, 0x20a9, 0x000e, 0x2011, 0x0032, 0x0078, 0x2c4c,
- 0xa282, 0x0028, 0x0040, 0x2c44, 0x2021, 0x2c84, 0x2019, 0x0014,
- 0x20a9, 0x000c, 0x0078, 0x2c4a, 0x2021, 0x2c90, 0x2019, 0x0019,
- 0x20a9, 0x000d, 0x2011, 0x0064, 0x2200, 0xa502, 0x0040, 0x2c5c,
- 0x0048, 0x2c5c, 0x8420, 0x2300, 0xa210, 0x0070, 0x2c59, 0x0078,
- 0x2c4c, 0x157f, 0xa006, 0x007c, 0x157f, 0xa582, 0x0064, 0x00c8,
- 0x2c65, 0x7808, 0xa085, 0x0070, 0x780a, 0x78ec, 0xa084, 0x0300,
- 0x0040, 0x2c73, 0x2404, 0xa09e, 0x1201, 0x00c0, 0x2c73, 0x2001,
- 0x2101, 0x0078, 0x2c74, 0x2404, 0xa005, 0x007c, 0x1201, 0x3002,
- 0x3202, 0x4203, 0x4403, 0x5404, 0x5604, 0x6605, 0x6805, 0x7806,
- 0x7a06, 0x0a07, 0x0c07, 0x0e07, 0x3202, 0x4202, 0x5202, 0x6202,
- 0x7202, 0x6605, 0x7605, 0x7805, 0x7a05, 0x7c05, 0x7e05, 0x7f05,
- 0x2202, 0x3202, 0x4202, 0x5202, 0x5404, 0x6404, 0x7404, 0x7604,
- 0x7804, 0x7a04, 0x7c04, 0x7e04, 0x7f04, 0x789b, 0x0010, 0xa046,
- 0x007c, 0xa784, 0x0f00, 0x800c, 0xa784, 0x0007, 0x8003, 0x8003,
- 0x8003, 0x8003, 0xa105, 0xa0e0, 0x3680, 0x007c, 0x79d8, 0x7adc,
- 0x78d0, 0x801b, 0x00c8, 0x2cb5, 0x8000, 0xa084, 0x003f, 0xa108,
- 0xa291, 0x0000, 0x007c, 0x0f7e, 0x2079, 0x0100, 0x2009, 0x3540,
- 0x2091, 0x8000, 0x2104, 0x0079, 0x2cc5, 0x2cf7, 0x2ccf, 0x2ccf,
- 0x2ccf, 0x2ccf, 0x2ccf, 0x2ccd, 0x2ccd, 0x1078, 0x1ba5, 0x784b,
- 0x0004, 0x7848, 0xa084, 0x0004, 0x00c0, 0x2cd1, 0x784b, 0x0008,
- 0x7848, 0xa084, 0x0008, 0x00c0, 0x2cd8, 0x68b0, 0xa085, 0x4000,
- 0x68b2, 0x7858, 0xa085, 0x4000, 0x785a, 0x7830, 0xa084, 0x0080,
- 0x00c0, 0x2cf7, 0x0018, 0x2cf7, 0x6818, 0xa084, 0x0020, 0x00c0,
- 0x2cf5, 0x781b, 0x00dd, 0x0078, 0x2cf7, 0x781b, 0x00e4, 0x2091,
- 0x8001, 0x0f7f, 0x007c, 0x0c7e, 0x6810, 0x8007, 0xa084, 0x000f,
- 0x8003, 0x8003, 0x8003, 0xa0e0, 0x3600, 0x6004, 0xa084, 0x000a,
- 0x00c0, 0x2d2e, 0x6108, 0xa194, 0xff00, 0x0040, 0x2d2e, 0xa18c,
- 0x00ff, 0x2001, 0x0019, 0xa106, 0x0040, 0x2d1d, 0x2001, 0x0032,
- 0xa106, 0x0040, 0x2d21, 0x0078, 0x2d25, 0x2009, 0x0020, 0x0078,
- 0x2d27, 0x2009, 0x003f, 0x0078, 0x2d27, 0x2011, 0x0000, 0x2100,
- 0xa205, 0x600a, 0x6004, 0xa085, 0x0002, 0x6006, 0x0c7f, 0x007c,
- 0x781b, 0x006a, 0x0078, 0x1bf7, 0x781b, 0x0069, 0x0078, 0x1bf7,
- 0x781b, 0x0058, 0x0078, 0x1bf7, 0x781b, 0x0055, 0x0078, 0x1bf7,
- 0x781b, 0x00dd, 0x0078, 0x1bf7, 0x781b, 0x00dc, 0x0078, 0x1bf7,
- 0x781b, 0x00e4, 0x0078, 0x1bf7, 0x781b, 0x00e3, 0x0078, 0x1bf7,
- 0x781b, 0x009e, 0x0078, 0x1bf7, 0x781b, 0x009d, 0x0078, 0x1bf7,
- 0x70a3, 0x0001, 0x781b, 0x0046, 0x0078, 0x1bf7, 0x007e, 0x7830,
- 0xa084, 0x00c0, 0x00c0, 0x2d75, 0x7808, 0xa084, 0xfffd, 0x780a,
- 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021, 0x0040,
- 0x2d75, 0x7808, 0xa085, 0x0002, 0x780a, 0x007f, 0x007c, 0x7808,
- 0xa085, 0x0002, 0x780a, 0x007c, 0x7830, 0xa084, 0x0040, 0x00c0,
- 0x2d7c, 0x0098, 0x2d85, 0x78ac, 0x007c, 0x7808, 0xa084, 0xfffd,
- 0x780a, 0x0005, 0x0005, 0x0005, 0x0005, 0x78ec, 0xa084, 0x0021,
- 0x0040, 0x2d94, 0x0098, 0x2d92, 0x78ac, 0x007e, 0x7808, 0xa085,
- 0x0002, 0x780a, 0x007f, 0x007c, 0xa784, 0x0070, 0x0040, 0x2da8,
- 0x0c7e, 0x2d60, 0x2f68, 0x1078, 0x1b6b, 0x2d78, 0x2c68, 0x0c7f,
- 0x6817, 0x0003, 0x7858, 0xa084, 0x3f00, 0x681a, 0x682f, 0x0000,
- 0x682b, 0x0000, 0x784b, 0x0008, 0x78e4, 0xa005, 0x00d0, 0x2015,
- 0xa084, 0x0020, 0x0040, 0x2015, 0x78ec, 0xa084, 0x0003, 0x0040,
- 0x2015, 0x0018, 0x2015, 0x0078, 0x2b70, 0x0c7e, 0x6810, 0x8007,
- 0xa084, 0x000f, 0x8003, 0x8003, 0x8003, 0xa080, 0x3600, 0x2060,
- 0x2048, 0x704a, 0x6000, 0x704e, 0x6004, 0x7052, 0x0c7f, 0x007c,
- 0x0020, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020, 0x0000, 0x0020,
- 0x0000, 0x0020, 0x0062, 0x0009, 0x0014, 0x0014, 0x9847, 0x0014,
- 0x0014, 0x98f5, 0x98e7, 0x0014, 0x0014, 0x0080, 0x00bf, 0x0100,
- 0x0402, 0x2008, 0xf880, 0xa20a, 0x0014, 0x300b, 0xa20c, 0x0014,
- 0xa200, 0x8838, 0x817e, 0x842a, 0x84a0, 0x3806, 0x8839, 0x28c2,
- 0x9cc3, 0xa805, 0x0864, 0xa83b, 0x3008, 0x28c1, 0x9cc3, 0xa201,
- 0x300c, 0x2847, 0x8161, 0x846a, 0x8000, 0x84a4, 0x1856, 0x883a,
- 0xa808, 0x28e2, 0x9ca0, 0xa8f3, 0x0864, 0xa829, 0x300c, 0xa801,
- 0x3008, 0x28e1, 0x9ca0, 0x280d, 0xa204, 0x64c0, 0x67a0, 0x6fc0,
- 0x1814, 0x883b, 0x7023, 0x8576, 0x8677, 0xa80f, 0x786e, 0x883e,
- 0xa80c, 0x282b, 0xa205, 0x64a0, 0x67a0, 0x6fc0, 0x1814, 0x883b,
- 0x7023, 0x8576, 0x8677, 0xa801, 0x883e, 0x2069, 0x28c1, 0x9cc3,
- 0x2044, 0x2103, 0x20a2, 0x2081, 0xa8dc, 0xa207, 0x0014, 0xa203,
- 0x8000, 0x84a8, 0x85a4, 0x1872, 0x849a, 0x883c, 0x1fe2, 0xf601,
- 0xa208, 0x856e, 0x866f, 0x0704, 0x3008, 0x9ca0, 0x0014, 0xa202,
- 0x8000, 0x85a4, 0x3009, 0x84a8, 0x19e2, 0xf848, 0x8174, 0x86eb,
- 0x85eb, 0x872e, 0x87a9, 0x883f, 0x08e6, 0xa8f1, 0xf861, 0xa8e8,
- 0xf801, 0x0014, 0xf881, 0x0016, 0x85b2, 0x80f0, 0x9532, 0xfaa2,
- 0x1de2, 0x0014, 0x8532, 0xf221, 0x0014, 0x1de2, 0x84a8, 0xd6e0,
- 0x1fe6, 0x0014, 0xa206, 0x6865, 0x817f, 0x842a, 0x1dc1, 0x8823,
- 0x0016, 0x6042, 0x8008, 0xa8fa, 0x8000, 0x84a4, 0x8160, 0x842a,
- 0xf021, 0x3008, 0x84a8, 0x1dc6, 0x20d7, 0x8822, 0x0016, 0x8000,
- 0x2848, 0x1011, 0xa8fc, 0x3008, 0x8000, 0xa000, 0x2802, 0x1011,
- 0xa8fd, 0xa887, 0x3008, 0x283d, 0x1011, 0xa8fd, 0xa209, 0x0017,
- 0x300c, 0x8000, 0x85a4, 0x1de2, 0xdac1, 0x0014, 0x26e0, 0x873a,
- 0xfaa2, 0x19f2, 0x1fe2, 0x0014, 0xa20b, 0x0014, 0xa20d, 0x817e,
- 0x842a, 0x84a0, 0x3806, 0x0210, 0x9ccd, 0x0704, 0x0000, 0x127e,
- 0x2091, 0x2200, 0x2049, 0x2ec7, 0x7000, 0x7204, 0xa205, 0x720c,
- 0xa215, 0x7008, 0xa084, 0xfffd, 0xa205, 0x0040, 0x2ed9, 0x0078,
- 0x2ede, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c, 0x7000, 0xa084,
- 0x0001, 0x00c0, 0x2f0c, 0x7108, 0x8104, 0x00c8, 0x2eeb, 0x1078,
- 0x2fa8, 0x0078, 0x2ee3, 0x700c, 0xa08c, 0x007f, 0x0040, 0x2f0c,
- 0x7004, 0x8004, 0x00c8, 0x2f03, 0x7014, 0xa005, 0x00c0, 0x2eff,
- 0x7010, 0xa005, 0x0040, 0x2f03, 0xa102, 0x00c8, 0x2ee3, 0x7007,
- 0x0010, 0x0078, 0x2f0c, 0x8aff, 0x0040, 0x2f0c, 0x1078, 0x316b,
- 0x00c0, 0x2f06, 0x0040, 0x2ee3, 0x1078, 0x2f56, 0x7003, 0x0000,
- 0x127f, 0x2000, 0x007c, 0x6424, 0x84ff, 0x0040, 0x2f30, 0x2c70,
- 0x2039, 0x2f35, 0x2704, 0xae68, 0x680c, 0xa630, 0x6808, 0xa529,
- 0x8421, 0x0040, 0x2f30, 0x8738, 0x2704, 0xa005, 0x00c0, 0x2f1b,
- 0x7098, 0xa075, 0x0040, 0x2f30, 0x2039, 0x2f32, 0x0078, 0x2f1a,
- 0x007c, 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018,
- 0x001c, 0x0000, 0x127e, 0x2091, 0x2200, 0x2079, 0x3500, 0x2071,
- 0x0010, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2071,
- 0x0020, 0x7007, 0x000a, 0x7007, 0x0002, 0x7003, 0x0000, 0x2049,
- 0x0000, 0x78b3, 0x0000, 0x127f, 0x2000, 0x007c, 0x2049, 0x2f56,
- 0x7004, 0x8004, 0x00c8, 0x2f82, 0x7007, 0x0012, 0x7108, 0x7008,
- 0xa106, 0x00c0, 0x2f5e, 0xa184, 0x0030, 0x0040, 0x2f6b, 0xa086,
- 0x0030, 0x00c0, 0x2f5e, 0x7000, 0xa084, 0x0001, 0x00c0, 0x2f82,
- 0x7008, 0xa084, 0x000c, 0x00c0, 0x2f80, 0x710c, 0xa184, 0x0300,
- 0x00c0, 0x2f80, 0xa184, 0x007f, 0x00c0, 0x2f56, 0x0078, 0x2f82,
- 0x6817, 0x0003, 0x7007, 0x0012, 0x7007, 0x0008, 0x7004, 0xa084,
- 0x0008, 0x00c0, 0x2f86, 0x7007, 0x0012, 0x7108, 0x8104, 0x0048,
- 0x2f8b, 0x78b3, 0x0000, 0x7003, 0x0000, 0x2049, 0x0000, 0x007c,
- 0x107e, 0x007e, 0x127e, 0x157e, 0x2091, 0x2200, 0x7108, 0x1078,
- 0x2fa8, 0x157f, 0x127f, 0x2091, 0x8001, 0x007f, 0x107f, 0x007c,
- 0x7204, 0x2118, 0x7108, 0x700c, 0xa084, 0x0300, 0x00c0, 0x2fea,
- 0xa184, 0x000c, 0x00c0, 0x2fea, 0x8213, 0x8213, 0x8213, 0x8213,
- 0xa284, 0x0100, 0xa10d, 0x810b, 0x810b, 0x810f, 0xa184, 0x0007,
- 0x0079, 0x2fc2, 0x2fcc, 0x2fdc, 0x2fea, 0x2fdc, 0x2ffe, 0x2ffe,
- 0x2fea, 0x2ffc, 0x1078, 0x1ba5, 0x7007, 0x0002, 0x8aff, 0x00c0,
- 0x2fd5, 0x2049, 0x0000, 0x0078, 0x2fd9, 0x1078, 0x316b, 0x00c0,
- 0x2fd5, 0x78b3, 0x0000, 0x007c, 0x7007, 0x0002, 0x8aff, 0x00c0,
- 0x2fe3, 0x0078, 0x2fe7, 0x1078, 0x316b, 0x00c0, 0x2fe3, 0x78b3,
- 0x0000, 0x007c, 0x7007, 0x0002, 0x1078, 0x2f56, 0x1078, 0x2cbb,
- 0x6814, 0xa084, 0x8000, 0x0040, 0x2ff7, 0x6817, 0x0002, 0x007c,
- 0x1078, 0x1ba5, 0x1078, 0x1ba5, 0x1078, 0x3050, 0x7210, 0x7114,
- 0x700c, 0xa09c, 0x007f, 0x2800, 0xa300, 0xa211, 0xa189, 0x0000,
- 0x78b0, 0xa005, 0x0040, 0x3010, 0x78b3, 0x0000, 0x0078, 0x3033,
- 0x1078, 0x3050, 0x2704, 0x2c58, 0xac60, 0x630c, 0x2200, 0xa322,
- 0x6308, 0x2100, 0xa31b, 0x2400, 0xa305, 0x0040, 0x3029, 0x00c8,
- 0x3029, 0x8412, 0x8210, 0x830a, 0xa189, 0x0000, 0x2b60, 0x0078,
- 0x3010, 0x2b60, 0x8a07, 0xa7ba, 0x2f32, 0xa73d, 0x2c00, 0x6882,
- 0x6f86, 0x6c8e, 0x6b8a, 0x7007, 0x0012, 0x1078, 0x2f56, 0x007c,
- 0x8738, 0x2704, 0xa005, 0x00c0, 0x3044, 0x6098, 0xa005, 0x0040,
- 0x304d, 0x2060, 0x2039, 0x2f32, 0x8a51, 0x0040, 0x304c, 0x7008,
- 0xa084, 0x00c0, 0xa086, 0x00c0, 0x007c, 0x2051, 0x0000, 0x007c,
- 0x8a50, 0x8739, 0x2704, 0xa004, 0x00c0, 0x305d, 0x2039, 0x2f38,
- 0x6000, 0xa064, 0x00c0, 0x305d, 0x2d60, 0x007c, 0x127e, 0x0d7e,
- 0x2091, 0x2200, 0x0d7f, 0x6880, 0x2060, 0x6884, 0x6b88, 0x6c8c,
- 0x8057, 0xaad4, 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f32, 0x7e08,
- 0xa6b5, 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3079, 0xa6b5,
- 0x0001, 0x0f7e, 0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084, 0x0040,
- 0x0040, 0x3088, 0xa684, 0x0001, 0x00c0, 0x3088, 0xa6b5, 0x0001,
- 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x308a, 0x7000,
- 0xa005, 0x0040, 0x3095, 0x1078, 0x1ba5, 0x2400, 0xa305, 0x00c0,
- 0x309b, 0x0078, 0x30d8, 0x2c58, 0x2704, 0xac60, 0x6004, 0xa400,
- 0x007e, 0x701a, 0x6000, 0xa301, 0x701e, 0x2009, 0x04fd, 0x2104,
- 0xa086, 0x04fd, 0x007f, 0x00c0, 0x30c8, 0xa084, 0x0001, 0x0040,
- 0x30c8, 0xa684, 0x0001, 0x00c0, 0x30c8, 0x7013, 0x0001, 0x7017,
- 0x0000, 0x7602, 0x7007, 0x0001, 0x78b3, 0x0001, 0xa4a0, 0x0001,
- 0xa399, 0x0000, 0x6004, 0xa400, 0x701a, 0x6000, 0xa301, 0x701e,
- 0x620c, 0x2400, 0xa202, 0x7012, 0x6208, 0x2300, 0xa203, 0x7016,
- 0x7602, 0x7007, 0x0001, 0x2b60, 0x1078, 0x3038, 0x0078, 0x30da,
- 0x1078, 0x316b, 0x00c0, 0x30d8, 0x127f, 0x2000, 0x007c, 0x127e,
- 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x7007, 0x0004, 0x7004, 0xa084,
- 0x0004, 0x00c0, 0x30e6, 0x7003, 0x0008, 0x127f, 0x2000, 0x007c,
- 0x127e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049, 0x30f0, 0x7007,
- 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x30f9, 0x7000, 0xa005,
- 0x0040, 0x3104, 0x1078, 0x1ba5, 0x7e08, 0xa6b5, 0x000c, 0x6818,
- 0xa084, 0x0040, 0x0040, 0x310e, 0xa6b5, 0x0001, 0x6824, 0xa005,
- 0x0040, 0x311a, 0x2050, 0x2039, 0x2f35, 0x2d60, 0x1078, 0x316b,
- 0x00c0, 0x3116, 0x127f, 0x2000, 0x007c, 0x127e, 0x007e, 0x017e,
- 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x037f, 0x047f, 0x7e08, 0xa6b5,
- 0x000c, 0x6818, 0xa084, 0x0040, 0x0040, 0x3130, 0xa6b5, 0x0001,
- 0x2049, 0x311d, 0x6824, 0xa055, 0x0040, 0x3168, 0x2d70, 0x2e60,
- 0x2039, 0x2f35, 0x2704, 0xae68, 0x680c, 0xa422, 0x6808, 0xa31b,
- 0x0048, 0x3155, 0x8a51, 0x00c0, 0x3147, 0x1078, 0x1ba5, 0x8738,
- 0x2704, 0xa005, 0x00c0, 0x313b, 0x7098, 0xa075, 0x2060, 0x0040,
- 0x3168, 0x2039, 0x2f32, 0x0078, 0x313a, 0x8422, 0x8420, 0x831a,
- 0xa399, 0x0000, 0x690c, 0x2400, 0xa122, 0x6908, 0x2300, 0xa11b,
- 0x00c8, 0x3164, 0x1078, 0x1ba5, 0x2071, 0x0020, 0x0078, 0x3088,
- 0x127f, 0x2000, 0x007c, 0x7008, 0xa084, 0x00c0, 0xa086, 0x00c0,
- 0x0040, 0x3193, 0x2704, 0xac08, 0x2104, 0x701e, 0x8108, 0x2104,
- 0x701a, 0x8108, 0x2104, 0x7016, 0x8108, 0x2104, 0x7012, 0x0f7e,
- 0x2079, 0x0100, 0x7858, 0x0f7f, 0xa084, 0x0040, 0x0040, 0x318e,
- 0xa684, 0x0001, 0x00c0, 0x318e, 0xa6b5, 0x0001, 0x7602, 0x7007,
- 0x0001, 0x1078, 0x3038, 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091,
- 0x2200, 0x2049, 0x3194, 0x0d7f, 0x087f, 0x7108, 0xa184, 0x00c0,
- 0x00c0, 0x31aa, 0x6824, 0xa005, 0x0040, 0x31ba, 0x0078, 0x2ede,
- 0x0078, 0x31ba, 0x7108, 0x8104, 0x00c8, 0x31b2, 0x1078, 0x2fa8,
- 0x0078, 0x319d, 0x7007, 0x0010, 0x7108, 0x8104, 0x00c8, 0x31b4,
- 0x1078, 0x2fa8, 0x7008, 0xa086, 0x0002, 0x00c0, 0x319d, 0x7000,
- 0xa005, 0x00c0, 0x319d, 0x7003, 0x0000, 0x2049, 0x0000, 0x127f,
- 0x2000, 0x007c, 0x127e, 0x147e, 0x137e, 0x157e, 0x0d7e, 0x2091,
- 0x2200, 0x0d7f, 0x2049, 0x31ca, 0xad80, 0x0010, 0x20a0, 0x2099,
- 0x0031, 0x700c, 0xa084, 0x007f, 0x6826, 0x7007, 0x0008, 0x7007,
- 0x0002, 0x7003, 0x0001, 0x0040, 0x31e8, 0x8000, 0x80ac, 0x53a5,
- 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x31ea, 0x2049,
- 0x0000, 0x7003, 0x0000, 0x157f, 0x137f, 0x147f, 0x127f, 0x2000,
- 0x007c, 0x127e, 0x007e, 0x0d7e, 0x2091, 0x2200, 0x0d7f, 0x2049,
- 0x31f9, 0x6880, 0x2060, 0x6884, 0x6b88, 0x6c8c, 0x8057, 0xaad4,
- 0x00ff, 0xa084, 0x00ff, 0xa0b8, 0x2f32, 0x7e08, 0xa6b5, 0x0004,
- 0x7007, 0x0004, 0x7004, 0xa084, 0x0004, 0x00c0, 0x3212, 0x2c58,
- 0x2704, 0xac60, 0x6004, 0xa400, 0x701a, 0x6000, 0xa301, 0x701e,
- 0x7013, 0x0001, 0x7017, 0x0000, 0x7602, 0x7007, 0x0001, 0x007f,
- 0x8007, 0x2009, 0x0031, 0x200a, 0x00a0, 0x322c, 0x7108, 0x7007,
- 0x0002, 0x810c, 0x00c8, 0x322c, 0x810c, 0x0048, 0x3239, 0x0078,
- 0x2fea, 0xa4a0, 0x0001, 0xa399, 0x0000, 0x6b8a, 0x6c8e, 0x7007,
- 0x0004, 0x2049, 0x0000, 0x7003, 0x0000, 0x127f, 0x2000, 0x007c,
- 0x20a9, 0x0010, 0xa006, 0x8004, 0x8086, 0x818e, 0x00c8, 0x3251,
- 0xa200, 0x00f0, 0x324c, 0x8086, 0x818e, 0x007c, 0x157e, 0x20a9,
- 0x0010, 0xa005, 0x0040, 0x3277, 0xa11a, 0x00c8, 0x3277, 0x8213,
- 0x818d, 0x0048, 0x326a, 0xa11a, 0x00c8, 0x326b, 0x00f0, 0x325f,
- 0x0078, 0x326f, 0xa11a, 0x2308, 0x8210, 0x00f0, 0x325f, 0x007e,
- 0x3200, 0xa084, 0xf7ff, 0x2080, 0x007f, 0x157f, 0x007c, 0x007e,
- 0x3200, 0xa085, 0x0800, 0x0078, 0x3273, 0x00e0, 0x32bf, 0x2091,
- 0x6000, 0x7820, 0x8001, 0x7822, 0x00c0, 0x32b9, 0x7824, 0x7822,
- 0x2091, 0x8000, 0x2069, 0x3540, 0x6800, 0xa084, 0x0007, 0x0040,
- 0x32a1, 0xa086, 0x0002, 0x0040, 0x32a1, 0x6830, 0xa00d, 0x0040,
- 0x32a1, 0x2104, 0xa005, 0x0040, 0x32a1, 0x8001, 0x200a, 0x0040,
- 0x336f, 0x2061, 0x3680, 0x20a9, 0x0080, 0x6034, 0xa005, 0x0040,
- 0x32b3, 0x8001, 0x6036, 0x00c0, 0x32b3, 0x6010, 0xa005, 0x0040,
- 0x32b3, 0x1078, 0x1a19, 0xace0, 0x0010, 0x0070, 0x32b9, 0x0078,
- 0x32a5, 0x1078, 0x32d4, 0x1078, 0x32c2, 0x1078, 0x32f9, 0x2091,
- 0x8001, 0x007c, 0x783c, 0x8001, 0x783e, 0x00c0, 0x32d3, 0x7840,
- 0x783e, 0x7848, 0xa005, 0x0040, 0x32d3, 0x8001, 0x784a, 0x00c0,
- 0x32d3, 0x1078, 0x1a19, 0x007c, 0x7834, 0x8001, 0x7836, 0x00c0,
- 0x32f8, 0x7838, 0x7836, 0x2091, 0x8000, 0x7844, 0xa005, 0x00c0,
- 0x32e3, 0x2001, 0x0101, 0x8001, 0x7846, 0xa080, 0x3e80, 0x2040,
- 0x2004, 0xa065, 0x0040, 0x32f8, 0x6020, 0xa005, 0x0040, 0x32f4,
- 0x8001, 0x6022, 0x0040, 0x3328, 0x6000, 0x2c40, 0x0078, 0x32e9,
- 0x007c, 0x7828, 0x8001, 0x782a, 0x00c0, 0x3327, 0x782c, 0x782a,
- 0x7830, 0xa005, 0x00c0, 0x3306, 0x2001, 0x0080, 0x8001, 0x7832,
- 0x8003, 0x8003, 0x8003, 0x8003, 0xa090, 0x3680, 0xa298, 0x0002,
- 0x2304, 0xa084, 0x0008, 0x0040, 0x3327, 0xa290, 0x0009, 0x2204,
- 0xa005, 0x0040, 0x331f, 0x8001, 0x2012, 0x00c0, 0x3327, 0x2304,
- 0xa084, 0xfff7, 0xa085, 0x0080, 0x201a, 0x1078, 0x1a19, 0x007c,
- 0x2069, 0x3540, 0x6800, 0xa005, 0x0040, 0x3332, 0x683c, 0xac06,
- 0x0040, 0x336f, 0x6017, 0x0006, 0x60b0, 0xa084, 0x3f00, 0x601a,
- 0x601c, 0xa084, 0x00ff, 0xa085, 0x0060, 0x601e, 0x6000, 0x2042,
- 0x6710, 0x6fb6, 0x1078, 0x1692, 0x6818, 0xa005, 0x0040, 0x334a,
- 0x8001, 0x681a, 0x6808, 0xa084, 0xffef, 0x680a, 0x6810, 0x8001,
- 0x00d0, 0x3354, 0x1078, 0x1ba5, 0x6812, 0x602f, 0x0000, 0x602b,
- 0x0000, 0x2c68, 0x1078, 0x17dd, 0x2069, 0x3540, 0x2001, 0x0006,
- 0x68a2, 0x7944, 0xa184, 0x0100, 0x00c0, 0x336a, 0x69ba, 0x2001,
- 0x0004, 0x68a2, 0x1078, 0x1a14, 0x2091, 0x8001, 0x007c, 0x2009,
- 0x354f, 0x2164, 0x2069, 0x0100, 0x1078, 0x1b6b, 0x6017, 0x0006,
- 0x6858, 0xa084, 0x3f00, 0x601a, 0x601c, 0xa084, 0x00ff, 0xa085,
- 0x0048, 0x601e, 0x602f, 0x0000, 0x602b, 0x0000, 0x6830, 0xa084,
- 0x0040, 0x0040, 0x33ab, 0x684b, 0x0004, 0x20a9, 0x0014, 0x6848,
- 0xa084, 0x0004, 0x0040, 0x3398, 0x0070, 0x3398, 0x0078, 0x338f,
- 0x684b, 0x0009, 0x20a9, 0x0014, 0x6848, 0xa084, 0x0001, 0x0040,
- 0x33a5, 0x0070, 0x33a5, 0x0078, 0x339c, 0x20a9, 0x00fa, 0x0070,
- 0x33ab, 0x0078, 0x33a7, 0x6808, 0xa084, 0xfffd, 0x680a, 0x681b,
- 0x0046, 0x2009, 0x3568, 0x200b, 0x0007, 0x784c, 0x784a, 0x2091,
- 0x8001, 0x007c, 0x2079, 0x3500, 0x1078, 0x3403, 0x1078, 0x33cb,
- 0x1078, 0x33e0, 0x1078, 0x33f5, 0x7833, 0x0000, 0x7847, 0x0000,
- 0x784b, 0x0000, 0x007c, 0x2019, 0x000a, 0x2011, 0x3546, 0x2204,
- 0xa086, 0x0032, 0x0040, 0x33dd, 0x2019, 0x000c, 0x2204, 0xa086,
- 0x003c, 0x0040, 0x33dd, 0x2019, 0x0008, 0x7b2a, 0x7b2e, 0x007c,
- 0x2019, 0x0030, 0x2011, 0x3546, 0x2204, 0xa086, 0x0032, 0x0040,
- 0x33f2, 0x2019, 0x0039, 0x2204, 0xa086, 0x003c, 0x0040, 0x33f2,
- 0x2019, 0x0027, 0x7b36, 0x7b3a, 0x007c, 0x2019, 0x000d, 0x2011,
- 0x3546, 0x2204, 0xa086, 0x003c, 0x0040, 0x3400, 0x2019, 0x000a,
- 0x7b3e, 0x7b42, 0x007c, 0x2019, 0x2faf, 0x2011, 0x3546, 0x2204,
- 0xa086, 0x0032, 0x0040, 0x3415, 0x2019, 0x3971, 0x2204, 0xa086,
- 0x003c, 0x0040, 0x3415, 0x2019, 0x2626, 0x7b22, 0x7b26, 0x007c,
- 0x92a7
-};
-unsigned short __devinitdata sbus_risc_code_length01 = 0x2419;
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index cbcd3f681b6..166417a6afb 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -169,12 +169,10 @@ scsi_pool_alloc_command(struct scsi_host_cmd_pool *pool, gfp_t gfp_mask)
{
struct scsi_cmnd *cmd;
- cmd = kmem_cache_alloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
+ cmd = kmem_cache_zalloc(pool->cmd_slab, gfp_mask | pool->gfp_mask);
if (!cmd)
return NULL;
- memset(cmd, 0, sizeof(*cmd));
-
cmd->sense_buffer = kmem_cache_alloc(pool->sense_slab,
gfp_mask | pool->gfp_mask);
if (!cmd->sense_buffer) {
@@ -967,6 +965,110 @@ int scsi_track_queue_full(struct scsi_device *sdev, int depth)
EXPORT_SYMBOL(scsi_track_queue_full);
/**
+ * scsi_vpd_inquiry - Request a device provide us with a VPD page
+ * @sdev: The device to ask
+ * @buffer: Where to put the result
+ * @page: Which Vital Product Data to return
+ * @len: The length of the buffer
+ *
+ * This is an internal helper function. You probably want to use
+ * scsi_get_vpd_page instead.
+ *
+ * Returns 0 on success or a negative error number.
+ */
+static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer,
+ u8 page, unsigned len)
+{
+ int result;
+ unsigned char cmd[16];
+
+ cmd[0] = INQUIRY;
+ cmd[1] = 1; /* EVPD */
+ cmd[2] = page;
+ cmd[3] = len >> 8;
+ cmd[4] = len & 0xff;
+ cmd[5] = 0; /* Control byte */
+
+ /*
+ * I'm not convinced we need to try quite this hard to get VPD, but
+ * all the existing users tried this hard.
+ */
+ result = scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buffer,
+ len + 4, NULL, 30 * HZ, 3, NULL);
+ if (result)
+ return result;
+
+ /* Sanity check that we got the page back that we asked for */
+ if (buffer[1] != page)
+ return -EIO;
+
+ return 0;
+}
+
+/**
+ * scsi_get_vpd_page - Get Vital Product Data from a SCSI device
+ * @sdev: The device to ask
+ * @page: Which Vital Product Data to return
+ *
+ * SCSI devices may optionally supply Vital Product Data. Each 'page'
+ * of VPD is defined in the appropriate SCSI document (eg SPC, SBC).
+ * If the device supports this VPD page, this routine returns a pointer
+ * to a buffer containing the data from that page. The caller is
+ * responsible for calling kfree() on this pointer when it is no longer
+ * needed. If we cannot retrieve the VPD page this routine returns %NULL.
+ */
+unsigned char *scsi_get_vpd_page(struct scsi_device *sdev, u8 page)
+{
+ int i, result;
+ unsigned int len;
+ unsigned char *buf = kmalloc(259, GFP_KERNEL);
+
+ if (!buf)
+ return NULL;
+
+ /* Ask for all the pages supported by this device */
+ result = scsi_vpd_inquiry(sdev, buf, 0, 255);
+ if (result)
+ goto fail;
+
+ /* If the user actually wanted this page, we can skip the rest */
+ if (page == 0)
+ return buf;
+
+ for (i = 0; i < buf[3]; i++)
+ if (buf[i + 4] == page)
+ goto found;
+ /* The device claims it doesn't support the requested page */
+ goto fail;
+
+ found:
+ result = scsi_vpd_inquiry(sdev, buf, page, 255);
+ if (result)
+ goto fail;
+
+ /*
+ * Some pages are longer than 255 bytes. The actual length of
+ * the page is returned in the header.
+ */
+ len = (buf[2] << 8) | buf[3];
+ if (len <= 255)
+ return buf;
+
+ kfree(buf);
+ buf = kmalloc(len + 4, GFP_KERNEL);
+ result = scsi_vpd_inquiry(sdev, buf, page, len);
+ if (result)
+ goto fail;
+
+ return buf;
+
+ fail:
+ kfree(buf);
+ return NULL;
+}
+EXPORT_SYMBOL_GPL(scsi_get_vpd_page);
+
+/**
* scsi_device_get - get an additional reference to a scsi_device
* @sdev: device to get a reference to
*
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 6eebd0bbe8a..213123b0486 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -40,6 +40,9 @@
#include <linux/moduleparam.h>
#include <linux/scatterlist.h>
#include <linux/blkdev.h>
+#include <linux/crc-t10dif.h>
+
+#include <net/checksum.h>
#include <scsi/scsi.h>
#include <scsi/scsi_cmnd.h>
@@ -48,8 +51,7 @@
#include <scsi/scsicam.h>
#include <scsi/scsi_eh.h>
-#include <linux/stat.h>
-
+#include "sd.h"
#include "scsi_logging.h"
#define SCSI_DEBUG_VERSION "1.81"
@@ -95,6 +97,10 @@ static const char * scsi_debug_version_date = "20070104";
#define DEF_FAKE_RW 0
#define DEF_VPD_USE_HOSTNO 1
#define DEF_SECTOR_SIZE 512
+#define DEF_DIX 0
+#define DEF_DIF 0
+#define DEF_GUARD 0
+#define DEF_ATO 1
/* bit mask values for scsi_debug_opts */
#define SCSI_DEBUG_OPT_NOISE 1
@@ -102,6 +108,8 @@ static const char * scsi_debug_version_date = "20070104";
#define SCSI_DEBUG_OPT_TIMEOUT 4
#define SCSI_DEBUG_OPT_RECOVERED_ERR 8
#define SCSI_DEBUG_OPT_TRANSPORT_ERR 16
+#define SCSI_DEBUG_OPT_DIF_ERR 32
+#define SCSI_DEBUG_OPT_DIX_ERR 64
/* When "every_nth" > 0 then modulo "every_nth" commands:
* - a no response is simulated if SCSI_DEBUG_OPT_TIMEOUT is set
* - a RECOVERED_ERROR is simulated on successful read and write
@@ -144,6 +152,10 @@ static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
static int scsi_debug_fake_rw = DEF_FAKE_RW;
static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
+static int scsi_debug_dix = DEF_DIX;
+static int scsi_debug_dif = DEF_DIF;
+static int scsi_debug_guard = DEF_GUARD;
+static int scsi_debug_ato = DEF_ATO;
static int scsi_debug_cmnd_count = 0;
@@ -204,11 +216,15 @@ struct sdebug_queued_cmd {
static struct sdebug_queued_cmd queued_arr[SCSI_DEBUG_CANQUEUE];
static unsigned char * fake_storep; /* ramdisk storage */
+static unsigned char *dif_storep; /* protection info */
static int num_aborts = 0;
static int num_dev_resets = 0;
static int num_bus_resets = 0;
static int num_host_resets = 0;
+static int dix_writes;
+static int dix_reads;
+static int dif_errors;
static DEFINE_SPINLOCK(queued_arr_lock);
static DEFINE_RWLOCK(atomic_rw);
@@ -217,6 +233,11 @@ static char sdebug_proc_name[] = "scsi_debug";
static struct bus_type pseudo_lld_bus;
+static inline sector_t dif_offset(sector_t sector)
+{
+ return sector << 3;
+}
+
static struct device_driver sdebug_driverfs_driver = {
.name = sdebug_proc_name,
.bus = &pseudo_lld_bus,
@@ -225,6 +246,9 @@ static struct device_driver sdebug_driverfs_driver = {
static const int check_condition_result =
(DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
+static const int illegal_condition_result =
+ (DRIVER_SENSE << 24) | (DID_ABORT << 16) | SAM_STAT_CHECK_CONDITION;
+
static unsigned char ctrl_m_pg[] = {0xa, 10, 2, 0, 0, 0, 0, 0,
0, 0, 0x2, 0x4b};
static unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0, 0, 0, 0, 0,
@@ -726,7 +750,12 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
} else if (0x86 == cmd[2]) { /* extended inquiry */
arr[1] = cmd[2]; /*sanity */
arr[3] = 0x3c; /* number of following entries */
- arr[4] = 0x0; /* no protection stuff */
+ if (scsi_debug_dif == SD_DIF_TYPE3_PROTECTION)
+ arr[4] = 0x4; /* SPT: GRD_CHK:1 */
+ else if (scsi_debug_dif)
+ arr[4] = 0x5; /* SPT: GRD_CHK:1, REF_CHK:1 */
+ else
+ arr[4] = 0x0; /* no protection stuff */
arr[5] = 0x7; /* head of q, ordered + simple q's */
} else if (0x87 == cmd[2]) { /* mode page policy */
arr[1] = cmd[2]; /*sanity */
@@ -767,6 +796,7 @@ static int resp_inquiry(struct scsi_cmnd * scp, int target,
arr[2] = scsi_debug_scsi_level;
arr[3] = 2; /* response_data_format==2 */
arr[4] = SDEBUG_LONG_INQ_SZ - 5;
+ arr[5] = scsi_debug_dif ? 1 : 0; /* PROTECT bit */
if (0 == scsi_debug_vpd_use_hostno)
arr[5] = 0x10; /* claim: implicit TGPS */
arr[6] = 0x10; /* claim: MultiP */
@@ -915,6 +945,12 @@ static int resp_readcap16(struct scsi_cmnd * scp,
arr[9] = (scsi_debug_sector_size >> 16) & 0xff;
arr[10] = (scsi_debug_sector_size >> 8) & 0xff;
arr[11] = scsi_debug_sector_size & 0xff;
+
+ if (scsi_debug_dif) {
+ arr[12] = (scsi_debug_dif - 1) << 1; /* P_TYPE */
+ arr[12] |= 1; /* PROT_EN */
+ }
+
return fill_from_dev_buffer(scp, arr,
min(alloc_len, SDEBUG_READCAP16_ARR_SZ));
}
@@ -1066,6 +1102,10 @@ static int resp_ctrl_m_pg(unsigned char * p, int pcontrol, int target)
ctrl_m_pg[2] |= 0x4;
else
ctrl_m_pg[2] &= ~0x4;
+
+ if (scsi_debug_ato)
+ ctrl_m_pg[5] |= 0x80; /* ATO=1 */
+
memcpy(p, ctrl_m_pg, sizeof(ctrl_m_pg));
if (1 == pcontrol)
memcpy(p + 2, ch_ctrl_m_pg, sizeof(ch_ctrl_m_pg));
@@ -1536,6 +1576,87 @@ static int do_device_access(struct scsi_cmnd *scmd,
return ret;
}
+static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
+ unsigned int sectors)
+{
+ unsigned int i, resid;
+ struct scatterlist *psgl;
+ struct sd_dif_tuple *sdt;
+ sector_t sector;
+ sector_t tmp_sec = start_sec;
+ void *paddr;
+
+ start_sec = do_div(tmp_sec, sdebug_store_sectors);
+
+ sdt = (struct sd_dif_tuple *)(dif_storep + dif_offset(start_sec));
+
+ for (i = 0 ; i < sectors ; i++) {
+ u16 csum;
+
+ if (sdt[i].app_tag == 0xffff)
+ continue;
+
+ sector = start_sec + i;
+
+ switch (scsi_debug_guard) {
+ case 1:
+ csum = ip_compute_csum(fake_storep +
+ sector * scsi_debug_sector_size,
+ scsi_debug_sector_size);
+ break;
+ case 0:
+ csum = crc_t10dif(fake_storep +
+ sector * scsi_debug_sector_size,
+ scsi_debug_sector_size);
+ csum = cpu_to_be16(csum);
+ break;
+ default:
+ BUG();
+ }
+
+ if (sdt[i].guard_tag != csum) {
+ printk(KERN_ERR "%s: GUARD check failed on sector %lu" \
+ " rcvd 0x%04x, data 0x%04x\n", __func__,
+ (unsigned long)sector,
+ be16_to_cpu(sdt[i].guard_tag),
+ be16_to_cpu(csum));
+ dif_errors++;
+ return 0x01;
+ }
+
+ if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION &&
+ be32_to_cpu(sdt[i].ref_tag) != (sector & 0xffffffff)) {
+ printk(KERN_ERR "%s: REF check failed on sector %lu\n",
+ __func__, (unsigned long)sector);
+ dif_errors++;
+ return 0x03;
+ }
+ }
+
+ resid = sectors * 8; /* Bytes of protection data to copy into sgl */
+ sector = start_sec;
+
+ scsi_for_each_prot_sg(SCpnt, psgl, scsi_prot_sg_count(SCpnt), i) {
+ int len = min(psgl->length, resid);
+
+ paddr = kmap_atomic(sg_page(psgl), KM_IRQ0) + psgl->offset;
+ memcpy(paddr, dif_storep + dif_offset(sector), len);
+
+ sector += len >> 3;
+ if (sector >= sdebug_store_sectors) {
+ /* Force wrap */
+ tmp_sec = sector;
+ sector = do_div(tmp_sec, sdebug_store_sectors);
+ }
+ resid -= len;
+ kunmap_atomic(paddr, KM_IRQ0);
+ }
+
+ dix_reads++;
+
+ return 0;
+}
+
static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
unsigned int num, struct sdebug_dev_info *devip)
{
@@ -1563,12 +1684,162 @@ static int resp_read(struct scsi_cmnd *SCpnt, unsigned long long lba,
}
return check_condition_result;
}
+
+ /* DIX + T10 DIF */
+ if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
+ int prot_ret = prot_verify_read(SCpnt, lba, num);
+
+ if (prot_ret) {
+ mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, prot_ret);
+ return illegal_condition_result;
+ }
+ }
+
read_lock_irqsave(&atomic_rw, iflags);
ret = do_device_access(SCpnt, devip, lba, num, 0);
read_unlock_irqrestore(&atomic_rw, iflags);
return ret;
}
+void dump_sector(unsigned char *buf, int len)
+{
+ int i, j;
+
+ printk(KERN_ERR ">>> Sector Dump <<<\n");
+
+ for (i = 0 ; i < len ; i += 16) {
+ printk(KERN_ERR "%04d: ", i);
+
+ for (j = 0 ; j < 16 ; j++) {
+ unsigned char c = buf[i+j];
+ if (c >= 0x20 && c < 0x7e)
+ printk(" %c ", buf[i+j]);
+ else
+ printk("%02x ", buf[i+j]);
+ }
+
+ printk("\n");
+ }
+}
+
+static int prot_verify_write(struct scsi_cmnd *SCpnt, sector_t start_sec,
+ unsigned int sectors)
+{
+ int i, j, ret;
+ struct sd_dif_tuple *sdt;
+ struct scatterlist *dsgl = scsi_sglist(SCpnt);
+ struct scatterlist *psgl = scsi_prot_sglist(SCpnt);
+ void *daddr, *paddr;
+ sector_t tmp_sec = start_sec;
+ sector_t sector;
+ int ppage_offset;
+ unsigned short csum;
+
+ sector = do_div(tmp_sec, sdebug_store_sectors);
+
+ if (((SCpnt->cmnd[1] >> 5) & 7) != 1) {
+ printk(KERN_WARNING "scsi_debug: WRPROTECT != 1\n");
+ return 0;
+ }
+
+ BUG_ON(scsi_sg_count(SCpnt) == 0);
+ BUG_ON(scsi_prot_sg_count(SCpnt) == 0);
+
+ paddr = kmap_atomic(sg_page(psgl), KM_IRQ1) + psgl->offset;
+ ppage_offset = 0;
+
+ /* For each data page */
+ scsi_for_each_sg(SCpnt, dsgl, scsi_sg_count(SCpnt), i) {
+ daddr = kmap_atomic(sg_page(dsgl), KM_IRQ0) + dsgl->offset;
+
+ /* For each sector-sized chunk in data page */
+ for (j = 0 ; j < dsgl->length ; j += scsi_debug_sector_size) {
+
+ /* If we're at the end of the current
+ * protection page advance to the next one
+ */
+ if (ppage_offset >= psgl->length) {
+ kunmap_atomic(paddr, KM_IRQ1);
+ psgl = sg_next(psgl);
+ BUG_ON(psgl == NULL);
+ paddr = kmap_atomic(sg_page(psgl), KM_IRQ1)
+ + psgl->offset;
+ ppage_offset = 0;
+ }
+
+ sdt = paddr + ppage_offset;
+
+ switch (scsi_debug_guard) {
+ case 1:
+ csum = ip_compute_csum(daddr,
+ scsi_debug_sector_size);
+ break;
+ case 0:
+ csum = cpu_to_be16(crc_t10dif(daddr,
+ scsi_debug_sector_size));
+ break;
+ default:
+ BUG();
+ ret = 0;
+ goto out;
+ }
+
+ if (sdt->guard_tag != csum) {
+ printk(KERN_ERR
+ "%s: GUARD check failed on sector %lu " \
+ "rcvd 0x%04x, calculated 0x%04x\n",
+ __func__, (unsigned long)sector,
+ be16_to_cpu(sdt->guard_tag),
+ be16_to_cpu(csum));
+ ret = 0x01;
+ dump_sector(daddr, scsi_debug_sector_size);
+ goto out;
+ }
+
+ if (scsi_debug_dif != SD_DIF_TYPE3_PROTECTION &&
+ be32_to_cpu(sdt->ref_tag)
+ != (start_sec & 0xffffffff)) {
+ printk(KERN_ERR
+ "%s: REF check failed on sector %lu\n",
+ __func__, (unsigned long)sector);
+ ret = 0x03;
+ dump_sector(daddr, scsi_debug_sector_size);
+ goto out;
+ }
+
+ /* Would be great to copy this in bigger
+ * chunks. However, for the sake of
+ * correctness we need to verify each sector
+ * before writing it to "stable" storage
+ */
+ memcpy(dif_storep + dif_offset(sector), sdt, 8);
+
+ sector++;
+
+ if (sector == sdebug_store_sectors)
+ sector = 0; /* Force wrap */
+
+ start_sec++;
+ daddr += scsi_debug_sector_size;
+ ppage_offset += sizeof(struct sd_dif_tuple);
+ }
+
+ kunmap_atomic(daddr, KM_IRQ0);
+ }
+
+ kunmap_atomic(paddr, KM_IRQ1);
+
+ dix_writes++;
+
+ return 0;
+
+out:
+ dif_errors++;
+ kunmap_atomic(daddr, KM_IRQ0);
+ kunmap_atomic(paddr, KM_IRQ1);
+ return ret;
+}
+
static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
unsigned int num, struct sdebug_dev_info *devip)
{
@@ -1579,6 +1850,16 @@ static int resp_write(struct scsi_cmnd *SCpnt, unsigned long long lba,
if (ret)
return ret;
+ /* DIX + T10 DIF */
+ if (scsi_debug_dix && scsi_prot_sg_count(SCpnt)) {
+ int prot_ret = prot_verify_write(SCpnt, lba, num);
+
+ if (prot_ret) {
+ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, prot_ret);
+ return illegal_condition_result;
+ }
+ }
+
write_lock_irqsave(&atomic_rw, iflags);
ret = do_device_access(SCpnt, devip, lba, num, 1);
write_unlock_irqrestore(&atomic_rw, iflags);
@@ -2095,6 +2376,10 @@ module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
S_IRUGO | S_IWUSR);
module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
+module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
+module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
+module_param_named(guard, scsi_debug_guard, int, S_IRUGO);
+module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2117,7 +2402,10 @@ MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
MODULE_PARM_DESC(sector_size, "hardware sector size in bytes (def=512)");
-
+MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
+MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
+MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
+MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
static char sdebug_info[256];
@@ -2164,14 +2452,14 @@ static int scsi_debug_proc_info(struct Scsi_Host *host, char *buffer, char **sta
"delay=%d, max_luns=%d, scsi_level=%d\n"
"sector_size=%d bytes, cylinders=%d, heads=%d, sectors=%d\n"
"number of aborts=%d, device_reset=%d, bus_resets=%d, "
- "host_resets=%d\n",
+ "host_resets=%d\ndix_reads=%d dix_writes=%d dif_errors=%d\n",
SCSI_DEBUG_VERSION, scsi_debug_version_date, scsi_debug_num_tgts,
scsi_debug_dev_size_mb, scsi_debug_opts, scsi_debug_every_nth,
scsi_debug_cmnd_count, scsi_debug_delay,
scsi_debug_max_luns, scsi_debug_scsi_level,
scsi_debug_sector_size, sdebug_cylinders_per, sdebug_heads,
sdebug_sectors_per, num_aborts, num_dev_resets, num_bus_resets,
- num_host_resets);
+ num_host_resets, dix_reads, dix_writes, dif_errors);
if (pos < offset) {
len = 0;
begin = pos;
@@ -2452,6 +2740,31 @@ static ssize_t sdebug_sector_size_show(struct device_driver * ddp, char * buf)
}
DRIVER_ATTR(sector_size, S_IRUGO, sdebug_sector_size_show, NULL);
+static ssize_t sdebug_dix_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dix);
+}
+DRIVER_ATTR(dix, S_IRUGO, sdebug_dix_show, NULL);
+
+static ssize_t sdebug_dif_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_dif);
+}
+DRIVER_ATTR(dif, S_IRUGO, sdebug_dif_show, NULL);
+
+static ssize_t sdebug_guard_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_guard);
+}
+DRIVER_ATTR(guard, S_IRUGO, sdebug_guard_show, NULL);
+
+static ssize_t sdebug_ato_show(struct device_driver *ddp, char *buf)
+{
+ return scnprintf(buf, PAGE_SIZE, "%d\n", scsi_debug_ato);
+}
+DRIVER_ATTR(ato, S_IRUGO, sdebug_ato_show, NULL);
+
+
/* Note: The following function creates attribute files in the
/sys/bus/pseudo/drivers/scsi_debug directory. The advantage of these
files (over those found in the /sys/module/scsi_debug/parameters
@@ -2478,11 +2791,19 @@ static int do_create_driverfs_files(void)
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb);
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno);
ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_sector_size);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dix);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_dif);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_guard);
+ ret |= driver_create_file(&sdebug_driverfs_driver, &driver_attr_ato);
return ret;
}
static void do_remove_driverfs_files(void)
{
+ driver_remove_file(&sdebug_driverfs_driver, &driver_attr_ato);
+ driver_remove_file(&sdebug_driverfs_driver, &driver_attr_guard);
+ driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dif);
+ driver_remove_file(&sdebug_driverfs_driver, &driver_attr_dix);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_sector_size);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_vpd_use_hostno);
driver_remove_file(&sdebug_driverfs_driver, &driver_attr_virtual_gb);
@@ -2526,11 +2847,33 @@ static int __init scsi_debug_init(void)
case 4096:
break;
default:
- printk(KERN_ERR "scsi_debug_init: invalid sector_size %u\n",
+ printk(KERN_ERR "scsi_debug_init: invalid sector_size %d\n",
scsi_debug_sector_size);
return -EINVAL;
}
+ switch (scsi_debug_dif) {
+
+ case SD_DIF_TYPE0_PROTECTION:
+ case SD_DIF_TYPE1_PROTECTION:
+ case SD_DIF_TYPE3_PROTECTION:
+ break;
+
+ default:
+ printk(KERN_ERR "scsi_debug_init: dif must be 0, 1 or 3\n");
+ return -EINVAL;
+ }
+
+ if (scsi_debug_guard > 1) {
+ printk(KERN_ERR "scsi_debug_init: guard must be 0 or 1\n");
+ return -EINVAL;
+ }
+
+ if (scsi_debug_ato > 1) {
+ printk(KERN_ERR "scsi_debug_init: ato must be 0 or 1\n");
+ return -EINVAL;
+ }
+
if (scsi_debug_dev_size_mb < 1)
scsi_debug_dev_size_mb = 1; /* force minimum 1 MB ramdisk */
sz = (unsigned long)scsi_debug_dev_size_mb * 1048576;
@@ -2563,6 +2906,24 @@ static int __init scsi_debug_init(void)
if (scsi_debug_num_parts > 0)
sdebug_build_parts(fake_storep, sz);
+ if (scsi_debug_dif) {
+ int dif_size;
+
+ dif_size = sdebug_store_sectors * sizeof(struct sd_dif_tuple);
+ dif_storep = vmalloc(dif_size);
+
+ printk(KERN_ERR "scsi_debug_init: dif_storep %u bytes @ %p\n",
+ dif_size, dif_storep);
+
+ if (dif_storep == NULL) {
+ printk(KERN_ERR "scsi_debug_init: out of mem. (DIX)\n");
+ ret = -ENOMEM;
+ goto free_vm;
+ }
+
+ memset(dif_storep, 0xff, dif_size);
+ }
+
ret = device_register(&pseudo_primary);
if (ret < 0) {
printk(KERN_WARNING "scsi_debug: device_register error: %d\n",
@@ -2615,6 +2976,8 @@ bus_unreg:
dev_unreg:
device_unregister(&pseudo_primary);
free_vm:
+ if (dif_storep)
+ vfree(dif_storep);
vfree(fake_storep);
return ret;
@@ -2632,6 +2995,9 @@ static void __exit scsi_debug_exit(void)
bus_unregister(&pseudo_lld_bus);
device_unregister(&pseudo_primary);
+ if (dif_storep)
+ vfree(dif_storep);
+
vfree(fake_storep);
}
@@ -2732,6 +3098,8 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
struct sdebug_dev_info *devip = NULL;
int inj_recovered = 0;
int inj_transport = 0;
+ int inj_dif = 0;
+ int inj_dix = 0;
int delay_override = 0;
scsi_set_resid(SCpnt, 0);
@@ -2769,6 +3137,10 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
inj_recovered = 1; /* to reads and writes below */
else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
inj_transport = 1; /* to reads and writes below */
+ else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts)
+ inj_dif = 1; /* to reads and writes below */
+ else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts)
+ inj_dix = 1; /* to reads and writes below */
}
if (devip->wlun) {
@@ -2870,6 +3242,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
mk_sense_buffer(devip, ABORTED_COMMAND,
TRANSPORT_PROBLEM, ACK_NAK_TO);
errsts = check_condition_result;
+ } else if (inj_dif && (0 == errsts)) {
+ mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
+ errsts = illegal_condition_result;
+ } else if (inj_dix && (0 == errsts)) {
+ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
+ errsts = illegal_condition_result;
}
break;
case REPORT_LUNS: /* mandatory, ignore unit attention */
@@ -2894,6 +3272,12 @@ int scsi_debug_queuecommand(struct scsi_cmnd *SCpnt, done_funct_t done)
mk_sense_buffer(devip, RECOVERED_ERROR,
THRESHOLD_EXCEEDED, 0);
errsts = check_condition_result;
+ } else if (inj_dif && (0 == errsts)) {
+ mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
+ errsts = illegal_condition_result;
+ } else if (inj_dix && (0 == errsts)) {
+ mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
+ errsts = illegal_condition_result;
}
break;
case MODE_SENSE:
@@ -2982,6 +3366,7 @@ static int sdebug_driver_probe(struct device * dev)
int error = 0;
struct sdebug_host_info *sdbg_host;
struct Scsi_Host *hpnt;
+ int host_prot;
sdbg_host = to_sdebug_host(dev);
@@ -3000,6 +3385,50 @@ static int sdebug_driver_probe(struct device * dev)
hpnt->max_id = scsi_debug_num_tgts;
hpnt->max_lun = SAM2_WLUN_REPORT_LUNS; /* = scsi_debug_max_luns; */
+ host_prot = 0;
+
+ switch (scsi_debug_dif) {
+
+ case SD_DIF_TYPE1_PROTECTION:
+ host_prot = SHOST_DIF_TYPE1_PROTECTION;
+ if (scsi_debug_dix)
+ host_prot |= SHOST_DIX_TYPE1_PROTECTION;
+ break;
+
+ case SD_DIF_TYPE2_PROTECTION:
+ host_prot = SHOST_DIF_TYPE2_PROTECTION;
+ if (scsi_debug_dix)
+ host_prot |= SHOST_DIX_TYPE2_PROTECTION;
+ break;
+
+ case SD_DIF_TYPE3_PROTECTION:
+ host_prot = SHOST_DIF_TYPE3_PROTECTION;
+ if (scsi_debug_dix)
+ host_prot |= SHOST_DIX_TYPE3_PROTECTION;
+ break;
+
+ default:
+ if (scsi_debug_dix)
+ host_prot |= SHOST_DIX_TYPE0_PROTECTION;
+ break;
+ }
+
+ scsi_host_set_prot(hpnt, host_prot);
+
+ printk(KERN_INFO "scsi_debug: host protection%s%s%s%s%s%s%s\n",
+ (host_prot & SHOST_DIF_TYPE1_PROTECTION) ? " DIF1" : "",
+ (host_prot & SHOST_DIF_TYPE2_PROTECTION) ? " DIF2" : "",
+ (host_prot & SHOST_DIF_TYPE3_PROTECTION) ? " DIF3" : "",
+ (host_prot & SHOST_DIX_TYPE0_PROTECTION) ? " DIX0" : "",
+ (host_prot & SHOST_DIX_TYPE1_PROTECTION) ? " DIX1" : "",
+ (host_prot & SHOST_DIX_TYPE2_PROTECTION) ? " DIX2" : "",
+ (host_prot & SHOST_DIX_TYPE3_PROTECTION) ? " DIX3" : "");
+
+ if (scsi_debug_guard == 1)
+ scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_IP);
+ else
+ scsi_host_set_guard(hpnt, SHOST_DIX_GUARD_CRC);
+
error = scsi_add_host(hpnt, &sdbg_host->dev);
if (error) {
printk(KERN_ERR "%s: scsi_add_host failed\n", __func__);
diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c
index 099b5455bbc..b1348136964 100644
--- a/drivers/scsi/scsi_devinfo.c
+++ b/drivers/scsi/scsi_devinfo.c
@@ -596,8 +596,6 @@ int __init scsi_init_devinfo(void)
error = -ENOMEM;
goto out;
}
-
- p->owner = THIS_MODULE;
#endif /* CONFIG_SCSI_PROC_FS */
out:
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index ad6a1370761..0c2c73be197 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -1441,6 +1441,11 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
}
}
+static void eh_lock_door_done(struct request *req, int uptodate)
+{
+ __blk_put_request(req->q, req);
+}
+
/**
* scsi_eh_lock_door - Prevent medium removal for the specified device
* @sdev: SCSI device to prevent medium removal
@@ -1463,19 +1468,28 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
*/
static void scsi_eh_lock_door(struct scsi_device *sdev)
{
- unsigned char cmnd[MAX_COMMAND_SIZE];
+ struct request *req;
- cmnd[0] = ALLOW_MEDIUM_REMOVAL;
- cmnd[1] = 0;
- cmnd[2] = 0;
- cmnd[3] = 0;
- cmnd[4] = SCSI_REMOVAL_PREVENT;
- cmnd[5] = 0;
+ req = blk_get_request(sdev->request_queue, READ, GFP_KERNEL);
+ if (!req)
+ return;
- scsi_execute_async(sdev, cmnd, 6, DMA_NONE, NULL, 0, 0, 10 * HZ,
- 5, NULL, NULL, GFP_KERNEL);
-}
+ req->cmd[0] = ALLOW_MEDIUM_REMOVAL;
+ req->cmd[1] = 0;
+ req->cmd[2] = 0;
+ req->cmd[3] = 0;
+ req->cmd[4] = SCSI_REMOVAL_PREVENT;
+ req->cmd[5] = 0;
+ req->cmd_len = COMMAND_SIZE(req->cmd[0]);
+
+ req->cmd_type = REQ_TYPE_BLOCK_PC;
+ req->cmd_flags |= REQ_QUIET;
+ req->timeout = 10 * HZ;
+ req->retries = 5;
+
+ blk_execute_rq_nowait(req->q, NULL, req, 1, eh_lock_door_done);
+}
/**
* scsi_restart_operations - restart io operations to the specified host.
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 940dc32ff0d..d1cb64ad1a3 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -277,196 +277,6 @@ int scsi_execute_req(struct scsi_device *sdev, const unsigned char *cmd,
}
EXPORT_SYMBOL(scsi_execute_req);
-struct scsi_io_context {
- void *data;
- void (*done)(void *data, char *sense, int result, int resid);
- char sense[SCSI_SENSE_BUFFERSIZE];
-};
-
-static struct kmem_cache *scsi_io_context_cache;
-
-static void scsi_end_async(struct request *req, int uptodate)
-{
- struct scsi_io_context *sioc = req->end_io_data;
-
- if (sioc->done)
- sioc->done(sioc->data, sioc->sense, req->errors, req->data_len);
-
- kmem_cache_free(scsi_io_context_cache, sioc);
- __blk_put_request(req->q, req);
-}
-
-static int scsi_merge_bio(struct request *rq, struct bio *bio)
-{
- struct request_queue *q = rq->q;
-
- bio->bi_flags &= ~(1 << BIO_SEG_VALID);
- if (rq_data_dir(rq) == WRITE)
- bio->bi_rw |= (1 << BIO_RW);
- blk_queue_bounce(q, &bio);
-
- return blk_rq_append_bio(q, rq, bio);
-}
-
-static void scsi_bi_endio(struct bio *bio, int error)
-{
- bio_put(bio);
-}
-
-/**
- * scsi_req_map_sg - map a scatterlist into a request
- * @rq: request to fill
- * @sgl: scatterlist
- * @nsegs: number of elements
- * @bufflen: len of buffer
- * @gfp: memory allocation flags
- *
- * scsi_req_map_sg maps a scatterlist into a request so that the
- * request can be sent to the block layer. We do not trust the scatterlist
- * sent to use, as some ULDs use that struct to only organize the pages.
- */
-static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl,
- int nsegs, unsigned bufflen, gfp_t gfp)
-{
- struct request_queue *q = rq->q;
- int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
- unsigned int data_len = bufflen, len, bytes, off;
- struct scatterlist *sg;
- struct page *page;
- struct bio *bio = NULL;
- int i, err, nr_vecs = 0;
-
- for_each_sg(sgl, sg, nsegs, i) {
- page = sg_page(sg);
- off = sg->offset;
- len = sg->length;
-
- while (len > 0 && data_len > 0) {
- /*
- * sg sends a scatterlist that is larger than
- * the data_len it wants transferred for certain
- * IO sizes
- */
- bytes = min_t(unsigned int, len, PAGE_SIZE - off);
- bytes = min(bytes, data_len);
-
- if (!bio) {
- nr_vecs = min_t(int, BIO_MAX_PAGES, nr_pages);
- nr_pages -= nr_vecs;
-
- bio = bio_alloc(gfp, nr_vecs);
- if (!bio) {
- err = -ENOMEM;
- goto free_bios;
- }
- bio->bi_end_io = scsi_bi_endio;
- }
-
- if (bio_add_pc_page(q, bio, page, bytes, off) !=
- bytes) {
- bio_put(bio);
- err = -EINVAL;
- goto free_bios;
- }
-
- if (bio->bi_vcnt >= nr_vecs) {
- err = scsi_merge_bio(rq, bio);
- if (err) {
- bio_endio(bio, 0);
- goto free_bios;
- }
- bio = NULL;
- }
-
- page++;
- len -= bytes;
- data_len -=bytes;
- off = 0;
- }
- }
-
- rq->buffer = rq->data = NULL;
- rq->data_len = bufflen;
- return 0;
-
-free_bios:
- while ((bio = rq->bio) != NULL) {
- rq->bio = bio->bi_next;
- /*
- * call endio instead of bio_put incase it was bounced
- */
- bio_endio(bio, 0);
- }
-
- return err;
-}
-
-/**
- * scsi_execute_async - insert request
- * @sdev: scsi device
- * @cmd: scsi command
- * @cmd_len: length of scsi cdb
- * @data_direction: DMA_TO_DEVICE, DMA_FROM_DEVICE, or DMA_NONE
- * @buffer: data buffer (this can be a kernel buffer or scatterlist)
- * @bufflen: len of buffer
- * @use_sg: if buffer is a scatterlist this is the number of elements
- * @timeout: request timeout in seconds
- * @retries: number of times to retry request
- * @privdata: data passed to done()
- * @done: callback function when done
- * @gfp: memory allocation flags
- */
-int scsi_execute_async(struct scsi_device *sdev, const unsigned char *cmd,
- int cmd_len, int data_direction, void *buffer, unsigned bufflen,
- int use_sg, int timeout, int retries, void *privdata,
- void (*done)(void *, char *, int, int), gfp_t gfp)
-{
- struct request *req;
- struct scsi_io_context *sioc;
- int err = 0;
- int write = (data_direction == DMA_TO_DEVICE);
-
- sioc = kmem_cache_zalloc(scsi_io_context_cache, gfp);
- if (!sioc)
- return DRIVER_ERROR << 24;
-
- req = blk_get_request(sdev->request_queue, write, gfp);
- if (!req)
- goto free_sense;
- req->cmd_type = REQ_TYPE_BLOCK_PC;
- req->cmd_flags |= REQ_QUIET;
-
- if (use_sg)
- err = scsi_req_map_sg(req, buffer, use_sg, bufflen, gfp);
- else if (bufflen)
- err = blk_rq_map_kern(req->q, req, buffer, bufflen, gfp);
-
- if (err)
- goto free_req;
-
- req->cmd_len = cmd_len;
- memset(req->cmd, 0, BLK_MAX_CDB); /* ATAPI hates garbage after CDB */
- memcpy(req->cmd, cmd, req->cmd_len);
- req->sense = sioc->sense;
- req->sense_len = 0;
- req->timeout = timeout;
- req->retries = retries;
- req->end_io_data = sioc;
-
- sioc->data = privdata;
- sioc->done = done;
-
- blk_execute_rq_nowait(req->q, NULL, req, 1, scsi_end_async);
- return 0;
-
-free_req:
- blk_put_request(req);
-free_sense:
- kmem_cache_free(scsi_io_context_cache, sioc);
- return DRIVER_ERROR << 24;
-}
-EXPORT_SYMBOL_GPL(scsi_execute_async);
-
/*
* Function: scsi_init_cmd_errh()
*
@@ -981,7 +791,22 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
"%d bytes done.\n",
req->nr_sectors, good_bytes));
- /* A number of bytes were successfully read. If there
+ /*
+ * Recovered errors need reporting, but they're always treated
+ * as success, so fiddle the result code here. For BLOCK_PC
+ * we already took a copy of the original into rq->errors which
+ * is what gets returned to the user
+ */
+ if (sense_valid && sshdr.sense_key == RECOVERED_ERROR) {
+ if (!(req->cmd_flags & REQ_QUIET))
+ scsi_print_sense("", cmd);
+ result = 0;
+ /* BLOCK_PC may have set error */
+ error = 0;
+ }
+
+ /*
+ * A number of bytes were successfully read. If there
* are leftovers and there is some kind of error
* (result != 0), retry the rest.
*/
@@ -1040,12 +865,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
action = ACTION_FAIL;
break;
case ABORTED_COMMAND:
+ action = ACTION_FAIL;
if (sshdr.asc == 0x10) { /* DIF */
description = "Target Data Integrity Failure";
- action = ACTION_FAIL;
error = -EILSEQ;
- } else
- action = ACTION_RETRY;
+ }
break;
case NOT_READY:
/* If the device is in the process of becoming
@@ -1921,20 +1745,12 @@ int __init scsi_init_queue(void)
{
int i;
- scsi_io_context_cache = kmem_cache_create("scsi_io_context",
- sizeof(struct scsi_io_context),
- 0, 0, NULL);
- if (!scsi_io_context_cache) {
- printk(KERN_ERR "SCSI: can't init scsi io context cache\n");
- return -ENOMEM;
- }
-
scsi_sdb_cache = kmem_cache_create("scsi_data_buffer",
sizeof(struct scsi_data_buffer),
0, 0, NULL);
if (!scsi_sdb_cache) {
printk(KERN_ERR "SCSI: can't init scsi sdb cache\n");
- goto cleanup_io_context;
+ return -ENOMEM;
}
for (i = 0; i < SG_MEMPOOL_NR; i++) {
@@ -1969,8 +1785,6 @@ cleanup_sdb:
kmem_cache_destroy(sgp->slab);
}
kmem_cache_destroy(scsi_sdb_cache);
-cleanup_io_context:
- kmem_cache_destroy(scsi_io_context_cache);
return -ENOMEM;
}
@@ -1979,7 +1793,6 @@ void scsi_exit_queue(void)
{
int i;
- kmem_cache_destroy(scsi_io_context_cache);
kmem_cache_destroy(scsi_sdb_cache);
for (i = 0; i < SG_MEMPOOL_NR; i++) {
diff --git a/drivers/scsi/scsi_proc.c b/drivers/scsi/scsi_proc.c
index 82f7b2dd08a..77fbddb507f 100644
--- a/drivers/scsi/scsi_proc.c
+++ b/drivers/scsi/scsi_proc.c
@@ -115,8 +115,6 @@ void scsi_proc_hostdir_add(struct scsi_host_template *sht)
if (!sht->proc_dir)
printk(KERN_ERR "%s: proc_mkdir failed for %s\n",
__func__, sht->proc_name);
- else
- sht->proc_dir->owner = sht->module;
}
mutex_unlock(&global_host_template_mutex);
}
@@ -163,7 +161,6 @@ void scsi_proc_host_add(struct Scsi_Host *shost)
}
p->write_proc = proc_scsi_write_proc;
- p->owner = sht->module;
}
/**
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index 66505bb7941..a14d245a66b 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -317,6 +317,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
return sdev;
out_device_destroy:
+ scsi_device_set_state(sdev, SDEV_DEL);
transport_destroy_device(&sdev->sdev_gendev);
put_device(&sdev->sdev_gendev);
out:
@@ -796,6 +797,7 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
case TYPE_ENCLOSURE:
case TYPE_COMM:
case TYPE_RAID:
+ case TYPE_OSD:
sdev->writeable = 1;
break;
case TYPE_ROM:
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index da63802cbf9..fa4711d1274 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1043,7 +1043,6 @@ EXPORT_SYMBOL(scsi_register_interface);
/**
* scsi_sysfs_add_host - add scsi host to subsystem
* @shost: scsi host struct to add to subsystem
- * @dev: parent struct device pointer
**/
int scsi_sysfs_add_host(struct Scsi_Host *shost)
{
diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c
index 5f77417ed58..a152f89ae51 100644
--- a/drivers/scsi/scsi_transport_fc.c
+++ b/drivers/scsi/scsi_transport_fc.c
@@ -95,7 +95,7 @@ static struct {
{ FC_PORTTYPE_NPORT, "NPort (fabric via point-to-point)" },
{ FC_PORTTYPE_NLPORT, "NLPort (fabric via loop)" },
{ FC_PORTTYPE_LPORT, "LPort (private loop)" },
- { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection" },
+ { FC_PORTTYPE_PTP, "Point-To-Point (direct nport connection)" },
{ FC_PORTTYPE_NPIV, "NPIV VPORT" },
};
fc_enum_name_search(port_type, fc_port_type, fc_port_type_names)
@@ -533,12 +533,8 @@ fc_host_post_event(struct Scsi_Host *shost, u32 event_number,
event->event_code = event_code;
event->event_data = event_data;
- err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
- GFP_KERNEL);
- if (err && (err != -ESRCH)) /* filter no recipient errors */
- /* nlmsg_multicast already kfree_skb'd */
- goto send_fail;
-
+ nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
+ GFP_KERNEL);
return;
send_fail_skb:
@@ -607,12 +603,8 @@ fc_host_post_vendor_event(struct Scsi_Host *shost, u32 event_number,
event->event_code = FCH_EVT_VENDOR_UNIQUE;
memcpy(&event->event_data, data_buf, data_len);
- err = nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
- GFP_KERNEL);
- if (err && (err != -ESRCH)) /* filter no recipient errors */
- /* nlmsg_multicast already kfree_skb'd */
- goto send_vendor_fail;
-
+ nlmsg_multicast(scsi_nl_sock, skb, 0, SCSI_NL_GRP_FC_EVENTS,
+ GFP_KERNEL);
return;
send_vendor_fail_skb:
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c
index 75c9297694c..09479545529 100644
--- a/drivers/scsi/scsi_transport_iscsi.c
+++ b/drivers/scsi/scsi_transport_iscsi.c
@@ -246,30 +246,13 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
memset(ihost, 0, sizeof(*ihost));
atomic_set(&ihost->nr_scans, 0);
mutex_init(&ihost->mutex);
-
- snprintf(ihost->scan_workq_name, sizeof(ihost->scan_workq_name),
- "iscsi_scan_%d", shost->host_no);
- ihost->scan_workq = create_singlethread_workqueue(
- ihost->scan_workq_name);
- if (!ihost->scan_workq)
- return -ENOMEM;
- return 0;
-}
-
-static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
- struct device *cdev)
-{
- struct Scsi_Host *shost = dev_to_shost(dev);
- struct iscsi_cls_host *ihost = shost->shost_data;
-
- destroy_workqueue(ihost->scan_workq);
return 0;
}
static DECLARE_TRANSPORT_CLASS(iscsi_host_class,
"iscsi_host",
iscsi_setup_host,
- iscsi_remove_host,
+ NULL,
NULL);
static DECLARE_TRANSPORT_CLASS(iscsi_session_class,
@@ -568,7 +551,7 @@ static void __iscsi_unblock_session(struct work_struct *work)
* scanning from userspace).
*/
if (shost->hostt->scan_finished) {
- if (queue_work(ihost->scan_workq, &session->scan_work))
+ if (scsi_queue_work(shost, &session->scan_work))
atomic_inc(&ihost->nr_scans);
}
}
@@ -636,14 +619,6 @@ static void __iscsi_unbind_session(struct work_struct *work)
iscsi_session_event(session, ISCSI_KEVENT_UNBIND_SESSION);
}
-static int iscsi_unbind_session(struct iscsi_cls_session *session)
-{
- struct Scsi_Host *shost = iscsi_session_to_shost(session);
- struct iscsi_cls_host *ihost = shost->shost_data;
-
- return queue_work(ihost->scan_workq, &session->unbind_work);
-}
-
struct iscsi_cls_session *
iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport,
int dd_size)
@@ -796,7 +771,6 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)
void iscsi_remove_session(struct iscsi_cls_session *session)
{
struct Scsi_Host *shost = iscsi_session_to_shost(session);
- struct iscsi_cls_host *ihost = shost->shost_data;
unsigned long flags;
int err;
@@ -821,7 +795,7 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
scsi_target_unblock(&session->dev);
/* flush running scans then delete devices */
- flush_workqueue(ihost->scan_workq);
+ scsi_flush_work(shost);
__iscsi_unbind_session(&session->unbind_work);
/* hw iscsi may not have removed all connections from session */
@@ -966,15 +940,7 @@ iscsi_if_transport_lookup(struct iscsi_transport *tt)
static int
iscsi_broadcast_skb(struct sk_buff *skb, gfp_t gfp)
{
- int rc;
-
- rc = netlink_broadcast(nls, skb, 0, 1, gfp);
- if (rc < 0) {
- printk(KERN_ERR "iscsi: can not broadcast skb (%d)\n", rc);
- return rc;
- }
-
- return 0;
+ return netlink_broadcast(nls, skb, 0, 1, gfp);
}
static int
@@ -1207,7 +1173,7 @@ int iscsi_session_event(struct iscsi_cls_session *session,
* the user and when the daemon is restarted it will handle it
*/
rc = iscsi_broadcast_skb(skb, GFP_KERNEL);
- if (rc < 0)
+ if (rc == -ESRCH)
iscsi_cls_session_printk(KERN_ERR, session,
"Cannot notify userspace of session "
"event %u. Check iscsi daemon\n",
@@ -1223,14 +1189,15 @@ iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep,
{
struct iscsi_transport *transport = priv->iscsi_transport;
struct iscsi_cls_session *session;
- uint32_t host_no;
+ struct Scsi_Host *shost;
session = transport->create_session(ep, cmds_max, queue_depth,
- initial_cmdsn, &host_no);
+ initial_cmdsn);
if (!session)
return -ENOMEM;
- ev->r.c_session_ret.host_no = host_no;
+ shost = iscsi_session_to_shost(session);
+ ev->r.c_session_ret.host_no = shost->host_no;
ev->r.c_session_ret.sid = session->sid;
return 0;
}
@@ -1447,7 +1414,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
case ISCSI_UEVENT_UNBIND_SESSION:
session = iscsi_session_lookup(ev->u.d_session.sid);
if (session)
- iscsi_unbind_session(session);
+ scsi_queue_work(iscsi_session_to_shost(session),
+ &session->unbind_work);
else
err = -EINVAL;
break;
@@ -1809,8 +1777,7 @@ iscsi_register_transport(struct iscsi_transport *tt)
priv->daemon_pid = -1;
priv->iscsi_transport = tt;
priv->t.user_scan = iscsi_user_scan;
- if (!(tt->caps & CAP_DATA_PATH_OFFLOAD))
- priv->t.create_work_queue = 1;
+ priv->t.create_work_queue = 1;
priv->dev.class = &iscsi_transport_class;
dev_set_name(&priv->dev, "%s", tt->name);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index d57566b8be0..3fcb64b91c4 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -107,6 +107,7 @@ static void scsi_disk_release(struct device *cdev);
static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *);
static void sd_print_result(struct scsi_disk *, int);
+static DEFINE_SPINLOCK(sd_index_lock);
static DEFINE_IDA(sd_index_ida);
/* This semaphore is used to mediate the 0->1 reference get in the
@@ -1050,12 +1051,6 @@ static int sd_done(struct scsi_cmnd *SCpnt)
good_bytes = sd_completed_bytes(SCpnt);
break;
case RECOVERED_ERROR:
- /* Inform the user, but make sure that it's not treated
- * as a hard error.
- */
- scsi_print_sense("sd", SCpnt);
- SCpnt->result = 0;
- memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
good_bytes = scsi_bufflen(SCpnt);
break;
case NO_SENSE:
@@ -1166,23 +1161,19 @@ sd_spinup_disk(struct scsi_disk *sdkp)
/*
* The device does not want the automatic start to be issued.
*/
- if (sdkp->device->no_start_on_add) {
+ if (sdkp->device->no_start_on_add)
break;
- }
-
- /*
- * If manual intervention is required, or this is an
- * absent USB storage device, a spinup is meaningless.
- */
- if (sense_valid &&
- sshdr.sense_key == NOT_READY &&
- sshdr.asc == 4 && sshdr.ascq == 3) {
- break; /* manual intervention required */
- /*
- * Issue command to spin up drive when not ready
- */
- } else if (sense_valid && sshdr.sense_key == NOT_READY) {
+ if (sense_valid && sshdr.sense_key == NOT_READY) {
+ if (sshdr.asc == 4 && sshdr.ascq == 3)
+ break; /* manual intervention required */
+ if (sshdr.asc == 4 && sshdr.ascq == 0xb)
+ break; /* standby */
+ if (sshdr.asc == 4 && sshdr.ascq == 0xc)
+ break; /* unavailable */
+ /*
+ * Issue command to spin up drive when not ready
+ */
if (!spintime) {
sd_printk(KERN_NOTICE, sdkp, "Spinning up disk...");
cmd[0] = START_STOP;
@@ -1276,42 +1267,126 @@ disable:
sdkp->capacity = 0;
}
-/*
- * read disk capacity
- */
-static void
-sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
+static void read_capacity_error(struct scsi_disk *sdkp, struct scsi_device *sdp,
+ struct scsi_sense_hdr *sshdr, int sense_valid,
+ int the_result)
+{
+ sd_print_result(sdkp, the_result);
+ if (driver_byte(the_result) & DRIVER_SENSE)
+ sd_print_sense_hdr(sdkp, sshdr);
+ else
+ sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n");
+
+ /*
+ * Set dirty bit for removable devices if not ready -
+ * sometimes drives will not report this properly.
+ */
+ if (sdp->removable &&
+ sense_valid && sshdr->sense_key == NOT_READY)
+ sdp->changed = 1;
+
+ /*
+ * We used to set media_present to 0 here to indicate no media
+ * in the drive, but some drives fail read capacity even with
+ * media present, so we can't do that.
+ */
+ sdkp->capacity = 0; /* unknown mapped to zero - as usual */
+}
+
+#define RC16_LEN 32
+#if RC16_LEN > SD_BUF_SIZE
+#error RC16_LEN must not be more than SD_BUF_SIZE
+#endif
+
+static int read_capacity_16(struct scsi_disk *sdkp, struct scsi_device *sdp,
+ unsigned char *buffer)
{
unsigned char cmd[16];
- int the_result, retries;
- int sector_size = 0;
- /* Force READ CAPACITY(16) when PROTECT=1 */
- int longrc = scsi_device_protection(sdkp->device) ? 1 : 0;
struct scsi_sense_hdr sshdr;
int sense_valid = 0;
- struct scsi_device *sdp = sdkp->device;
+ int the_result;
+ int retries = 3;
+ unsigned long long lba;
+ unsigned sector_size;
-repeat:
- retries = 3;
do {
- if (longrc) {
- memset((void *) cmd, 0, 16);
- cmd[0] = SERVICE_ACTION_IN;
- cmd[1] = SAI_READ_CAPACITY_16;
- cmd[13] = 13;
- memset((void *) buffer, 0, 13);
- } else {
- cmd[0] = READ_CAPACITY;
- memset((void *) &cmd[1], 0, 9);
- memset((void *) buffer, 0, 8);
+ memset(cmd, 0, 16);
+ cmd[0] = SERVICE_ACTION_IN;
+ cmd[1] = SAI_READ_CAPACITY_16;
+ cmd[13] = RC16_LEN;
+ memset(buffer, 0, RC16_LEN);
+
+ the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
+ buffer, RC16_LEN, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+
+ if (media_not_present(sdkp, &sshdr))
+ return -ENODEV;
+
+ if (the_result) {
+ sense_valid = scsi_sense_valid(&sshdr);
+ if (sense_valid &&
+ sshdr.sense_key == ILLEGAL_REQUEST &&
+ (sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
+ sshdr.ascq == 0x00)
+ /* Invalid Command Operation Code or
+ * Invalid Field in CDB, just retry
+ * silently with RC10 */
+ return -EINVAL;
}
-
+ retries--;
+
+ } while (the_result && retries);
+
+ if (the_result) {
+ sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n");
+ read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result);
+ return -EINVAL;
+ }
+
+ sector_size = (buffer[8] << 24) | (buffer[9] << 16) |
+ (buffer[10] << 8) | buffer[11];
+ lba = (((u64)buffer[0] << 56) | ((u64)buffer[1] << 48) |
+ ((u64)buffer[2] << 40) | ((u64)buffer[3] << 32) |
+ ((u64)buffer[4] << 24) | ((u64)buffer[5] << 16) |
+ ((u64)buffer[6] << 8) | (u64)buffer[7]);
+
+ sd_read_protection_type(sdkp, buffer);
+
+ if ((sizeof(sdkp->capacity) == 4) && (lba >= 0xffffffffULL)) {
+ sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
+ "kernel compiled with support for large block "
+ "devices.\n");
+ sdkp->capacity = 0;
+ return -EOVERFLOW;
+ }
+
+ sdkp->capacity = lba + 1;
+ return sector_size;
+}
+
+static int read_capacity_10(struct scsi_disk *sdkp, struct scsi_device *sdp,
+ unsigned char *buffer)
+{
+ unsigned char cmd[16];
+ struct scsi_sense_hdr sshdr;
+ int sense_valid = 0;
+ int the_result;
+ int retries = 3;
+ sector_t lba;
+ unsigned sector_size;
+
+ do {
+ cmd[0] = READ_CAPACITY;
+ memset(&cmd[1], 0, 9);
+ memset(buffer, 0, 8);
+
the_result = scsi_execute_req(sdp, cmd, DMA_FROM_DEVICE,
- buffer, longrc ? 13 : 8, &sshdr,
- SD_TIMEOUT, SD_MAX_RETRIES, NULL);
+ buffer, 8, &sshdr,
+ SD_TIMEOUT, SD_MAX_RETRIES, NULL);
if (media_not_present(sdkp, &sshdr))
- return;
+ return -ENODEV;
if (the_result)
sense_valid = scsi_sense_valid(&sshdr);
@@ -1319,85 +1394,96 @@ repeat:
} while (the_result && retries);
- if (the_result && !longrc) {
+ if (the_result) {
sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY failed\n");
- sd_print_result(sdkp, the_result);
- if (driver_byte(the_result) & DRIVER_SENSE)
- sd_print_sense_hdr(sdkp, &sshdr);
- else
- sd_printk(KERN_NOTICE, sdkp, "Sense not available.\n");
+ read_capacity_error(sdkp, sdp, &sshdr, sense_valid, the_result);
+ return -EINVAL;
+ }
- /* Set dirty bit for removable devices if not ready -
- * sometimes drives will not report this properly. */
- if (sdp->removable &&
- sense_valid && sshdr.sense_key == NOT_READY)
- sdp->changed = 1;
+ sector_size = (buffer[4] << 24) | (buffer[5] << 16) |
+ (buffer[6] << 8) | buffer[7];
+ lba = (buffer[0] << 24) | (buffer[1] << 16) |
+ (buffer[2] << 8) | buffer[3];
- /* Either no media are present but the drive didn't tell us,
- or they are present but the read capacity command fails */
- /* sdkp->media_present = 0; -- not always correct */
- sdkp->capacity = 0; /* unknown mapped to zero - as usual */
+ if ((sizeof(sdkp->capacity) == 4) && (lba == 0xffffffff)) {
+ sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use a "
+ "kernel compiled with support for large block "
+ "devices.\n");
+ sdkp->capacity = 0;
+ return -EOVERFLOW;
+ }
- return;
- } else if (the_result && longrc) {
- /* READ CAPACITY(16) has been failed */
- sd_printk(KERN_NOTICE, sdkp, "READ CAPACITY(16) failed\n");
- sd_print_result(sdkp, the_result);
- sd_printk(KERN_NOTICE, sdkp, "Use 0xffffffff as device size\n");
+ sdkp->capacity = lba + 1;
+ return sector_size;
+}
- sdkp->capacity = 1 + (sector_t) 0xffffffff;
- goto got_data;
- }
-
- if (!longrc) {
- sector_size = (buffer[4] << 24) |
- (buffer[5] << 16) | (buffer[6] << 8) | buffer[7];
- if (buffer[0] == 0xff && buffer[1] == 0xff &&
- buffer[2] == 0xff && buffer[3] == 0xff) {
- if(sizeof(sdkp->capacity) > 4) {
- sd_printk(KERN_NOTICE, sdkp, "Very big device. "
- "Trying to use READ CAPACITY(16).\n");
- longrc = 1;
- goto repeat;
- }
- sd_printk(KERN_ERR, sdkp, "Too big for this kernel. Use "
- "a kernel compiled with support for large "
- "block devices.\n");
- sdkp->capacity = 0;
+static int sd_try_rc16_first(struct scsi_device *sdp)
+{
+ if (sdp->scsi_level > SCSI_SPC_2)
+ return 1;
+ if (scsi_device_protection(sdp))
+ return 1;
+ return 0;
+}
+
+/*
+ * read disk capacity
+ */
+static void
+sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer)
+{
+ int sector_size;
+ struct scsi_device *sdp = sdkp->device;
+ sector_t old_capacity = sdkp->capacity;
+
+ if (sd_try_rc16_first(sdp)) {
+ sector_size = read_capacity_16(sdkp, sdp, buffer);
+ if (sector_size == -EOVERFLOW)
goto got_data;
- }
- sdkp->capacity = 1 + (((sector_t)buffer[0] << 24) |
- (buffer[1] << 16) |
- (buffer[2] << 8) |
- buffer[3]);
+ if (sector_size == -ENODEV)
+ return;
+ if (sector_size < 0)
+ sector_size = read_capacity_10(sdkp, sdp, buffer);
+ if (sector_size < 0)
+ return;
} else {
- sdkp->capacity = 1 + (((u64)buffer[0] << 56) |
- ((u64)buffer[1] << 48) |
- ((u64)buffer[2] << 40) |
- ((u64)buffer[3] << 32) |
- ((sector_t)buffer[4] << 24) |
- ((sector_t)buffer[5] << 16) |
- ((sector_t)buffer[6] << 8) |
- (sector_t)buffer[7]);
-
- sector_size = (buffer[8] << 24) |
- (buffer[9] << 16) | (buffer[10] << 8) | buffer[11];
-
- sd_read_protection_type(sdkp, buffer);
- }
-
- /* Some devices return the total number of sectors, not the
- * highest sector number. Make the necessary adjustment. */
- if (sdp->fix_capacity) {
- --sdkp->capacity;
+ sector_size = read_capacity_10(sdkp, sdp, buffer);
+ if (sector_size == -EOVERFLOW)
+ goto got_data;
+ if (sector_size < 0)
+ return;
+ if ((sizeof(sdkp->capacity) > 4) &&
+ (sdkp->capacity > 0xffffffffULL)) {
+ int old_sector_size = sector_size;
+ sd_printk(KERN_NOTICE, sdkp, "Very big device. "
+ "Trying to use READ CAPACITY(16).\n");
+ sector_size = read_capacity_16(sdkp, sdp, buffer);
+ if (sector_size < 0) {
+ sd_printk(KERN_NOTICE, sdkp,
+ "Using 0xffffffff as device size\n");
+ sdkp->capacity = 1 + (sector_t) 0xffffffff;
+ sector_size = old_sector_size;
+ goto got_data;
+ }
+ }
+ }
- /* Some devices have version which report the correct sizes
- * and others which do not. We guess size according to a heuristic
- * and err on the side of lowering the capacity. */
- } else {
- if (sdp->guess_capacity)
- if (sdkp->capacity & 0x01) /* odd sizes are odd */
- --sdkp->capacity;
+ /* Some devices are known to return the total number of blocks,
+ * not the highest block number. Some devices have versions
+ * which do this and others which do not. Some devices we might
+ * suspect of doing this but we don't know for certain.
+ *
+ * If we know the reported capacity is wrong, decrement it. If
+ * we can only guess, then assume the number of blocks is even
+ * (usually true but not always) and err on the side of lowering
+ * the capacity.
+ */
+ if (sdp->fix_capacity ||
+ (sdp->guess_capacity && (sdkp->capacity & 0x01))) {
+ sd_printk(KERN_INFO, sdkp, "Adjusting the sector count "
+ "from its reported value: %llu\n",
+ (unsigned long long) sdkp->capacity);
+ --sdkp->capacity;
}
got_data:
@@ -1440,10 +1526,11 @@ got_data:
string_get_size(sz, STRING_UNITS_10, cap_str_10,
sizeof(cap_str_10));
- sd_printk(KERN_NOTICE, sdkp,
- "%llu %d-byte hardware sectors: (%s/%s)\n",
- (unsigned long long)sdkp->capacity,
- sector_size, cap_str_10, cap_str_2);
+ if (sdkp->first_scan || old_capacity != sdkp->capacity)
+ sd_printk(KERN_NOTICE, sdkp,
+ "%llu %d-byte hardware sectors: (%s/%s)\n",
+ (unsigned long long)sdkp->capacity,
+ sector_size, cap_str_10, cap_str_2);
}
/* Rescale capacity to 512-byte units */
@@ -1480,6 +1567,7 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
int res;
struct scsi_device *sdp = sdkp->device;
struct scsi_mode_data data;
+ int old_wp = sdkp->write_prot;
set_disk_ro(sdkp->disk, 0);
if (sdp->skip_ms_page_3f) {
@@ -1520,11 +1608,13 @@ sd_read_write_protect_flag(struct scsi_disk *sdkp, unsigned char *buffer)
} else {
sdkp->write_prot = ((data.device_specific & 0x80) != 0);
set_disk_ro(sdkp->disk, sdkp->write_prot);
- sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
- sdkp->write_prot ? "on" : "off");
- sd_printk(KERN_DEBUG, sdkp,
- "Mode Sense: %02x %02x %02x %02x\n",
- buffer[0], buffer[1], buffer[2], buffer[3]);
+ if (sdkp->first_scan || old_wp != sdkp->write_prot) {
+ sd_printk(KERN_NOTICE, sdkp, "Write Protect is %s\n",
+ sdkp->write_prot ? "on" : "off");
+ sd_printk(KERN_DEBUG, sdkp,
+ "Mode Sense: %02x %02x %02x %02x\n",
+ buffer[0], buffer[1], buffer[2], buffer[3]);
+ }
}
}
@@ -1542,6 +1632,9 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
int modepage;
struct scsi_mode_data data;
struct scsi_sense_hdr sshdr;
+ int old_wce = sdkp->WCE;
+ int old_rcd = sdkp->RCD;
+ int old_dpofua = sdkp->DPOFUA;
if (sdp->skip_ms_page_8)
goto defaults;
@@ -1613,12 +1706,14 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer)
sdkp->DPOFUA = 0;
}
- sd_printk(KERN_NOTICE, sdkp,
- "Write cache: %s, read cache: %s, %s\n",
- sdkp->WCE ? "enabled" : "disabled",
- sdkp->RCD ? "disabled" : "enabled",
- sdkp->DPOFUA ? "supports DPO and FUA"
- : "doesn't support DPO or FUA");
+ if (sdkp->first_scan || old_wce != sdkp->WCE ||
+ old_rcd != sdkp->RCD || old_dpofua != sdkp->DPOFUA)
+ sd_printk(KERN_NOTICE, sdkp,
+ "Write cache: %s, read cache: %s, %s\n",
+ sdkp->WCE ? "enabled" : "disabled",
+ sdkp->RCD ? "disabled" : "enabled",
+ sdkp->DPOFUA ? "supports DPO and FUA"
+ : "doesn't support DPO or FUA");
return;
}
@@ -1714,15 +1809,6 @@ static int sd_revalidate_disk(struct gendisk *disk)
goto out;
}
- /* defaults, until the device tells us otherwise */
- sdp->sector_size = 512;
- sdkp->capacity = 0;
- sdkp->media_present = 1;
- sdkp->write_prot = 0;
- sdkp->WCE = 0;
- sdkp->RCD = 0;
- sdkp->ATO = 0;
-
sd_spinup_disk(sdkp);
/*
@@ -1736,6 +1822,8 @@ static int sd_revalidate_disk(struct gendisk *disk)
sd_read_app_tag_own(sdkp, buffer);
}
+ sdkp->first_scan = 0;
+
/*
* We now have all cache related info, determine how we deal
* with ordered requests. Note that as the current SCSI
@@ -1846,6 +1934,16 @@ static void sd_probe_async(void *data, async_cookie_t cookie)
gd->private_data = &sdkp->driver;
gd->queue = sdkp->device->request_queue;
+ /* defaults, until the device tells us otherwise */
+ sdp->sector_size = 512;
+ sdkp->capacity = 0;
+ sdkp->media_present = 1;
+ sdkp->write_prot = 0;
+ sdkp->WCE = 0;
+ sdkp->RCD = 0;
+ sdkp->ATO = 0;
+ sdkp->first_scan = 1;
+
sd_revalidate_disk(gd);
blk_queue_prep_rq(sdp->request_queue, sd_prep_fn);
@@ -1914,7 +2012,9 @@ static int sd_probe(struct device *dev)
if (!ida_pre_get(&sd_index_ida, GFP_KERNEL))
goto out_put;
+ spin_lock(&sd_index_lock);
error = ida_get_new(&sd_index_ida, &index);
+ spin_unlock(&sd_index_lock);
} while (error == -EAGAIN);
if (error)
@@ -1936,7 +2036,9 @@ static int sd_probe(struct device *dev)
return 0;
out_free_index:
+ spin_lock(&sd_index_lock);
ida_remove(&sd_index_ida, index);
+ spin_unlock(&sd_index_lock);
out_put:
put_disk(gd);
out_free:
@@ -1986,7 +2088,9 @@ static void scsi_disk_release(struct device *dev)
struct scsi_disk *sdkp = to_scsi_disk(dev);
struct gendisk *disk = sdkp->disk;
+ spin_lock(&sd_index_lock);
ida_remove(&sd_index_ida, sdkp->index);
+ spin_unlock(&sd_index_lock);
disk->private_data = NULL;
put_disk(disk);
diff --git a/drivers/scsi/sd.h b/drivers/scsi/sd.h
index 75638e7d3f6..708778cf5f0 100644
--- a/drivers/scsi/sd.h
+++ b/drivers/scsi/sd.h
@@ -53,6 +53,7 @@ struct scsi_disk {
unsigned WCE : 1; /* state of disk WCE bit */
unsigned RCD : 1; /* state of disk RCD bit, unused */
unsigned DPOFUA : 1; /* state of disk DPOFUA bit */
+ unsigned first_scan : 1;
};
#define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
diff --git a/drivers/scsi/ses.c b/drivers/scsi/ses.c
index e946e05db7f..4f618f48735 100644
--- a/drivers/scsi/ses.c
+++ b/drivers/scsi/ses.c
@@ -264,6 +264,7 @@ struct ses_host_edev {
struct enclosure_device *edev;
};
+#if 0
int ses_match_host(struct enclosure_device *edev, void *data)
{
struct ses_host_edev *sed = data;
@@ -280,6 +281,7 @@ int ses_match_host(struct enclosure_device *edev, void *data)
sed->edev = edev;
return 1;
}
+#endif /* 0 */
static void ses_process_descriptor(struct enclosure_component *ecomp,
unsigned char *desc)
@@ -345,44 +347,21 @@ static int ses_enclosure_find_by_addr(struct enclosure_device *edev,
return 0;
}
-#define VPD_INQUIRY_SIZE 36
-
static void ses_match_to_enclosure(struct enclosure_device *edev,
struct scsi_device *sdev)
{
- unsigned char *buf = kmalloc(VPD_INQUIRY_SIZE, GFP_KERNEL);
+ unsigned char *buf;
unsigned char *desc;
- u16 vpd_len;
+ unsigned int vpd_len;
struct efd efd = {
.addr = 0,
};
- unsigned char cmd[] = {
- INQUIRY,
- 1,
- 0x83,
- VPD_INQUIRY_SIZE >> 8,
- VPD_INQUIRY_SIZE & 0xff,
- 0
- };
+ buf = scsi_get_vpd_page(sdev, 0x83);
if (!buf)
return;
- if (scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf,
- VPD_INQUIRY_SIZE, NULL, SES_TIMEOUT, SES_RETRIES,
- NULL))
- goto free;
-
- vpd_len = (buf[2] << 8) + buf[3];
- kfree(buf);
- buf = kmalloc(vpd_len, GFP_KERNEL);
- if (!buf)
- return;
- cmd[3] = vpd_len >> 8;
- cmd[4] = vpd_len & 0xff;
- if (scsi_execute_req(sdev, cmd, DMA_FROM_DEVICE, buf,
- vpd_len, NULL, SES_TIMEOUT, SES_RETRIES, NULL))
- goto free;
+ vpd_len = ((buf[2] << 8) | buf[3]) + 4;
desc = buf + 4;
while (desc < buf + vpd_len) {
@@ -393,7 +372,7 @@ static void ses_match_to_enclosure(struct enclosure_device *edev,
u8 type = desc[1] & 0x0f;
u8 len = desc[3];
- if (piv && code_set == 1 && assoc == 1 && code_set == 1
+ if (piv && code_set == 1 && assoc == 1
&& proto == SCSI_PROTOCOL_SAS && type == 3 && len == 8)
efd.addr = (u64)desc[4] << 56 |
(u64)desc[5] << 48 |
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 8f0bd3f7a59..82312df9b0b 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -98,7 +98,6 @@ static int scatter_elem_sz = SG_SCATTER_SZ;
static int scatter_elem_sz_prev = SG_SCATTER_SZ;
#define SG_SECTOR_SZ 512
-#define SG_SECTOR_MSK (SG_SECTOR_SZ - 1)
static int sg_add(struct device *, struct class_interface *);
static void sg_remove(struct device *, struct class_interface *);
@@ -137,10 +136,11 @@ typedef struct sg_request { /* SG_MAX_QUEUE requests outstanding per file */
volatile char done; /* 0->before bh, 1->before read, 2->read */
struct request *rq;
struct bio *bio;
+ struct execute_work ew;
} Sg_request;
typedef struct sg_fd { /* holds the state of a file descriptor */
- struct sg_fd *nextfp; /* NULL when last opened fd on this device */
+ struct list_head sfd_siblings;
struct sg_device *parentdp; /* owning device */
wait_queue_head_t read_wait; /* queue read until command done */
rwlock_t rq_list_lock; /* protect access to list in req_arr */
@@ -158,6 +158,8 @@ typedef struct sg_fd { /* holds the state of a file descriptor */
char next_cmd_len; /* 0 -> automatic (def), >0 -> use on next write() */
char keep_orphan; /* 0 -> drop orphan (def), 1 -> keep for read() */
char mmap_called; /* 0 -> mmap() never called on this fd */
+ struct kref f_ref;
+ struct execute_work ew;
} Sg_fd;
typedef struct sg_device { /* holds the state of each scsi generic device */
@@ -165,27 +167,25 @@ typedef struct sg_device { /* holds the state of each scsi generic device */
wait_queue_head_t o_excl_wait; /* queue open() when O_EXCL in use */
int sg_tablesize; /* adapter's max scatter-gather table size */
u32 index; /* device index number */
- Sg_fd *headfp; /* first open fd belonging to this device */
+ struct list_head sfds;
volatile char detached; /* 0->attached, 1->detached pending removal */
volatile char exclude; /* opened for exclusive access */
char sgdebug; /* 0->off, 1->sense, 9->dump dev, 10-> all devs */
struct gendisk *disk;
struct cdev * cdev; /* char_dev [sysfs: /sys/cdev/major/sg<n>] */
+ struct kref d_ref;
} Sg_device;
-static int sg_fasync(int fd, struct file *filp, int mode);
/* tasklet or soft irq callback */
static void sg_rq_end_io(struct request *rq, int uptodate);
static int sg_start_req(Sg_request *srp, unsigned char *cmd);
static void sg_finish_rem_req(Sg_request * srp);
static int sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size);
-static int sg_build_sgat(Sg_scatter_hold * schp, const Sg_fd * sfp,
- int tablesize);
static ssize_t sg_new_read(Sg_fd * sfp, char __user *buf, size_t count,
Sg_request * srp);
static ssize_t sg_new_write(Sg_fd *sfp, struct file *file,
const char __user *buf, size_t count, int blocking,
- int read_only, Sg_request **o_srp);
+ int read_only, int sg_io_owned, Sg_request **o_srp);
static int sg_common_write(Sg_fd * sfp, Sg_request * srp,
unsigned char *cmnd, int timeout, int blocking);
static int sg_read_oxfer(Sg_request * srp, char __user *outp, int num_read_xfer);
@@ -194,16 +194,13 @@ static void sg_build_reserve(Sg_fd * sfp, int req_size);
static void sg_link_reserve(Sg_fd * sfp, Sg_request * srp, int size);
static void sg_unlink_reserve(Sg_fd * sfp, Sg_request * srp);
static Sg_fd *sg_add_sfp(Sg_device * sdp, int dev);
-static int sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
-static void __sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp);
+static void sg_remove_sfp(struct kref *);
static Sg_request *sg_get_rq_mark(Sg_fd * sfp, int pack_id);
static Sg_request *sg_add_request(Sg_fd * sfp);
static int sg_remove_request(Sg_fd * sfp, Sg_request * srp);
static int sg_res_in_use(Sg_fd * sfp);
static Sg_device *sg_get_dev(int dev);
-#ifdef CONFIG_SCSI_PROC_FS
-static int sg_last_dev(void);
-#endif
+static void sg_put_dev(Sg_device *sdp);
#define SZ_SG_HEADER sizeof(struct sg_header)
#define SZ_SG_IO_HDR sizeof(sg_io_hdr_t)
@@ -237,22 +234,17 @@ sg_open(struct inode *inode, struct file *filp)
nonseekable_open(inode, filp);
SCSI_LOG_TIMEOUT(3, printk("sg_open: dev=%d, flags=0x%x\n", dev, flags));
sdp = sg_get_dev(dev);
- if ((!sdp) || (!sdp->device)) {
- unlock_kernel();
- return -ENXIO;
- }
- if (sdp->detached) {
- unlock_kernel();
- return -ENODEV;
+ if (IS_ERR(sdp)) {
+ retval = PTR_ERR(sdp);
+ sdp = NULL;
+ goto sg_put;
}
/* This driver's module count bumped by fops_get in <linux/fs.h> */
/* Prevent the device driver from vanishing while we sleep */
retval = scsi_device_get(sdp->device);
- if (retval) {
- unlock_kernel();
- return retval;
- }
+ if (retval)
+ goto sg_put;
if (!((flags & O_NONBLOCK) ||
scsi_block_when_processing_errors(sdp->device))) {
@@ -266,13 +258,13 @@ sg_open(struct inode *inode, struct file *filp)
retval = -EPERM; /* Can't lock it with read only access */
goto error_out;
}
- if (sdp->headfp && (flags & O_NONBLOCK)) {
+ if (!list_empty(&sdp->sfds) && (flags & O_NONBLOCK)) {
retval = -EBUSY;
goto error_out;
}
res = 0;
__wait_event_interruptible(sdp->o_excl_wait,
- ((sdp->headfp || sdp->exclude) ? 0 : (sdp->exclude = 1)), res);
+ ((!list_empty(&sdp->sfds) || sdp->exclude) ? 0 : (sdp->exclude = 1)), res);
if (res) {
retval = res; /* -ERESTARTSYS because signal hit process */
goto error_out;
@@ -294,7 +286,7 @@ sg_open(struct inode *inode, struct file *filp)
retval = -ENODEV;
goto error_out;
}
- if (!sdp->headfp) { /* no existing opens on this device */
+ if (list_empty(&sdp->sfds)) { /* no existing opens on this device */
sdp->sgdebug = 0;
q = sdp->device->request_queue;
sdp->sg_tablesize = min(q->max_hw_segments,
@@ -303,16 +295,20 @@ sg_open(struct inode *inode, struct file *filp)
if ((sfp = sg_add_sfp(sdp, dev)))
filp->private_data = sfp;
else {
- if (flags & O_EXCL)
+ if (flags & O_EXCL) {
sdp->exclude = 0; /* undo if error */
+ wake_up_interruptible(&sdp->o_excl_wait);
+ }
retval = -ENOMEM;
goto error_out;
}
- unlock_kernel();
- return 0;
-
- error_out:
- scsi_device_put(sdp->device);
+ retval = 0;
+error_out:
+ if (retval)
+ scsi_device_put(sdp->device);
+sg_put:
+ if (sdp)
+ sg_put_dev(sdp);
unlock_kernel();
return retval;
}
@@ -327,13 +323,13 @@ sg_release(struct inode *inode, struct file *filp)
if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp)))
return -ENXIO;
SCSI_LOG_TIMEOUT(3, printk("sg_release: %s\n", sdp->disk->disk_name));
- if (0 == sg_remove_sfp(sdp, sfp)) { /* Returns 1 when sdp gone */
- if (!sdp->detached) {
- scsi_device_put(sdp->device);
- }
- sdp->exclude = 0;
- wake_up_interruptible(&sdp->o_excl_wait);
- }
+
+ sfp->closed = 1;
+
+ sdp->exclude = 0;
+ wake_up_interruptible(&sdp->o_excl_wait);
+
+ kref_put(&sfp->f_ref, sg_remove_sfp);
return 0;
}
@@ -557,7 +553,8 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
return -EFAULT;
blocking = !(filp->f_flags & O_NONBLOCK);
if (old_hdr.reply_len < 0)
- return sg_new_write(sfp, filp, buf, count, blocking, 0, NULL);
+ return sg_new_write(sfp, filp, buf, count,
+ blocking, 0, 0, NULL);
if (count < (SZ_SG_HEADER + 6))
return -EIO; /* The minimum scsi command length is 6 bytes. */
@@ -638,7 +635,7 @@ sg_write(struct file *filp, const char __user *buf, size_t count, loff_t * ppos)
static ssize_t
sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
- size_t count, int blocking, int read_only,
+ size_t count, int blocking, int read_only, int sg_io_owned,
Sg_request **o_srp)
{
int k;
@@ -658,6 +655,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf,
SCSI_LOG_TIMEOUT(1, printk("sg_new_write: queue full\n"));
return -EDOM;
}
+ srp->sg_io_owned = sg_io_owned;
hp = &srp->header;
if (__copy_from_user(hp, buf, SZ_SG_IO_HDR)) {
sg_remove_request(sfp, srp);
@@ -755,24 +753,13 @@ sg_common_write(Sg_fd * sfp, Sg_request * srp,
hp->duration = jiffies_to_msecs(jiffies);
srp->rq->timeout = timeout;
+ kref_get(&sfp->f_ref); /* sg_rq_end_io() does kref_put(). */
blk_execute_rq_nowait(sdp->device->request_queue, sdp->disk,
srp->rq, 1, sg_rq_end_io);
return 0;
}
static int
-sg_srp_done(Sg_request *srp, Sg_fd *sfp)
-{
- unsigned long iflags;
- int done;
-
- read_lock_irqsave(&sfp->rq_list_lock, iflags);
- done = srp->done;
- read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
- return done;
-}
-
-static int
sg_ioctl(struct inode *inode, struct file *filp,
unsigned int cmd_in, unsigned long arg)
{
@@ -804,27 +791,26 @@ sg_ioctl(struct inode *inode, struct file *filp,
return -EFAULT;
result =
sg_new_write(sfp, filp, p, SZ_SG_IO_HDR,
- blocking, read_only, &srp);
+ blocking, read_only, 1, &srp);
if (result < 0)
return result;
- srp->sg_io_owned = 1;
while (1) {
result = 0; /* following macro to beat race condition */
__wait_event_interruptible(sfp->read_wait,
- (sdp->detached || sfp->closed || sg_srp_done(srp, sfp)),
- result);
+ (srp->done || sdp->detached),
+ result);
if (sdp->detached)
return -ENODEV;
- if (sfp->closed)
- return 0; /* request packet dropped already */
- if (0 == result)
+ write_lock_irq(&sfp->rq_list_lock);
+ if (srp->done) {
+ srp->done = 2;
+ write_unlock_irq(&sfp->rq_list_lock);
break;
+ }
srp->orphan = 1;
+ write_unlock_irq(&sfp->rq_list_lock);
return result; /* -ERESTARTSYS because signal hit process */
}
- write_lock_irqsave(&sfp->rq_list_lock, iflags);
- srp->done = 2;
- write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
result = sg_new_read(sfp, p, SZ_SG_IO_HDR, srp);
return (result < 0) ? result : 0;
}
@@ -1078,7 +1064,7 @@ sg_ioctl(struct inode *inode, struct file *filp,
case BLKTRACESETUP:
return blk_trace_setup(sdp->device->request_queue,
sdp->disk->disk_name,
- sdp->device->sdev_gendev.devt,
+ MKDEV(SCSI_GENERIC_MAJOR, sdp->index),
(char *)arg);
case BLKTRACESTART:
return blk_trace_startstop(sdp->device->request_queue, 1);
@@ -1154,7 +1140,6 @@ sg_poll(struct file *filp, poll_table * wait)
static int
sg_fasync(int fd, struct file *filp, int mode)
{
- int retval;
Sg_device *sdp;
Sg_fd *sfp;
@@ -1163,8 +1148,7 @@ sg_fasync(int fd, struct file *filp, int mode)
SCSI_LOG_TIMEOUT(3, printk("sg_fasync: %s, mode=%d\n",
sdp->disk->disk_name, mode));
- retval = fasync_helper(fd, filp, mode, &sfp->async_qp);
- return (retval < 0) ? retval : 0;
+ return fasync_helper(fd, filp, mode, &sfp->async_qp);
}
static int
@@ -1240,6 +1224,15 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
return 0;
}
+static void sg_rq_end_io_usercontext(struct work_struct *work)
+{
+ struct sg_request *srp = container_of(work, struct sg_request, ew.work);
+ struct sg_fd *sfp = srp->parentfp;
+
+ sg_finish_rem_req(srp);
+ kref_put(&sfp->f_ref, sg_remove_sfp);
+}
+
/*
* This function is a "bottom half" handler that is called by the mid
* level when a command is completed (or has failed).
@@ -1247,24 +1240,23 @@ sg_mmap(struct file *filp, struct vm_area_struct *vma)
static void sg_rq_end_io(struct request *rq, int uptodate)
{
struct sg_request *srp = rq->end_io_data;
- Sg_device *sdp = NULL;
+ Sg_device *sdp;
Sg_fd *sfp;
unsigned long iflags;
unsigned int ms;
char *sense;
- int result, resid;
+ int result, resid, done = 1;
- if (NULL == srp) {
- printk(KERN_ERR "sg_cmd_done: NULL request\n");
+ if (WARN_ON(srp->done != 0))
return;
- }
+
sfp = srp->parentfp;
- if (sfp)
- sdp = sfp->parentdp;
- if ((NULL == sdp) || sdp->detached) {
- printk(KERN_INFO "sg_cmd_done: device detached\n");
+ if (WARN_ON(sfp == NULL))
return;
- }
+
+ sdp = sfp->parentdp;
+ if (unlikely(sdp->detached))
+ printk(KERN_INFO "sg_rq_end_io: device detached\n");
sense = rq->sense;
result = rq->errors;
@@ -1303,32 +1295,26 @@ static void sg_rq_end_io(struct request *rq, int uptodate)
}
/* Rely on write phase to clean out srp status values, so no "else" */
- if (sfp->closed) { /* whoops this fd already released, cleanup */
- SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, freeing ...\n"));
- sg_finish_rem_req(srp);
- srp = NULL;
- if (NULL == sfp->headrp) {
- SCSI_LOG_TIMEOUT(1, printk("sg_cmd_done: already closed, final cleanup\n"));
- if (0 == sg_remove_sfp(sdp, sfp)) { /* device still present */
- scsi_device_put(sdp->device);
- }
- sfp = NULL;
- }
- } else if (srp && srp->orphan) {
+ write_lock_irqsave(&sfp->rq_list_lock, iflags);
+ if (unlikely(srp->orphan)) {
if (sfp->keep_orphan)
srp->sg_io_owned = 0;
- else {
- sg_finish_rem_req(srp);
- srp = NULL;
- }
+ else
+ done = 0;
}
- if (sfp && srp) {
- /* Now wake up any sg_read() that is waiting for this packet. */
- kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN);
- write_lock_irqsave(&sfp->rq_list_lock, iflags);
- srp->done = 1;
+ srp->done = done;
+ write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+
+ if (likely(done)) {
+ /* Now wake up any sg_read() that is waiting for this
+ * packet.
+ */
wake_up_interruptible(&sfp->read_wait);
- write_unlock_irqrestore(&sfp->rq_list_lock, iflags);
+ kill_fasync(&sfp->async_qp, SIGPOLL, POLL_IN);
+ kref_put(&sfp->f_ref, sg_remove_sfp);
+ } else {
+ INIT_WORK(&srp->ew.work, sg_rq_end_io_usercontext);
+ schedule_work(&srp->ew.work);
}
}
@@ -1364,17 +1350,18 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
printk(KERN_WARNING "kmalloc Sg_device failure\n");
return ERR_PTR(-ENOMEM);
}
- error = -ENOMEM;
+
if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) {
printk(KERN_WARNING "idr expansion Sg_device failure\n");
+ error = -ENOMEM;
goto out;
}
write_lock_irqsave(&sg_index_lock, iflags);
- error = idr_get_new(&sg_index_idr, sdp, &k);
- write_unlock_irqrestore(&sg_index_lock, iflags);
+ error = idr_get_new(&sg_index_idr, sdp, &k);
if (error) {
+ write_unlock_irqrestore(&sg_index_lock, iflags);
printk(KERN_WARNING "idr allocation Sg_device failure: %d\n",
error);
goto out;
@@ -1388,9 +1375,13 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
disk->first_minor = k;
sdp->disk = disk;
sdp->device = scsidp;
+ INIT_LIST_HEAD(&sdp->sfds);
init_waitqueue_head(&sdp->o_excl_wait);
sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments);
sdp->index = k;
+ kref_init(&sdp->d_ref);
+
+ write_unlock_irqrestore(&sg_index_lock, iflags);
error = 0;
out:
@@ -1401,6 +1392,8 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp)
return sdp;
overflow:
+ idr_remove(&sg_index_idr, k);
+ write_unlock_irqrestore(&sg_index_lock, iflags);
sdev_printk(KERN_WARNING, scsidp,
"Unable to attach sg device type=%d, minor "
"number exceeds %d\n", scsidp->type, SG_MAX_DEVS - 1);
@@ -1488,49 +1481,46 @@ out:
return error;
}
-static void
-sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
+static void sg_device_destroy(struct kref *kref)
+{
+ struct sg_device *sdp = container_of(kref, struct sg_device, d_ref);
+ unsigned long flags;
+
+ /* CAUTION! Note that the device can still be found via idr_find()
+ * even though the refcount is 0. Therefore, do idr_remove() BEFORE
+ * any other cleanup.
+ */
+
+ write_lock_irqsave(&sg_index_lock, flags);
+ idr_remove(&sg_index_idr, sdp->index);
+ write_unlock_irqrestore(&sg_index_lock, flags);
+
+ SCSI_LOG_TIMEOUT(3,
+ printk("sg_device_destroy: %s\n",
+ sdp->disk->disk_name));
+
+ put_disk(sdp->disk);
+ kfree(sdp);
+}
+
+static void sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
{
struct scsi_device *scsidp = to_scsi_device(cl_dev->parent);
Sg_device *sdp = dev_get_drvdata(cl_dev);
unsigned long iflags;
Sg_fd *sfp;
- Sg_fd *tsfp;
- Sg_request *srp;
- Sg_request *tsrp;
- int delay;
- if (!sdp)
+ if (!sdp || sdp->detached)
return;
- delay = 0;
+ SCSI_LOG_TIMEOUT(3, printk("sg_remove: %s\n", sdp->disk->disk_name));
+
+ /* Need a write lock to set sdp->detached. */
write_lock_irqsave(&sg_index_lock, iflags);
- if (sdp->headfp) {
- sdp->detached = 1;
- for (sfp = sdp->headfp; sfp; sfp = tsfp) {
- tsfp = sfp->nextfp;
- for (srp = sfp->headrp; srp; srp = tsrp) {
- tsrp = srp->nextrp;
- if (sfp->closed || (0 == sg_srp_done(srp, sfp)))
- sg_finish_rem_req(srp);
- }
- if (sfp->closed) {
- scsi_device_put(sdp->device);
- __sg_remove_sfp(sdp, sfp);
- } else {
- delay = 1;
- wake_up_interruptible(&sfp->read_wait);
- kill_fasync(&sfp->async_qp, SIGPOLL,
- POLL_HUP);
- }
- }
- SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", sdp->index));
- if (NULL == sdp->headfp) {
- idr_remove(&sg_index_idr, sdp->index);
- }
- } else { /* nothing active, simple case */
- SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", sdp->index));
- idr_remove(&sg_index_idr, sdp->index);
+ sdp->detached = 1;
+ list_for_each_entry(sfp, &sdp->sfds, sfd_siblings) {
+ wake_up_interruptible(&sfp->read_wait);
+ kill_fasync(&sfp->async_qp, SIGPOLL, POLL_HUP);
}
write_unlock_irqrestore(&sg_index_lock, iflags);
@@ -1538,13 +1528,8 @@ sg_remove(struct device *cl_dev, struct class_interface *cl_intf)
device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, sdp->index));
cdev_del(sdp->cdev);
sdp->cdev = NULL;
- put_disk(sdp->disk);
- sdp->disk = NULL;
- if (NULL == sdp->headfp)
- kfree(sdp);
- if (delay)
- msleep(10); /* dirty detach so delay device destruction */
+ sg_put_dev(sdp);
}
module_param_named(scatter_elem_sz, scatter_elem_sz, int, S_IRUGO | S_IWUSR);
@@ -1673,10 +1658,30 @@ static int sg_start_req(Sg_request *srp, unsigned char *cmd)
md->null_mapped = hp->dxferp ? 0 : 1;
}
- if (iov_count)
- res = blk_rq_map_user_iov(q, rq, md, hp->dxferp, iov_count,
- hp->dxfer_len, GFP_ATOMIC);
- else
+ if (iov_count) {
+ int len, size = sizeof(struct sg_iovec) * iov_count;
+ struct iovec *iov;
+
+ iov = kmalloc(size, GFP_ATOMIC);
+ if (!iov)
+ return -ENOMEM;
+
+ if (copy_from_user(iov, hp->dxferp, size)) {
+ kfree(iov);
+ return -EFAULT;
+ }
+
+ len = iov_length(iov, iov_count);
+ if (hp->dxfer_len < len) {
+ iov_count = iov_shorten(iov, iov_count, hp->dxfer_len);
+ len = hp->dxfer_len;
+ }
+
+ res = blk_rq_map_user_iov(q, rq, md, (struct sg_iovec *)iov,
+ iov_count,
+ len, GFP_ATOMIC);
+ kfree(iov);
+ } else
res = blk_rq_map_user(q, rq, md, hp->dxferp,
hp->dxfer_len, GFP_ATOMIC);
@@ -1738,8 +1743,8 @@ sg_build_indirect(Sg_scatter_hold * schp, Sg_fd * sfp, int buff_size)
return -EFAULT;
if (0 == blk_size)
++blk_size; /* don't know why */
-/* round request up to next highest SG_SECTOR_SZ byte boundary */
- blk_size = (blk_size + SG_SECTOR_MSK) & (~SG_SECTOR_MSK);
+ /* round request up to next highest SG_SECTOR_SZ byte boundary */
+ blk_size = ALIGN(blk_size, SG_SECTOR_SZ);
SCSI_LOG_TIMEOUT(4, printk("sg_build_indirect: buff_size=%d, blk_size=%d\n",
buff_size, blk_size));
@@ -1941,22 +1946,6 @@ sg_get_rq_mark(Sg_fd * sfp, int pack_id)
return resp;
}
-#ifdef CONFIG_SCSI_PROC_FS
-static Sg_request *
-sg_get_nth_request(Sg_fd * sfp, int nth)
-{
- Sg_request *resp;
- unsigned long iflags;
- int k;
-
- read_lock_irqsave(&sfp->rq_list_lock, iflags);
- for (k = 0, resp = sfp->headrp; resp && (k < nth);
- ++k, resp = resp->nextrp) ;
- read_unlock_irqrestore(&sfp->rq_list_lock, iflags);
- return resp;
-}
-#endif
-
/* always adds to end of list */
static Sg_request *
sg_add_request(Sg_fd * sfp)
@@ -2032,22 +2021,6 @@ sg_remove_request(Sg_fd * sfp, Sg_request * srp)
return res;
}
-#ifdef CONFIG_SCSI_PROC_FS
-static Sg_fd *
-sg_get_nth_sfp(Sg_device * sdp, int nth)
-{
- Sg_fd *resp;
- unsigned long iflags;
- int k;
-
- read_lock_irqsave(&sg_index_lock, iflags);
- for (k = 0, resp = sdp->headfp; resp && (k < nth);
- ++k, resp = resp->nextfp) ;
- read_unlock_irqrestore(&sg_index_lock, iflags);
- return resp;
-}
-#endif
-
static Sg_fd *
sg_add_sfp(Sg_device * sdp, int dev)
{
@@ -2062,6 +2035,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
init_waitqueue_head(&sfp->read_wait);
rwlock_init(&sfp->rq_list_lock);
+ kref_init(&sfp->f_ref);
sfp->timeout = SG_DEFAULT_TIMEOUT;
sfp->timeout_user = SG_DEFAULT_TIMEOUT_USER;
sfp->force_packid = SG_DEF_FORCE_PACK_ID;
@@ -2071,14 +2045,7 @@ sg_add_sfp(Sg_device * sdp, int dev)
sfp->keep_orphan = SG_DEF_KEEP_ORPHAN;
sfp->parentdp = sdp;
write_lock_irqsave(&sg_index_lock, iflags);
- if (!sdp->headfp)
- sdp->headfp = sfp;
- else { /* add to tail of existing list */
- Sg_fd *pfp = sdp->headfp;
- while (pfp->nextfp)
- pfp = pfp->nextfp;
- pfp->nextfp = sfp;
- }
+ list_add_tail(&sfp->sfd_siblings, &sdp->sfds);
write_unlock_irqrestore(&sg_index_lock, iflags);
SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: sfp=0x%p\n", sfp));
if (unlikely(sg_big_buff != def_reserved_size))
@@ -2089,75 +2056,53 @@ sg_add_sfp(Sg_device * sdp, int dev)
sg_build_reserve(sfp, bufflen);
SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n",
sfp->reserve.bufflen, sfp->reserve.k_use_sg));
+
+ kref_get(&sdp->d_ref);
+ __module_get(THIS_MODULE);
return sfp;
}
-static void
-__sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
+static void sg_remove_sfp_usercontext(struct work_struct *work)
{
- Sg_fd *fp;
- Sg_fd *prev_fp;
+ struct sg_fd *sfp = container_of(work, struct sg_fd, ew.work);
+ struct sg_device *sdp = sfp->parentdp;
+
+ /* Cleanup any responses which were never read(). */
+ while (sfp->headrp)
+ sg_finish_rem_req(sfp->headrp);
- prev_fp = sdp->headfp;
- if (sfp == prev_fp)
- sdp->headfp = prev_fp->nextfp;
- else {
- while ((fp = prev_fp->nextfp)) {
- if (sfp == fp) {
- prev_fp->nextfp = fp->nextfp;
- break;
- }
- prev_fp = fp;
- }
- }
if (sfp->reserve.bufflen > 0) {
- SCSI_LOG_TIMEOUT(6,
- printk("__sg_remove_sfp: bufflen=%d, k_use_sg=%d\n",
- (int) sfp->reserve.bufflen, (int) sfp->reserve.k_use_sg));
+ SCSI_LOG_TIMEOUT(6,
+ printk("sg_remove_sfp: bufflen=%d, k_use_sg=%d\n",
+ (int) sfp->reserve.bufflen,
+ (int) sfp->reserve.k_use_sg));
sg_remove_scat(&sfp->reserve);
}
- sfp->parentdp = NULL;
- SCSI_LOG_TIMEOUT(6, printk("__sg_remove_sfp: sfp=0x%p\n", sfp));
+
+ SCSI_LOG_TIMEOUT(6,
+ printk("sg_remove_sfp: %s, sfp=0x%p\n",
+ sdp->disk->disk_name,
+ sfp));
kfree(sfp);
+
+ scsi_device_put(sdp->device);
+ sg_put_dev(sdp);
+ module_put(THIS_MODULE);
}
-/* Returns 0 in normal case, 1 when detached and sdp object removed */
-static int
-sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp)
+static void sg_remove_sfp(struct kref *kref)
{
- Sg_request *srp;
- Sg_request *tsrp;
- int dirty = 0;
- int res = 0;
+ struct sg_fd *sfp = container_of(kref, struct sg_fd, f_ref);
+ struct sg_device *sdp = sfp->parentdp;
+ unsigned long iflags;
- for (srp = sfp->headrp; srp; srp = tsrp) {
- tsrp = srp->nextrp;
- if (sg_srp_done(srp, sfp))
- sg_finish_rem_req(srp);
- else
- ++dirty;
- }
- if (0 == dirty) {
- unsigned long iflags;
+ write_lock_irqsave(&sg_index_lock, iflags);
+ list_del(&sfp->sfd_siblings);
+ write_unlock_irqrestore(&sg_index_lock, iflags);
+ wake_up_interruptible(&sdp->o_excl_wait);
- write_lock_irqsave(&sg_index_lock, iflags);
- __sg_remove_sfp(sdp, sfp);
- if (sdp->detached && (NULL == sdp->headfp)) {
- idr_remove(&sg_index_idr, sdp->index);
- kfree(sdp);
- res = 1;
- }
- write_unlock_irqrestore(&sg_index_lock, iflags);
- } else {
- /* MOD_INC's to inhibit unloading sg and associated adapter driver */
- /* only bump the access_count if we actually succeeded in
- * throwing another counter on the host module */
- scsi_device_get(sdp->device); /* XXX: retval ignored? */
- sfp->closed = 1; /* flag dirty state on this fd */
- SCSI_LOG_TIMEOUT(1, printk("sg_remove_sfp: worrisome, %d writes pending\n",
- dirty));
- }
- return res;
+ INIT_WORK(&sfp->ew.work, sg_remove_sfp_usercontext);
+ schedule_work(&sfp->ew.work);
}
static int
@@ -2199,19 +2144,38 @@ sg_last_dev(void)
}
#endif
-static Sg_device *
-sg_get_dev(int dev)
+/* must be called with sg_index_lock held */
+static Sg_device *sg_lookup_dev(int dev)
{
- Sg_device *sdp;
- unsigned long iflags;
+ return idr_find(&sg_index_idr, dev);
+}
- read_lock_irqsave(&sg_index_lock, iflags);
- sdp = idr_find(&sg_index_idr, dev);
- read_unlock_irqrestore(&sg_index_lock, iflags);
+static Sg_device *sg_get_dev(int dev)
+{
+ struct sg_device *sdp;
+ unsigned long flags;
+
+ read_lock_irqsave(&sg_index_lock, flags);
+ sdp = sg_lookup_dev(dev);
+ if (!sdp)
+ sdp = ERR_PTR(-ENXIO);
+ else if (sdp->detached) {
+ /* If sdp->detached, then the refcount may already be 0, in
+ * which case it would be a bug to do kref_get().
+ */
+ sdp = ERR_PTR(-ENODEV);
+ } else
+ kref_get(&sdp->d_ref);
+ read_unlock_irqrestore(&sg_index_lock, flags);
return sdp;
}
+static void sg_put_dev(struct sg_device *sdp)
+{
+ kref_put(&sdp->d_ref, sg_device_destroy);
+}
+
#ifdef CONFIG_SCSI_PROC_FS
static struct proc_dir_entry *sg_proc_sgp = NULL;
@@ -2468,8 +2432,10 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v)
struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
Sg_device *sdp;
struct scsi_device *scsidp;
+ unsigned long iflags;
- sdp = it ? sg_get_dev(it->index) : NULL;
+ read_lock_irqsave(&sg_index_lock, iflags);
+ sdp = it ? sg_lookup_dev(it->index) : NULL;
if (sdp && (scsidp = sdp->device) && (!sdp->detached))
seq_printf(s, "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n",
scsidp->host->host_no, scsidp->channel,
@@ -2480,6 +2446,7 @@ static int sg_proc_seq_show_dev(struct seq_file *s, void *v)
(int) scsi_device_online(scsidp));
else
seq_printf(s, "-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\t-1\n");
+ read_unlock_irqrestore(&sg_index_lock, iflags);
return 0;
}
@@ -2493,16 +2460,20 @@ static int sg_proc_seq_show_devstrs(struct seq_file *s, void *v)
struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
Sg_device *sdp;
struct scsi_device *scsidp;
+ unsigned long iflags;
- sdp = it ? sg_get_dev(it->index) : NULL;
+ read_lock_irqsave(&sg_index_lock, iflags);
+ sdp = it ? sg_lookup_dev(it->index) : NULL;
if (sdp && (scsidp = sdp->device) && (!sdp->detached))
seq_printf(s, "%8.8s\t%16.16s\t%4.4s\n",
scsidp->vendor, scsidp->model, scsidp->rev);
else
seq_printf(s, "<no active device>\n");
+ read_unlock_irqrestore(&sg_index_lock, iflags);
return 0;
}
+/* must be called while holding sg_index_lock */
static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
{
int k, m, new_interface, blen, usg;
@@ -2512,9 +2483,12 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
const char * cp;
unsigned int ms;
- for (k = 0; (fp = sg_get_nth_sfp(sdp, k)); ++k) {
+ k = 0;
+ list_for_each_entry(fp, &sdp->sfds, sfd_siblings) {
+ k++;
+ read_lock(&fp->rq_list_lock); /* irqs already disabled */
seq_printf(s, " FD(%d): timeout=%dms bufflen=%d "
- "(res)sgat=%d low_dma=%d\n", k + 1,
+ "(res)sgat=%d low_dma=%d\n", k,
jiffies_to_msecs(fp->timeout),
fp->reserve.bufflen,
(int) fp->reserve.k_use_sg,
@@ -2522,7 +2496,9 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
seq_printf(s, " cmd_q=%d f_packid=%d k_orphan=%d closed=%d\n",
(int) fp->cmd_q, (int) fp->force_packid,
(int) fp->keep_orphan, (int) fp->closed);
- for (m = 0; (srp = sg_get_nth_request(fp, m)); ++m) {
+ for (m = 0, srp = fp->headrp;
+ srp != NULL;
+ ++m, srp = srp->nextrp) {
hp = &srp->header;
new_interface = (hp->interface_id == '\0') ? 0 : 1;
if (srp->res_used) {
@@ -2559,6 +2535,7 @@ static void sg_proc_debug_helper(struct seq_file *s, Sg_device * sdp)
}
if (0 == m)
seq_printf(s, " No requests active\n");
+ read_unlock(&fp->rq_list_lock);
}
}
@@ -2571,39 +2548,34 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v)
{
struct sg_proc_deviter * it = (struct sg_proc_deviter *) v;
Sg_device *sdp;
+ unsigned long iflags;
if (it && (0 == it->index)) {
seq_printf(s, "max_active_device=%d(origin 1)\n",
(int)it->max);
seq_printf(s, " def_reserved_size=%d\n", sg_big_buff);
}
- sdp = it ? sg_get_dev(it->index) : NULL;
- if (sdp) {
- struct scsi_device *scsidp = sdp->device;
- if (NULL == scsidp) {
- seq_printf(s, "device %d detached ??\n",
- (int)it->index);
- return 0;
- }
+ read_lock_irqsave(&sg_index_lock, iflags);
+ sdp = it ? sg_lookup_dev(it->index) : NULL;
+ if (sdp && !list_empty(&sdp->sfds)) {
+ struct scsi_device *scsidp = sdp->device;
- if (sg_get_nth_sfp(sdp, 0)) {
- seq_printf(s, " >>> device=%s ",
- sdp->disk->disk_name);
- if (sdp->detached)
- seq_printf(s, "detached pending close ");
- else
- seq_printf
- (s, "scsi%d chan=%d id=%d lun=%d em=%d",
- scsidp->host->host_no,
- scsidp->channel, scsidp->id,
- scsidp->lun,
- scsidp->host->hostt->emulated);
- seq_printf(s, " sg_tablesize=%d excl=%d\n",
- sdp->sg_tablesize, sdp->exclude);
- }
+ seq_printf(s, " >>> device=%s ", sdp->disk->disk_name);
+ if (sdp->detached)
+ seq_printf(s, "detached pending close ");
+ else
+ seq_printf
+ (s, "scsi%d chan=%d id=%d lun=%d em=%d",
+ scsidp->host->host_no,
+ scsidp->channel, scsidp->id,
+ scsidp->lun,
+ scsidp->host->hostt->emulated);
+ seq_printf(s, " sg_tablesize=%d excl=%d\n",
+ sdp->sg_tablesize, sdp->exclude);
sg_proc_debug_helper(s, sdp);
}
+ read_unlock_irqrestore(&sg_index_lock, iflags);
return 0;
}
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index e7fa3caead7..0e1a0f2d2ad 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -309,15 +309,6 @@ static int sr_done(struct scsi_cmnd *SCpnt)
break;
case RECOVERED_ERROR:
-
- /*
- * An error occured, but it recovered. Inform the
- * user, but make sure that it's not treated as a
- * hard error.
- */
- scsi_print_sense("sr", SCpnt);
- SCpnt->result = 0;
- SCpnt->sense_buffer[0] = 0x0;
good_bytes = this_count;
break;
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c
index c6f19ee8f2c..eb24efea8f1 100644
--- a/drivers/scsi/st.c
+++ b/drivers/scsi/st.c
@@ -374,9 +374,9 @@ static int st_chk_result(struct scsi_tape *STp, struct st_request * SRpnt)
if (!debugging) { /* Abnormal conditions for tape */
if (!cmdstatp->have_sense)
printk(KERN_WARNING
- "%s: Error %x (sugg. bt 0x%x, driver bt 0x%x, host bt 0x%x).\n",
- name, result, suggestion(result),
- driver_byte(result) & DRIVER_MASK, host_byte(result));
+ "%s: Error %x (driver bt 0x%x, host bt 0x%x).\n",
+ name, result, driver_byte(result),
+ host_byte(result));
else if (cmdstatp->have_sense &&
scode != NO_SENSE &&
scode != RECOVERED_ERROR &&
diff --git a/drivers/scsi/stex.c b/drivers/scsi/stex.c
index a3a18ad7312..df7f96caa1c 100644
--- a/drivers/scsi/stex.c
+++ b/drivers/scsi/stex.c
@@ -1,7 +1,7 @@
/*
* SuperTrak EX Series Storage Controller driver for Linux
*
- * Copyright (C) 2005, 2006 Promise Technology Inc.
+ * Copyright (C) 2005-2009 Promise Technology Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -36,11 +36,11 @@
#include <scsi/scsi_eh.h>
#define DRV_NAME "stex"
-#define ST_DRIVER_VERSION "3.6.0000.1"
-#define ST_VER_MAJOR 3
-#define ST_VER_MINOR 6
-#define ST_OEM 0
-#define ST_BUILD_VER 1
+#define ST_DRIVER_VERSION "4.6.0000.3"
+#define ST_VER_MAJOR 4
+#define ST_VER_MINOR 6
+#define ST_OEM 0
+#define ST_BUILD_VER 3
enum {
/* MU register offset */
@@ -55,6 +55,13 @@ enum {
OIS = 0x30, /* MU_OUTBOUND_INTERRUPT_STATUS */
OIM = 0x3c, /* MU_OUTBOUND_INTERRUPT_MASK */
+ YH2I_INT = 0x20,
+ YINT_EN = 0x34,
+ YI2H_INT = 0x9c,
+ YI2H_INT_C = 0xa0,
+ YH2I_REQ = 0xc0,
+ YH2I_REQ_HI = 0xc4,
+
/* MU register value */
MU_INBOUND_DOORBELL_HANDSHAKE = 1,
MU_INBOUND_DOORBELL_REQHEADCHANGED = 2,
@@ -95,34 +102,32 @@ enum {
TASK_ATTRIBUTE_ORDERED = 0x2,
TASK_ATTRIBUTE_ACA = 0x4,
- /* request count, etc. */
- MU_MAX_REQUEST = 32,
+ SS_STS_NORMAL = 0x80000000,
+ SS_STS_DONE = 0x40000000,
+ SS_STS_HANDSHAKE = 0x20000000,
- /* one message wasted, use MU_MAX_REQUEST+1
- to handle MU_MAX_REQUEST messages */
- MU_REQ_COUNT = (MU_MAX_REQUEST + 1),
- MU_STATUS_COUNT = (MU_MAX_REQUEST + 1),
+ SS_HEAD_HANDSHAKE = 0x80,
- STEX_CDB_LENGTH = MAX_COMMAND_SIZE,
- REQ_VARIABLE_LEN = 1024,
+ STEX_CDB_LENGTH = 16,
STATUS_VAR_LEN = 128,
- ST_CAN_QUEUE = MU_MAX_REQUEST,
- ST_CMD_PER_LUN = MU_MAX_REQUEST,
- ST_MAX_SG = 32,
/* sg flags */
SG_CF_EOT = 0x80, /* end of table */
SG_CF_64B = 0x40, /* 64 bit item */
SG_CF_HOST = 0x20, /* sg in host memory */
+ MSG_DATA_DIR_ND = 0,
+ MSG_DATA_DIR_IN = 1,
+ MSG_DATA_DIR_OUT = 2,
st_shasta = 0,
st_vsc = 1,
- st_vsc1 = 2,
- st_yosemite = 3,
+ st_yosemite = 2,
+ st_seq = 3,
+ st_yel = 4,
PASSTHRU_REQ_TYPE = 0x00000001,
PASSTHRU_REQ_NO_WAKEUP = 0x00000100,
- ST_INTERNAL_TIMEOUT = 30,
+ ST_INTERNAL_TIMEOUT = 180,
ST_TO_CMD = 0,
ST_FROM_CMD = 1,
@@ -152,59 +157,40 @@ enum {
ST_ADDITIONAL_MEM = 0x200000,
};
-/* SCSI inquiry data */
-typedef struct st_inq {
- u8 DeviceType :5;
- u8 DeviceTypeQualifier :3;
- u8 DeviceTypeModifier :7;
- u8 RemovableMedia :1;
- u8 Versions;
- u8 ResponseDataFormat :4;
- u8 HiSupport :1;
- u8 NormACA :1;
- u8 ReservedBit :1;
- u8 AERC :1;
- u8 AdditionalLength;
- u8 Reserved[2];
- u8 SoftReset :1;
- u8 CommandQueue :1;
- u8 Reserved2 :1;
- u8 LinkedCommands :1;
- u8 Synchronous :1;
- u8 Wide16Bit :1;
- u8 Wide32Bit :1;
- u8 RelativeAddressing :1;
- u8 VendorId[8];
- u8 ProductId[16];
- u8 ProductRevisionLevel[4];
- u8 VendorSpecific[20];
- u8 Reserved3[40];
-} ST_INQ;
-
struct st_sgitem {
u8 ctrl; /* SG_CF_xxx */
u8 reserved[3];
__le32 count;
+ __le64 addr;
+};
+
+struct st_ss_sgitem {
__le32 addr;
__le32 addr_hi;
+ __le32 count;
};
struct st_sgtable {
__le16 sg_count;
__le16 max_sg_count;
__le32 sz_in_byte;
- struct st_sgitem table[ST_MAX_SG];
+};
+
+struct st_msg_header {
+ __le64 handle;
+ u8 flag;
+ u8 channel;
+ __le16 timeout;
+ u32 reserved;
};
struct handshake_frame {
- __le32 rb_phy; /* request payload queue physical address */
- __le32 rb_phy_hi;
+ __le64 rb_phy; /* request payload queue physical address */
__le16 req_sz; /* size of each request payload */
__le16 req_cnt; /* count of reqs the buffer can hold */
__le16 status_sz; /* size of each status payload */
__le16 status_cnt; /* count of status the buffer can hold */
- __le32 hosttime; /* seconds from Jan 1, 1970 (GMT) */
- __le32 hosttime_hi;
+ __le64 hosttime; /* seconds from Jan 1, 1970 (GMT) */
u8 partner_type; /* who sends this frame */
u8 reserved0[7];
__le32 partner_ver_major;
@@ -213,7 +199,8 @@ struct handshake_frame {
__le32 partner_ver_build;
__le32 extra_offset; /* NEW */
__le32 extra_size; /* NEW */
- u32 reserved1[2];
+ __le32 scratch_size;
+ u32 reserved1;
};
struct req_msg {
@@ -222,10 +209,10 @@ struct req_msg {
u8 target;
u8 task_attr;
u8 task_manage;
- u8 prd_entry;
+ u8 data_dir;
u8 payload_sz; /* payload size in 4-byte, not used */
u8 cdb[STEX_CDB_LENGTH];
- u8 variable[REQ_VARIABLE_LEN];
+ u32 variable[0];
};
struct status_msg {
@@ -281,12 +268,6 @@ struct st_drvver {
u32 reserved[3];
};
-#define MU_REQ_BUFFER_SIZE (MU_REQ_COUNT * sizeof(struct req_msg))
-#define MU_STATUS_BUFFER_SIZE (MU_STATUS_COUNT * sizeof(struct status_msg))
-#define MU_BUFFER_SIZE (MU_REQ_BUFFER_SIZE + MU_STATUS_BUFFER_SIZE)
-#define STEX_EXTRA_SIZE max(sizeof(struct st_frame), sizeof(ST_INQ))
-#define STEX_BUFFER_SIZE (MU_BUFFER_SIZE + STEX_EXTRA_SIZE)
-
struct st_ccb {
struct req_msg *req;
struct scsi_cmnd *cmd;
@@ -298,6 +279,7 @@ struct st_ccb {
u32 req_type;
u8 srb_status;
u8 scsi_status;
+ u8 reserved[2];
};
struct st_hba {
@@ -309,6 +291,10 @@ struct st_hba {
struct Scsi_Host *host;
struct pci_dev *pdev;
+ struct req_msg * (*alloc_rq) (struct st_hba *);
+ int (*map_sg)(struct st_hba *, struct req_msg *, struct st_ccb *);
+ void (*send) (struct st_hba *, struct req_msg *, u16);
+
u32 req_head;
u32 req_tail;
u32 status_head;
@@ -316,16 +302,36 @@ struct st_hba {
struct status_msg *status_buffer;
void *copy_buffer; /* temp buffer for driver-handled commands */
- struct st_ccb ccb[MU_MAX_REQUEST];
+ struct st_ccb *ccb;
struct st_ccb *wait_ccb;
- wait_queue_head_t waitq;
+ __le32 *scratch;
unsigned int mu_status;
+ unsigned int cardtype;
+ int msi_enabled;
int out_req_cnt;
+ u32 extra_offset;
+ u16 rq_count;
+ u16 rq_size;
+ u16 sts_count;
+};
- unsigned int cardtype;
+struct st_card_info {
+ struct req_msg * (*alloc_rq) (struct st_hba *);
+ int (*map_sg)(struct st_hba *, struct req_msg *, struct st_ccb *);
+ void (*send) (struct st_hba *, struct req_msg *, u16);
+ unsigned int max_id;
+ unsigned int max_lun;
+ unsigned int max_channel;
+ u16 rq_count;
+ u16 rq_size;
+ u16 sts_count;
};
+static int msi;
+module_param(msi, int, 0);
+MODULE_PARM_DESC(msi, "Enable Message Signaled Interrupts(0=off, 1=on)");
+
static const char console_inq_page[] =
{
0x03,0x00,0x03,0x03,0xFA,0x00,0x00,0x30,
@@ -343,22 +349,20 @@ MODULE_DESCRIPTION("Promise Technology SuperTrak EX Controllers");
MODULE_LICENSE("GPL");
MODULE_VERSION(ST_DRIVER_VERSION);
-static void stex_gettime(__le32 *time)
+static void stex_gettime(__le64 *time)
{
struct timeval tv;
- do_gettimeofday(&tv);
- *time = cpu_to_le32(tv.tv_sec & 0xffffffff);
- *(time + 1) = cpu_to_le32((tv.tv_sec >> 16) >> 16);
+ do_gettimeofday(&tv);
+ *time = cpu_to_le64(tv.tv_sec);
}
static struct status_msg *stex_get_status(struct st_hba *hba)
{
- struct status_msg *status =
- hba->status_buffer + hba->status_tail;
+ struct status_msg *status = hba->status_buffer + hba->status_tail;
++hba->status_tail;
- hba->status_tail %= MU_STATUS_COUNT;
+ hba->status_tail %= hba->sts_count+1;
return status;
}
@@ -368,7 +372,7 @@ static void stex_invalid_field(struct scsi_cmnd *cmd,
{
cmd->result = (DRIVER_SENSE << 24) | SAM_STAT_CHECK_CONDITION;
- /* "Invalid field in cbd" */
+ /* "Invalid field in cdb" */
scsi_build_sense_buffer(0, cmd->sense_buffer, ILLEGAL_REQUEST, 0x24,
0x0);
done(cmd);
@@ -376,47 +380,83 @@ static void stex_invalid_field(struct scsi_cmnd *cmd,
static struct req_msg *stex_alloc_req(struct st_hba *hba)
{
- struct req_msg *req = ((struct req_msg *)hba->dma_mem) +
- hba->req_head;
+ struct req_msg *req = hba->dma_mem + hba->req_head * hba->rq_size;
++hba->req_head;
- hba->req_head %= MU_REQ_COUNT;
+ hba->req_head %= hba->rq_count+1;
return req;
}
+static struct req_msg *stex_ss_alloc_req(struct st_hba *hba)
+{
+ return (struct req_msg *)(hba->dma_mem +
+ hba->req_head * hba->rq_size + sizeof(struct st_msg_header));
+}
+
static int stex_map_sg(struct st_hba *hba,
struct req_msg *req, struct st_ccb *ccb)
{
struct scsi_cmnd *cmd;
struct scatterlist *sg;
struct st_sgtable *dst;
+ struct st_sgitem *table;
int i, nseg;
cmd = ccb->cmd;
- dst = (struct st_sgtable *)req->variable;
- dst->max_sg_count = cpu_to_le16(ST_MAX_SG);
- dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd));
+ nseg = scsi_dma_map(cmd);
+ BUG_ON(nseg < 0);
+ if (nseg) {
+ dst = (struct st_sgtable *)req->variable;
+
+ ccb->sg_count = nseg;
+ dst->sg_count = cpu_to_le16((u16)nseg);
+ dst->max_sg_count = cpu_to_le16(hba->host->sg_tablesize);
+ dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd));
+
+ table = (struct st_sgitem *)(dst + 1);
+ scsi_for_each_sg(cmd, sg, nseg, i) {
+ table[i].count = cpu_to_le32((u32)sg_dma_len(sg));
+ table[i].addr = cpu_to_le64(sg_dma_address(sg));
+ table[i].ctrl = SG_CF_64B | SG_CF_HOST;
+ }
+ table[--i].ctrl |= SG_CF_EOT;
+ }
+
+ return nseg;
+}
+
+static int stex_ss_map_sg(struct st_hba *hba,
+ struct req_msg *req, struct st_ccb *ccb)
+{
+ struct scsi_cmnd *cmd;
+ struct scatterlist *sg;
+ struct st_sgtable *dst;
+ struct st_ss_sgitem *table;
+ int i, nseg;
+ cmd = ccb->cmd;
nseg = scsi_dma_map(cmd);
- if (nseg < 0)
- return -EIO;
+ BUG_ON(nseg < 0);
if (nseg) {
+ dst = (struct st_sgtable *)req->variable;
+
ccb->sg_count = nseg;
dst->sg_count = cpu_to_le16((u16)nseg);
+ dst->max_sg_count = cpu_to_le16(hba->host->sg_tablesize);
+ dst->sz_in_byte = cpu_to_le32(scsi_bufflen(cmd));
+ table = (struct st_ss_sgitem *)(dst + 1);
scsi_for_each_sg(cmd, sg, nseg, i) {
- dst->table[i].count = cpu_to_le32((u32)sg_dma_len(sg));
- dst->table[i].addr =
+ table[i].count = cpu_to_le32((u32)sg_dma_len(sg));
+ table[i].addr =
cpu_to_le32(sg_dma_address(sg) & 0xffffffff);
- dst->table[i].addr_hi =
+ table[i].addr_hi =
cpu_to_le32((sg_dma_address(sg) >> 16) >> 16);
- dst->table[i].ctrl = SG_CF_64B | SG_CF_HOST;
}
- dst->table[--i].ctrl |= SG_CF_EOT;
}
- return 0;
+ return nseg;
}
static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
@@ -425,7 +465,7 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
size_t count = sizeof(struct st_frame);
p = hba->copy_buffer;
- count = scsi_sg_copy_to_buffer(ccb->cmd, p, count);
+ scsi_sg_copy_to_buffer(ccb->cmd, p, count);
memset(p->base, 0, sizeof(u32)*6);
*(unsigned long *)(p->base) = pci_resource_start(hba->pdev, 0);
p->rom_addr = 0;
@@ -443,15 +483,13 @@ static void stex_controller_info(struct st_hba *hba, struct st_ccb *ccb)
p->subid =
hba->pdev->subsystem_vendor << 16 | hba->pdev->subsystem_device;
- count = scsi_sg_copy_from_buffer(ccb->cmd, p, count);
+ scsi_sg_copy_from_buffer(ccb->cmd, p, count);
}
static void
stex_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
{
req->tag = cpu_to_le16(tag);
- req->task_attr = TASK_ATTRIBUTE_SIMPLE;
- req->task_manage = 0; /* not supported yet */
hba->ccb[tag].req = req;
hba->out_req_cnt++;
@@ -461,13 +499,44 @@ stex_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
readl(hba->mmio_base + IDBL); /* flush */
}
+static void
+stex_ss_send_cmd(struct st_hba *hba, struct req_msg *req, u16 tag)
+{
+ struct scsi_cmnd *cmd;
+ struct st_msg_header *msg_h;
+ dma_addr_t addr;
+
+ req->tag = cpu_to_le16(tag);
+
+ hba->ccb[tag].req = req;
+ hba->out_req_cnt++;
+
+ cmd = hba->ccb[tag].cmd;
+ msg_h = (struct st_msg_header *)req - 1;
+ if (likely(cmd)) {
+ msg_h->channel = (u8)cmd->device->channel;
+ msg_h->timeout = cpu_to_le16(cmd->request->timeout/HZ);
+ }
+ addr = hba->dma_handle + hba->req_head * hba->rq_size;
+ addr += (hba->ccb[tag].sg_count+4)/11;
+ msg_h->handle = cpu_to_le64(addr);
+
+ ++hba->req_head;
+ hba->req_head %= hba->rq_count+1;
+
+ writel((addr >> 16) >> 16, hba->mmio_base + YH2I_REQ_HI);
+ readl(hba->mmio_base + YH2I_REQ_HI); /* flush */
+ writel(addr, hba->mmio_base + YH2I_REQ);
+ readl(hba->mmio_base + YH2I_REQ); /* flush */
+}
+
static int
stex_slave_alloc(struct scsi_device *sdev)
{
/* Cheat: usually extracted from Inquiry data */
sdev->tagged_supported = 1;
- scsi_activate_tcq(sdev, ST_CMD_PER_LUN);
+ scsi_activate_tcq(sdev, sdev->host->can_queue);
return 0;
}
@@ -494,9 +563,10 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
{
struct st_hba *hba;
struct Scsi_Host *host;
- unsigned int id,lun;
+ unsigned int id, lun;
struct req_msg *req;
u16 tag;
+
host = cmd->device->host;
id = cmd->device->id;
lun = cmd->device->lun;
@@ -508,6 +578,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
static char ms10_caching_page[12] =
{ 0, 0x12, 0, 0, 0, 0, 0, 0, 0x8, 0xa, 0x4, 0 };
unsigned char page;
+
page = cmd->cmnd[2] & 0x3f;
if (page == 0x8 || page == 0x3f) {
scsi_sg_copy_from_buffer(cmd, ms10_caching_page,
@@ -539,7 +610,8 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
case INQUIRY:
if (id != host->max_id - 1)
break;
- if (lun == 0 && (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
+ if (!lun && !cmd->device->channel &&
+ (cmd->cmnd[1] & INQUIRY_EVPD) == 0) {
scsi_sg_copy_from_buffer(cmd, (void *)console_inq_page,
sizeof(console_inq_page));
cmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
@@ -551,6 +623,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
if (cmd->cmnd[1] == PASSTHRU_GET_DRVVER) {
struct st_drvver ver;
size_t cp_len = sizeof(ver);
+
ver.major = ST_VER_MAJOR;
ver.minor = ST_VER_MINOR;
ver.oem = ST_OEM;
@@ -576,7 +649,7 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
if (unlikely(tag >= host->can_queue))
return SCSI_MLQUEUE_HOST_BUSY;
- req = stex_alloc_req(hba);
+ req = hba->alloc_rq(hba);
req->lun = lun;
req->target = id;
@@ -584,15 +657,23 @@ stex_queuecommand(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *))
/* cdb */
memcpy(req->cdb, cmd->cmnd, STEX_CDB_LENGTH);
+ if (cmd->sc_data_direction == DMA_FROM_DEVICE)
+ req->data_dir = MSG_DATA_DIR_IN;
+ else if (cmd->sc_data_direction == DMA_TO_DEVICE)
+ req->data_dir = MSG_DATA_DIR_OUT;
+ else
+ req->data_dir = MSG_DATA_DIR_ND;
+
hba->ccb[tag].cmd = cmd;
hba->ccb[tag].sense_bufflen = SCSI_SENSE_BUFFERSIZE;
hba->ccb[tag].sense_buffer = cmd->sense_buffer;
- hba->ccb[tag].req_type = 0;
- if (cmd->sc_data_direction != DMA_NONE)
- stex_map_sg(hba, req, &hba->ccb[tag]);
+ if (!hba->map_sg(hba, req, &hba->ccb[tag])) {
+ hba->ccb[tag].sg_count = 0;
+ memset(&req->variable[0], 0, 8);
+ }
- stex_send_cmd(hba, req, tag);
+ hba->send(hba, req, tag);
return 0;
}
@@ -601,7 +682,7 @@ static void stex_scsi_done(struct st_ccb *ccb)
struct scsi_cmnd *cmd = ccb->cmd;
int result;
- if (ccb->srb_status == SRB_STATUS_SUCCESS || ccb->srb_status == 0) {
+ if (ccb->srb_status == SRB_STATUS_SUCCESS || ccb->srb_status == 0) {
result = ccb->scsi_status;
switch (ccb->scsi_status) {
case SAM_STAT_GOOD:
@@ -641,7 +722,6 @@ static void stex_scsi_done(struct st_ccb *ccb)
static void stex_copy_data(struct st_ccb *ccb,
struct status_msg *resp, unsigned int variable)
{
- size_t count = variable;
if (resp->scsi_status != SAM_STAT_GOOD) {
if (ccb->sense_buffer != NULL)
memcpy(ccb->sense_buffer, resp->variable,
@@ -651,35 +731,16 @@ static void stex_copy_data(struct st_ccb *ccb,
if (ccb->cmd == NULL)
return;
- count = scsi_sg_copy_from_buffer(ccb->cmd, resp->variable, count);
+ scsi_sg_copy_from_buffer(ccb->cmd, resp->variable, variable);
}
-static void stex_ys_commands(struct st_hba *hba,
+static void stex_check_cmd(struct st_hba *hba,
struct st_ccb *ccb, struct status_msg *resp)
{
if (ccb->cmd->cmnd[0] == MGT_CMD &&
- resp->scsi_status != SAM_STAT_CHECK_CONDITION) {
+ resp->scsi_status != SAM_STAT_CHECK_CONDITION)
scsi_set_resid(ccb->cmd, scsi_bufflen(ccb->cmd) -
le32_to_cpu(*(__le32 *)&resp->variable[0]));
- return;
- }
-
- if (resp->srb_status != 0)
- return;
-
- /* determine inquiry command status by DeviceTypeQualifier */
- if (ccb->cmd->cmnd[0] == INQUIRY &&
- resp->scsi_status == SAM_STAT_GOOD) {
- ST_INQ *inq_data;
-
- scsi_sg_copy_to_buffer(ccb->cmd, hba->copy_buffer,
- STEX_EXTRA_SIZE);
- inq_data = (ST_INQ *)hba->copy_buffer;
- if (inq_data->DeviceTypeQualifier != 0)
- ccb->srb_status = SRB_STATUS_SELECTION_TIMEOUT;
- else
- ccb->srb_status = SRB_STATUS_SUCCESS;
- }
}
static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
@@ -690,12 +751,12 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
unsigned int size;
u16 tag;
- if (!(doorbell & MU_OUTBOUND_DOORBELL_STATUSHEADCHANGED))
+ if (unlikely(!(doorbell & MU_OUTBOUND_DOORBELL_STATUSHEADCHANGED)))
return;
/* status payloads */
hba->status_head = readl(base + OMR1);
- if (unlikely(hba->status_head >= MU_STATUS_COUNT)) {
+ if (unlikely(hba->status_head > hba->sts_count)) {
printk(KERN_WARNING DRV_NAME "(%s): invalid status head\n",
pci_name(hba->pdev));
return;
@@ -725,13 +786,13 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
continue;
}
+ hba->out_req_cnt--;
ccb = &hba->ccb[tag];
- if (hba->wait_ccb == ccb)
+ if (unlikely(hba->wait_ccb == ccb))
hba->wait_ccb = NULL;
if (unlikely(ccb->req == NULL)) {
printk(KERN_WARNING DRV_NAME
"(%s): lagging req\n", pci_name(hba->pdev));
- hba->out_req_cnt--;
continue;
}
@@ -746,12 +807,13 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
stex_copy_data(ccb, resp, size);
}
+ ccb->req = NULL;
ccb->srb_status = resp->srb_status;
ccb->scsi_status = resp->scsi_status;
if (likely(ccb->cmd != NULL)) {
if (hba->cardtype == st_yosemite)
- stex_ys_commands(hba, ccb, resp);
+ stex_check_cmd(hba, ccb, resp);
if (unlikely(ccb->cmd->cmnd[0] == PASSTHRU_CMD &&
ccb->cmd->cmnd[1] == PASSTHRU_GET_ADAPTER))
@@ -759,17 +821,8 @@ static void stex_mu_intr(struct st_hba *hba, u32 doorbell)
scsi_dma_unmap(ccb->cmd);
stex_scsi_done(ccb);
- hba->out_req_cnt--;
- } else if (ccb->req_type & PASSTHRU_REQ_TYPE) {
- hba->out_req_cnt--;
- if (ccb->req_type & PASSTHRU_REQ_NO_WAKEUP) {
- ccb->req_type = 0;
- continue;
- }
+ } else
ccb->req_type = 0;
- if (waitqueue_active(&hba->waitq))
- wake_up(&hba->waitq);
- }
}
update_status:
@@ -802,7 +855,103 @@ static irqreturn_t stex_intr(int irq, void *__hba)
return IRQ_RETVAL(handled);
}
-static int stex_handshake(struct st_hba *hba)
+static void stex_ss_mu_intr(struct st_hba *hba)
+{
+ struct status_msg *resp;
+ struct st_ccb *ccb;
+ __le32 *scratch;
+ unsigned int size;
+ int count = 0;
+ u32 value;
+ u16 tag;
+
+ if (unlikely(hba->out_req_cnt <= 0 ||
+ hba->mu_status == MU_STATE_RESETTING))
+ return;
+
+ while (count < hba->sts_count) {
+ scratch = hba->scratch + hba->status_tail;
+ value = le32_to_cpu(*scratch);
+ if (unlikely(!(value & SS_STS_NORMAL)))
+ return;
+
+ resp = hba->status_buffer + hba->status_tail;
+ *scratch = 0;
+ ++count;
+ ++hba->status_tail;
+ hba->status_tail %= hba->sts_count+1;
+
+ tag = (u16)value;
+ if (unlikely(tag >= hba->host->can_queue)) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): invalid tag\n", pci_name(hba->pdev));
+ continue;
+ }
+
+ hba->out_req_cnt--;
+ ccb = &hba->ccb[tag];
+ if (unlikely(hba->wait_ccb == ccb))
+ hba->wait_ccb = NULL;
+ if (unlikely(ccb->req == NULL)) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): lagging req\n", pci_name(hba->pdev));
+ continue;
+ }
+
+ ccb->req = NULL;
+ if (likely(value & SS_STS_DONE)) { /* normal case */
+ ccb->srb_status = SRB_STATUS_SUCCESS;
+ ccb->scsi_status = SAM_STAT_GOOD;
+ } else {
+ ccb->srb_status = resp->srb_status;
+ ccb->scsi_status = resp->scsi_status;
+ size = resp->payload_sz * sizeof(u32);
+ if (unlikely(size < sizeof(*resp) - STATUS_VAR_LEN ||
+ size > sizeof(*resp))) {
+ printk(KERN_WARNING DRV_NAME
+ "(%s): bad status size\n",
+ pci_name(hba->pdev));
+ } else {
+ size -= sizeof(*resp) - STATUS_VAR_LEN;
+ if (size)
+ stex_copy_data(ccb, resp, size);
+ }
+ if (likely(ccb->cmd != NULL))
+ stex_check_cmd(hba, ccb, resp);
+ }
+
+ if (likely(ccb->cmd != NULL)) {
+ scsi_dma_unmap(ccb->cmd);
+ stex_scsi_done(ccb);
+ } else
+ ccb->req_type = 0;
+ }
+}
+
+static irqreturn_t stex_ss_intr(int irq, void *__hba)
+{
+ struct st_hba *hba = __hba;
+ void __iomem *base = hba->mmio_base;
+ u32 data;
+ unsigned long flags;
+ int handled = 0;
+
+ spin_lock_irqsave(hba->host->host_lock, flags);
+
+ data = readl(base + YI2H_INT);
+ if (data && data != 0xffffffff) {
+ /* clear the interrupt */
+ writel(data, base + YI2H_INT_C);
+ stex_ss_mu_intr(hba);
+ handled = 1;
+ }
+
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+
+ return IRQ_RETVAL(handled);
+}
+
+static int stex_common_handshake(struct st_hba *hba)
{
void __iomem *base = hba->mmio_base;
struct handshake_frame *h;
@@ -831,26 +980,27 @@ static int stex_handshake(struct st_hba *hba)
data = readl(base + OMR1);
if ((data & 0xffff0000) == MU_HANDSHAKE_SIGNATURE_HALF) {
data &= 0x0000ffff;
- if (hba->host->can_queue > data)
+ if (hba->host->can_queue > data) {
hba->host->can_queue = data;
+ hba->host->cmd_per_lun = data;
+ }
}
- h = (struct handshake_frame *)(hba->dma_mem + MU_REQ_BUFFER_SIZE);
- h->rb_phy = cpu_to_le32(hba->dma_handle);
- h->rb_phy_hi = cpu_to_le32((hba->dma_handle >> 16) >> 16);
- h->req_sz = cpu_to_le16(sizeof(struct req_msg));
- h->req_cnt = cpu_to_le16(MU_REQ_COUNT);
+ h = (struct handshake_frame *)hba->status_buffer;
+ h->rb_phy = cpu_to_le64(hba->dma_handle);
+ h->req_sz = cpu_to_le16(hba->rq_size);
+ h->req_cnt = cpu_to_le16(hba->rq_count+1);
h->status_sz = cpu_to_le16(sizeof(struct status_msg));
- h->status_cnt = cpu_to_le16(MU_STATUS_COUNT);
+ h->status_cnt = cpu_to_le16(hba->sts_count+1);
stex_gettime(&h->hosttime);
h->partner_type = HMU_PARTNER_TYPE;
- if (hba->dma_size > STEX_BUFFER_SIZE) {
- h->extra_offset = cpu_to_le32(STEX_BUFFER_SIZE);
+ if (hba->extra_offset) {
+ h->extra_offset = cpu_to_le32(hba->extra_offset);
h->extra_size = cpu_to_le32(ST_ADDITIONAL_MEM);
} else
h->extra_offset = h->extra_size = 0;
- status_phys = hba->dma_handle + MU_REQ_BUFFER_SIZE;
+ status_phys = hba->dma_handle + (hba->rq_count+1) * hba->rq_size;
writel(status_phys, base + IMR0);
readl(base + IMR0);
writel((status_phys >> 16) >> 16, base + IMR1);
@@ -882,10 +1032,79 @@ static int stex_handshake(struct st_hba *hba)
readl(base + IMR1);
writel(0, base + OMR1);
readl(base + OMR1); /* flush */
- hba->mu_status = MU_STATE_STARTED;
return 0;
}
+static int stex_ss_handshake(struct st_hba *hba)
+{
+ void __iomem *base = hba->mmio_base;
+ struct st_msg_header *msg_h;
+ struct handshake_frame *h;
+ __le32 *scratch = hba->scratch;
+ u32 data;
+ unsigned long before;
+ int ret = 0;
+
+ h = (struct handshake_frame *)(hba->alloc_rq(hba));
+ msg_h = (struct st_msg_header *)h - 1;
+ msg_h->handle = cpu_to_le64(hba->dma_handle);
+ msg_h->flag = SS_HEAD_HANDSHAKE;
+
+ h->rb_phy = cpu_to_le64(hba->dma_handle);
+ h->req_sz = cpu_to_le16(hba->rq_size);
+ h->req_cnt = cpu_to_le16(hba->rq_count+1);
+ h->status_sz = cpu_to_le16(sizeof(struct status_msg));
+ h->status_cnt = cpu_to_le16(hba->sts_count+1);
+ stex_gettime(&h->hosttime);
+ h->partner_type = HMU_PARTNER_TYPE;
+ h->extra_offset = h->extra_size = 0;
+ h->scratch_size = cpu_to_le32((hba->sts_count+1)*sizeof(u32));
+
+ data = readl(base + YINT_EN);
+ data &= ~4;
+ writel(data, base + YINT_EN);
+ writel((hba->dma_handle >> 16) >> 16, base + YH2I_REQ_HI);
+ writel(hba->dma_handle, base + YH2I_REQ);
+
+ scratch = hba->scratch;
+ before = jiffies;
+ while (!(le32_to_cpu(*scratch) & SS_STS_HANDSHAKE)) {
+ if (time_after(jiffies, before + MU_MAX_DELAY * HZ)) {
+ printk(KERN_ERR DRV_NAME
+ "(%s): no signature after handshake frame\n",
+ pci_name(hba->pdev));
+ ret = -1;
+ break;
+ }
+ rmb();
+ msleep(1);
+ }
+
+ *scratch = 0;
+ msg_h->flag = 0;
+ return ret;
+}
+
+static int stex_handshake(struct st_hba *hba)
+{
+ int err;
+ unsigned long flags;
+
+ err = (hba->cardtype == st_yel) ?
+ stex_ss_handshake(hba) : stex_common_handshake(hba);
+ if (err == 0) {
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->req_head = 0;
+ hba->req_tail = 0;
+ hba->status_head = 0;
+ hba->status_tail = 0;
+ hba->out_req_cnt = 0;
+ hba->mu_status = MU_STATE_STARTED;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
+ }
+ return err;
+}
+
static int stex_abort(struct scsi_cmnd *cmd)
{
struct Scsi_Host *host = cmd->device->host;
@@ -914,15 +1133,23 @@ static int stex_abort(struct scsi_cmnd *cmd)
goto out;
}
- data = readl(base + ODBL);
- if (data == 0 || data == 0xffffffff)
- goto fail_out;
+ if (hba->cardtype == st_yel) {
+ data = readl(base + YI2H_INT);
+ if (data == 0 || data == 0xffffffff)
+ goto fail_out;
- writel(data, base + ODBL);
- readl(base + ODBL); /* flush */
+ writel(data, base + YI2H_INT_C);
+ stex_ss_mu_intr(hba);
+ } else {
+ data = readl(base + ODBL);
+ if (data == 0 || data == 0xffffffff)
+ goto fail_out;
- stex_mu_intr(hba, data);
+ writel(data, base + ODBL);
+ readl(base + ODBL); /* flush */
+ stex_mu_intr(hba, data);
+ }
if (hba->wait_ccb == NULL) {
printk(KERN_WARNING DRV_NAME
"(%s): lost interrupt\n", pci_name(hba->pdev));
@@ -981,8 +1208,9 @@ static void stex_hard_reset(struct st_hba *hba)
static int stex_reset(struct scsi_cmnd *cmd)
{
struct st_hba *hba;
- unsigned long flags;
- unsigned long before;
+ void __iomem *base;
+ unsigned long flags, before;
+
hba = (struct st_hba *) &cmd->device->host->hostdata[0];
printk(KERN_INFO DRV_NAME
@@ -1001,13 +1229,6 @@ static int stex_reset(struct scsi_cmnd *cmd)
pci_name(hba->pdev));
return FAILED;
}
- spin_lock_irqsave(hba->host->host_lock, flags);
- hba->req_head = 0;
- hba->req_tail = 0;
- hba->status_head = 0;
- hba->status_tail = 0;
- hba->out_req_cnt = 0;
- spin_unlock_irqrestore(hba->host->host_lock, flags);
return SUCCESS;
}
@@ -1024,7 +1245,23 @@ static int stex_reset(struct scsi_cmnd *cmd)
msleep(1);
}
+ base = hba->mmio_base;
+ writel(0, base + IMR0);
+ readl(base + IMR0);
+ writel(0, base + OMR0);
+ readl(base + OMR0);
+ writel(0, base + IMR1);
+ readl(base + IMR1);
+ writel(0, base + OMR1);
+ readl(base + OMR1); /* flush */
+ spin_lock_irqsave(hba->host->host_lock, flags);
+ hba->req_head = 0;
+ hba->req_tail = 0;
+ hba->status_head = 0;
+ hba->status_tail = 0;
+ hba->out_req_cnt = 0;
hba->mu_status = MU_STATE_STARTED;
+ spin_unlock_irqrestore(hba->host->host_lock, flags);
return SUCCESS;
}
@@ -1058,15 +1295,106 @@ static struct scsi_host_template driver_template = {
.slave_destroy = stex_slave_destroy,
.eh_abort_handler = stex_abort,
.eh_host_reset_handler = stex_reset,
- .can_queue = ST_CAN_QUEUE,
.this_id = -1,
- .sg_tablesize = ST_MAX_SG,
- .cmd_per_lun = ST_CMD_PER_LUN,
+};
+
+static struct pci_device_id stex_pci_tbl[] = {
+ /* st_shasta */
+ { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_shasta }, /* SuperTrak EX8350/8300/16350/16300 */
+ { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_shasta }, /* SuperTrak EX12350 */
+ { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_shasta }, /* SuperTrak EX4350 */
+ { 0x105a, 0xe350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ st_shasta }, /* SuperTrak EX24350 */
+
+ /* st_vsc */
+ { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc },
+
+ /* st_yosemite */
+ { 0x105a, 0x8650, 0x105a, PCI_ANY_ID, 0, 0, st_yosemite },
+
+ /* st_seq */
+ { 0x105a, 0x3360, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_seq },
+
+ /* st_yel */
+ { 0x105a, 0x8650, 0x1033, PCI_ANY_ID, 0, 0, st_yel },
+ { 0x105a, 0x8760, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_yel },
+ { } /* terminate list */
+};
+
+static struct st_card_info stex_card_info[] = {
+ /* st_shasta */
+ {
+ .max_id = 17,
+ .max_lun = 8,
+ .max_channel = 0,
+ .rq_count = 32,
+ .rq_size = 1048,
+ .sts_count = 32,
+ .alloc_rq = stex_alloc_req,
+ .map_sg = stex_map_sg,
+ .send = stex_send_cmd,
+ },
+
+ /* st_vsc */
+ {
+ .max_id = 129,
+ .max_lun = 1,
+ .max_channel = 0,
+ .rq_count = 32,
+ .rq_size = 1048,
+ .sts_count = 32,
+ .alloc_rq = stex_alloc_req,
+ .map_sg = stex_map_sg,
+ .send = stex_send_cmd,
+ },
+
+ /* st_yosemite */
+ {
+ .max_id = 2,
+ .max_lun = 256,
+ .max_channel = 0,
+ .rq_count = 256,
+ .rq_size = 1048,
+ .sts_count = 256,
+ .alloc_rq = stex_alloc_req,
+ .map_sg = stex_map_sg,
+ .send = stex_send_cmd,
+ },
+
+ /* st_seq */
+ {
+ .max_id = 129,
+ .max_lun = 1,
+ .max_channel = 0,
+ .rq_count = 32,
+ .rq_size = 1048,
+ .sts_count = 32,
+ .alloc_rq = stex_alloc_req,
+ .map_sg = stex_map_sg,
+ .send = stex_send_cmd,
+ },
+
+ /* st_yel */
+ {
+ .max_id = 129,
+ .max_lun = 256,
+ .max_channel = 3,
+ .rq_count = 801,
+ .rq_size = 512,
+ .sts_count = 801,
+ .alloc_rq = stex_ss_alloc_req,
+ .map_sg = stex_ss_map_sg,
+ .send = stex_ss_send_cmd,
+ },
};
static int stex_set_dma_mask(struct pci_dev * pdev)
{
int ret;
+
if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)
&& !pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK))
return 0;
@@ -1076,11 +1404,48 @@ static int stex_set_dma_mask(struct pci_dev * pdev)
return ret;
}
+static int stex_request_irq(struct st_hba *hba)
+{
+ struct pci_dev *pdev = hba->pdev;
+ int status;
+
+ if (msi) {
+ status = pci_enable_msi(pdev);
+ if (status != 0)
+ printk(KERN_ERR DRV_NAME
+ "(%s): error %d setting up MSI\n",
+ pci_name(pdev), status);
+ else
+ hba->msi_enabled = 1;
+ } else
+ hba->msi_enabled = 0;
+
+ status = request_irq(pdev->irq, hba->cardtype == st_yel ?
+ stex_ss_intr : stex_intr, IRQF_SHARED, DRV_NAME, hba);
+
+ if (status != 0) {
+ if (hba->msi_enabled)
+ pci_disable_msi(pdev);
+ }
+ return status;
+}
+
+static void stex_free_irq(struct st_hba *hba)
+{
+ struct pci_dev *pdev = hba->pdev;
+
+ free_irq(pdev->irq, hba);
+ if (hba->msi_enabled)
+ pci_disable_msi(pdev);
+}
+
static int __devinit
stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct st_hba *hba;
struct Scsi_Host *host;
+ const struct st_card_info *ci = NULL;
+ u32 sts_offset, cp_offset, scratch_offset;
int err;
err = pci_enable_device(pdev);
@@ -1124,10 +1489,17 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
hba->cardtype = (unsigned int) id->driver_data;
- if (hba->cardtype == st_vsc && (pdev->subsystem_device & 0xf) == 0x1)
- hba->cardtype = st_vsc1;
- hba->dma_size = (hba->cardtype == st_vsc1) ?
- (STEX_BUFFER_SIZE + ST_ADDITIONAL_MEM) : (STEX_BUFFER_SIZE);
+ ci = &stex_card_info[hba->cardtype];
+ sts_offset = scratch_offset = (ci->rq_count+1) * ci->rq_size;
+ if (hba->cardtype == st_yel)
+ sts_offset += (ci->sts_count+1) * sizeof(u32);
+ cp_offset = sts_offset + (ci->sts_count+1) * sizeof(struct status_msg);
+ hba->dma_size = cp_offset + sizeof(struct st_frame);
+ if (hba->cardtype == st_seq ||
+ (hba->cardtype == st_vsc && (pdev->subsystem_device & 1))) {
+ hba->extra_offset = hba->dma_size;
+ hba->dma_size += ST_ADDITIONAL_MEM;
+ }
hba->dma_mem = dma_alloc_coherent(&pdev->dev,
hba->dma_size, &hba->dma_handle, GFP_KERNEL);
if (!hba->dma_mem) {
@@ -1137,35 +1509,46 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto out_iounmap;
}
- hba->status_buffer =
- (struct status_msg *)(hba->dma_mem + MU_REQ_BUFFER_SIZE);
- hba->copy_buffer = hba->dma_mem + MU_BUFFER_SIZE;
+ hba->ccb = kcalloc(ci->rq_count, sizeof(struct st_ccb), GFP_KERNEL);
+ if (!hba->ccb) {
+ err = -ENOMEM;
+ printk(KERN_ERR DRV_NAME "(%s): ccb alloc failed\n",
+ pci_name(pdev));
+ goto out_pci_free;
+ }
+
+ if (hba->cardtype == st_yel)
+ hba->scratch = (__le32 *)(hba->dma_mem + scratch_offset);
+ hba->status_buffer = (struct status_msg *)(hba->dma_mem + sts_offset);
+ hba->copy_buffer = hba->dma_mem + cp_offset;
+ hba->rq_count = ci->rq_count;
+ hba->rq_size = ci->rq_size;
+ hba->sts_count = ci->sts_count;
+ hba->alloc_rq = ci->alloc_rq;
+ hba->map_sg = ci->map_sg;
+ hba->send = ci->send;
hba->mu_status = MU_STATE_STARTING;
- if (hba->cardtype == st_shasta) {
- host->max_lun = 8;
- host->max_id = 16 + 1;
- } else if (hba->cardtype == st_yosemite) {
- host->max_lun = 128;
- host->max_id = 1 + 1;
- } else {
- /* st_vsc and st_vsc1 */
- host->max_lun = 1;
- host->max_id = 128 + 1;
- }
- host->max_channel = 0;
+ if (hba->cardtype == st_yel)
+ host->sg_tablesize = 38;
+ else
+ host->sg_tablesize = 32;
+ host->can_queue = ci->rq_count;
+ host->cmd_per_lun = ci->rq_count;
+ host->max_id = ci->max_id;
+ host->max_lun = ci->max_lun;
+ host->max_channel = ci->max_channel;
host->unique_id = host->host_no;
host->max_cmd_len = STEX_CDB_LENGTH;
hba->host = host;
hba->pdev = pdev;
- init_waitqueue_head(&hba->waitq);
- err = request_irq(pdev->irq, stex_intr, IRQF_SHARED, DRV_NAME, hba);
+ err = stex_request_irq(hba);
if (err) {
printk(KERN_ERR DRV_NAME "(%s): request irq failed\n",
pci_name(pdev));
- goto out_pci_free;
+ goto out_ccb_free;
}
err = stex_handshake(hba);
@@ -1193,7 +1576,9 @@ stex_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0;
out_free_irq:
- free_irq(pdev->irq, hba);
+ stex_free_irq(hba);
+out_ccb_free:
+ kfree(hba->ccb);
out_pci_free:
dma_free_coherent(&pdev->dev, hba->dma_size,
hba->dma_mem, hba->dma_handle);
@@ -1212,15 +1597,20 @@ out_disable:
static void stex_hba_stop(struct st_hba *hba)
{
struct req_msg *req;
+ struct st_msg_header *msg_h;
unsigned long flags;
unsigned long before;
u16 tag = 0;
spin_lock_irqsave(hba->host->host_lock, flags);
- req = stex_alloc_req(hba);
- memset(req->cdb, 0, STEX_CDB_LENGTH);
+ req = hba->alloc_rq(hba);
+ if (hba->cardtype == st_yel) {
+ msg_h = (struct st_msg_header *)req - 1;
+ memset(msg_h, 0, hba->rq_size);
+ } else
+ memset(req, 0, hba->rq_size);
- if (hba->cardtype == st_yosemite) {
+ if (hba->cardtype == st_yosemite || hba->cardtype == st_yel) {
req->cdb[0] = MGT_CMD;
req->cdb[1] = MGT_CMD_SIGNATURE;
req->cdb[2] = CTLR_CONFIG_CMD;
@@ -1235,27 +1625,31 @@ static void stex_hba_stop(struct st_hba *hba)
hba->ccb[tag].sg_count = 0;
hba->ccb[tag].sense_bufflen = 0;
hba->ccb[tag].sense_buffer = NULL;
- hba->ccb[tag].req_type |= PASSTHRU_REQ_TYPE;
+ hba->ccb[tag].req_type = PASSTHRU_REQ_TYPE;
- stex_send_cmd(hba, req, tag);
+ hba->send(hba, req, tag);
spin_unlock_irqrestore(hba->host->host_lock, flags);
before = jiffies;
while (hba->ccb[tag].req_type & PASSTHRU_REQ_TYPE) {
- if (time_after(jiffies, before + ST_INTERNAL_TIMEOUT * HZ))
+ if (time_after(jiffies, before + ST_INTERNAL_TIMEOUT * HZ)) {
+ hba->ccb[tag].req_type = 0;
return;
- msleep(10);
+ }
+ msleep(1);
}
}
static void stex_hba_free(struct st_hba *hba)
{
- free_irq(hba->pdev->irq, hba);
+ stex_free_irq(hba);
iounmap(hba->mmio_base);
pci_release_regions(hba->pdev);
+ kfree(hba->ccb);
+
dma_free_coherent(&hba->pdev->dev, hba->dma_size,
hba->dma_mem, hba->dma_handle);
}
@@ -1284,35 +1678,6 @@ static void stex_shutdown(struct pci_dev *pdev)
stex_hba_stop(hba);
}
-static struct pci_device_id stex_pci_tbl[] = {
- /* st_shasta */
- { 0x105a, 0x8350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- st_shasta }, /* SuperTrak EX8350/8300/16350/16300 */
- { 0x105a, 0xc350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- st_shasta }, /* SuperTrak EX12350 */
- { 0x105a, 0x4302, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- st_shasta }, /* SuperTrak EX4350 */
- { 0x105a, 0xe350, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- st_shasta }, /* SuperTrak EX24350 */
-
- /* st_vsc */
- { 0x105a, 0x7250, PCI_ANY_ID, PCI_ANY_ID, 0, 0, st_vsc },
-
- /* st_yosemite */
- { 0x105a, 0x8650, PCI_ANY_ID, 0x4600, 0, 0,
- st_yosemite }, /* SuperTrak EX4650 */
- { 0x105a, 0x8650, PCI_ANY_ID, 0x4610, 0, 0,
- st_yosemite }, /* SuperTrak EX4650o */
- { 0x105a, 0x8650, PCI_ANY_ID, 0x8600, 0, 0,
- st_yosemite }, /* SuperTrak EX8650EL */
- { 0x105a, 0x8650, PCI_ANY_ID, 0x8601, 0, 0,
- st_yosemite }, /* SuperTrak EX8650 */
- { 0x105a, 0x8650, PCI_ANY_ID, 0x8602, 0, 0,
- st_yosemite }, /* SuperTrak EX8654 */
- { 0x105a, 0x8650, PCI_ANY_ID, PCI_ANY_ID, 0, 0,
- st_yosemite }, /* generic st_yosemite */
- { } /* terminate list */
-};
MODULE_DEVICE_TABLE(pci, stex_pci_tbl);
static struct pci_driver stex_pci_driver = {
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.c b/drivers/scsi/sym53c8xx_2/sym_glue.c
index f4e6cde1fd0..23e78201588 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.c
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.c
@@ -792,9 +792,9 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev)
/*
* Select queue depth from driver setup.
- * Donnot use more than configured by user.
- * Use at least 2.
- * Donnot use more than our maximum.
+ * Do not use more than configured by user.
+ * Use at least 1.
+ * Do not use more than our maximum.
*/
reqtags = sym_driver_setup.max_tag;
if (reqtags > tp->usrtags)
@@ -803,7 +803,7 @@ static int sym53c8xx_slave_configure(struct scsi_device *sdev)
reqtags = 0;
if (reqtags > SYM_CONF_MAX_TAG)
reqtags = SYM_CONF_MAX_TAG;
- depth_to_use = reqtags ? reqtags : 2;
+ depth_to_use = reqtags ? reqtags : 1;
scsi_adjust_queue_depth(sdev,
sdev->tagged_supported ? MSG_SIMPLE_TAG : 0,
depth_to_use);
@@ -1236,14 +1236,29 @@ static int sym53c8xx_proc_info(struct Scsi_Host *shost, char *buffer,
#endif /* SYM_LINUX_PROC_INFO_SUPPORT */
/*
+ * Free resources claimed by sym_iomap_device(). Note that
+ * sym_free_resources() should be used instead of this function after calling
+ * sym_attach().
+ */
+static void __devinit
+sym_iounmap_device(struct sym_device *device)
+{
+ if (device->s.ioaddr)
+ pci_iounmap(device->pdev, device->s.ioaddr);
+ if (device->s.ramaddr)
+ pci_iounmap(device->pdev, device->s.ramaddr);
+}
+
+/*
* Free controller resources.
*/
-static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev)
+static void sym_free_resources(struct sym_hcb *np, struct pci_dev *pdev,
+ int do_free_irq)
{
/*
* Free O/S specific resources.
*/
- if (pdev->irq)
+ if (do_free_irq)
free_irq(pdev->irq, np->s.host);
if (np->s.ioaddr)
pci_iounmap(pdev, np->s.ioaddr);
@@ -1271,10 +1286,11 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
{
struct sym_data *sym_data;
struct sym_hcb *np = NULL;
- struct Scsi_Host *shost;
+ struct Scsi_Host *shost = NULL;
struct pci_dev *pdev = dev->pdev;
unsigned long flags;
struct sym_fw *fw;
+ int do_free_irq = 0;
printk(KERN_INFO "sym%d: <%s> rev 0x%x at pci %s irq %u\n",
unit, dev->chip.name, pdev->revision, pci_name(pdev),
@@ -1285,11 +1301,11 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
*/
fw = sym_find_firmware(&dev->chip);
if (!fw)
- return NULL;
+ goto attach_failed;
shost = scsi_host_alloc(tpnt, sizeof(*sym_data));
if (!shost)
- return NULL;
+ goto attach_failed;
sym_data = shost_priv(shost);
/*
@@ -1319,6 +1335,10 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
np->maxoffs = dev->chip.offset_max;
np->maxburst = dev->chip.burst_max;
np->myaddr = dev->host_id;
+ np->mmio_ba = (u32)dev->mmio_base;
+ np->ram_ba = (u32)dev->ram_base;
+ np->s.ioaddr = dev->s.ioaddr;
+ np->s.ramaddr = dev->s.ramaddr;
/*
* Edit its name.
@@ -1334,22 +1354,6 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
goto attach_failed;
}
- /*
- * Try to map the controller chip to
- * virtual and physical memory.
- */
- np->mmio_ba = (u32)dev->mmio_base;
- np->s.ioaddr = dev->s.ioaddr;
- np->s.ramaddr = dev->s.ramaddr;
-
- /*
- * Map on-chip RAM if present and supported.
- */
- if (!(np->features & FE_RAM))
- dev->ram_base = 0;
- if (dev->ram_base)
- np->ram_ba = (u32)dev->ram_base;
-
if (sym_hcb_attach(shost, fw, dev->nvram))
goto attach_failed;
@@ -1364,6 +1368,7 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
sym_name(np), pdev->irq);
goto attach_failed;
}
+ do_free_irq = 1;
/*
* After SCSI devices have been opened, we cannot
@@ -1416,12 +1421,13 @@ static struct Scsi_Host * __devinit sym_attach(struct scsi_host_template *tpnt,
"TERMINATION, DEVICE POWER etc.!\n", sym_name(np));
spin_unlock_irqrestore(shost->host_lock, flags);
attach_failed:
- if (!shost)
- return NULL;
- printf_info("%s: giving up ...\n", sym_name(np));
+ printf_info("sym%d: giving up ...\n", unit);
if (np)
- sym_free_resources(np, pdev);
- scsi_host_put(shost);
+ sym_free_resources(np, pdev, do_free_irq);
+ else
+ sym_iounmap_device(dev);
+ if (shost)
+ scsi_host_put(shost);
return NULL;
}
@@ -1550,30 +1556,28 @@ static int __devinit sym_set_workarounds(struct sym_device *device)
}
/*
- * Read and check the PCI configuration for any detected NCR
- * boards and save data for attaching after all boards have
- * been detected.
+ * Map HBA registers and on-chip SRAM (if present).
*/
-static void __devinit
-sym_init_device(struct pci_dev *pdev, struct sym_device *device)
+static int __devinit
+sym_iomap_device(struct sym_device *device)
{
- int i = 2;
+ struct pci_dev *pdev = device->pdev;
struct pci_bus_region bus_addr;
-
- device->host_id = SYM_SETUP_HOST_ID;
- device->pdev = pdev;
+ int i = 2;
pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[1]);
device->mmio_base = bus_addr.start;
- /*
- * If the BAR is 64-bit, resource 2 will be occupied by the
- * upper 32 bits
- */
- if (!pdev->resource[i].flags)
- i++;
- pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]);
- device->ram_base = bus_addr.start;
+ if (device->chip.features & FE_RAM) {
+ /*
+ * If the BAR is 64-bit, resource 2 will be occupied by the
+ * upper 32 bits
+ */
+ if (!pdev->resource[i].flags)
+ i++;
+ pcibios_resource_to_bus(pdev, &bus_addr, &pdev->resource[i]);
+ device->ram_base = bus_addr.start;
+ }
#ifdef CONFIG_SCSI_SYM53C8XX_MMIO
if (device->mmio_base)
@@ -1583,9 +1587,21 @@ sym_init_device(struct pci_dev *pdev, struct sym_device *device)
if (!device->s.ioaddr)
device->s.ioaddr = pci_iomap(pdev, 0,
pci_resource_len(pdev, 0));
- if (device->ram_base)
+ if (!device->s.ioaddr) {
+ dev_err(&pdev->dev, "could not map registers; giving up.\n");
+ return -EIO;
+ }
+ if (device->ram_base) {
device->s.ramaddr = pci_iomap(pdev, i,
pci_resource_len(pdev, i));
+ if (!device->s.ramaddr) {
+ dev_warn(&pdev->dev,
+ "could not map SRAM; continuing anyway.\n");
+ device->ram_base = 0;
+ }
+ }
+
+ return 0;
}
/*
@@ -1659,7 +1675,8 @@ static int sym_detach(struct Scsi_Host *shost, struct pci_dev *pdev)
udelay(10);
OUTB(np, nc_istat, 0);
- sym_free_resources(np, pdev);
+ sym_free_resources(np, pdev, 1);
+ scsi_host_put(shost);
return 1;
}
@@ -1696,9 +1713,13 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
struct sym_device sym_dev;
struct sym_nvram nvram;
struct Scsi_Host *shost;
+ int do_iounmap = 0;
+ int do_disable_device = 1;
memset(&sym_dev, 0, sizeof(sym_dev));
memset(&nvram, 0, sizeof(nvram));
+ sym_dev.pdev = pdev;
+ sym_dev.host_id = SYM_SETUP_HOST_ID;
if (pci_enable_device(pdev))
goto leave;
@@ -1708,12 +1729,17 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
if (pci_request_regions(pdev, NAME53C8XX))
goto disable;
- sym_init_device(pdev, &sym_dev);
if (sym_check_supported(&sym_dev))
goto free;
- if (sym_check_raid(&sym_dev))
- goto leave; /* Don't disable the device */
+ if (sym_iomap_device(&sym_dev))
+ goto free;
+ do_iounmap = 1;
+
+ if (sym_check_raid(&sym_dev)) {
+ do_disable_device = 0; /* Don't disable the device */
+ goto free;
+ }
if (sym_set_workarounds(&sym_dev))
goto free;
@@ -1722,6 +1748,7 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
sym_get_nvram(&sym_dev, &nvram);
+ do_iounmap = 0; /* Don't sym_iounmap_device() after sym_attach(). */
shost = sym_attach(&sym2_template, attach_count, &sym_dev);
if (!shost)
goto free;
@@ -1737,9 +1764,12 @@ static int __devinit sym2_probe(struct pci_dev *pdev,
detach:
sym_detach(pci_get_drvdata(pdev), pdev);
free:
+ if (do_iounmap)
+ sym_iounmap_device(&sym_dev);
pci_release_regions(pdev);
disable:
- pci_disable_device(pdev);
+ if (do_disable_device)
+ pci_disable_device(pdev);
leave:
return -ENODEV;
}
@@ -1749,7 +1779,6 @@ static void sym2_remove(struct pci_dev *pdev)
struct Scsi_Host *shost = pci_get_drvdata(pdev);
scsi_remove_host(shost);
- scsi_host_put(shost);
sym_detach(shost, pdev);
pci_release_regions(pdev);
pci_disable_device(pdev);
diff --git a/drivers/scsi/sym53c8xx_2/sym_glue.h b/drivers/scsi/sym53c8xx_2/sym_glue.h
index 567fbe0b4f0..b80bf709f10 100644
--- a/drivers/scsi/sym53c8xx_2/sym_glue.h
+++ b/drivers/scsi/sym53c8xx_2/sym_glue.h
@@ -234,7 +234,7 @@ static inline struct sym_hcb * sym_get_hcb(struct Scsi_Host *host)
/*
* Set the status field of a CAM CCB.
*/
-static __inline void
+static inline void
sym_set_cam_status(struct scsi_cmnd *cmd, int status)
{
cmd->result &= ~(0xff << 16);
@@ -244,7 +244,7 @@ sym_set_cam_status(struct scsi_cmnd *cmd, int status)
/*
* Get the status field of a CAM CCB.
*/
-static __inline int
+static inline int
sym_get_cam_status(struct scsi_cmnd *cmd)
{
return host_byte(cmd->result);
@@ -253,7 +253,7 @@ sym_get_cam_status(struct scsi_cmnd *cmd)
/*
* Build CAM result for a successful IO and for a failed IO.
*/
-static __inline void sym_set_cam_result_ok(struct sym_ccb *cp, struct scsi_cmnd *cmd, int resid)
+static inline void sym_set_cam_result_ok(struct sym_ccb *cp, struct scsi_cmnd *cmd, int resid)
{
scsi_set_resid(cmd, resid);
cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.c b/drivers/scsi/sym53c8xx_2/sym_hipd.c
index 98df1651404..ffa70d1ed18 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.c
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.c
@@ -602,7 +602,7 @@ sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fa
/*
* Set initial io register bits from burst code.
*/
-static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
+static inline void sym_init_burst(struct sym_hcb *np, u_char bc)
{
np->rv_ctest4 &= ~0x80;
np->rv_dmode &= ~(0x3 << 6);
@@ -1433,13 +1433,12 @@ static int sym_prepare_nego(struct sym_hcb *np, struct sym_ccb *cp, u_char *msgp
* Many devices implement PPR in a buggy way, so only use it if we
* really want to.
*/
- if (goal->offset &&
- (goal->iu || goal->dt || goal->qas || (goal->period < 0xa))) {
+ if (goal->renego == NS_PPR || (goal->offset &&
+ (goal->iu || goal->dt || goal->qas || (goal->period < 0xa)))) {
nego = NS_PPR;
- } else if (spi_width(starget) != goal->width) {
+ } else if (goal->renego == NS_WIDE || goal->width) {
nego = NS_WIDE;
- } else if (spi_period(starget) != goal->period ||
- spi_offset(starget) != goal->offset) {
+ } else if (goal->renego == NS_SYNC || goal->offset) {
nego = NS_SYNC;
} else {
goal->check_nego = 0;
@@ -2040,6 +2039,29 @@ static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs
}
}
+static void sym_announce_transfer_rate(struct sym_tcb *tp)
+{
+ struct scsi_target *starget = tp->starget;
+
+ if (tp->tprint.period != spi_period(starget) ||
+ tp->tprint.offset != spi_offset(starget) ||
+ tp->tprint.width != spi_width(starget) ||
+ tp->tprint.iu != spi_iu(starget) ||
+ tp->tprint.dt != spi_dt(starget) ||
+ tp->tprint.qas != spi_qas(starget) ||
+ !tp->tprint.check_nego) {
+ tp->tprint.period = spi_period(starget);
+ tp->tprint.offset = spi_offset(starget);
+ tp->tprint.width = spi_width(starget);
+ tp->tprint.iu = spi_iu(starget);
+ tp->tprint.dt = spi_dt(starget);
+ tp->tprint.qas = spi_qas(starget);
+ tp->tprint.check_nego = 1;
+
+ spi_display_xfer_agreement(starget);
+ }
+}
+
/*
* We received a WDTR.
* Let everything be aware of the changes.
@@ -2049,11 +2071,13 @@ static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
struct sym_tcb *tp = &np->target[target];
struct scsi_target *starget = tp->starget;
- if (spi_width(starget) == wide)
- return;
-
sym_settrans(np, target, 0, 0, 0, wide, 0, 0);
+ if (wide)
+ tp->tgoal.renego = NS_WIDE;
+ else
+ tp->tgoal.renego = 0;
+ tp->tgoal.check_nego = 0;
tp->tgoal.width = wide;
spi_offset(starget) = 0;
spi_period(starget) = 0;
@@ -2063,7 +2087,7 @@ static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
spi_qas(starget) = 0;
if (sym_verbose >= 3)
- spi_display_xfer_agreement(starget);
+ sym_announce_transfer_rate(tp);
}
/*
@@ -2080,6 +2104,12 @@ sym_setsync(struct sym_hcb *np, int target,
sym_settrans(np, target, 0, ofs, per, wide, div, fak);
+ if (wide)
+ tp->tgoal.renego = NS_WIDE;
+ else if (ofs)
+ tp->tgoal.renego = NS_SYNC;
+ else
+ tp->tgoal.renego = 0;
spi_period(starget) = per;
spi_offset(starget) = ofs;
spi_iu(starget) = spi_dt(starget) = spi_qas(starget) = 0;
@@ -2090,7 +2120,7 @@ sym_setsync(struct sym_hcb *np, int target,
tp->tgoal.check_nego = 0;
}
- spi_display_xfer_agreement(starget);
+ sym_announce_transfer_rate(tp);
}
/*
@@ -2106,6 +2136,10 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
sym_settrans(np, target, opts, ofs, per, wide, div, fak);
+ if (wide || ofs)
+ tp->tgoal.renego = NS_PPR;
+ else
+ tp->tgoal.renego = 0;
spi_width(starget) = tp->tgoal.width = wide;
spi_period(starget) = tp->tgoal.period = per;
spi_offset(starget) = tp->tgoal.offset = ofs;
@@ -2114,7 +2148,7 @@ sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
spi_qas(starget) = tp->tgoal.qas = !!(opts & PPR_OPT_QAS);
tp->tgoal.check_nego = 0;
- spi_display_xfer_agreement(starget);
+ sym_announce_transfer_rate(tp);
}
/*
@@ -3516,6 +3550,7 @@ static void sym_sir_task_recovery(struct sym_hcb *np, int num)
spi_dt(starget) = 0;
spi_qas(starget) = 0;
tp->tgoal.check_nego = 1;
+ tp->tgoal.renego = 0;
}
/*
@@ -5135,9 +5170,14 @@ int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *cmd, struct sym_ccb *
/*
* Build a negotiation message if needed.
* (nego_status is filled by sym_prepare_nego())
+ *
+ * Always negotiate on INQUIRY and REQUEST SENSE.
+ *
*/
cp->nego_status = 0;
- if (tp->tgoal.check_nego && !tp->nego_cp && lp) {
+ if ((tp->tgoal.check_nego ||
+ cmd->cmnd[0] == INQUIRY || cmd->cmnd[0] == REQUEST_SENSE) &&
+ !tp->nego_cp && lp) {
msglen += sym_prepare_nego(np, cp, msgptr + msglen);
}
diff --git a/drivers/scsi/sym53c8xx_2/sym_hipd.h b/drivers/scsi/sym53c8xx_2/sym_hipd.h
index ad078805e62..1588c90518d 100644
--- a/drivers/scsi/sym53c8xx_2/sym_hipd.h
+++ b/drivers/scsi/sym53c8xx_2/sym_hipd.h
@@ -354,6 +354,7 @@ struct sym_trans {
unsigned int dt:1;
unsigned int qas:1;
unsigned int check_nego:1;
+ unsigned int renego:2;
};
/*
@@ -419,6 +420,9 @@ struct sym_tcb {
/* Transfer goal */
struct sym_trans tgoal;
+ /* Last printed transfer speed */
+ struct sym_trans tprint;
+
/*
* Keep track of the CCB used for the negotiation in order
* to ensure that only 1 negotiation is queued at a time.
@@ -1092,7 +1096,7 @@ do { \
#elif SYM_CONF_DMA_ADDRESSING_MODE == 2
#define DMA_DAC_MASK DMA_64BIT_MASK
int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
-static __inline void
+static inline void
sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
{
u32 h = (badd>>32);
@@ -1197,7 +1201,7 @@ dma_addr_t __vtobus(m_pool_ident_t dev_dmat, void *m);
#define sym_m_pool_match(mp_id1, mp_id2) (mp_id1 == mp_id2)
-static __inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+static inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{
void *vaddr = NULL;
dma_addr_t baddr = 0;
@@ -1211,7 +1215,7 @@ static __inline void *sym_m_get_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
return vaddr;
}
-static __inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
+static inline void sym_m_free_dma_mem_cluster(m_pool_p mp, m_vtob_p vbp)
{
dma_free_coherent(mp->dev_dmat, SYM_MEM_CLUSTER_SIZE, vbp->vaddr,
vbp->baddr);
diff --git a/drivers/scsi/sym53c8xx_2/sym_malloc.c b/drivers/scsi/sym53c8xx_2/sym_malloc.c
index 92bf9b14a7a..883cac10daf 100644
--- a/drivers/scsi/sym53c8xx_2/sym_malloc.c
+++ b/drivers/scsi/sym53c8xx_2/sym_malloc.c
@@ -262,7 +262,7 @@ static void ___free_dma_mem_cluster(m_pool_p mp, void *m)
#endif
/* Fetch the memory pool for a given pool id (i.e. DMA constraints) */
-static __inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
+static inline m_pool_p ___get_dma_pool(m_pool_ident_t dev_dmat)
{
m_pool_p mp;
for (mp = mp0.next;
diff --git a/drivers/scsi/sym53c8xx_2/sym_misc.h b/drivers/scsi/sym53c8xx_2/sym_misc.h
index 430537183c1..96c15145902 100644
--- a/drivers/scsi/sym53c8xx_2/sym_misc.h
+++ b/drivers/scsi/sym53c8xx_2/sym_misc.h
@@ -52,17 +52,17 @@ typedef struct sym_quehead {
(ptr)->flink = (ptr); (ptr)->blink = (ptr); \
} while (0)
-static __inline struct sym_quehead *sym_que_first(struct sym_quehead *head)
+static inline struct sym_quehead *sym_que_first(struct sym_quehead *head)
{
return (head->flink == head) ? 0 : head->flink;
}
-static __inline struct sym_quehead *sym_que_last(struct sym_quehead *head)
+static inline struct sym_quehead *sym_que_last(struct sym_quehead *head)
{
return (head->blink == head) ? 0 : head->blink;
}
-static __inline void __sym_que_add(struct sym_quehead * new,
+static inline void __sym_que_add(struct sym_quehead * new,
struct sym_quehead * blink,
struct sym_quehead * flink)
{
@@ -72,19 +72,19 @@ static __inline void __sym_que_add(struct sym_quehead * new,
blink->flink = new;
}
-static __inline void __sym_que_del(struct sym_quehead * blink,
+static inline void __sym_que_del(struct sym_quehead * blink,
struct sym_quehead * flink)
{
flink->blink = blink;
blink->flink = flink;
}
-static __inline int sym_que_empty(struct sym_quehead *head)
+static inline int sym_que_empty(struct sym_quehead *head)
{
return head->flink == head;
}
-static __inline void sym_que_splice(struct sym_quehead *list,
+static inline void sym_que_splice(struct sym_quehead *list,
struct sym_quehead *head)
{
struct sym_quehead *first = list->flink;
@@ -101,7 +101,7 @@ static __inline void sym_que_splice(struct sym_quehead *list,
}
}
-static __inline void sym_que_move(struct sym_quehead *orig,
+static inline void sym_que_move(struct sym_quehead *orig,
struct sym_quehead *dest)
{
struct sym_quehead *first, *last;
@@ -129,7 +129,7 @@ static __inline void sym_que_move(struct sym_quehead *orig,
#define sym_insque_head(new, head) __sym_que_add(new, head, (head)->flink)
-static __inline struct sym_quehead *sym_remque_head(struct sym_quehead *head)
+static inline struct sym_quehead *sym_remque_head(struct sym_quehead *head)
{
struct sym_quehead *elem = head->flink;
@@ -142,7 +142,7 @@ static __inline struct sym_quehead *sym_remque_head(struct sym_quehead *head)
#define sym_insque_tail(new, head) __sym_que_add(new, (head)->blink, head)
-static __inline struct sym_quehead *sym_remque_tail(struct sym_quehead *head)
+static inline struct sym_quehead *sym_remque_tail(struct sym_quehead *head)
{
struct sym_quehead *elem = head->blink;
diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c
index a8d61a62522..97f3158fa7b 100644
--- a/drivers/scsi/zalon.c
+++ b/drivers/scsi/zalon.c
@@ -137,7 +137,7 @@ zalon_probe(struct parisc_device *dev)
goto fail;
if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) {
- dev_printk(KERN_ERR, dev, "irq problem with %d, detaching\n ",
+ dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ",
dev->irq);
goto fail;
}