diff options
291 files changed, 21127 insertions, 25095 deletions
diff --git a/Documentation/sched-design-CFS.txt b/Documentation/sched-design-CFS.txt index 84901e7c0508..88bcb8767335 100644 --- a/Documentation/sched-design-CFS.txt +++ b/Documentation/sched-design-CFS.txt @@ -117,3 +117,70 @@ Some implementation details: iterators of the scheduling modules are used. The balancing code got quite a bit simpler as a result. + +Group scheduler extension to CFS +================================ + +Normally the scheduler operates on individual tasks and strives to provide +fair CPU time to each task. Sometimes, it may be desirable to group tasks +and provide fair CPU time to each such task group. For example, it may +be desirable to first provide fair CPU time to each user on the system +and then to each task belonging to a user. + +CONFIG_FAIR_GROUP_SCHED strives to achieve exactly that. It lets +SCHED_NORMAL/BATCH tasks be be grouped and divides CPU time fairly among such +groups. At present, there are two (mutually exclusive) mechanisms to group +tasks for CPU bandwidth control purpose: + + - Based on user id (CONFIG_FAIR_USER_SCHED) + In this option, tasks are grouped according to their user id. + - Based on "cgroup" pseudo filesystem (CONFIG_FAIR_CGROUP_SCHED) + This options lets the administrator create arbitrary groups + of tasks, using the "cgroup" pseudo filesystem. See + Documentation/cgroups.txt for more information about this + filesystem. + +Only one of these options to group tasks can be chosen and not both. + +Group scheduler tunables: + +When CONFIG_FAIR_USER_SCHED is defined, a directory is created in sysfs for +each new user and a "cpu_share" file is added in that directory. + + # cd /sys/kernel/uids + # cat 512/cpu_share # Display user 512's CPU share + 1024 + # echo 2048 > 512/cpu_share # Modify user 512's CPU share + # cat 512/cpu_share # Display user 512's CPU share + 2048 + # + +CPU bandwidth between two users are divided in the ratio of their CPU shares. +For ex: if you would like user "root" to get twice the bandwidth of user +"guest", then set the cpu_share for both the users such that "root"'s +cpu_share is twice "guest"'s cpu_share + + +When CONFIG_FAIR_CGROUP_SCHED is defined, a "cpu.shares" file is created +for each group created using the pseudo filesystem. See example steps +below to create task groups and modify their CPU share using the "cgroups" +pseudo filesystem + + # mkdir /dev/cpuctl + # mount -t cgroup -ocpu none /dev/cpuctl + # cd /dev/cpuctl + + # mkdir multimedia # create "multimedia" group of tasks + # mkdir browser # create "browser" group of tasks + + # #Configure the multimedia group to receive twice the CPU bandwidth + # #that of browser group + + # echo 2048 > multimedia/cpu.shares + # echo 1024 > browser/cpu.shares + + # firefox & # Launch firefox and move it to "browser" group + # echo <firefox_pid> > browser/tasks + + # #Launch gmplayer (or your favourite movie player) + # echo <movie_player_pid> > multimedia/tasks diff --git a/Documentation/scsi/00-INDEX b/Documentation/scsi/00-INDEX index 12354830c6b0..aa1f7e927834 100644 --- a/Documentation/scsi/00-INDEX +++ b/Documentation/scsi/00-INDEX @@ -2,14 +2,20 @@ - this file 53c700.txt - info on driver for 53c700 based adapters -AM53C974.txt - - info on driver for AM53c974 based adapters BusLogic.txt - info on driver for adapters with BusLogic chips -ChangeLog +ChangeLog.1992-1997 - Changes to scsi files, if not listed elsewhere +ChangeLog.arcmsr + - Changes to driver for ARECA's SATA RAID controller cards ChangeLog.ips - IBM ServeRAID driver Changelog +ChangeLog.lpfc + - Changes to lpfc driver +ChangeLog.megaraid + - Changes to LSI megaraid controller. +ChangeLog.megaraid_sas + - Changes to serial attached scsi version of LSI megaraid controller. ChangeLog.ncr53c8xx - Changes to ncr53c8xx driver ChangeLog.sym53c8xx @@ -20,26 +26,44 @@ FlashPoint.txt - info on driver for BusLogic FlashPoint adapters LICENSE.FlashPoint - Licence of the Flashpoint driver +LICENSE.qla2xxx + - License for QLogic Linux Fibre Channel HBA Driver firmware. Mylex.txt - info on driver for Mylex adapters NinjaSCSI.txt - info on WorkBiT NinjaSCSI-32/32Bi driver +aacraid.txt + - Driver supporting Adaptec RAID controllers aha152x.txt - info on driver for Adaptec AHA152x based adapters +aic79xx.txt + - Adaptec Ultra320 SCSI host adapters aic7xxx.txt - info on driver for Adaptec controllers aic7xxx_old.txt - info on driver for Adaptec controllers, old generation +arcmsr_spec.txt + - ARECA FIRMWARE SPEC (for IOP331 adapter) +dc395x.txt + - README file for the dc395x SCSI driver dpti.txt - info on driver for DPT SmartRAID and Adaptec I2O RAID based adapters dtc3x80.txt - info on driver for DTC 2x80 based adapters g_NCR5380.txt - info on driver for NCR5380 and NCR53c400 based adapters +hptiop.txt + - HIGHPOINT ROCKETRAID 3xxx RAID DRIVER ibmmca.txt - info on driver for IBM adapters with MCA bus in2000.txt - info on in2000 driver +libsas.txt + - Serial Attached SCSI management layer. +lpfc.txt + - LPFC driver release notes +megaraid.txt + - Common Management Module, shared code handling ioctls for LSI drivers ncr53c7xx.txt - info on driver for NCR53c7xx based adapters ncr53c8xx.txt @@ -50,6 +74,8 @@ ppa.txt - info on driver for IOmega zip drive qlogicfas.txt - info on driver for QLogic FASxxx based adapters +scsi-changer.txt + - README for the SCSI media changer driver scsi-generic.txt - info on the sg driver for generic (non-disk/CD/tape) SCSI devices. scsi.txt @@ -58,6 +84,8 @@ scsi_mid_low_api.txt - info on API between SCSI layer and low level drivers scsi_eh.txt - info on SCSI midlayer error handling infrastructure +scsi_fc_transport.txt + - SCSI Fiber Channel Tansport st.txt - info on scsi tape driver sym53c500_cs.txt diff --git a/Documentation/scsi/ChangeLog.arcmsr b/Documentation/scsi/ChangeLog.arcmsr index 162c47fdf45f..cd8403a33ee6 100644 --- a/Documentation/scsi/ChangeLog.arcmsr +++ b/Documentation/scsi/ChangeLog.arcmsr @@ -53,4 +53,19 @@ ** for linux standard list ** enable usage of pci message signal interrupt ** follow Randy.Danlup kindness suggestion cleanup this code -**************************************************************************
\ No newline at end of file +** 1.20.00.14 05/02/2007 Erich Chen & Nick Cheng +** 1.implement PCI-Express error recovery function and AER capability +** 2.implement the selection of ARCMSR_MAX_XFER_SECTORS_B=4096 +** if firmware version is newer than 1.42 +** 3.modify arcmsr_iop_reset to improve the ability +** 4.modify the ISR, arcmsr_interrupt routine,to prevent the +** inconsistency with sg_mod driver if application directly calls +** the arcmsr driver w/o passing through scsi mid layer +** specially thanks to Yanmin Zhang's openhanded help about AER +** 1.20.00.15 08/30/2007 Erich Chen & Nick Cheng +** 1. support ARC1200/1201/1202 SATA RAID adapter, which is named +** ACB_ADAPTER_TYPE_B +** 2. modify the arcmsr_pci_slot_reset function +** 3. modify the arcmsr_pci_ers_disconnect_forepart function +** 4. modify the arcmsr_pci_ers_need_reset_forepart function +************************************************************************** diff --git a/Documentation/scsi/aacraid.txt b/Documentation/scsi/aacraid.txt index cc12b55d4b3d..a8257840695a 100644 --- a/Documentation/scsi/aacraid.txt +++ b/Documentation/scsi/aacraid.txt @@ -38,10 +38,8 @@ Supported Cards/Chipsets 9005:0286:9005:02ac Adaptec 1800 (Typhoon44) 9005:0285:9005:02b5 Adaptec 5445 (Voodoo44) 9005:0285:15d9:02b5 SMC AOC-USAS-S4i - 9005:0285:15d9:02c9 SMC AOC-USAS-S4iR 9005:0285:9005:02b6 Adaptec 5805 (Voodoo80) 9005:0285:15d9:02b6 SMC AOC-USAS-S8i - 9005:0285:15d9:02ca SMC AOC-USAS-S8iR 9005:0285:9005:02b7 Adaptec 5085 (Voodoo08) 9005:0285:9005:02bb Adaptec 3405 (Marauder40LP) 9005:0285:9005:02bc Adaptec 3805 (Marauder80LP) @@ -50,9 +48,14 @@ Supported Cards/Chipsets 9005:0285:9005:02be Adaptec 31605 (Marauder160) 9005:0285:9005:02c3 Adaptec 51205 (Voodoo120) 9005:0285:9005:02c4 Adaptec 51605 (Voodoo160) + 9005:0285:15d9:02c9 SMC AOC-USAS-S4iR + 9005:0285:15d9:02ca SMC AOC-USAS-S8iR 9005:0285:9005:02ce Adaptec 51245 (Voodoo124) 9005:0285:9005:02cf Adaptec 51645 (Voodoo164) 9005:0285:9005:02d0 Adaptec 52445 (Voodoo244) + 9005:0285:9005:02d1 Adaptec 5405 (Voodoo40) + 9005:0285:15d9:02d2 SMC AOC-USAS-S8i-LP + 9005:0285:15d9:02d3 SMC AOC-USAS-S8iR-LP 1011:0046:9005:0364 Adaptec 5400S (Mustang) 9005:0287:9005:0800 Adaptec Themisto (Jupiter) 9005:0200:9005:0200 Adaptec Themisto (Jupiter) @@ -103,6 +106,7 @@ Supported Cards/Chipsets 9005:0285:108e:7aac SUN STK RAID REM (Voodoo44 Coyote) 9005:0285:108e:0286 SUN STK RAID INT (Cougar) 9005:0285:108e:0287 SUN STK RAID EXT (Prometheus) + 9005:0285:108e:7aae SUN STK RAID EM (Narvi) People ------------------------- diff --git a/Documentation/scsi/advansys.txt b/Documentation/scsi/advansys.txt new file mode 100644 index 000000000000..4a3db62b7424 --- /dev/null +++ b/Documentation/scsi/advansys.txt @@ -0,0 +1,243 @@ +AdvanSys (Advanced System Products, Inc.) manufactures the following +RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow +(8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI +buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit +transfer) SCSI Host Adapters for the PCI bus. + +The CDB counts below indicate the number of SCSI CDB (Command +Descriptor Block) requests that can be stored in the RISC chip +cache and board LRAM. A CDB is a single SCSI command. The driver +detect routine will display the number of CDBs available for each +adapter detected. The number of CDBs used by the driver can be +lowered in the BIOS by changing the 'Host Queue Size' adapter setting. + +Laptop Products: + ABP-480 - Bus-Master CardBus (16 CDB) + +Connectivity Products: + ABP510/5150 - Bus-Master ISA (240 CDB) + ABP5140 - Bus-Master ISA PnP (16 CDB) + ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) + ABP902/3902 - Bus-Master PCI (16 CDB) + ABP3905 - Bus-Master PCI (16 CDB) + ABP915 - Bus-Master PCI (16 CDB) + ABP920 - Bus-Master PCI (16 CDB) + ABP3922 - Bus-Master PCI (16 CDB) + ABP3925 - Bus-Master PCI (16 CDB) + ABP930 - Bus-Master PCI (16 CDB) + ABP930U - Bus-Master PCI Ultra (16 CDB) + ABP930UA - Bus-Master PCI Ultra (16 CDB) + ABP960 - Bus-Master PCI MAC/PC (16 CDB) + ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) + +Single Channel Products: + ABP542 - Bus-Master ISA with floppy (240 CDB) + ABP742 - Bus-Master EISA (240 CDB) + ABP842 - Bus-Master VL (240 CDB) + ABP940 - Bus-Master PCI (240 CDB) + ABP940U - Bus-Master PCI Ultra (240 CDB) + ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) + ABP970 - Bus-Master PCI MAC/PC (240 CDB) + ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) + ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB) + ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB) + ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB) + ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB) + +Multi-Channel Products: + ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) + ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel) + ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) + ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel) + ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) + ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) + ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) + ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB) + ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB) + +Driver Compile Time Options and Debugging + +The following constants can be defined in the source file. + +1. ADVANSYS_ASSERT - Enable driver assertions (Def: Enabled) + + Enabling this option adds assertion logic statements to the + driver. If an assertion fails a message will be displayed to + the console, but the system will continue to operate. Any + assertions encountered should be reported to the person + responsible for the driver. Assertion statements may proactively + detect problems with the driver and facilitate fixing these + problems. Enabling assertions will add a small overhead to the + execution of the driver. + +2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled) + + Enabling this option adds tracing functions to the driver and the + ability to set a driver tracing level at boot time. This option is + very useful for debugging the driver, but it will add to the size + of the driver execution image and add overhead to the execution of + the driver. + + The amount of debugging output can be controlled with the global + variable 'asc_dbglvl'. The higher the number the more output. By + default the debug level is 0. + + If the driver is loaded at boot time and the LILO Driver Option + is included in the system, the debug level can be changed by + specifying a 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. The + first three hex digits of the pseudo I/O Port must be set to + 'deb' and the fourth hex digit specifies the debug level: 0 - F. + The following command line will look for an adapter at 0x330 + and set the debug level to 2. + + linux advansys=0x330,0,0,0,0xdeb2 + + If the driver is built as a loadable module this variable can be + defined when the driver is loaded. The following insmod command + will set the debug level to one. + + insmod advansys.o asc_dbglvl=1 + + Debugging Message Levels: + 0: Errors Only + 1: High-Level Tracing + 2-N: Verbose Tracing + + To enable debug output to console, please make sure that: + + a. System and kernel logging is enabled (syslogd, klogd running). + b. Kernel messages are routed to console output. Check + /etc/syslog.conf for an entry similar to this: + + kern.* /dev/console + + c. klogd is started with the appropriate -c parameter + (e.g. klogd -c 8) + + This will cause printk() messages to be be displayed on the + current console. Refer to the klogd(8) and syslogd(8) man pages + for details. + + Alternatively you can enable printk() to console with this + program. However, this is not the 'official' way to do this. + Debug output is logged in /var/log/messages. + + main() + { + syscall(103, 7, 0, 0); + } + + Increasing LOG_BUF_LEN in kernel/printk.c to something like + 40960 allows more debug messages to be buffered in the kernel + and written to the console or log file. + +3. ADVANSYS_STATS - Enable statistics (Def: Enabled) + + Enabling this option adds statistics collection and display + through /proc to the driver. The information is useful for + monitoring driver and device performance. It will add to the + size of the driver execution image and add minor overhead to + the execution of the driver. + + Statistics are maintained on a per adapter basis. Driver entry + point call counts and transfer size counts are maintained. + Statistics are only available for kernels greater than or equal + to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured. + + AdvanSys SCSI adapter files have the following path name format: + + /proc/scsi/advansys/{0,1,2,3,...} + + This information can be displayed with cat. For example: + + cat /proc/scsi/advansys/0 + + When ADVANSYS_STATS is not defined the AdvanSys /proc files only + contain adapter and device configuration information. + +Driver LILO Option + +If init/main.c is modified as described in the 'Directions for Adding +the AdvanSys Driver to Linux' section (B.4.) above, the driver will +recognize the 'advansys' LILO command line and /etc/lilo.conf option. +This option can be used to either disable I/O port scanning or to limit +scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and +PCI boards will still be searched for and detected. This option only +affects searching for ISA and VL boards. + +Examples: + 1. Eliminate I/O port scanning: + boot: linux advansys= + or + boot: linux advansys=0x0 + 2. Limit I/O port scanning to one I/O port: + boot: linux advansys=0x110 + 3. Limit I/O port scanning to four I/O ports: + boot: linux advansys=0x110,0x210,0x230,0x330 + +For a loadable module the same effect can be achieved by setting +the 'asc_iopflag' variable and 'asc_ioport' array when loading +the driver, e.g. + + insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330 + +If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_IOPORT_PROBE + 1) +I/O Port may be added to specify the driver debug level. Refer to +the 'Driver Compile Time Options and Debugging' section above for +more information. + +Credits (Chronological Order) + +Bob Frey <bfrey@turbolinux.com.cn> wrote the AdvanSys SCSI driver +and maintained it up to 3.3F. He continues to answer questions +and help maintain the driver. + +Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and +basis for the Linux v1.3.X changes which were included in the +1.2 release. + +Thomas E Zerucha <zerucha@shell.portal.com> pointed out a bug +in advansys_biosparam() which was fixed in the 1.3 release. + +Erik Ratcliffe <erik@caldera.com> has done testing of the +AdvanSys driver in the Caldera releases. + +Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to +AscWaitTixISRDone() which he found necessary to make the +driver work with a SCSI-1 disk. + +Mark Moran <mmoran@mmoran.com> has helped test Ultra-Wide +support in the 3.1A driver. + +Doug Gilbert <dgilbert@interlog.com> has made changes and +suggestions to improve the driver and done a lot of testing. + +Ken Mort <ken@mort.net> reported a DEBUG compile bug fixed +in 3.2K. + +Tom Rini <trini@kernel.crashing.org> provided the CONFIG_ISA +patch and helped with PowerPC wide and narrow board support. + +Philip Blundell <philb@gnu.org> provided an +advansys_interrupts_enabled patch. + +Dave Jones <dave@denial.force9.co.uk> reported the compiler +warnings generated when CONFIG_PROC_FS was not defined in +the 3.2M driver. + +Jerry Quinn <jlquinn@us.ibm.com> fixed PowerPC support (endian +problems) for wide cards. + +Bryan Henderson <bryanh@giraffe-data.com> helped debug narrow +card error handling. + +Manuel Veloso <veloso@pobox.com> worked hard on PowerPC narrow +board support and fixed a bug in AscGetEEPConfig(). + +Arnaldo Carvalho de Melo <acme@conectiva.com.br> made +save_flags/restore_flags changes. + +Andy Kellner <AKellner@connectcom.net> continued the Advansys SCSI +driver development for ConnectCom (Version > 3.3F). + +Ken Witherow for extensive testing during the development of version 3.4. diff --git a/MAINTAINERS b/MAINTAINERS index 0f60fdb47fba..c7355e7f09ff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -297,6 +297,12 @@ P: Colin Leroy M: colin@colino.net S: Maintained +ADVANSYS SCSI DRIVER +P: Matthew Wilcox +M: matthew@wil.cx +L: linux-scsi@vger.kernel.org +S: Maintained + AEDSP16 DRIVER P: Riccardo Facchetti M: fizban@tin.it @@ -1889,6 +1895,11 @@ M: Gadi Oxman <gadio@netvision.net.il> L: linux-kernel@vger.kernel.org S: Maintained +IDE-SCSI DRIVER +L: linux-ide@vger.kernel.org +L: linux-scsi@vger.kernel.org +S: Orphan + IEEE 1394 SUBSYSTEM P: Ben Collins M: ben.collins@ubuntu.com @@ -2413,7 +2424,7 @@ LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) P: Eric Moore M: Eric.Moore@lsi.com M: support@lsi.com -L: mpt_linux_developer@lsi.com +L: DL-MPTFusionLinux@lsi.com L: linux-scsi@vger.kernel.org W: http://www.lsilogic.com/support S: Supported diff --git a/arch/i386/Kconfig b/arch/i386/Kconfig index f1486f8a3e6d..bf9aafad4978 100644 --- a/arch/i386/Kconfig +++ b/arch/i386/Kconfig @@ -214,6 +214,17 @@ config X86_ES7000 endchoice +config SCHED_NO_NO_OMIT_FRAME_POINTER + bool "Single-depth WCHAN output" + default y + help + Calculate simpler /proc/<PID>/wchan values. If this option + is disabled then wchan values will recurse back to the + caller function. This provides more accurate wchan values, + at the expense of slightly more scheduling overhead. + + If in doubt, say "Y". + config PARAVIRT bool "Paravirtualization support (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/arch/ia64/Kconfig b/arch/ia64/Kconfig index 8c39913d1729..2e6310b8eab7 100644 --- a/arch/ia64/Kconfig +++ b/arch/ia64/Kconfig @@ -461,6 +461,16 @@ config IA64_ESI firmware extensions, such as the ability to inject memory-errors for test-purposes. If you're unsure, say N. +config IA64_HP_AML_NFW + bool "Support ACPI AML calls to native firmware" + help + This driver installs a global ACPI Operation Region handler for + region 0xA1. AML methods can use this OpRegion to call arbitrary + native firmware functions. The driver installs the OpRegion + handler if there is an HPQ5001 device or if the user supplies + the "force" module parameter, e.g., with the "aml_nfw.force" + kernel command line option. + source "drivers/sn/Kconfig" config KEXEC diff --git a/arch/ia64/configs/sn2_defconfig b/arch/ia64/configs/sn2_defconfig index 9aecfceeb38c..449d3e75bfc2 100644 --- a/arch/ia64/configs/sn2_defconfig +++ b/arch/ia64/configs/sn2_defconfig @@ -1,40 +1,40 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.19-rc1 -# Mon Oct 9 10:53:59 2006 +# Linux kernel version: 2.6.23-rc6 +# Tue Sep 18 11:24:01 2007 # CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y CONFIG_LOCK_KERNEL=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" # CONFIG_LOCALVERSION_AUTO is not set CONFIG_SWAP=y CONFIG_SYSVIPC=y -# CONFIG_IPC_NS is not set +CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_TASKSTATS=y # CONFIG_TASK_DELAY_ACCT is not set -# CONFIG_UTS_NS is not set +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set +CONFIG_LOG_BUF_SHIFT=20 CONFIG_CPUSETS=y +CONFIG_SYSFS_DEPRECATED=y CONFIG_RELAY=y +CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y -CONFIG_TASK_XACCT=y CONFIG_SYSCTL=y # CONFIG_EMBEDDED is not set -# CONFIG_SYSCTL_SYSCALL is not set +CONFIG_SYSCTL_SYSCALL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -44,18 +44,20 @@ CONFIG_BUG=y CONFIG_ELF_CORE=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y +CONFIG_ANON_INODES=y CONFIG_EPOLL=y +CONFIG_SIGNALFD=y +CONFIG_TIMERFD=y +CONFIG_EVENTFD=y CONFIG_SHMEM=y -CONFIG_SLUB=y CONFIG_VM_EVENT_COUNTERS=y +CONFIG_SLUB_DEBUG=y +# CONFIG_SLAB is not set +CONFIG_SLUB=y +# CONFIG_SLOB is not set CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 -# CONFIG_SLOB is not set - -# -# Loadable module support -# CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set @@ -63,12 +65,9 @@ CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_SRCVERSION_ALL is not set CONFIG_KMOD=y CONFIG_STOP_MACHINE=y - -# -# Block layer -# CONFIG_BLOCK=y # CONFIG_BLK_DEV_IO_TRACE is not set +CONFIG_BLK_DEV_BSG=y # # IO Schedulers @@ -88,12 +87,15 @@ CONFIG_DEFAULT_IOSCHED="anticipatory" # CONFIG_IA64=y CONFIG_64BIT=y +CONFIG_QUICKLIST=y CONFIG_MMU=y -CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +# CONFIG_ARCH_HAS_ILOG2_U32 is not set +# CONFIG_ARCH_HAS_ILOG2_U64 is not set CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_GENERIC_TIME=y +CONFIG_GENERIC_TIME_VSYSCALL=y CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y @@ -116,6 +118,7 @@ CONFIG_IA64_PAGE_SIZE_16KB=y CONFIG_PGTABLE_4=y # CONFIG_HZ_100 is not set CONFIG_HZ_250=y +# CONFIG_HZ_300 is not set # CONFIG_HZ_1000 is not set CONFIG_HZ=250 CONFIG_IA64_L1_CACHE_SHIFT=7 @@ -128,7 +131,10 @@ CONFIG_NR_CPUS=1024 # CONFIG_HOTPLUG_CPU is not set CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y CONFIG_SCHED_SMT=y -CONFIG_PREEMPT=y +CONFIG_PREEMPT_NONE=y +# CONFIG_PREEMPT_VOLUNTARY is not set +# CONFIG_PREEMPT is not set +CONFIG_PREEMPT_BKL=y CONFIG_SELECT_MEMORY_MODEL=y # CONFIG_FLATMEM_MANUAL is not set CONFIG_DISCONTIGMEM_MANUAL=y @@ -140,6 +146,9 @@ CONFIG_NEED_MULTIPLE_NODES=y CONFIG_SPLIT_PTLOCK_CPUS=4 CONFIG_MIGRATION=y CONFIG_RESOURCES_64BIT=y +CONFIG_ZONE_DMA_FLAG=0 +CONFIG_NR_QUICK=1 +CONFIG_VIRT_TO_BUS=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -154,16 +163,17 @@ CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID=y CONFIG_HAVE_ARCH_NODEDATA_EXTENSION=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y +CONFIG_COMPAT_FOR_U64_ALIGNMENT=y CONFIG_IA64_MCA_RECOVERY=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y +CONFIG_IA64_MC_ERR_INJECT=y CONFIG_SGI_SN=y # CONFIG_IA64_ESI is not set # # SN Devices # -CONFIG_SGI_IOC4=y CONFIG_SGI_IOC3=y # @@ -171,6 +181,7 @@ CONFIG_SGI_IOC3=y # CONFIG_EFI_VARS=y CONFIG_EFI_PCDP=y +CONFIG_DMIID=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set @@ -180,12 +191,9 @@ CONFIG_BINFMT_ELF=y CONFIG_PM=y # CONFIG_PM_LEGACY is not set # CONFIG_PM_DEBUG is not set -# CONFIG_PM_SYSFS_DEPRECATED is not set - -# -# ACPI (Advanced Configuration and Power Interface) Support -# CONFIG_ACPI=y +# CONFIG_ACPI_PROCFS is not set +CONFIG_ACPI_PROC_EVENT=y # CONFIG_ACPI_BUTTON is not set # CONFIG_ACPI_FAN is not set # CONFIG_ACPI_DOCK is not set @@ -208,17 +216,14 @@ CONFIG_ACPI_SYSTEM=y # CONFIG_PCI=y CONFIG_PCI_DOMAINS=y +CONFIG_PCI_SYSCALL=y CONFIG_PCIEPORTBUS=y CONFIG_HOTPLUG_PCI_PCIE=y # CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set CONFIG_PCIEAER=y +CONFIG_ARCH_SUPPORTS_MSI=y # CONFIG_PCI_MSI is not set -# CONFIG_PCI_MULTITHREAD_PROBE is not set # CONFIG_PCI_DEBUG is not set - -# -# PCI Hotplug Support -# CONFIG_HOTPLUG_PCI=y # CONFIG_HOTPLUG_PCI_FAKE is not set # CONFIG_HOTPLUG_PCI_ACPI is not set @@ -239,13 +244,13 @@ CONFIG_NET=y # # Networking options # -# CONFIG_NETDEBUG is not set CONFIG_PACKET=y CONFIG_PACKET_MMAP=y CONFIG_UNIX=y CONFIG_XFRM=y # CONFIG_XFRM_USER is not set # CONFIG_XFRM_SUB_POLICY is not set +# CONFIG_XFRM_MIGRATE is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -261,7 +266,7 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_INET_XFRM_TUNNEL is not set -# CONFIG_INET_TUNNEL is not set +CONFIG_INET_TUNNEL=m CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y @@ -270,9 +275,11 @@ CONFIG_INET_TCP_DIAG=m # CONFIG_TCP_CONG_ADVANCED is not set CONFIG_TCP_CONG_CUBIC=y CONFIG_DEFAULT_TCP_CONG="cubic" +# CONFIG_TCP_MD5SIG is not set CONFIG_IPV6=m # CONFIG_IPV6_PRIVACY is not set # CONFIG_IPV6_ROUTER_PREF is not set +# CONFIG_IPV6_OPTIMISTIC_DAD is not set # CONFIG_INET6_AH is not set # CONFIG_INET6_ESP is not set # CONFIG_INET6_IPCOMP is not set @@ -283,25 +290,13 @@ CONFIG_INET6_XFRM_MODE_TRANSPORT=m CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_INET6_XFRM_MODE_BEET=m # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set +CONFIG_IPV6_SIT=m # CONFIG_IPV6_TUNNEL is not set -# CONFIG_IPV6_SUBTREES is not set # CONFIG_IPV6_MULTIPLE_TABLES is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set - -# -# DCCP Configuration (EXPERIMENTAL) -# # CONFIG_IP_DCCP is not set - -# -# SCTP Configuration (EXPERIMENTAL) -# # CONFIG_IP_SCTP is not set - -# -# TIPC Configuration (EXPERIMENTAL) -# # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -327,7 +322,17 @@ CONFIG_INET6_XFRM_MODE_BEET=m # CONFIG_HAMRADIO is not set # CONFIG_IRDA is not set # CONFIG_BT is not set +# CONFIG_AF_RXRPC is not set + +# +# Wireless +# +# CONFIG_CFG80211 is not set +# CONFIG_WIRELESS_EXT is not set +# CONFIG_MAC80211 is not set # CONFIG_IEEE80211 is not set +# CONFIG_RFKILL is not set +# CONFIG_NET_9P is not set # # Device Drivers @@ -340,31 +345,19 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set +# CONFIG_DEBUG_DEVRES is not set # CONFIG_SYS_HYPERVISOR is not set - -# -# Connector - unified userspace <-> kernelspace linker -# # CONFIG_CONNECTOR is not set - -# -# Memory Technology Devices (MTD) -# # CONFIG_MTD is not set - -# -# Parallel port support -# # CONFIG_PARPORT is not set +CONFIG_PNP=y +# CONFIG_PNP_DEBUG is not set # -# Plug and Play support -# -# CONFIG_PNP is not set - -# -# Block devices +# Protocols # +CONFIG_PNPACPI=y +CONFIG_BLK_DEV=y # CONFIG_BLK_CPQ_DA is not set # CONFIG_BLK_CPQ_CISS_DA is not set # CONFIG_BLK_DEV_DAC960 is not set @@ -379,13 +372,13 @@ CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 -CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set CONFIG_ATA_OVER_ETH=m - -# -# ATA/ATAPI/MFM/RLL support -# +CONFIG_MISC_DEVICES=y +# CONFIG_PHANTOM is not set +# CONFIG_EEPROM_93CX6 is not set +CONFIG_SGI_IOC4=y +# CONFIG_TIFM_CORE is not set CONFIG_IDE=y CONFIG_IDE_MAX_HWIFS=4 CONFIG_BLK_DEV_IDE=y @@ -400,20 +393,23 @@ CONFIG_BLK_DEV_IDECD=y # CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set # CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_BLK_DEV_IDEACPI is not set # CONFIG_IDE_TASK_IOCTL is not set +CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes # CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEPNP is not set CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y +CONFIG_IDEPCI_PCIBUS_ORDER=y # CONFIG_BLK_DEV_OFFBOARD is not set # CONFIG_BLK_DEV_GENERIC is not set # CONFIG_BLK_DEV_OPTI621 is not set CONFIG_BLK_DEV_IDEDMA_PCI=y # CONFIG_BLK_DEV_IDEDMA_FORCED is not set -CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_IDEDMA_ONLYDISK is not set # CONFIG_BLK_DEV_AEC62XX is not set # CONFIG_BLK_DEV_ALI15X3 is not set @@ -428,6 +424,7 @@ CONFIG_IDEDMA_PCI_AUTO=y # CONFIG_BLK_DEV_JMICRON is not set # CONFIG_BLK_DEV_SC1200 is not set # CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_IT8213 is not set # CONFIG_BLK_DEV_IT821X is not set # CONFIG_BLK_DEV_NS87415 is not set # CONFIG_BLK_DEV_PDC202XX_OLD is not set @@ -438,10 +435,10 @@ CONFIG_BLK_DEV_SGIIOC4=y # CONFIG_BLK_DEV_SLC90E66 is not set # CONFIG_BLK_DEV_TRM290 is not set # CONFIG_BLK_DEV_VIA82CXXX is not set +# CONFIG_BLK_DEV_TC86C001 is not set # CONFIG_IDE_ARM is not set CONFIG_BLK_DEV_IDEDMA=y # CONFIG_IDEDMA_IVB is not set -CONFIG_IDEDMA_AUTO=y # CONFIG_BLK_DEV_HD is not set # @@ -449,6 +446,8 @@ CONFIG_IDEDMA_AUTO=y # # CONFIG_RAID_ATTRS is not set CONFIG_SCSI=y +CONFIG_SCSI_DMA=y +# CONFIG_SCSI_TGT is not set CONFIG_SCSI_NETLINK=y CONFIG_SCSI_PROC_FS=y @@ -469,6 +468,8 @@ CONFIG_CHR_DEV_SCH=m # CONFIG_SCSI_MULTI_LUN is not set CONFIG_SCSI_CONSTANTS=y # CONFIG_SCSI_LOGGING is not set +# CONFIG_SCSI_SCAN_ASYNC is not set +CONFIG_SCSI_WAIT_SCAN=m # # SCSI Transports @@ -478,11 +479,9 @@ CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_ISCSI_ATTRS=m CONFIG_SCSI_SAS_ATTRS=y CONFIG_SCSI_SAS_LIBSAS=y +# CONFIG_SCSI_SAS_ATA is not set # CONFIG_SCSI_SAS_LIBSAS_DEBUG is not set - -# -# SCSI low-level drivers -# +CONFIG_SCSI_LOWLEVEL=y CONFIG_ISCSI_TCP=m # CONFIG_BLK_DEV_3W_XXXX_RAID is not set # CONFIG_SCSI_3W_9XXX is not set @@ -512,11 +511,10 @@ CONFIG_SCSI_QLA_FC=y # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set # CONFIG_SCSI_DEBUG is not set - -# -# Serial ATA (prod) and Parallel ATA (experimental) drivers -# +# CONFIG_SCSI_SRP is not set CONFIG_ATA=y +CONFIG_ATA_NONSTANDARD=y +CONFIG_ATA_ACPI=y # CONFIG_SATA_AHCI is not set # CONFIG_SATA_SVW is not set # CONFIG_ATA_PIIX is not set @@ -532,10 +530,12 @@ CONFIG_ATA=y # CONFIG_SATA_ULI is not set # CONFIG_SATA_VIA is not set CONFIG_SATA_VITESSE=y +# CONFIG_SATA_INIC162X is not set # CONFIG_PATA_ALI is not set # CONFIG_PATA_AMD is not set # CONFIG_PATA_ARTOP is not set # CONFIG_PATA_ATIIXP is not set +# CONFIG_PATA_CMD640_PCI is not set # CONFIG_PATA_CMD64X is not set # CONFIG_PATA_CS5520 is not set # CONFIG_PATA_CS5530 is not set @@ -547,8 +547,10 @@ CONFIG_SATA_VITESSE=y # CONFIG_PATA_HPT3X2N is not set # CONFIG_PATA_HPT3X3 is not set # CONFIG_PATA_IT821X is not set +# CONFIG_PATA_IT8213 is not set # CONFIG_PATA_JMICRON is not set # CONFIG_PATA_TRIFLEX is not set +# CONFIG_PATA_MARVELL is not set # CONFIG_PATA_MPIIX is not set # CONFIG_PATA_OLDPIIX is not set # CONFIG_PATA_NETCELL is not set @@ -565,10 +567,6 @@ CONFIG_SATA_VITESSE=y # CONFIG_PATA_SIS is not set # CONFIG_PATA_VIA is not set # CONFIG_PATA_WINBOND is not set - -# -# Multi-device support (RAID and LVM) -# CONFIG_MD=y CONFIG_BLK_DEV_MD=y CONFIG_MD_LINEAR=y @@ -587,6 +585,8 @@ CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_DM_MULTIPATH=m CONFIG_DM_MULTIPATH_EMC=m +# CONFIG_DM_MULTIPATH_RDAC is not set +# CONFIG_DM_DELAY is not set # # Fusion MPT device support @@ -597,43 +597,25 @@ CONFIG_FUSION_FC=y CONFIG_FUSION_SAS=y CONFIG_FUSION_MAX_SGE=128 CONFIG_FUSION_CTL=m +CONFIG_FUSION_LOGGING=y # # IEEE 1394 (FireWire) support # +# CONFIG_FIREWIRE is not set # CONFIG_IEEE1394 is not set - -# -# I2O device support -# # CONFIG_I2O is not set - -# -# Network device support -# CONFIG_NETDEVICES=y +# CONFIG_NETDEVICES_MULTIQUEUE is not set # CONFIG_DUMMY is not set # CONFIG_BONDING is not set +# CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set - -# -# ARCnet devices -# +# CONFIG_NET_SB1000 is not set # CONFIG_ARCNET is not set - -# -# PHY device support -# - -# -# Ethernet (10 or 100Mbit) -# # CONFIG_NET_ETHERNET is not set - -# -# Ethernet (1000 Mbit) -# +CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set @@ -645,32 +627,39 @@ CONFIG_NETDEVICES=y # CONFIG_SKGE is not set # CONFIG_SKY2 is not set # CONFIG_SK98LIN is not set +# CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=y # CONFIG_BNX2 is not set # CONFIG_QLA3XXX is not set - -# -# Ethernet (10000 Mbit) -# +# CONFIG_ATL1 is not set +CONFIG_NETDEV_10000=y CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +# CONFIG_CHELSIO_T1_NAPI is not set +CONFIG_CHELSIO_T3=m # CONFIG_IXGB is not set CONFIG_S2IO=m # CONFIG_S2IO_NAPI is not set # CONFIG_MYRI10GE is not set - -# -# Token Ring devices -# +# CONFIG_NETXEN_NIC is not set +# CONFIG_MLX4_CORE is not set # CONFIG_TR is not set # -# Wireless LAN (non-hamradio) +# Wireless LAN # -# CONFIG_NET_RADIO is not set +# CONFIG_WLAN_PRE80211 is not set +# CONFIG_WLAN_80211 is not set # -# Wan interfaces +# USB Network Adapters # +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +# CONFIG_USB_USBNET_MII is not set +# CONFIG_USB_USBNET is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set @@ -680,18 +669,9 @@ CONFIG_S2IO=m # CONFIG_SHAPER is not set CONFIG_NETCONSOLE=y CONFIG_NETPOLL=y -# CONFIG_NETPOLL_RX is not set # CONFIG_NETPOLL_TRAP is not set CONFIG_NET_POLL_CONTROLLER=y - -# -# ISDN subsystem -# # CONFIG_ISDN is not set - -# -# Telephony Support -# # CONFIG_PHONE is not set # @@ -699,6 +679,7 @@ CONFIG_NET_POLL_CONTROLLER=y # CONFIG_INPUT=y # CONFIG_INPUT_FF_MEMLESS is not set +# CONFIG_INPUT_POLLDEV is not set # # Userland interfaces @@ -718,6 +699,7 @@ CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 # CONFIG_INPUT_KEYBOARD is not set # CONFIG_INPUT_MOUSE is not set # CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TABLET is not set # CONFIG_INPUT_TOUCHSCREEN is not set # CONFIG_INPUT_MISC is not set @@ -741,6 +723,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_DIGIEPCA is not set # CONFIG_MOXA_INTELLIO is not set # CONFIG_MOXA_SMARTIO is not set +# CONFIG_MOXA_SMARTIO_NEW is not set # CONFIG_ISI is not set # CONFIG_SYNCLINKMP is not set # CONFIG_SYNCLINK_GT is not set @@ -752,7 +735,6 @@ CONFIG_SERIAL_NONSTANDARD=y CONFIG_SGI_SNSC=y CONFIG_SGI_TIOCX=y CONFIG_SGI_MBCS=m -CONFIG_MSPEC=y # # Serial drivers @@ -771,28 +753,13 @@ CONFIG_SERIAL_SGI_IOC3=y CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 - -# -# IPMI -# # CONFIG_IPMI_HANDLER is not set - -# -# Watchdog Cards -# # CONFIG_WATCHDOG is not set # CONFIG_HW_RANDOM is not set CONFIG_EFI_RTC=y -# CONFIG_DTLK is not set # CONFIG_R3964 is not set # CONFIG_APPLICOM is not set - -# -# Ftape, the floppy tape device driver -# CONFIG_AGP=y -# CONFIG_AGP_SIS is not set -# CONFIG_AGP_VIA is not set CONFIG_AGP_SGI_TIOCA=y # CONFIG_DRM is not set CONFIG_RAW_DRIVER=m @@ -800,16 +767,8 @@ CONFIG_MAX_RAW_DEVS=256 # CONFIG_HPET is not set # CONFIG_HANGCHECK_TIMER is not set CONFIG_MMTIMER=y - -# -# TPM devices -# # CONFIG_TCG_TPM is not set -# CONFIG_TELCLOCK is not set - -# -# I2C support -# +CONFIG_DEVPORT=y # CONFIG_I2C is not set # @@ -817,37 +776,33 @@ CONFIG_MMTIMER=y # # CONFIG_SPI is not set # CONFIG_SPI_MASTER is not set - -# -# Dallas's 1-wire bus -# - -# -# Hardware Monitoring support -# +# CONFIG_W1 is not set +# CONFIG_POWER_SUPPLY is not set # CONFIG_HWMON is not set -# CONFIG_HWMON_VID is not set # -# Misc devices +# Multifunction device drivers # -# CONFIG_TIFM_CORE is not set +# CONFIG_MFD_SM501 is not set # # Multimedia devices # # CONFIG_VIDEO_DEV is not set +# CONFIG_DVB_CORE is not set +# CONFIG_DAB is not set # -# Digital Video Broadcasting Devices +# Graphics support # -# CONFIG_DVB is not set -# CONFIG_USB_DABUSB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # -# Graphics support +# Display device support # -CONFIG_FIRMWARE_EDID=y +# CONFIG_DISPLAY_SUPPORT is not set +# CONFIG_VGASTATE is not set +CONFIG_VIDEO_OUTPUT_CONTROL=m # CONFIG_FB is not set # @@ -856,16 +811,29 @@ CONFIG_FIRMWARE_EDID=y CONFIG_VGA_CONSOLE=y # CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y -# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Sound # # CONFIG_SOUND is not set +CONFIG_HID_SUPPORT=y +CONFIG_HID=y +CONFIG_HID_DEBUG=y # -# USB support +# USB Input Devices +# +CONFIG_USB_HID=m +# CONFIG_USB_HIDINPUT_POWERBOOK is not set +# CONFIG_HID_FF is not set +# CONFIG_USB_HIDDEV is not set + +# +# USB HID Boot Protocol drivers # +# CONFIG_USB_KBD is not set +# CONFIG_USB_MOUSE is not set +CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y CONFIG_USB_ARCH_HAS_EHCI=y @@ -876,9 +844,10 @@ CONFIG_USB=m # Miscellaneous USB options # # CONFIG_USB_DEVICEFS is not set -# CONFIG_USB_BANDWIDTH is not set +CONFIG_USB_DEVICE_CLASS=y # CONFIG_USB_DYNAMIC_MINORS is not set # CONFIG_USB_SUSPEND is not set +# CONFIG_USB_PERSIST is not set # CONFIG_USB_OTG is not set # @@ -890,10 +859,12 @@ CONFIG_USB_EHCI_HCD=m # CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=m -# CONFIG_USB_OHCI_BIG_ENDIAN is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_DESC is not set +# CONFIG_USB_OHCI_BIG_ENDIAN_MMIO is not set CONFIG_USB_OHCI_LITTLE_ENDIAN=y CONFIG_USB_UHCI_HCD=m # CONFIG_USB_SL811_HCD is not set +# CONFIG_USB_R8A66597_HCD is not set # # USB Device Class drivers @@ -912,47 +883,10 @@ CONFIG_USB_UHCI_HCD=m # CONFIG_USB_LIBUSUAL is not set # -# USB Input Devices -# -CONFIG_USB_HID=m -CONFIG_USB_HIDINPUT=y -# CONFIG_USB_HIDINPUT_POWERBOOK is not set -# CONFIG_HID_FF is not set -# CONFIG_USB_HIDDEV is not set - -# -# USB HID Boot Protocol drivers -# -# CONFIG_USB_KBD is not set -# CONFIG_USB_MOUSE is not set -# CONFIG_USB_AIPTEK is not set -# CONFIG_USB_WACOM is not set -# CONFIG_USB_ACECAD is not set -# CONFIG_USB_KBTAB is not set -# CONFIG_USB_POWERMATE is not set -# CONFIG_USB_TOUCHSCREEN is not set -# CONFIG_USB_YEALINK is not set -# CONFIG_USB_XPAD is not set -# CONFIG_USB_ATI_REMOTE is not set -# CONFIG_USB_ATI_REMOTE2 is not set -# CONFIG_USB_KEYSPAN_REMOTE is not set -# CONFIG_USB_APPLETOUCH is not set -# CONFIG_USB_TRANCEVIBRATOR is not set - -# # USB Imaging devices # # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set - -# -# USB Network Adapters -# -# CONFIG_USB_CATC is not set -# CONFIG_USB_KAWETH is not set -# CONFIG_USB_PEGASUS is not set -# CONFIG_USB_RTL8150 is not set -# CONFIG_USB_USBNET is not set CONFIG_USB_MON=y # @@ -974,6 +908,7 @@ CONFIG_USB_MON=y # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set +# CONFIG_USB_BERRY_CHARGE is not set # CONFIG_USB_LED is not set # CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set @@ -983,6 +918,8 @@ CONFIG_USB_MON=y # CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set +# CONFIG_USB_TRANCEVIBRATOR is not set +# CONFIG_USB_IOWARRIOR is not set # # USB DSL modem support @@ -992,48 +929,24 @@ CONFIG_USB_MON=y # USB Gadget Support # # CONFIG_USB_GADGET is not set - -# -# MMC/SD Card support -# # CONFIG_MMC is not set - -# -# LED devices -# # CONFIG_NEW_LEDS is not set - -# -# LED drivers -# - -# -# LED Triggers -# - -# -# InfiniBand support -# CONFIG_INFINIBAND=m # CONFIG_INFINIBAND_USER_MAD is not set CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_USER_MEM=y CONFIG_INFINIBAND_ADDR_TRANS=y CONFIG_INFINIBAND_MTHCA=m CONFIG_INFINIBAND_MTHCA_DEBUG=y # CONFIG_INFINIBAND_AMSO1100 is not set +# CONFIG_INFINIBAND_CXGB3 is not set +# CONFIG_MLX4_INFINIBAND is not set CONFIG_INFINIBAND_IPOIB=m +# CONFIG_INFINIBAND_IPOIB_CM is not set CONFIG_INFINIBAND_IPOIB_DEBUG=y # CONFIG_INFINIBAND_IPOIB_DEBUG_DATA is not set CONFIG_INFINIBAND_SRP=m # CONFIG_INFINIBAND_ISER is not set - -# -# EDAC - error detection and reporting (RAS) (EXPERIMENTAL) -# - -# -# Real Time Clock -# # CONFIG_RTC_CLASS is not set # @@ -1050,6 +963,12 @@ CONFIG_INFINIBAND_SRP=m # # +# Userspace I/O +# +# CONFIG_UIO is not set +CONFIG_MSPEC=y + +# # File systems # CONFIG_EXT2_FS=y @@ -1061,6 +980,7 @@ CONFIG_EXT3_FS=y CONFIG_EXT3_FS_XATTR=y CONFIG_EXT3_FS_POSIX_ACL=y CONFIG_EXT3_FS_SECURITY=y +# CONFIG_EXT4DEV_FS is not set CONFIG_JBD=y # CONFIG_JBD_DEBUG is not set CONFIG_FS_MBCACHE=y @@ -1161,6 +1081,7 @@ CONFIG_EXPORTFS=m CONFIG_NFS_COMMON=y CONFIG_SUNRPC=m CONFIG_SUNRPC_GSS=m +# CONFIG_SUNRPC_BIND34 is not set CONFIG_RPCSEC_GSS_KRB5=m # CONFIG_RPCSEC_GSS_SPKM3 is not set CONFIG_SMB_FS=m @@ -1174,7 +1095,6 @@ CONFIG_CIFS=m # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set # CONFIG_AFS_FS is not set -# CONFIG_9P_FS is not set # # Partition Types @@ -1196,6 +1116,7 @@ CONFIG_SGI_PARTITION=y # CONFIG_SUN_PARTITION is not set # CONFIG_KARMA_PARTITION is not set CONFIG_EFI_PARTITION=y +# CONFIG_SYSV68_PARTITION is not set # # Native Language Support @@ -1244,18 +1165,25 @@ CONFIG_NLS_UTF8=y # # Distributed Lock Manager # +# CONFIG_DLM is not set # # Library routines # +CONFIG_BITREVERSE=y # CONFIG_CRC_CCITT is not set CONFIG_CRC16=m +# CONFIG_CRC_ITU_T is not set CONFIG_CRC32=y +# CONFIG_CRC7 is not set CONFIG_LIBCRC32C=m CONFIG_ZLIB_INFLATE=m CONFIG_ZLIB_DEFLATE=m CONFIG_GENERIC_ALLOCATOR=y CONFIG_PLIST=y +CONFIG_HAS_IOMEM=y +CONFIG_HAS_IOPORT=y +CONFIG_HAS_DMA=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y @@ -1274,25 +1202,28 @@ CONFIG_IRQ_PER_CPU=y CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set +# CONFIG_DEBUG_FS is not set +# CONFIG_HEADERS_CHECK is not set CONFIG_DEBUG_KERNEL=y -CONFIG_LOG_BUF_SHIFT=20 +# CONFIG_DEBUG_SHIRQ is not set CONFIG_DETECT_SOFTLOCKUP=y +CONFIG_SCHED_DEBUG=y # CONFIG_SCHEDSTATS is not set -# CONFIG_DEBUG_SLAB is not set +# CONFIG_TIMER_STATS is not set +# CONFIG_SLUB_DEBUG_ON is not set # CONFIG_DEBUG_RT_MUTEXES is not set # CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_MUTEXES is not set -# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set # CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set CONFIG_DEBUG_INFO=y -# CONFIG_DEBUG_FS is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set CONFIG_FORCED_INLINING=y # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_FAULT_INJECTION is not set CONFIG_IA64_GRANULE_16MB=y # CONFIG_IA64_GRANULE_64MB is not set # CONFIG_IA64_PRINT_HAZARDS is not set @@ -1306,16 +1237,17 @@ CONFIG_SYSVIPC_COMPAT=y # # CONFIG_KEYS is not set # CONFIG_SECURITY is not set - -# -# Cryptographic options -# +CONFIG_XOR_BLOCKS=y +CONFIG_ASYNC_CORE=y +CONFIG_ASYNC_MEMCPY=y +CONFIG_ASYNC_XOR=y CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y CONFIG_CRYPTO_BLKCIPHER=m CONFIG_CRYPTO_HASH=y -CONFIG_CRYPTO_MANAGER=m +CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y +# CONFIG_CRYPTO_XCBC is not set # CONFIG_CRYPTO_NULL is not set # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=y @@ -1324,9 +1256,14 @@ CONFIG_CRYPTO_SHA1=m # CONFIG_CRYPTO_SHA512 is not set # CONFIG_CRYPTO_WP512 is not set # CONFIG_CRYPTO_TGR192 is not set +# CONFIG_CRYPTO_GF128MUL is not set CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=m +CONFIG_CRYPTO_PCBC=m +# CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=m +# CONFIG_CRYPTO_FCRYPT is not set # CONFIG_CRYPTO_BLOWFISH is not set # CONFIG_CRYPTO_TWOFISH is not set # CONFIG_CRYPTO_SERPENT is not set @@ -1340,8 +1277,6 @@ CONFIG_CRYPTO_DES=m CONFIG_CRYPTO_DEFLATE=m # CONFIG_CRYPTO_MICHAEL_MIC is not set CONFIG_CRYPTO_CRC32C=m +# CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set - -# -# Hardware crypto devices -# +# CONFIG_CRYPTO_HW is not set diff --git a/arch/ia64/hp/common/Makefile b/arch/ia64/hp/common/Makefile index f61a60057ff7..9e179dd06b85 100644 --- a/arch/ia64/hp/common/Makefile +++ b/arch/ia64/hp/common/Makefile @@ -8,3 +8,4 @@ obj-y := sba_iommu.o obj-$(CONFIG_IA64_HP_ZX1_SWIOTLB) += hwsw_iommu.o obj-$(CONFIG_IA64_GENERIC) += hwsw_iommu.o +obj-$(CONFIG_IA64_HP_AML_NFW) += aml_nfw.o diff --git a/arch/ia64/hp/common/aml_nfw.c b/arch/ia64/hp/common/aml_nfw.c new file mode 100644 index 000000000000..4abd2c79bb1d --- /dev/null +++ b/arch/ia64/hp/common/aml_nfw.c @@ -0,0 +1,236 @@ +/* + * OpRegion handler to allow AML to call native firmware + * + * (c) Copyright 2007 Hewlett-Packard Development Company, L.P. + * Bjorn Helgaas <bjorn.helgaas@hp.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This driver implements HP Open Source Review Board proposal 1842, + * which was approved on 9/20/2006. + * + * For technical documentation, see the HP SPPA Firmware EAS, Appendix F. + * + * ACPI does not define a mechanism for AML methods to call native firmware + * interfaces such as PAL or SAL. This OpRegion handler adds such a mechanism. + * After the handler is installed, an AML method can call native firmware by + * storing the arguments and firmware entry point to specific offsets in the + * OpRegion. When AML reads the "return value" offset from the OpRegion, this + * handler loads up the arguments, makes the firmware call, and returns the + * result. + */ + +#include <linux/module.h> +#include <acpi/acpi_bus.h> +#include <acpi/acpi_drivers.h> +#include <asm/sal.h> + +MODULE_AUTHOR("Bjorn Helgaas <bjorn.helgaas@hp.com>"); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("ACPI opregion handler for native firmware calls"); + +static int force_register; +module_param_named(force, force_register, bool, 0); +MODULE_PARM_DESC(force, "Install opregion handler even without HPQ5001 device"); + +#define AML_NFW_SPACE 0xA1 + +struct ia64_pdesc { + void *ip; + void *gp; +}; + +/* + * N.B. The layout of this structure is defined in the HP SPPA FW EAS, and + * the member offsets are embedded in AML methods. + */ +struct ia64_nfw_context { + u64 arg[8]; + struct ia64_sal_retval ret; + u64 ip; + u64 gp; + u64 pad[2]; +}; + +static void *virt_map(u64 address) +{ + if (address & (1UL << 63)) + return (void *) (__IA64_UNCACHED_OFFSET | address); + + return __va(address); +} + +static void aml_nfw_execute(struct ia64_nfw_context *c) +{ + struct ia64_pdesc virt_entry; + ia64_sal_handler entry; + + virt_entry.ip = virt_map(c->ip); + virt_entry.gp = virt_map(c->gp); + + entry = (ia64_sal_handler) &virt_entry; + + IA64_FW_CALL(entry, c->ret, + c->arg[0], c->arg[1], c->arg[2], c->arg[3], + c->arg[4], c->arg[5], c->arg[6], c->arg[7]); +} + +static void aml_nfw_read_arg(u8 *offset, u32 bit_width, acpi_integer *value) +{ + switch (bit_width) { + case 8: + *value = *(u8 *)offset; + break; + case 16: + *value = *(u16 *)offset; + break; + case 32: + *value = *(u32 *)offset; + break; + case 64: + *value = *(u64 *)offset; + break; + } +} + +static void aml_nfw_write_arg(u8 *offset, u32 bit_width, acpi_integer *value) +{ + switch (bit_width) { + case 8: + *(u8 *) offset = *value; + break; + case 16: + *(u16 *) offset = *value; + break; + case 32: + *(u32 *) offset = *value; + break; + case 64: + *(u64 *) offset = *value; + break; + } +} + +static acpi_status aml_nfw_handler(u32 function, acpi_physical_address address, + u32 bit_width, acpi_integer *value, void *handler_context, + void *region_context) +{ + struct ia64_nfw_context *context = handler_context; + u8 *offset = (u8 *) context + address; + + if (bit_width != 8 && bit_width != 16 && + bit_width != 32 && bit_width != 64) + return AE_BAD_PARAMETER; + + if (address + (bit_width >> 3) > sizeof(struct ia64_nfw_context)) + return AE_BAD_PARAMETER; + + switch (function) { + case ACPI_READ: + if (address == offsetof(struct ia64_nfw_context, ret)) + aml_nfw_execute(context); + aml_nfw_read_arg(offset, bit_width, value); + break; + case ACPI_WRITE: + aml_nfw_write_arg(offset, bit_width, value); + break; + } + + return AE_OK; +} + +static struct ia64_nfw_context global_context; +static int global_handler_registered; + +static int aml_nfw_add_global_handler(void) +{ + acpi_status status; + + if (global_handler_registered) + return 0; + + status = acpi_install_address_space_handler(ACPI_ROOT_OBJECT, + AML_NFW_SPACE, aml_nfw_handler, NULL, &global_context); + if (ACPI_FAILURE(status)) + return -ENODEV; + + global_handler_registered = 1; + printk(KERN_INFO "Global 0x%02X opregion handler registered\n", + AML_NFW_SPACE); + return 0; +} + +static int aml_nfw_remove_global_handler(void) +{ + acpi_status status; + + if (!global_handler_registered) + return 0; + + status = acpi_remove_address_space_handler(ACPI_ROOT_OBJECT, + AML_NFW_SPACE, aml_nfw_handler); + if (ACPI_FAILURE(status)) + return -ENODEV; + + global_handler_registered = 0; + printk(KERN_INFO "Global 0x%02X opregion handler removed\n", + AML_NFW_SPACE); + return 0; +} + +static int aml_nfw_add(struct acpi_device *device) +{ + /* + * We would normally allocate a new context structure and install + * the address space handler for the specific device we found. + * But the HP-UX implementation shares a single global context + * and always puts the handler at the root, so we'll do the same. + */ + return aml_nfw_add_global_handler(); +} + +static int aml_nfw_remove(struct acpi_device *device, int type) +{ + return aml_nfw_remove_global_handler(); +} + +static const struct acpi_device_id aml_nfw_ids[] = { + {"HPQ5001", 0}, + {"", 0} +}; + +static struct acpi_driver acpi_aml_nfw_driver = { + .name = "native firmware", + .ids = aml_nfw_ids, + .ops = { + .add = aml_nfw_add, + .remove = aml_nfw_remove, + }, +}; + +static int __init aml_nfw_init(void) +{ + int result; + + if (force_register) + aml_nfw_add_global_handler(); + + result = acpi_bus_register_driver(&acpi_aml_nfw_driver); + if (result < 0) { + aml_nfw_remove_global_handler(); + return result; + } + + return 0; +} + +static void __exit aml_nfw_exit(void) +{ + acpi_bus_unregister_driver(&acpi_aml_nfw_driver); + aml_nfw_remove_global_handler(); +} + +module_init(aml_nfw_init); +module_exit(aml_nfw_exit); diff --git a/arch/ia64/hp/sim/simscsi.c b/arch/ia64/hp/sim/simscsi.c index 4552a1cf5b33..d62fa76e5a7d 100644 --- a/arch/ia64/hp/sim/simscsi.c +++ b/arch/ia64/hp/sim/simscsi.c @@ -372,8 +372,13 @@ simscsi_init(void) return -ENOMEM; error = scsi_add_host(host, NULL); - if (!error) - scsi_scan_host(host); + if (error) + goto free_host; + scsi_scan_host(host); + return 0; + + free_host: + scsi_host_put(host); return error; } diff --git a/arch/ia64/kernel/crash.c b/arch/ia64/kernel/crash.c index 1d64ef478dde..f1cf2df97a2d 100644 --- a/arch/ia64/kernel/crash.c +++ b/arch/ia64/kernel/crash.c @@ -118,11 +118,6 @@ machine_crash_shutdown(struct pt_regs *pt) static void machine_kdump_on_init(void) { - if (!ia64_kimage) { - printk(KERN_NOTICE "machine_kdump_on_init(): " - "kdump not configured\n"); - return; - } local_irq_disable(); kexec_disable_iosapic(); machine_kexec(ia64_kimage); @@ -156,6 +151,14 @@ kdump_init_notifier(struct notifier_block *self, unsigned long val, void *data) if (!kdump_on_init) return NOTIFY_DONE; + if (!ia64_kimage) { + if (val == DIE_INIT_MONARCH_LEAVE) + ia64_mca_printk(KERN_NOTICE + "%s: kdump not configured\n", + __FUNCTION__); + return NOTIFY_DONE; + } + if (val != DIE_INIT_MONARCH_LEAVE && val != DIE_INIT_SLAVE_LEAVE && val != DIE_INIT_MONARCH_PROCESS && diff --git a/arch/ia64/kernel/machine_kexec.c b/arch/ia64/kernel/machine_kexec.c index 4f0f3b8c1ee2..58e943a5d95c 100644 --- a/arch/ia64/kernel/machine_kexec.c +++ b/arch/ia64/kernel/machine_kexec.c @@ -79,7 +79,6 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) relocate_new_kernel_t rnk; void *pal_addr = efi_get_pal_addr(); unsigned long code_addr = (unsigned long)page_address(image->control_code_page); - unsigned long vector; int ii; BUG_ON(!image); @@ -107,11 +106,8 @@ static void ia64_machine_kexec(struct unw_frame_info *info, void *arg) /* unmask TPR and clear any pending interrupts */ ia64_setreg(_IA64_REG_CR_TPR, 0); ia64_srlz_d(); - vector = ia64_get_ivr(); - while (vector != IA64_SPURIOUS_INT_VECTOR) { + while (ia64_get_ivr() != IA64_SPURIOUS_INT_VECTOR) ia64_eoi(); - vector = ia64_get_ivr(); - } platform_kernel_launch_event(); rnk = (relocate_new_kernel_t)&code_addr; (*rnk)(image->head, image->start, ia64_boot_param, diff --git a/arch/ia64/kernel/mca.c b/arch/ia64/kernel/mca.c index 63b73f3d4c9f..cc87025e8f54 100644 --- a/arch/ia64/kernel/mca.c +++ b/arch/ia64/kernel/mca.c @@ -701,8 +701,7 @@ ia64_mca_cmc_vector_enable_keventd(struct work_struct *unused) /* * ia64_mca_wakeup * - * Send an inter-cpu interrupt to wake-up a particular cpu - * and mark that cpu to be out of rendez. + * Send an inter-cpu interrupt to wake-up a particular cpu. * * Inputs : cpuid * Outputs : None @@ -711,14 +710,12 @@ static void ia64_mca_wakeup(int cpu) { platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0); - ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; - } /* * ia64_mca_wakeup_all * - * Wakeup all the cpus which have rendez'ed previously. + * Wakeup all the slave cpus which have rendez'ed previously. * * Inputs : None * Outputs : None @@ -741,7 +738,10 @@ ia64_mca_wakeup_all(void) * * This is handler used to put slave processors into spinloop * while the monarch processor does the mca handling and later - * wake each slave up once the monarch is done. + * wake each slave up once the monarch is done. The state + * IA64_MCA_RENDEZ_CHECKIN_DONE indicates the cpu is rendez'ed + * in SAL. The state IA64_MCA_RENDEZ_CHECKIN_NOTDONE indicates + * the cpu has come out of OS rendezvous. * * Inputs : None * Outputs : None @@ -778,6 +778,7 @@ ia64_mca_rendez_int_handler(int rendez_irq, void *arg) (long)&nd, 0, 0) == NOTIFY_STOP) ia64_mca_spin(__FUNCTION__); + ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; /* Enable all interrupts */ local_irq_restore(flags); return IRQ_HANDLED; @@ -1135,30 +1136,27 @@ no_mod: static void ia64_wait_for_slaves(int monarch, const char *type) { - int c, wait = 0, missing = 0; - for_each_online_cpu(c) { - if (c == monarch) - continue; - if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { - udelay(1000); /* short wait first */ - wait = 1; - break; - } - } - if (!wait) - goto all_in; - for_each_online_cpu(c) { - if (c == monarch) - continue; - if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { - udelay(5*1000000); /* wait 5 seconds for slaves (arbitrary) */ - if (ia64_mc_info.imi_rendez_checkin[c] == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) - missing = 1; - break; + int c, i , wait; + + /* + * wait 5 seconds total for slaves (arbitrary) + */ + for (i = 0; i < 5000; i++) { + wait = 0; + for_each_online_cpu(c) { + if (c == monarch) + continue; + if (ia64_mc_info.imi_rendez_checkin[c] + == IA64_MCA_RENDEZ_CHECKIN_NOTDONE) { + udelay(1000); /* short wait */ + wait = 1; + break; + } } + if (!wait) + goto all_in; } - if (!missing) - goto all_in; + /* * Maybe slave(s) dead. Print buffered messages immediately. */ @@ -1224,26 +1222,27 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, if (notify_die(DIE_MCA_MONARCH_ENTER, "MCA", regs, (long)&nd, 0, 0) == NOTIFY_STOP) ia64_mca_spin(__FUNCTION__); + + ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; if (sos->monarch) { ia64_wait_for_slaves(cpu, "MCA"); + + /* Wakeup all the processors which are spinning in the + * rendezvous loop. They will leave SAL, then spin in the OS + * with interrupts disabled until this monarch cpu leaves the + * MCA handler. That gets control back to the OS so we can + * backtrace the other cpus, backtrace when spinning in SAL + * does not work. + */ + ia64_mca_wakeup_all(); + if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0) + == NOTIFY_STOP) + ia64_mca_spin(__FUNCTION__); } else { - ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; while (cpu_isset(cpu, mca_cpu)) cpu_relax(); /* spin until monarch wakes us */ - ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; } - /* Wakeup all the processors which are spinning in the rendezvous loop. - * They will leave SAL, then spin in the OS with interrupts disabled - * until this monarch cpu leaves the MCA handler. That gets control - * back to the OS so we can backtrace the other cpus, backtrace when - * spinning in SAL does not work. - */ - ia64_mca_wakeup_all(); - if (notify_die(DIE_MCA_MONARCH_PROCESS, "MCA", regs, (long)&nd, 0, 0) - == NOTIFY_STOP) - ia64_mca_spin(__FUNCTION__); - /* Get the MCA error record and log it */ ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); @@ -1277,21 +1276,22 @@ ia64_mca_handler(struct pt_regs *regs, struct switch_stack *sw, /* wake up the next monarch cpu, * and put this cpu in the rendez loop. */ - ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_CONCURRENT_MCA; for_each_online_cpu(i) { if (cpu_isset(i, mca_cpu)) { monarch_cpu = i; cpu_clear(i, mca_cpu); /* wake next cpu */ while (monarch_cpu != -1) cpu_relax(); /* spin until last cpu leaves */ - ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; set_curr_task(cpu, previous_current); + ia64_mc_info.imi_rendez_checkin[cpu] + = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; return; } } } set_curr_task(cpu, previous_current); - monarch_cpu = -1; + ia64_mc_info.imi_rendez_checkin[cpu] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; + monarch_cpu = -1; /* This frees the slaves and previous monarchs */ } static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd); diff --git a/arch/ia64/kernel/mca_drv.h b/arch/ia64/kernel/mca_drv.h index c85e943ba5fd..485e34d0b199 100644 --- a/arch/ia64/kernel/mca_drv.h +++ b/arch/ia64/kernel/mca_drv.h @@ -118,7 +118,5 @@ struct mca_table_entry { extern const struct mca_table_entry *search_mca_tables (unsigned long addr); extern int mca_recover_range(unsigned long); -extern void ia64_mca_printk(const char * fmt, ...) - __attribute__ ((format (printf, 1, 2))); extern void ia64_mlogbuf_dump(void); diff --git a/arch/ia64/kernel/palinfo.c b/arch/ia64/kernel/palinfo.c index 85829e27785c..6ef6ffb943a0 100644 --- a/arch/ia64/kernel/palinfo.c +++ b/arch/ia64/kernel/palinfo.c @@ -907,7 +907,7 @@ palinfo_read_entry(char *page, char **start, off_t off, int count, int *eof, voi return len; } -static void +static void __cpuinit create_palinfo_proc_entries(unsigned int cpu) { # define CPUSTR "cpu%d" @@ -968,7 +968,7 @@ remove_palinfo_proc_entries(unsigned int hcpu) } } -static int palinfo_cpu_callback(struct notifier_block *nfb, +static int __cpuinit palinfo_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { unsigned int hotcpu = (unsigned long)hcpu; @@ -986,7 +986,7 @@ static int palinfo_cpu_callback(struct notifier_block *nfb, return NOTIFY_OK; } -static struct notifier_block palinfo_cpu_notifier = +static struct notifier_block palinfo_cpu_notifier __cpuinitdata = { .notifier_call = palinfo_cpu_callback, .priority = 0, diff --git a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c index 14b8e5a6222b..f55fa07849c4 100644 --- a/arch/ia64/kernel/perfmon.c +++ b/arch/ia64/kernel/perfmon.c @@ -1538,13 +1538,6 @@ init_pfm_fs(void) return err; } -static void __exit -exit_pfm_fs(void) -{ - unregister_filesystem(&pfm_fs_type); - mntput(pfmfs_mnt); -} - static ssize_t pfm_read(struct file *filp, char __user *buf, size_t size, loff_t *ppos) { diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index 25cd75f50ab1..779c3cca206c 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -574,7 +574,7 @@ static const struct file_operations salinfo_data_fops = { .write = salinfo_log_write, }; -static int __devinit +static int __cpuinit salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu) { unsigned int i, cpu = (unsigned long)hcpu; @@ -615,7 +615,7 @@ salinfo_cpu_callback(struct notifier_block *nb, unsigned long action, void *hcpu return NOTIFY_OK; } -static struct notifier_block salinfo_cpu_notifier = +static struct notifier_block salinfo_cpu_notifier __cpuinitdata = { .notifier_call = salinfo_cpu_callback, .priority = 0, diff --git a/arch/ia64/kernel/topology.c b/arch/ia64/kernel/topology.c index 94ae3c87d828..14261fee5f4d 100644 --- a/arch/ia64/kernel/topology.c +++ b/arch/ia64/kernel/topology.c @@ -118,11 +118,11 @@ struct cpu_cache_info { struct kobject kobj; }; -static struct cpu_cache_info all_cpu_cache_info[NR_CPUS]; +static struct cpu_cache_info all_cpu_cache_info[NR_CPUS] __cpuinitdata; #define LEAF_KOBJECT_PTR(x,y) (&all_cpu_cache_info[x].cache_leaves[y]) #ifdef CONFIG_SMP -static void cache_shared_cpu_map_setup( unsigned int cpu, +static void __cpuinit cache_shared_cpu_map_setup( unsigned int cpu, struct cache_info * this_leaf) { pal_cache_shared_info_t csi; @@ -157,7 +157,7 @@ static void cache_shared_cpu_map_setup( unsigned int cpu, &csi) == PAL_STATUS_SUCCESS); } #else -static void cache_shared_cpu_map_setup(unsigned int cpu, +static void __cpuinit cache_shared_cpu_map_setup(unsigned int cpu, struct cache_info * this_leaf) { cpu_set(cpu, this_leaf->shared_cpu_map); @@ -428,13 +428,13 @@ static struct notifier_block __cpuinitdata cache_cpu_notifier = .notifier_call = cache_cpu_callback }; -static int __cpuinit cache_sysfs_init(void) +static int __init cache_sysfs_init(void) { int i; for_each_online_cpu(i) { - cache_cpu_callback(&cache_cpu_notifier, CPU_ONLINE, - (void *)(long)i); + struct sys_device *sys_dev = get_cpu_sysdev((unsigned int)i); + cache_add_dev(sys_dev); } register_hotcpu_notifier(&cache_cpu_notifier); diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c index ea0b2c790412..190ff4b59a55 100644 --- a/arch/powerpc/platforms/ps3/system-bus.c +++ b/arch/powerpc/platforms/ps3/system-bus.c @@ -440,7 +440,6 @@ static void ps3_system_bus_shutdown(struct device *_dev) static int ps3_system_bus_uevent(struct device *_dev, struct kobj_uevent_env *env) { struct ps3_system_bus_device *dev = ps3_dev_to_system_bus_dev(_dev); - int i = 0, length = 0; if (add_uevent_var(env, "MODALIAS=ps3:%d", dev->match_id)) return -ENOMEM; diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h index 8955e7ff759a..b83824c41329 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h @@ -58,6 +58,9 @@ struct gatt_mask { * devices this will probably be ignored */ }; +#define AGP_PAGE_DESTROY_UNMAP 1 +#define AGP_PAGE_DESTROY_FREE 2 + struct aper_size_info_8 { int size; int num_entries; @@ -113,7 +116,7 @@ struct agp_bridge_driver { struct agp_memory *(*alloc_by_type) (size_t, int); void (*free_by_type)(struct agp_memory *); void *(*agp_alloc_page)(struct agp_bridge_data *); - void (*agp_destroy_page)(void *); + void (*agp_destroy_page)(void *, int flags); int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); }; @@ -267,7 +270,7 @@ int agp_generic_remove_memory(struct agp_memory *mem, off_t pg_start, int type); struct agp_memory *agp_generic_alloc_by_type(size_t page_count, int type); void agp_generic_free_by_type(struct agp_memory *curr); void *agp_generic_alloc_page(struct agp_bridge_data *bridge); -void agp_generic_destroy_page(void *addr); +void agp_generic_destroy_page(void *addr, int flags); void agp_free_key(int key); int agp_num_entries(void); u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 mode, u32 command); diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 4941ddb78939..aa5ddb716ffb 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c @@ -156,29 +156,34 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge) return addr; } -static void ali_destroy_page(void * addr) +static void ali_destroy_page(void * addr, int flags) { if (addr) { - global_cache_flush(); /* is this really needed? --hch */ - agp_generic_destroy_page(addr); - global_flush_tlb(); + if (flags & AGP_PAGE_DESTROY_UNMAP) { + global_cache_flush(); /* is this really needed? --hch */ + agp_generic_destroy_page(addr, flags); + global_flush_tlb(); + } else + agp_generic_destroy_page(addr, flags); } } -static void m1541_destroy_page(void * addr) +static void m1541_destroy_page(void * addr, int flags) { u32 temp; if (addr == NULL) return; - global_cache_flush(); + if (flags & AGP_PAGE_DESTROY_UNMAP) { + global_cache_flush(); - pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); - pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, - (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | - virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN)); - agp_generic_destroy_page(addr); + pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); + pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, + (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | + virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN)); + } + agp_generic_destroy_page(addr, flags); } diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index f60bca70d1fb..1405a42585e1 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c @@ -100,21 +100,16 @@ static int amd_create_gatt_pages(int nr_tables) for (i = 0; i < nr_tables; i++) { entry = kzalloc(sizeof(struct amd_page_map), GFP_KERNEL); + tables[i] = entry; if (entry == NULL) { - while (i > 0) { - kfree(tables[i-1]); - i--; - } - kfree(tables); retval = -ENOMEM; break; } - tables[i] = entry; retval = amd_create_page_map(entry); if (retval != 0) break; } - amd_irongate_private.num_tables = nr_tables; + amd_irongate_private.num_tables = i; amd_irongate_private.gatt_pages = tables; if (retval != 0) diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 1b47c89a1b99..832ded20fe70 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c @@ -189,9 +189,11 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) err_out: if (bridge->driver->needs_scratch_page) { - bridge->driver->agp_destroy_page( - gart_to_virt(bridge->scratch_page_real)); + bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), + AGP_PAGE_DESTROY_UNMAP); flush_agp_mappings(); + bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), + AGP_PAGE_DESTROY_FREE); } if (got_gatt) bridge->driver->free_gatt_table(bridge); @@ -215,9 +217,11 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) if (bridge->driver->agp_destroy_page && bridge->driver->needs_scratch_page) { - bridge->driver->agp_destroy_page( - gart_to_virt(bridge->scratch_page_real)); + bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), + AGP_PAGE_DESTROY_UNMAP); flush_agp_mappings(); + bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), + AGP_PAGE_DESTROY_FREE); } } diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index 3db4f4076ed4..64b2f6d7059d 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c @@ -195,9 +195,12 @@ void agp_free_memory(struct agp_memory *curr) } if (curr->page_count != 0) { for (i = 0; i < curr->page_count; i++) { - curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i])); + curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_UNMAP); } flush_agp_mappings(); + for (i = 0; i < curr->page_count; i++) { + curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i]), AGP_PAGE_DESTROY_FREE); + } } agp_free_key(curr->key); agp_free_page_array(curr); @@ -1176,7 +1179,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) EXPORT_SYMBOL(agp_generic_alloc_page); -void agp_generic_destroy_page(void *addr) +void agp_generic_destroy_page(void *addr, int flags) { struct page *page; @@ -1184,10 +1187,14 @@ void agp_generic_destroy_page(void *addr) return; page = virt_to_page(addr); - unmap_page_from_agp(page); - put_page(page); - free_page((unsigned long)addr); - atomic_dec(&agp_bridge->current_memory_agp); + if (flags & AGP_PAGE_DESTROY_UNMAP) + unmap_page_from_agp(page); + + if (flags & AGP_PAGE_DESTROY_FREE) { + put_page(page); + free_page((unsigned long)addr); + atomic_dec(&agp_bridge->current_memory_agp); + } } EXPORT_SYMBOL(agp_generic_destroy_page); diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 75d2aca6353d..70117df4d067 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c @@ -536,10 +536,10 @@ static void *i460_alloc_page (struct agp_bridge_data *bridge) return page; } -static void i460_destroy_page (void *page) +static void i460_destroy_page (void *page, int flags) { if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) { - agp_generic_destroy_page(page); + agp_generic_destroy_page(page, flags); global_flush_tlb(); } } diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 141ca176c397..d87961993ccf 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -400,9 +400,11 @@ static void intel_i810_free_by_type(struct agp_memory *curr) if (curr->page_count == 4) i8xx_destroy_pages(gart_to_virt(curr->memory[0])); else { - agp_bridge->driver->agp_destroy_page( - gart_to_virt(curr->memory[0])); + agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]), + AGP_PAGE_DESTROY_UNMAP); global_flush_tlb(); + agp_bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[0]), + AGP_PAGE_DESTROY_FREE); } agp_free_page_array(curr); } diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h index 2d6f2d0bd02b..82fb3d0d2785 100644 --- a/drivers/char/drm/drm.h +++ b/drivers/char/drm/drm.h @@ -63,27 +63,9 @@ #define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size) #endif -#define XFREE86_VERSION(major,minor,patch,snap) \ - ((major << 16) | (minor << 8) | patch) - -#ifndef CONFIG_XFREE86_VERSION -#define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0) -#endif - -#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) -#define DRM_PROC_DEVICES "/proc/devices" -#define DRM_PROC_MISC "/proc/misc" -#define DRM_PROC_DRM "/proc/drm" -#define DRM_DEV_DRM "/dev/drm" -#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) -#define DRM_DEV_UID 0 -#define DRM_DEV_GID 0 -#endif - -#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0) #define DRM_MAJOR 226 #define DRM_MAX_MINOR 15 -#endif + #define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */ #define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */ #define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */ diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 0df87fc3dcb2..9dd0760dd87a 100644 --- a/drivers/char/drm/drmP.h +++ b/drivers/char/drm/drmP.h @@ -80,6 +80,9 @@ #define __OS_HAS_AGP (defined(CONFIG_AGP) || (defined(CONFIG_AGP_MODULE) && defined(MODULE))) #define __OS_HAS_MTRR (defined(CONFIG_MTRR)) +struct drm_file; +struct drm_device; + #include "drm_os_linux.h" #include "drm_hashtab.h" @@ -231,12 +234,13 @@ * \param dev DRM device. * \param filp file pointer of the caller. */ -#define LOCK_TEST_WITH_RETURN( dev, filp ) \ +#define LOCK_TEST_WITH_RETURN( dev, file_priv ) \ do { \ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ - dev->lock.filp != filp ) { \ - DRM_ERROR( "%s called without lock held\n", \ - __FUNCTION__ ); \ + dev->lock.file_priv != file_priv ) { \ + DRM_ERROR( "%s called without lock held, held %d owner %p %p\n",\ + __FUNCTION__, _DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ),\ + dev->lock.file_priv, file_priv ); \ return -EINVAL; \ } \ } while (0) @@ -257,12 +261,12 @@ do { \ * Ioctl function type. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private pointer. * \param cmd command. * \param arg argument. */ -typedef int drm_ioctl_t(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +typedef int drm_ioctl_t(struct drm_device *dev, void *data, + struct drm_file *file_priv); typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, unsigned long arg); @@ -271,10 +275,18 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, #define DRM_MASTER 0x2 #define DRM_ROOT_ONLY 0x4 -typedef struct drm_ioctl_desc { +struct drm_ioctl_desc { + unsigned int cmd; drm_ioctl_t *func; int flags; -} drm_ioctl_desc_t; +}; + +/** + * Creates a driver or general drm_ioctl_desc array entry for the given + * ioctl, for use by drm_ioctl(). + */ +#define DRM_IOCTL_DEF(ioctl, func, flags) \ + [DRM_IOCTL_NR(ioctl)] = {ioctl, func, flags} struct drm_magic_entry { struct list_head head; @@ -304,7 +316,7 @@ struct drm_buf { __volatile__ int waiting; /**< On kernel DMA queue */ __volatile__ int pending; /**< On hardware DMA queue */ wait_queue_head_t dma_wait; /**< Processes waiting */ - struct file *filp; /**< Pointer to holding file descr */ + struct drm_file *file_priv; /**< Private of holding file descr */ int context; /**< Kernel queue for this buffer */ int while_locked; /**< Dispatch this buffer while locked */ enum { @@ -377,6 +389,7 @@ struct drm_file { int remove_auth_on_close; unsigned long lock_count; void *driver_priv; + struct file *filp; }; /** Wait queue */ @@ -403,7 +416,7 @@ struct drm_queue { */ struct drm_lock_data { struct drm_hw_lock *hw_lock; /**< Hardware lock */ - struct file *filp; /**< File descr of lock holder (0=kernel) */ + struct drm_file *file_priv; /**< File descr of lock holder (0=kernel) */ wait_queue_head_t lock_queue; /**< Queue of blocked processes */ unsigned long lock_time; /**< Time of last lock in jiffies */ spinlock_t spinlock; @@ -552,11 +565,11 @@ struct drm_driver { int (*load) (struct drm_device *, unsigned long flags); int (*firstopen) (struct drm_device *); int (*open) (struct drm_device *, struct drm_file *); - void (*preclose) (struct drm_device *, struct file * filp); + void (*preclose) (struct drm_device *, struct drm_file *file_priv); void (*postclose) (struct drm_device *, struct drm_file *); void (*lastclose) (struct drm_device *); int (*unload) (struct drm_device *); - int (*dma_ioctl) (DRM_IOCTL_ARGS); + int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); void (*dma_ready) (struct drm_device *); int (*dma_quiescent) (struct drm_device *); int (*context_ctor) (struct drm_device *dev, int context); @@ -587,11 +600,12 @@ struct drm_driver { void (*irq_preinstall) (struct drm_device *dev); void (*irq_postinstall) (struct drm_device *dev); void (*irq_uninstall) (struct drm_device *dev); - void (*reclaim_buffers) (struct drm_device *dev, struct file * filp); + void (*reclaim_buffers) (struct drm_device *dev, + struct drm_file * file_priv); void (*reclaim_buffers_locked) (struct drm_device *dev, - struct file *filp); + struct drm_file *file_priv); void (*reclaim_buffers_idlelocked) (struct drm_device *dev, - struct file * filp); + struct drm_file *file_priv); unsigned long (*get_map_ofs) (struct drm_map * map); unsigned long (*get_reg_ofs) (struct drm_device *dev); void (*set_version) (struct drm_device *dev, @@ -606,7 +620,7 @@ struct drm_driver { u32 driver_features; int dev_priv_size; - drm_ioctl_desc_t *ioctls; + struct drm_ioctl_desc *ioctls; int num_ioctls; struct file_operations fops; struct pci_driver pci_driver; @@ -850,70 +864,70 @@ extern int drm_bind_agp(DRM_AGP_MEM * handle, unsigned int start); extern int drm_unbind_agp(DRM_AGP_MEM * handle); /* Misc. IOCTL support (drm_ioctl.h) */ -extern int drm_irq_by_busid(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_getunique(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_setunique(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_getmap(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_getclient(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_getstats(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_setversion(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_noop(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_irq_by_busid(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_getunique(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_setunique(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_getmap(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_getclient(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_getstats(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_setversion(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_noop(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* Context IOCTL support (drm_context.h) */ -extern int drm_resctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_addctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_modctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_getctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_switchctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_newctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_rmctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_resctx(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_addctx(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_modctx(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_getctx(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_switchctx(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_newctx(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_rmctx(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_ctxbitmap_init(struct drm_device *dev); extern void drm_ctxbitmap_cleanup(struct drm_device *dev); extern void drm_ctxbitmap_free(struct drm_device *dev, int ctx_handle); -extern int drm_setsareactx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_getsareactx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_setsareactx(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_getsareactx(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* Drawable IOCTL support (drm_drawable.h) */ -extern int drm_adddraw(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_rmdraw(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_update_drawable_info(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_adddraw(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_rmdraw(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_update_drawable_info(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern struct drm_drawable_info *drm_get_drawable_info(struct drm_device *dev, drm_drawable_t id); extern void drm_drawable_free_all(struct drm_device *dev); /* Authentication IOCTL support (drm_auth.h) */ -extern int drm_getmagic(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_authmagic(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_getmagic(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_authmagic(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* Locking IOCTL support (drm_lock.h) */ -extern int drm_lock(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_unlock(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_lock(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_unlock(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_lock_take(struct drm_lock_data *lock_data, unsigned int context); extern int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context); extern void drm_idlelock_take(struct drm_lock_data *lock_data); @@ -924,8 +938,7 @@ extern void drm_idlelock_release(struct drm_lock_data *lock_data); * DMA quiscent + idle. DMA quiescent usually requires the hardware lock. */ -extern int drm_i_have_hw_lock(struct file *filp); -extern int drm_kernel_take_hw_lock(struct file *filp); +extern int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv); /* Buffer management support (drm_bufs.h) */ extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request); @@ -933,24 +946,23 @@ extern int drm_addbufs_pci(struct drm_device *dev, struct drm_buf_desc * request extern int drm_addmap(struct drm_device *dev, unsigned int offset, unsigned int size, enum drm_map_type type, enum drm_map_flags flags, drm_local_map_t ** map_ptr); -extern int drm_addmap_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_rmmap(struct drm_device *dev, drm_local_map_t * map); -extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t * map); -extern int drm_rmmap_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); - +extern int drm_addmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_rmmap(struct drm_device *dev, drm_local_map_t *map); +extern int drm_rmmap_locked(struct drm_device *dev, drm_local_map_t *map); +extern int drm_rmmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_addbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_infobufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_markbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_freebufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_mapbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_order(unsigned long size); -extern int drm_addbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_infobufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_markbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_freebufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_mapbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); extern unsigned long drm_get_resource_start(struct drm_device *dev, unsigned int resource); extern unsigned long drm_get_resource_len(struct drm_device *dev, @@ -960,19 +972,20 @@ extern unsigned long drm_get_resource_len(struct drm_device *dev, extern int drm_dma_setup(struct drm_device *dev); extern void drm_dma_takedown(struct drm_device *dev); extern void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf); -extern void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp); +extern void drm_core_reclaim_buffers(struct drm_device *dev, + struct drm_file *filp); /* IRQ support (drm_irq.h) */ -extern int drm_control(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_control(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern irqreturn_t drm_irq_handler(DRM_IRQ_ARGS); extern int drm_irq_uninstall(struct drm_device *dev); extern void drm_driver_irq_preinstall(struct drm_device *dev); extern void drm_driver_irq_postinstall(struct drm_device *dev); extern void drm_driver_irq_uninstall(struct drm_device *dev); -extern int drm_wait_vblank(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_wait_vblank(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq); extern void drm_vbl_send_signals(struct drm_device *dev); extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*)); @@ -980,31 +993,30 @@ extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_de /* AGP/GART support (drm_agpsupport.h) */ extern struct drm_agp_head *drm_agp_init(struct drm_device *dev); extern int drm_agp_acquire(struct drm_device *dev); -extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_agp_release(struct drm_device *dev); -extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_agp_release_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode); -extern int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info * info); -extern int drm_agp_info_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_agp_enable_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info); +extern int drm_agp_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request); -extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request); -extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_agp_free_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request); -extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); -extern int drm_agp_bind_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, - size_t pages, u32 type); +extern int drm_agp_bind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern DRM_AGP_MEM *drm_agp_allocate_memory(struct agp_bridge_data *bridge, size_t pages, u32 type); extern int drm_agp_free_memory(DRM_AGP_MEM * handle); extern int drm_agp_bind_memory(DRM_AGP_MEM * handle, off_t start); extern int drm_agp_unbind_memory(DRM_AGP_MEM * handle); @@ -1033,10 +1045,11 @@ extern int drm_proc_cleanup(int minor, /* Scatter Gather Support (drm_scatter.h) */ extern void drm_sg_cleanup(struct drm_sg_mem * entry); -extern int drm_sg_alloc(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int drm_sg_free(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int drm_sg_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request); +extern int drm_sg_free(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* ATI PCIGART support (ati_pcigart.h) */ extern int drm_ati_pcigart_init(struct drm_device *dev, diff --git a/drivers/char/drm/drm_agpsupport.c b/drivers/char/drm/drm_agpsupport.c index 354f0e3674bf..214f4fbcba73 100644 --- a/drivers/char/drm/drm_agpsupport.c +++ b/drivers/char/drm/drm_agpsupport.c @@ -40,7 +40,7 @@ * Get AGP information. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a (output) drm_agp_info structure. * \return zero on success or a negative number on failure. @@ -71,20 +71,16 @@ int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info) EXPORT_SYMBOL(drm_agp_info); -int drm_agp_info_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_agp_info_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_agp_info info; + struct drm_agp_info *info = data; int err; - err = drm_agp_info(dev, &info); + err = drm_agp_info(dev, info); if (err) return err; - if (copy_to_user((struct drm_agp_info __user *) arg, &info, sizeof(info))) - return -EFAULT; return 0; } @@ -115,7 +111,7 @@ EXPORT_SYMBOL(drm_agp_acquire); * Acquire the AGP device (ioctl). * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument. * \return zero on success or a negative number on failure. @@ -123,12 +119,10 @@ EXPORT_SYMBOL(drm_agp_acquire); * Verifies the AGP device hasn't been acquired before and calls * \c agp_backend_acquire. */ -int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_agp_acquire_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - - return drm_agp_acquire((struct drm_device *) priv->head->dev); + return drm_agp_acquire((struct drm_device *) file_priv->head->dev); } /** @@ -149,12 +143,9 @@ int drm_agp_release(struct drm_device * dev) } EXPORT_SYMBOL(drm_agp_release); -int drm_agp_release_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_agp_release_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - return drm_agp_release(dev); } @@ -182,24 +173,19 @@ int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode) EXPORT_SYMBOL(drm_agp_enable); -int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_agp_enable_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_agp_mode mode; - - if (copy_from_user(&mode, (struct drm_agp_mode __user *) arg, sizeof(mode))) - return -EFAULT; + struct drm_agp_mode *mode = data; - return drm_agp_enable(dev, mode); + return drm_agp_enable(dev, *mode); } /** * Allocate AGP memory. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv file private pointer. * \param cmd command. * \param arg pointer to a drm_agp_buffer structure. * \return zero on success or a negative number on failure. @@ -241,35 +227,13 @@ int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) } EXPORT_SYMBOL(drm_agp_alloc); -int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_agp_buffer request; - struct drm_agp_buffer __user *argp = (void __user *)arg; - int err; - - if (copy_from_user(&request, argp, sizeof(request))) - return -EFAULT; - err = drm_agp_alloc(dev, &request); - if (err) - return err; - - if (copy_to_user(argp, &request, sizeof(request))) { - struct drm_agp_mem *entry; - list_for_each_entry(entry, &dev->agp->memory, head) { - if (entry->handle == request.handle) - break; - } - list_del(&entry->head); - drm_free_agp(entry->memory, entry->pages); - drm_free(entry, sizeof(*entry), DRM_MEM_AGPLISTS); - return -EFAULT; - } +int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_agp_buffer *request = data; - return 0; + return drm_agp_alloc(dev, request); } /** @@ -297,7 +261,7 @@ static struct drm_agp_mem *drm_agp_lookup_entry(struct drm_device * dev, * Unbind AGP memory from the GATT (ioctl). * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a drm_agp_binding structure. * \return zero on success or a negative number on failure. @@ -323,25 +287,20 @@ int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request) } EXPORT_SYMBOL(drm_agp_unbind); -int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_agp_binding request; - if (copy_from_user - (&request, (struct drm_agp_binding __user *) arg, sizeof(request))) - return -EFAULT; +int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_agp_binding *request = data; - return drm_agp_unbind(dev, &request); + return drm_agp_unbind(dev, request); } /** * Bind AGP memory into the GATT (ioctl) * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a drm_agp_binding structure. * \return zero on success or a negative number on failure. @@ -372,25 +331,20 @@ int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request) } EXPORT_SYMBOL(drm_agp_bind); -int drm_agp_bind_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_agp_binding request; - if (copy_from_user - (&request, (struct drm_agp_binding __user *) arg, sizeof(request))) - return -EFAULT; +int drm_agp_bind_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_agp_binding *request = data; - return drm_agp_bind(dev, &request); + return drm_agp_bind(dev, request); } /** * Free AGP memory (ioctl). * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a drm_agp_buffer structure. * \return zero on success or a negative number on failure. @@ -419,18 +373,14 @@ int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request) } EXPORT_SYMBOL(drm_agp_free); -int drm_agp_free_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_agp_buffer request; - if (copy_from_user - (&request, (struct drm_agp_buffer __user *) arg, sizeof(request))) - return -EFAULT; - return drm_agp_free(dev, &request); +int drm_agp_free_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_agp_buffer *request = data; + + return drm_agp_free(dev, request); } /** diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c index 7f777da872cd..a73462723d2d 100644 --- a/drivers/char/drm/drm_auth.c +++ b/drivers/char/drm/drm_auth.c @@ -128,42 +128,38 @@ static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic) * Get a unique magic number (ioctl). * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a resulting drm_auth structure. * \return zero on success, or a negative number on failure. * * If there is a magic number in drm_file::magic then use it, otherwise * searches an unique non-zero magic number and add it associating it with \p - * filp. + * file_priv. */ -int drm_getmagic(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) { static drm_magic_t sequence = 0; static DEFINE_SPINLOCK(lock); - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_auth auth; + struct drm_auth *auth = data; /* Find unique magic */ - if (priv->magic) { - auth.magic = priv->magic; + if (file_priv->magic) { + auth->magic = file_priv->magic; } else { do { spin_lock(&lock); if (!sequence) ++sequence; /* reserve 0 */ - auth.magic = sequence++; + auth->magic = sequence++; spin_unlock(&lock); - } while (drm_find_file(dev, auth.magic)); - priv->magic = auth.magic; - drm_add_magic(dev, priv, auth.magic); + } while (drm_find_file(dev, auth->magic)); + file_priv->magic = auth->magic; + drm_add_magic(dev, file_priv, auth->magic); } - DRM_DEBUG("%u\n", auth.magic); - if (copy_to_user((struct drm_auth __user *) arg, &auth, sizeof(auth))) - return -EFAULT; + DRM_DEBUG("%u\n", auth->magic); + return 0; } @@ -171,27 +167,23 @@ int drm_getmagic(struct inode *inode, struct file *filp, * Authenticate with a magic. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a drm_auth structure. * \return zero if authentication successed, or a negative number otherwise. * - * Checks if \p filp is associated with the magic number passed in \arg. + * Checks if \p file_priv is associated with the magic number passed in \arg. */ -int drm_authmagic(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_authmagic(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_auth auth; + struct drm_auth *auth = data; struct drm_file *file; - if (copy_from_user(&auth, (struct drm_auth __user *) arg, sizeof(auth))) - return -EFAULT; - DRM_DEBUG("%u\n", auth.magic); - if ((file = drm_find_file(dev, auth.magic))) { + DRM_DEBUG("%u\n", auth->magic); + if ((file = drm_find_file(dev, auth->magic))) { file->authenticated = 1; - drm_remove_magic(dev, auth.magic); + drm_remove_magic(dev, auth->magic); return 0; } return -EINVAL; diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index c115b39b8517..856774fbe025 100644 --- a/drivers/char/drm/drm_bufs.c +++ b/drivers/char/drm/drm_bufs.c @@ -92,7 +92,7 @@ static int drm_map_handle(struct drm_device *dev, struct drm_hash_item *hash, * Ioctl to specify a range of memory that is available for mapping by a non-root process. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a drm_map structure. * \return zero on success or a negative value on error. @@ -332,38 +332,24 @@ int drm_addmap(struct drm_device * dev, unsigned int offset, EXPORT_SYMBOL(drm_addmap); -int drm_addmap_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_addmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_map map; + struct drm_map *map = data; struct drm_map_list *maplist; - struct drm_map __user *argp = (void __user *)arg; int err; - if (!(filp->f_mode & 3)) - return -EACCES; /* Require read/write */ - - if (copy_from_user(&map, argp, sizeof(map))) { - return -EFAULT; - } - - if (!(capable(CAP_SYS_ADMIN) || map.type == _DRM_AGP)) + if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP)) return -EPERM; - err = drm_addmap_core(dev, map.offset, map.size, map.type, map.flags, - &maplist); + err = drm_addmap_core(dev, map->offset, map->size, map->type, + map->flags, &maplist); if (err) return err; - if (copy_to_user(argp, maplist->map, sizeof(struct drm_map))) - return -EFAULT; - /* avoid a warning on 64-bit, this casting isn't very nice, but the API is set so too late */ - if (put_user((void *)(unsigned long)maplist->user_token, &argp->handle)) - return -EFAULT; + map->handle = (void *)(unsigned long)maplist->user_token; return 0; } @@ -372,7 +358,7 @@ int drm_addmap_ioctl(struct inode *inode, struct file *filp, * isn't in use. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a struct drm_map structure. * \return zero on success or a negative value on error. @@ -453,24 +439,18 @@ int drm_rmmap(struct drm_device *dev, drm_local_map_t *map) * gets used by drivers that the server doesn't need to care about. This seems * unlikely. */ -int drm_rmmap_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_rmmap_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_map request; + struct drm_map *request = data; drm_local_map_t *map = NULL; struct drm_map_list *r_list; int ret; - if (copy_from_user(&request, (struct drm_map __user *) arg, sizeof(request))) { - return -EFAULT; - } - mutex_lock(&dev->struct_mutex); list_for_each_entry(r_list, &dev->maplist, head) { if (r_list->map && - r_list->user_token == (unsigned long)request.handle && + r_list->user_token == (unsigned long)request->handle && r_list->map->flags & _DRM_REMOVABLE) { map = r_list->map; break; @@ -661,7 +641,7 @@ int drm_addbufs_agp(struct drm_device * dev, struct drm_buf_desc * request) buf->waiting = 0; buf->pending = 0; init_waitqueue_head(&buf->dma_wait); - buf->filp = NULL; + buf->file_priv = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); @@ -872,7 +852,7 @@ int drm_addbufs_pci(struct drm_device * dev, struct drm_buf_desc * request) buf->waiting = 0; buf->pending = 0; init_waitqueue_head(&buf->dma_wait); - buf->filp = NULL; + buf->file_priv = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; buf->dev_private = drm_alloc(buf->dev_priv_size, @@ -1050,7 +1030,7 @@ static int drm_addbufs_sg(struct drm_device * dev, struct drm_buf_desc * request buf->waiting = 0; buf->pending = 0; init_waitqueue_head(&buf->dma_wait); - buf->filp = NULL; + buf->file_priv = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); @@ -1211,7 +1191,7 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request buf->waiting = 0; buf->pending = 0; init_waitqueue_head(&buf->dma_wait); - buf->filp = NULL; + buf->file_priv = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); @@ -1275,7 +1255,7 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request * Add buffers for DMA transfers (ioctl). * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a struct drm_buf_desc request. * \return zero on success or a negative number on failure. @@ -1285,38 +1265,27 @@ static int drm_addbufs_fb(struct drm_device * dev, struct drm_buf_desc * request * addbufs_sg() or addbufs_pci() for AGP, scatter-gather or consistent * PCI memory respectively. */ -int drm_addbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_addbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_buf_desc request; - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_buf_desc *request = data; int ret; if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) return -EINVAL; - if (copy_from_user(&request, (struct drm_buf_desc __user *) arg, - sizeof(request))) - return -EFAULT; - #if __OS_HAS_AGP - if (request.flags & _DRM_AGP_BUFFER) - ret = drm_addbufs_agp(dev, &request); + if (request->flags & _DRM_AGP_BUFFER) + ret = drm_addbufs_agp(dev, request); else #endif - if (request.flags & _DRM_SG_BUFFER) - ret = drm_addbufs_sg(dev, &request); - else if (request.flags & _DRM_FB_BUFFER) - ret = drm_addbufs_fb(dev, &request); + if (request->flags & _DRM_SG_BUFFER) + ret = drm_addbufs_sg(dev, request); + else if (request->flags & _DRM_FB_BUFFER) + ret = drm_addbufs_fb(dev, request); else - ret = drm_addbufs_pci(dev, &request); + ret = drm_addbufs_pci(dev, request); - if (ret == 0) { - if (copy_to_user((void __user *)arg, &request, sizeof(request))) { - ret = -EFAULT; - } - } return ret; } @@ -1328,7 +1297,7 @@ int drm_addbufs(struct inode *inode, struct file *filp, * large buffers can be used for image transfer). * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a drm_buf_info structure. * \return zero on success or a negative number on failure. @@ -1337,14 +1306,11 @@ int drm_addbufs(struct inode *inode, struct file *filp, * lock, preventing of allocating more buffers after this call. Information * about each requested buffer is then copied into user space. */ -int drm_infobufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_infobufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; struct drm_device_dma *dma = dev->dma; - struct drm_buf_info request; - struct drm_buf_info __user *argp = (void __user *)arg; + struct drm_buf_info *request = data; int i; int count; @@ -1362,9 +1328,6 @@ int drm_infobufs(struct inode *inode, struct file *filp, ++dev->buf_use; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - if (copy_from_user(&request, argp, sizeof(request))) - return -EFAULT; - for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) { if (dma->bufs[i].buf_count) ++count; @@ -1372,11 +1335,11 @@ int drm_infobufs(struct inode *inode, struct file *filp, DRM_DEBUG("count = %d\n", count); - if (request.count >= count) { + if (request->count >= count) { for (i = 0, count = 0; i < DRM_MAX_ORDER + 1; i++) { if (dma->bufs[i].buf_count) { struct drm_buf_desc __user *to = - &request.list[count]; + &request->list[count]; struct drm_buf_entry *from = &dma->bufs[i]; struct drm_freelist *list = &dma->bufs[i].freelist; if (copy_to_user(&to->count, @@ -1403,10 +1366,7 @@ int drm_infobufs(struct inode *inode, struct file *filp, } } } - request.count = count; - - if (copy_to_user(argp, &request, sizeof(request))) - return -EFAULT; + request->count = count; return 0; } @@ -1415,7 +1375,7 @@ int drm_infobufs(struct inode *inode, struct file *filp, * Specifies a low and high water mark for buffer allocation * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg a pointer to a drm_buf_desc structure. * \return zero on success or a negative number on failure. @@ -1425,13 +1385,11 @@ int drm_infobufs(struct inode *inode, struct file *filp, * * \note This ioctl is deprecated and mostly never used. */ -int drm_markbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_markbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; struct drm_device_dma *dma = dev->dma; - struct drm_buf_desc request; + struct drm_buf_desc *request = data; int order; struct drm_buf_entry *entry; @@ -1441,24 +1399,20 @@ int drm_markbufs(struct inode *inode, struct file *filp, if (!dma) return -EINVAL; - if (copy_from_user(&request, - (struct drm_buf_desc __user *) arg, sizeof(request))) - return -EFAULT; - DRM_DEBUG("%d, %d, %d\n", - request.size, request.low_mark, request.high_mark); - order = drm_order(request.size); + request->size, request->low_mark, request->high_mark); + order = drm_order(request->size); if (order < DRM_MIN_ORDER || order > DRM_MAX_ORDER) return -EINVAL; entry = &dma->bufs[order]; - if (request.low_mark < 0 || request.low_mark > entry->buf_count) + if (request->low_mark < 0 || request->low_mark > entry->buf_count) return -EINVAL; - if (request.high_mark < 0 || request.high_mark > entry->buf_count) + if (request->high_mark < 0 || request->high_mark > entry->buf_count) return -EINVAL; - entry->freelist.low_mark = request.low_mark; - entry->freelist.high_mark = request.high_mark; + entry->freelist.low_mark = request->low_mark; + entry->freelist.high_mark = request->high_mark; return 0; } @@ -1467,7 +1421,7 @@ int drm_markbufs(struct inode *inode, struct file *filp, * Unreserve the buffers in list, previously reserved using drmDMA. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a drm_buf_free structure. * \return zero on success or a negative number on failure. @@ -1475,13 +1429,11 @@ int drm_markbufs(struct inode *inode, struct file *filp, * Calls free_buffer() for each used buffer. * This function is primarily used for debugging. */ -int drm_freebufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_freebufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; struct drm_device_dma *dma = dev->dma; - struct drm_buf_free request; + struct drm_buf_free *request = data; int i; int idx; struct drm_buf *buf; @@ -1492,13 +1444,9 @@ int drm_freebufs(struct inode *inode, struct file *filp, if (!dma) return -EINVAL; - if (copy_from_user(&request, - (struct drm_buf_free __user *) arg, sizeof(request))) - return -EFAULT; - - DRM_DEBUG("%d\n", request.count); - for (i = 0; i < request.count; i++) { - if (copy_from_user(&idx, &request.list[i], sizeof(idx))) + DRM_DEBUG("%d\n", request->count); + for (i = 0; i < request->count; i++) { + if (copy_from_user(&idx, &request->list[i], sizeof(idx))) return -EFAULT; if (idx < 0 || idx >= dma->buf_count) { DRM_ERROR("Index %d (of %d max)\n", @@ -1506,7 +1454,7 @@ int drm_freebufs(struct inode *inode, struct file *filp, return -EINVAL; } buf = dma->buflist[idx]; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("Process %d freeing buffer not owned\n", current->pid); return -EINVAL; @@ -1521,7 +1469,7 @@ int drm_freebufs(struct inode *inode, struct file *filp, * Maps all of the DMA buffers into client-virtual space (ioctl). * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg pointer to a drm_buf_map structure. * \return zero on success or a negative number on failure. @@ -1531,18 +1479,15 @@ int drm_freebufs(struct inode *inode, struct file *filp, * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls * drm_mmap_dma(). */ -int drm_mapbufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_mapbufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; struct drm_device_dma *dma = dev->dma; - struct drm_buf_map __user *argp = (void __user *)arg; int retcode = 0; const int zero = 0; unsigned long virtual; unsigned long address; - struct drm_buf_map request; + struct drm_buf_map *request = data; int i; if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) @@ -1559,10 +1504,7 @@ int drm_mapbufs(struct inode *inode, struct file *filp, dev->buf_use++; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - if (copy_from_user(&request, argp, sizeof(request))) - return -EFAULT; - - if (request.count >= dma->buf_count) { + if (request->count >= dma->buf_count) { if ((drm_core_has_AGP(dev) && (dma->flags & _DRM_DMA_USE_AGP)) || (drm_core_check_feature(dev, DRIVER_SG) && (dma->flags & _DRM_DMA_USE_SG)) @@ -1575,15 +1517,15 @@ int drm_mapbufs(struct inode *inode, struct file *filp, retcode = -EINVAL; goto done; } - down_write(¤t->mm->mmap_sem); - virtual = do_mmap(filp, 0, map->size, + virtual = do_mmap(file_priv->filp, 0, map->size, PROT_READ | PROT_WRITE, - MAP_SHARED, token); + MAP_SHARED, + token); up_write(¤t->mm->mmap_sem); } else { down_write(¤t->mm->mmap_sem); - virtual = do_mmap(filp, 0, dma->byte_count, + virtual = do_mmap(file_priv->filp, 0, dma->byte_count, PROT_READ | PROT_WRITE, MAP_SHARED, 0); up_write(¤t->mm->mmap_sem); @@ -1593,28 +1535,28 @@ int drm_mapbufs(struct inode *inode, struct file *filp, retcode = (signed long)virtual; goto done; } - request.virtual = (void __user *)virtual; + request->virtual = (void __user *)virtual; for (i = 0; i < dma->buf_count; i++) { - if (copy_to_user(&request.list[i].idx, + if (copy_to_user(&request->list[i].idx, &dma->buflist[i]->idx, - sizeof(request.list[0].idx))) { + sizeof(request->list[0].idx))) { retcode = -EFAULT; goto done; } - if (copy_to_user(&request.list[i].total, + if (copy_to_user(&request->list[i].total, &dma->buflist[i]->total, - sizeof(request.list[0].total))) { + sizeof(request->list[0].total))) { retcode = -EFAULT; goto done; } - if (copy_to_user(&request.list[i].used, + if (copy_to_user(&request->list[i].used, &zero, sizeof(zero))) { retcode = -EFAULT; goto done; } address = virtual + dma->buflist[i]->offset; /* *** */ - if (copy_to_user(&request.list[i].address, + if (copy_to_user(&request->list[i].address, &address, sizeof(address))) { retcode = -EFAULT; goto done; @@ -1622,11 +1564,8 @@ int drm_mapbufs(struct inode *inode, struct file *filp, } } done: - request.count = dma->buf_count; - DRM_DEBUG("%d buffers, retcode = %d\n", request.count, retcode); - - if (copy_to_user(argp, &request, sizeof(request))) - return -EFAULT; + request->count = dma->buf_count; + DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode); return retcode; } diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index 61ad986baa8d..17fe69e7bfc1 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c @@ -131,7 +131,7 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev) * Get per-context SAREA. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx_priv_map structure. * \return zero on success or a negative number on failure. @@ -139,22 +139,16 @@ void drm_ctxbitmap_cleanup(struct drm_device * dev) * Gets the map from drm_device::ctx_idr with the handle specified and * returns its handle. */ -int drm_getsareactx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_getsareactx(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_ctx_priv_map __user *argp = (void __user *)arg; - struct drm_ctx_priv_map request; + struct drm_ctx_priv_map *request = data; struct drm_map *map; struct drm_map_list *_entry; - if (copy_from_user(&request, argp, sizeof(request))) - return -EFAULT; - mutex_lock(&dev->struct_mutex); - map = idr_find(&dev->ctx_idr, request.ctx_id); + map = idr_find(&dev->ctx_idr, request->ctx_id); if (!map) { mutex_unlock(&dev->struct_mutex); return -EINVAL; @@ -162,19 +156,17 @@ int drm_getsareactx(struct inode *inode, struct file *filp, mutex_unlock(&dev->struct_mutex); - request.handle = NULL; + request->handle = NULL; list_for_each_entry(_entry, &dev->maplist, head) { if (_entry->map == map) { - request.handle = + request->handle = (void *)(unsigned long)_entry->user_token; break; } } - if (request.handle == NULL) + if (request->handle == NULL) return -EINVAL; - if (copy_to_user(argp, &request, sizeof(request))) - return -EFAULT; return 0; } @@ -182,7 +174,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp, * Set per-context SAREA. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx_priv_map structure. * \return zero on success or a negative number on failure. @@ -190,24 +182,17 @@ int drm_getsareactx(struct inode *inode, struct file *filp, * Searches the mapping specified in \p arg and update the entry in * drm_device::ctx_idr with it. */ -int drm_setsareactx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_setsareactx(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_ctx_priv_map request; + struct drm_ctx_priv_map *request = data; struct drm_map *map = NULL; struct drm_map_list *r_list = NULL; - if (copy_from_user(&request, - (struct drm_ctx_priv_map __user *) arg, - sizeof(request))) - return -EFAULT; - mutex_lock(&dev->struct_mutex); list_for_each_entry(r_list, &dev->maplist, head) { if (r_list->map - && r_list->user_token == (unsigned long)request.handle) + && r_list->user_token == (unsigned long) request->handle) goto found; } bad: @@ -219,10 +204,11 @@ int drm_setsareactx(struct inode *inode, struct file *filp, if (!map) goto bad; - if (IS_ERR(idr_replace(&dev->ctx_idr, map, request.ctx_id))) + if (IS_ERR(idr_replace(&dev->ctx_idr, map, request->ctx_id))) goto bad; mutex_unlock(&dev->struct_mutex); + return 0; } @@ -292,34 +278,28 @@ static int drm_context_switch_complete(struct drm_device * dev, int new) * Reserve contexts. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx_res structure. * \return zero on success or a negative number on failure. */ -int drm_resctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_resctx(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_ctx_res res; - struct drm_ctx_res __user *argp = (void __user *)arg; + struct drm_ctx_res *res = data; struct drm_ctx ctx; int i; - if (copy_from_user(&res, argp, sizeof(res))) - return -EFAULT; - - if (res.count >= DRM_RESERVED_CONTEXTS) { + if (res->count >= DRM_RESERVED_CONTEXTS) { memset(&ctx, 0, sizeof(ctx)); for (i = 0; i < DRM_RESERVED_CONTEXTS; i++) { ctx.handle = i; - if (copy_to_user(&res.contexts[i], &ctx, sizeof(ctx))) + if (copy_to_user(&res->contexts[i], &ctx, sizeof(ctx))) return -EFAULT; } } - res.count = DRM_RESERVED_CONTEXTS; + res->count = DRM_RESERVED_CONTEXTS; - if (copy_to_user(argp, &res, sizeof(res))) - return -EFAULT; return 0; } @@ -327,40 +307,34 @@ int drm_resctx(struct inode *inode, struct file *filp, * Add context. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Get a new handle for the context and copy to userspace. */ -int drm_addctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_addctx(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; struct drm_ctx_list *ctx_entry; - struct drm_ctx __user *argp = (void __user *)arg; - struct drm_ctx ctx; - - if (copy_from_user(&ctx, argp, sizeof(ctx))) - return -EFAULT; + struct drm_ctx *ctx = data; - ctx.handle = drm_ctxbitmap_next(dev); - if (ctx.handle == DRM_KERNEL_CONTEXT) { + ctx->handle = drm_ctxbitmap_next(dev); + if (ctx->handle == DRM_KERNEL_CONTEXT) { /* Skip kernel's context and get a new one. */ - ctx.handle = drm_ctxbitmap_next(dev); + ctx->handle = drm_ctxbitmap_next(dev); } - DRM_DEBUG("%d\n", ctx.handle); - if (ctx.handle == -1) { + DRM_DEBUG("%d\n", ctx->handle); + if (ctx->handle == -1) { DRM_DEBUG("Not enough free contexts.\n"); /* Should this return -EBUSY instead? */ return -ENOMEM; } - if (ctx.handle != DRM_KERNEL_CONTEXT) { + if (ctx->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_ctor) - if (!dev->driver->context_ctor(dev, ctx.handle)) { + if (!dev->driver->context_ctor(dev, ctx->handle)) { DRM_DEBUG("Running out of ctxs or memory.\n"); return -ENOMEM; } @@ -373,21 +347,18 @@ int drm_addctx(struct inode *inode, struct file *filp, } INIT_LIST_HEAD(&ctx_entry->head); - ctx_entry->handle = ctx.handle; - ctx_entry->tag = priv; + ctx_entry->handle = ctx->handle; + ctx_entry->tag = file_priv; mutex_lock(&dev->ctxlist_mutex); list_add(&ctx_entry->head, &dev->ctxlist); ++dev->ctx_count; mutex_unlock(&dev->ctxlist_mutex); - if (copy_to_user(argp, &ctx, sizeof(ctx))) - return -EFAULT; return 0; } -int drm_modctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { /* This does nothing */ return 0; @@ -397,25 +368,18 @@ int drm_modctx(struct inode *inode, struct file *filp, * Get context. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. */ -int drm_getctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_ctx __user *argp = (void __user *)arg; - struct drm_ctx ctx; - - if (copy_from_user(&ctx, argp, sizeof(ctx))) - return -EFAULT; + struct drm_ctx *ctx = data; /* This is 0, because we don't handle any context flags */ - ctx.flags = 0; + ctx->flags = 0; - if (copy_to_user(argp, &ctx, sizeof(ctx))) - return -EFAULT; return 0; } @@ -423,50 +387,40 @@ int drm_getctx(struct inode *inode, struct file *filp, * Switch context. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Calls context_switch(). */ -int drm_switchctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_switchctx(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_ctx ctx; + struct drm_ctx *ctx = data; - if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx))) - return -EFAULT; - - DRM_DEBUG("%d\n", ctx.handle); - return drm_context_switch(dev, dev->last_context, ctx.handle); + DRM_DEBUG("%d\n", ctx->handle); + return drm_context_switch(dev, dev->last_context, ctx->handle); } /** * New context. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * Calls context_switch_complete(). */ -int drm_newctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_newctx(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_ctx ctx; + struct drm_ctx *ctx = data; - if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx))) - return -EFAULT; - - DRM_DEBUG("%d\n", ctx.handle); - drm_context_switch_complete(dev, ctx.handle); + DRM_DEBUG("%d\n", ctx->handle); + drm_context_switch_complete(dev, ctx->handle); return 0; } @@ -475,31 +429,26 @@ int drm_newctx(struct inode *inode, struct file *filp, * Remove context. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument pointing to a drm_ctx structure. * \return zero on success or a negative number on failure. * * If not the special kernel context, calls ctxbitmap_free() to free the specified context. */ -int drm_rmctx(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_rmctx(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_ctx ctx; - - if (copy_from_user(&ctx, (struct drm_ctx __user *) arg, sizeof(ctx))) - return -EFAULT; + struct drm_ctx *ctx = data; - DRM_DEBUG("%d\n", ctx.handle); - if (ctx.handle == DRM_KERNEL_CONTEXT + 1) { - priv->remove_auth_on_close = 1; + DRM_DEBUG("%d\n", ctx->handle); + if (ctx->handle == DRM_KERNEL_CONTEXT + 1) { + file_priv->remove_auth_on_close = 1; } - if (ctx.handle != DRM_KERNEL_CONTEXT) { + if (ctx->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_dtor) - dev->driver->context_dtor(dev, ctx.handle); - drm_ctxbitmap_free(dev, ctx.handle); + dev->driver->context_dtor(dev, ctx->handle); + drm_ctxbitmap_free(dev, ctx->handle); } mutex_lock(&dev->ctxlist_mutex); @@ -507,7 +456,7 @@ int drm_rmctx(struct inode *inode, struct file *filp, struct drm_ctx_list *pos, *n; list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { - if (pos->handle == ctx.handle) { + if (pos->handle == ctx->handle) { list_del(&pos->head); drm_free(pos, sizeof(*pos), DRM_MEM_CTXLIST); --dev->ctx_count; diff --git a/drivers/char/drm/drm_dma.c b/drivers/char/drm/drm_dma.c index 802fbdbfe1b3..7a8e2fba4678 100644 --- a/drivers/char/drm/drm_dma.c +++ b/drivers/char/drm/drm_dma.c @@ -136,7 +136,7 @@ void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf) buf->waiting = 0; buf->pending = 0; - buf->filp = NULL; + buf->file_priv = NULL; buf->used = 0; if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) @@ -148,11 +148,12 @@ void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf) /** * Reclaim the buffers. * - * \param filp file pointer. + * \param file_priv DRM file private. * - * Frees each buffer associated with \p filp not already on the hardware. + * Frees each buffer associated with \p file_priv not already on the hardware. */ -void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp) +void drm_core_reclaim_buffers(struct drm_device *dev, + struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; int i; @@ -160,7 +161,7 @@ void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp) if (!dma) return; for (i = 0; i < dma->buf_count; i++) { - if (dma->buflist[i]->filp == filp) { + if (dma->buflist[i]->file_priv == file_priv) { switch (dma->buflist[i]->list) { case DRM_LIST_NONE: drm_free_buffer(dev, dma->buflist[i]); diff --git a/drivers/char/drm/drm_drawable.c b/drivers/char/drm/drm_drawable.c index d6cdba5644e2..1839c57663c5 100644 --- a/drivers/char/drm/drm_drawable.c +++ b/drivers/char/drm/drm_drawable.c @@ -40,11 +40,10 @@ /** * Allocate drawable ID and memory to store information about it. */ -int drm_adddraw(DRM_IOCTL_ARGS) +int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; unsigned long irqflags; - struct drm_draw draw; + struct drm_draw *draw = data; int new_id = 0; int ret; @@ -63,11 +62,9 @@ again: spin_unlock_irqrestore(&dev->drw_lock, irqflags); - draw.handle = new_id; + draw->handle = new_id; - DRM_DEBUG("%d\n", draw.handle); - - DRM_COPY_TO_USER_IOCTL((struct drm_draw __user *)data, draw, sizeof(draw)); + DRM_DEBUG("%d\n", draw->handle); return 0; } @@ -75,72 +72,64 @@ again: /** * Free drawable ID and memory to store information about it. */ -int drm_rmdraw(DRM_IOCTL_ARGS) +int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - struct drm_draw draw; + struct drm_draw *draw = data; unsigned long irqflags; - DRM_COPY_FROM_USER_IOCTL(draw, (struct drm_draw __user *) data, - sizeof(draw)); - spin_lock_irqsave(&dev->drw_lock, irqflags); - drm_free(drm_get_drawable_info(dev, draw.handle), + drm_free(drm_get_drawable_info(dev, draw->handle), sizeof(struct drm_drawable_info), DRM_MEM_BUFS); - idr_remove(&dev->drw_idr, draw.handle); + idr_remove(&dev->drw_idr, draw->handle); spin_unlock_irqrestore(&dev->drw_lock, irqflags); - DRM_DEBUG("%d\n", draw.handle); + DRM_DEBUG("%d\n", draw->handle); return 0; } -int drm_update_drawable_info(DRM_IOCTL_ARGS) +int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - struct drm_update_draw update; + struct drm_update_draw *update = data; unsigned long irqflags; struct drm_clip_rect *rects; struct drm_drawable_info *info; int err; - DRM_COPY_FROM_USER_IOCTL(update, (struct drm_update_draw __user *) data, - sizeof(update)); - - info = idr_find(&dev->drw_idr, update.handle); + info = idr_find(&dev->drw_idr, update->handle); if (!info) { info = drm_calloc(1, sizeof(*info), DRM_MEM_BUFS); if (!info) return -ENOMEM; - if (IS_ERR(idr_replace(&dev->drw_idr, info, update.handle))) { - DRM_ERROR("No such drawable %d\n", update.handle); + if (IS_ERR(idr_replace(&dev->drw_idr, info, update->handle))) { + DRM_ERROR("No such drawable %d\n", update->handle); drm_free(info, sizeof(*info), DRM_MEM_BUFS); return -EINVAL; } } - switch (update.type) { + switch (update->type) { case DRM_DRAWABLE_CLIPRECTS: - if (update.num != info->num_rects) { - rects = drm_alloc(update.num * sizeof(struct drm_clip_rect), + if (update->num != info->num_rects) { + rects = drm_alloc(update->num * sizeof(struct drm_clip_rect), DRM_MEM_BUFS); } else rects = info->rects; - if (update.num && !rects) { + if (update->num && !rects) { DRM_ERROR("Failed to allocate cliprect memory\n"); - err = DRM_ERR(ENOMEM); + err = -ENOMEM; goto error; } - if (update.num && DRM_COPY_FROM_USER(rects, + if (update->num && DRM_COPY_FROM_USER(rects, (struct drm_clip_rect __user *) - (unsigned long)update.data, - update.num * + (unsigned long)update->data, + update->num * sizeof(*rects))) { DRM_ERROR("Failed to copy cliprects from userspace\n"); - err = DRM_ERR(EFAULT); + err = -EFAULT; goto error; } @@ -152,23 +141,23 @@ int drm_update_drawable_info(DRM_IOCTL_ARGS) } info->rects = rects; - info->num_rects = update.num; + info->num_rects = update->num; spin_unlock_irqrestore(&dev->drw_lock, irqflags); DRM_DEBUG("Updated %d cliprects for drawable %d\n", - info->num_rects, update.handle); + info->num_rects, update->handle); break; default: - DRM_ERROR("Invalid update type %d\n", update.type); - return DRM_ERR(EINVAL); + DRM_ERROR("Invalid update type %d\n", update->type); + return -EINVAL; } return 0; error: if (rects != info->rects) - drm_free(rects, update.num * sizeof(struct drm_clip_rect), + drm_free(rects, update->num * sizeof(struct drm_clip_rect), DRM_MEM_BUFS); return err; diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c index 19994cd865de..72668b15e5ce 100644 --- a/drivers/char/drm/drm_drv.c +++ b/drivers/char/drm/drm_drv.c @@ -49,73 +49,74 @@ #include "drmP.h" #include "drm_core.h" -static int drm_version(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +static int drm_version(struct drm_device *dev, void *data, + struct drm_file *file_priv); /** Ioctl table */ -static drm_ioctl_desc_t drm_ioctls[] = { - [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = {drm_version, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = {drm_getunique, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = {drm_getmagic, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_IRQ_BUSID)] = {drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP)] = {drm_getmap, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT)] = {drm_getclient, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS)] = {drm_getstats, 0}, - [DRM_IOCTL_NR(DRM_IOCTL_SET_VERSION)] = {drm_setversion, DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE)] = {drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_BLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_UNBLOCK)] = {drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AUTH_MAGIC)] = {drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP)] = {drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP)] = {drm_rmmap_ioctl, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX)] = {drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX)] = {drm_getsareactx, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_CTX)] = {drm_addctx, DRM_AUTH|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RM_CTX)] = {drm_rmctx, DRM_AUTH|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_MOD_CTX)] = {drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_GET_CTX)] = {drm_getctx, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_SWITCH_CTX)] = {drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_NEW_CTX)] = {drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX)] = {drm_resctx, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_DRAW)] = {drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_RM_DRAW)] = {drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - - [DRM_IOCTL_NR(DRM_IOCTL_LOCK)] = {drm_lock, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_UNLOCK)] = {drm_unlock, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_FINISH)] = {drm_noop, DRM_AUTH}, - - [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS)] = {drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS)] = {drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS)] = {drm_infobufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS)] = {drm_mapbufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS)] = {drm_freebufs, DRM_AUTH}, +static struct drm_ioctl_desc drm_ioctls[] = { + DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0), + DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0), + DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0), + DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER|DRM_ROOT_ONLY), + + DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_BLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_UNBLOCK, drm_noop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AUTH_MAGIC, drm_authmagic, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + + DRM_IOCTL_DEF(DRM_IOCTL_ADD_MAP, drm_addmap_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RM_MAP, drm_rmmap_ioctl, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_SET_SAREA_CTX, drm_setsareactx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_GET_SAREA_CTX, drm_getsareactx, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_ADD_CTX, drm_addctx, DRM_AUTH|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RM_CTX, drm_rmctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MOD_CTX, drm_modctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_GET_CTX, drm_getctx, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_SWITCH_CTX, drm_switchctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_NEW_CTX, drm_newctx, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RES_CTX, drm_resctx, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_ADD_DRAW, drm_adddraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_RM_DRAW, drm_rmdraw, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + + DRM_IOCTL_DEF(DRM_IOCTL_LOCK, drm_lock, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_UNLOCK, drm_unlock, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_FINISH, drm_noop, DRM_AUTH), + + DRM_IOCTL_DEF(DRM_IOCTL_ADD_BUFS, drm_addbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_MARK_BUFS, drm_markbufs, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_INFO_BUFS, drm_infobufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_MAP_BUFS, drm_mapbufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_FREE_BUFS, drm_freebufs, DRM_AUTH), /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ - [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH}, + DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH), - [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), #if __OS_HAS_AGP - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ACQUIRE)] = {drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_RELEASE)] = {drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE)] = {drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO)] = {drm_agp_info_ioctl, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC)] = {drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE)] = {drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND)] = {drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND)] = {drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_INFO, drm_agp_info_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_ALLOC, drm_agp_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_FREE, drm_agp_free_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_BIND, drm_agp_bind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_AGP_UNBIND, drm_agp_unbind_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), #endif - [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC)] = {drm_sg_alloc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE)] = {drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + DRM_IOCTL_DEF(DRM_IOCTL_SG_ALLOC, drm_sg_alloc_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_IOCTL_SG_FREE, drm_sg_free, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, + DRM_IOCTL_DEF(DRM_IOCTL_WAIT_VBLANK, drm_wait_vblank, 0), - [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, + DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) @@ -224,7 +225,7 @@ int drm_lastclose(struct drm_device * dev) if (dev->lock.hw_lock) { dev->sigdata.lock = dev->lock.hw_lock = NULL; /* SHM removed */ - dev->lock.filp = NULL; + dev->lock.file_priv = NULL; wake_up_interruptible(&dev->lock.lock_queue); } mutex_unlock(&dev->struct_mutex); @@ -418,27 +419,19 @@ module_exit(drm_core_exit); * * Fills in the version information in \p arg. */ -static int drm_version(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int drm_version(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_version __user *argp = (void __user *)arg; - struct drm_version version; + struct drm_version *version = data; int len; - if (copy_from_user(&version, argp, sizeof(version))) - return -EFAULT; + version->version_major = dev->driver->major; + version->version_minor = dev->driver->minor; + version->version_patchlevel = dev->driver->patchlevel; + DRM_COPY(version->name, dev->driver->name); + DRM_COPY(version->date, dev->driver->date); + DRM_COPY(version->desc, dev->driver->desc); - version.version_major = dev->driver->major; - version.version_minor = dev->driver->minor; - version.version_patchlevel = dev->driver->patchlevel; - DRM_COPY(version.name, dev->driver->name); - DRM_COPY(version.date, dev->driver->date); - DRM_COPY(version.desc, dev->driver->desc); - - if (copy_to_user(argp, &version, sizeof(version))) - return -EFAULT; return 0; } @@ -446,7 +439,7 @@ static int drm_version(struct inode *inode, struct file *filp, * Called whenever a process performs an ioctl on /dev/drm. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument. * \return zero on success or negative number on failure. @@ -457,21 +450,22 @@ static int drm_version(struct inode *inode, struct file *filp, int drm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - drm_ioctl_desc_t *ioctl; + struct drm_file *file_priv = filp->private_data; + struct drm_device *dev = file_priv->head->dev; + struct drm_ioctl_desc *ioctl; drm_ioctl_t *func; unsigned int nr = DRM_IOCTL_NR(cmd); int retcode = -EINVAL; + char *kdata = NULL; atomic_inc(&dev->ioctl_count); atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); - ++priv->ioctl_count; + ++file_priv->ioctl_count; DRM_DEBUG("pid=%d, cmd=0x%02x, nr=0x%02x, dev 0x%lx, auth=%d\n", current->pid, cmd, nr, - (long)old_encode_dev(priv->head->device), - priv->authenticated); + (long)old_encode_dev(file_priv->head->device), + file_priv->authenticated); if ((nr >= DRM_CORE_IOCTL_COUNT) && ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) @@ -489,18 +483,40 @@ int drm_ioctl(struct inode *inode, struct file *filp, if ((nr == DRM_IOCTL_NR(DRM_IOCTL_DMA)) && dev->driver->dma_ioctl) func = dev->driver->dma_ioctl; + if (!func) { DRM_DEBUG("no function\n"); retcode = -EINVAL; } else if (((ioctl->flags & DRM_ROOT_ONLY) && !capable(CAP_SYS_ADMIN)) || - ((ioctl->flags & DRM_AUTH) && !priv->authenticated) || - ((ioctl->flags & DRM_MASTER) && !priv->master)) { + ((ioctl->flags & DRM_AUTH) && !file_priv->authenticated) || + ((ioctl->flags & DRM_MASTER) && !file_priv->master)) { retcode = -EACCES; } else { - retcode = func(inode, filp, cmd, arg); + if (cmd & (IOC_IN | IOC_OUT)) { + kdata = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL); + if (!kdata) + return -ENOMEM; + } + + if (cmd & IOC_IN) { + if (copy_from_user(kdata, (void __user *)arg, + _IOC_SIZE(cmd)) != 0) { + retcode = -EACCES; + goto err_i1; + } + } + retcode = func(dev, kdata, file_priv); + + if (cmd & IOC_OUT) { + if (copy_to_user((void __user *)arg, kdata, + _IOC_SIZE(cmd)) != 0) + retcode = -EACCES; + } } err_i1: + if (kdata) + kfree(kdata); atomic_dec(&dev->ioctl_count); if (retcode) DRM_DEBUG("ret = %x\n", retcode); diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c index 7bc51bac450d..f383fc37190c 100644 --- a/drivers/char/drm/drm_fops.c +++ b/drivers/char/drm/drm_fops.c @@ -242,6 +242,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, memset(priv, 0, sizeof(*priv)); filp->private_data = priv; + priv->filp = filp; priv->uid = current->euid; priv->pid = current->pid; priv->minor = minor; @@ -312,7 +313,7 @@ EXPORT_SYMBOL(drm_fasync); * Release file. * * \param inode device inode - * \param filp file pointer. + * \param file_priv DRM file private. * \return zero on success or a negative number on failure. * * If the hardware lock is held then free it, and take it again for the kernel @@ -322,29 +323,28 @@ EXPORT_SYMBOL(drm_fasync); */ int drm_release(struct inode *inode, struct file *filp) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev; + struct drm_file *file_priv = filp->private_data; + struct drm_device *dev = file_priv->head->dev; int retcode = 0; lock_kernel(); - dev = priv->head->dev; DRM_DEBUG("open_count = %d\n", dev->open_count); if (dev->driver->preclose) - dev->driver->preclose(dev, filp); + dev->driver->preclose(dev, file_priv); /* ======================================================== * Begin inline drm_release */ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", - current->pid, (long)old_encode_dev(priv->head->device), + current->pid, (long)old_encode_dev(file_priv->head->device), dev->open_count); if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { - if (drm_i_have_hw_lock(filp)) { - dev->driver->reclaim_buffers_locked(dev, filp); + if (drm_i_have_hw_lock(dev, file_priv)) { + dev->driver->reclaim_buffers_locked(dev, file_priv); } else { unsigned long _end=jiffies + 3*DRM_HZ; int locked = 0; @@ -370,7 +370,7 @@ int drm_release(struct inode *inode, struct file *filp) "\tI will go on reclaiming the buffers anyway.\n"); } - dev->driver->reclaim_buffers_locked(dev, filp); + dev->driver->reclaim_buffers_locked(dev, file_priv); drm_idlelock_release(&dev->lock); } } @@ -378,12 +378,12 @@ int drm_release(struct inode *inode, struct file *filp) if (dev->driver->reclaim_buffers_idlelocked && dev->lock.hw_lock) { drm_idlelock_take(&dev->lock); - dev->driver->reclaim_buffers_idlelocked(dev, filp); + dev->driver->reclaim_buffers_idlelocked(dev, file_priv); drm_idlelock_release(&dev->lock); } - if (drm_i_have_hw_lock(filp)) { + if (drm_i_have_hw_lock(dev, file_priv)) { DRM_DEBUG("File %p released, freeing lock for context %d\n", filp, _DRM_LOCKING_CONTEXT(dev->lock.hw_lock->lock)); @@ -394,7 +394,7 @@ int drm_release(struct inode *inode, struct file *filp) if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !dev->driver->reclaim_buffers_locked) { - dev->driver->reclaim_buffers(dev, filp); + dev->driver->reclaim_buffers(dev, file_priv); } drm_fasync(-1, filp, 0); @@ -404,7 +404,7 @@ int drm_release(struct inode *inode, struct file *filp) struct drm_ctx_list *pos, *n; list_for_each_entry_safe(pos, n, &dev->ctxlist, head) { - if (pos->tag == priv && + if (pos->tag == file_priv && pos->handle != DRM_KERNEL_CONTEXT) { if (dev->driver->context_dtor) dev->driver->context_dtor(dev, @@ -421,18 +421,18 @@ int drm_release(struct inode *inode, struct file *filp) mutex_unlock(&dev->ctxlist_mutex); mutex_lock(&dev->struct_mutex); - if (priv->remove_auth_on_close == 1) { + if (file_priv->remove_auth_on_close == 1) { struct drm_file *temp; list_for_each_entry(temp, &dev->filelist, lhead) temp->authenticated = 0; } - list_del(&priv->lhead); + list_del(&file_priv->lhead); mutex_unlock(&dev->struct_mutex); if (dev->driver->postclose) - dev->driver->postclose(dev, priv); - drm_free(priv, sizeof(*priv), DRM_MEM_FILES); + dev->driver->postclose(dev, file_priv); + drm_free(file_priv, sizeof(*file_priv), DRM_MEM_FILES); /* ======================================================== * End inline drm_release diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c index 462f46f2049a..2286f3312c5c 100644 --- a/drivers/char/drm/drm_ioc32.c +++ b/drivers/char/drm/drm_ioc32.c @@ -1040,7 +1040,7 @@ drm_ioctl_compat_t *drm_compat_ioctls[] = { * Called whenever a 32-bit process running under a 64-bit kernel * performs an ioctl on /dev/drm. * - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument. * \return zero on success or negative number on failure. diff --git a/drivers/char/drm/drm_ioctl.c b/drivers/char/drm/drm_ioctl.c index b195e102e737..d9be14624526 100644 --- a/drivers/char/drm/drm_ioctl.c +++ b/drivers/char/drm/drm_ioctl.c @@ -42,30 +42,24 @@ * Get the bus id. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_unique structure. * \return zero on success or a negative number on failure. * * Copies the bus id from drm_device::unique into user space. */ -int drm_getunique(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_getunique(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_unique __user *argp = (void __user *)arg; - struct drm_unique u; + struct drm_unique *u = data; - if (copy_from_user(&u, argp, sizeof(u))) - return -EFAULT; - if (u.unique_len >= dev->unique_len) { - if (copy_to_user(u.unique, dev->unique, dev->unique_len)) + if (u->unique_len >= dev->unique_len) { + if (copy_to_user(u->unique, dev->unique, dev->unique_len)) return -EFAULT; } - u.unique_len = dev->unique_len; - if (copy_to_user(argp, &u, sizeof(u))) - return -EFAULT; + u->unique_len = dev->unique_len; + return 0; } @@ -73,7 +67,7 @@ int drm_getunique(struct inode *inode, struct file *filp, * Set the bus id. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_unique structure. * \return zero on success or a negative number on failure. @@ -83,28 +77,23 @@ int drm_getunique(struct inode *inode, struct file *filp, * in interface version 1.1 and will return EBUSY when setversion has requested * version 1.1 or greater. */ -int drm_setunique(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_setunique(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_unique u; + struct drm_unique *u = data; int domain, bus, slot, func, ret; if (dev->unique_len || dev->unique) return -EBUSY; - if (copy_from_user(&u, (struct drm_unique __user *) arg, sizeof(u))) - return -EFAULT; - - if (!u.unique_len || u.unique_len > 1024) + if (!u->unique_len || u->unique_len > 1024) return -EINVAL; - dev->unique_len = u.unique_len; - dev->unique = drm_alloc(u.unique_len + 1, DRM_MEM_DRIVER); + dev->unique_len = u->unique_len; + dev->unique = drm_alloc(u->unique_len + 1, DRM_MEM_DRIVER); if (!dev->unique) return -ENOMEM; - if (copy_from_user(dev->unique, u.unique, dev->unique_len)) + if (copy_from_user(dev->unique, u->unique, dev->unique_len)) return -EFAULT; dev->unique[dev->unique_len] = '\0'; @@ -123,7 +112,7 @@ int drm_setunique(struct inode *inode, struct file *filp, */ ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func); if (ret != 3) - return DRM_ERR(EINVAL); + return -EINVAL; domain = bus >> 8; bus &= 0xff; @@ -172,7 +161,7 @@ static int drm_set_busid(struct drm_device * dev) * Get a mapping information. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_map structure. * @@ -181,21 +170,16 @@ static int drm_set_busid(struct drm_device * dev) * Searches for the mapping with the specified offset and copies its information * into userspace */ -int drm_getmap(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_getmap(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_map __user *argp = (void __user *)arg; - struct drm_map map; + struct drm_map *map = data; struct drm_map_list *r_list = NULL; struct list_head *list; int idx; int i; - if (copy_from_user(&map, argp, sizeof(map))) - return -EFAULT; - idx = map.offset; + idx = map->offset; mutex_lock(&dev->struct_mutex); if (idx < 0) { @@ -216,16 +200,14 @@ int drm_getmap(struct inode *inode, struct file *filp, return -EINVAL; } - map.offset = r_list->map->offset; - map.size = r_list->map->size; - map.type = r_list->map->type; - map.flags = r_list->map->flags; - map.handle = (void *)(unsigned long)r_list->user_token; - map.mtrr = r_list->map->mtrr; + map->offset = r_list->map->offset; + map->size = r_list->map->size; + map->type = r_list->map->type; + map->flags = r_list->map->flags; + map->handle = (void *)(unsigned long) r_list->user_token; + map->mtrr = r_list->map->mtrr; mutex_unlock(&dev->struct_mutex); - if (copy_to_user(argp, &map, sizeof(map))) - return -EFAULT; return 0; } @@ -233,7 +215,7 @@ int drm_getmap(struct inode *inode, struct file *filp, * Get client information. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_client structure. * @@ -242,20 +224,15 @@ int drm_getmap(struct inode *inode, struct file *filp, * Searches for the client with the specified index and copies its information * into userspace */ -int drm_getclient(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_getclient(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_client __user *argp = (struct drm_client __user *)arg; - struct drm_client client; + struct drm_client *client = data; struct drm_file *pt; int idx; int i; - if (copy_from_user(&client, argp, sizeof(client))) - return -EFAULT; - idx = client.idx; + idx = client->idx; mutex_lock(&dev->struct_mutex); if (list_empty(&dev->filelist)) { @@ -269,15 +246,13 @@ int drm_getclient(struct inode *inode, struct file *filp, break; } - client.auth = pt->authenticated; - client.pid = pt->pid; - client.uid = pt->uid; - client.magic = pt->magic; - client.iocs = pt->ioctl_count; + client->auth = pt->authenticated; + client->pid = pt->pid; + client->uid = pt->uid; + client->magic = pt->magic; + client->iocs = pt->ioctl_count; mutex_unlock(&dev->struct_mutex); - if (copy_to_user(argp, &client, sizeof(client))) - return -EFAULT; return 0; } @@ -285,39 +260,35 @@ int drm_getclient(struct inode *inode, struct file *filp, * Get statistics information. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_stats structure. * * \return zero on success or a negative number on failure. */ -int drm_getstats(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_getstats(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_stats stats; + struct drm_stats *stats = data; int i; - memset(&stats, 0, sizeof(stats)); + memset(stats, 0, sizeof(stats)); mutex_lock(&dev->struct_mutex); for (i = 0; i < dev->counters; i++) { if (dev->types[i] == _DRM_STAT_LOCK) - stats.data[i].value - = (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0); + stats->data[i].value = + (dev->lock.hw_lock ? dev->lock.hw_lock->lock : 0); else - stats.data[i].value = atomic_read(&dev->counts[i]); - stats.data[i].type = dev->types[i]; + stats->data[i].value = atomic_read(&dev->counts[i]); + stats->data[i].type = dev->types[i]; } - stats.count = dev->counters; + stats->count = dev->counters; mutex_unlock(&dev->struct_mutex); - if (copy_to_user((struct drm_stats __user *) arg, &stats, sizeof(stats))) - return -EFAULT; return 0; } @@ -325,64 +296,59 @@ int drm_getstats(struct inode *inode, struct file *filp, * Setversion ioctl. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_lock structure. * \return zero on success or negative number on failure. * * Sets the requested interface version */ -int drm_setversion(DRM_IOCTL_ARGS) +int drm_setversion(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - struct drm_set_version sv; - struct drm_set_version retv; - int if_version; - struct drm_set_version __user *argp = (void __user *)data; - int ret; - - if (copy_from_user(&sv, argp, sizeof(sv))) - return -EFAULT; - - retv.drm_di_major = DRM_IF_MAJOR; - retv.drm_di_minor = DRM_IF_MINOR; - retv.drm_dd_major = dev->driver->major; - retv.drm_dd_minor = dev->driver->minor; - - if (copy_to_user(argp, &retv, sizeof(retv))) - return -EFAULT; - - if (sv.drm_di_major != -1) { - if (sv.drm_di_major != DRM_IF_MAJOR || - sv.drm_di_minor < 0 || sv.drm_di_minor > DRM_IF_MINOR) - return -EINVAL; - if_version = DRM_IF_VERSION(sv.drm_di_major, sv.drm_di_minor); + struct drm_set_version *sv = data; + int if_version, retcode = 0; + + if (sv->drm_di_major != -1) { + if (sv->drm_di_major != DRM_IF_MAJOR || + sv->drm_di_minor < 0 || sv->drm_di_minor > DRM_IF_MINOR) { + retcode = -EINVAL; + goto done; + } + if_version = DRM_IF_VERSION(sv->drm_di_major, + sv->drm_di_minor); dev->if_version = max(if_version, dev->if_version); - if (sv.drm_di_minor >= 1) { + if (sv->drm_di_minor >= 1) { /* * Version 1.1 includes tying of DRM to specific device */ - ret = drm_set_busid(dev); - if (ret) - return ret; + drm_set_busid(dev); } } - if (sv.drm_dd_major != -1) { - if (sv.drm_dd_major != dev->driver->major || - sv.drm_dd_minor < 0 - || sv.drm_dd_minor > dev->driver->minor) - return -EINVAL; + if (sv->drm_dd_major != -1) { + if (sv->drm_dd_major != dev->driver->major || + sv->drm_dd_minor < 0 || sv->drm_dd_minor > + dev->driver->minor) { + retcode = -EINVAL; + goto done; + } if (dev->driver->set_version) - dev->driver->set_version(dev, &sv); + dev->driver->set_version(dev, sv); } - return 0; + +done: + sv->drm_di_major = DRM_IF_MAJOR; + sv->drm_di_minor = DRM_IF_MINOR; + sv->drm_dd_major = dev->driver->major; + sv->drm_dd_minor = dev->driver->minor; + + return retcode; } /** No-op ioctl. */ -int drm_noop(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int drm_noop(struct drm_device *dev, void *data, + struct drm_file *file_priv) { DRM_DEBUG("\n"); return 0; diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c index 871d2fde09b3..05eae63f85ba 100644 --- a/drivers/char/drm/drm_irq.c +++ b/drivers/char/drm/drm_irq.c @@ -41,7 +41,7 @@ * Get interrupt from bus id. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_irq_busid structure. * \return zero on success or a negative number on failure. @@ -50,30 +50,24 @@ * This IOCTL is deprecated, and will now return EINVAL for any busid not equal * to that of the device that this DRM instance attached to. */ -int drm_irq_by_busid(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_irq_by_busid(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_irq_busid __user *argp = (void __user *)arg; - struct drm_irq_busid p; + struct drm_irq_busid *p = data; if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; - if (copy_from_user(&p, argp, sizeof(p))) - return -EFAULT; - - if ((p.busnum >> 8) != drm_get_pci_domain(dev) || - (p.busnum & 0xff) != dev->pdev->bus->number || - p.devnum != PCI_SLOT(dev->pdev->devfn) || p.funcnum != PCI_FUNC(dev->pdev->devfn)) + if ((p->busnum >> 8) != drm_get_pci_domain(dev) || + (p->busnum & 0xff) != dev->pdev->bus->number || + p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn)) return -EINVAL; - p.irq = dev->irq; + p->irq = dev->irq; + + DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum, + p->irq); - DRM_DEBUG("%d:%d:%d => IRQ %d\n", p.busnum, p.devnum, p.funcnum, p.irq); - if (copy_to_user(argp, &p, sizeof(p))) - return -EFAULT; return 0; } @@ -187,31 +181,27 @@ EXPORT_SYMBOL(drm_irq_uninstall); * IRQ control ioctl. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_control structure. * \return zero on success or a negative number on failure. * * Calls irq_install() or irq_uninstall() according to \p arg. */ -int drm_control(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_control(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_control ctl; + struct drm_control *ctl = data; /* if we haven't irq we fallback for compatibility reasons - this used to be a separate function in drm_dma.h */ - if (copy_from_user(&ctl, (struct drm_control __user *) arg, sizeof(ctl))) - return -EFAULT; - switch (ctl.func) { + switch (ctl->func) { case DRM_INST_HANDLER: if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return 0; if (dev->if_version < DRM_IF_VERSION(1, 2) && - ctl.irq != dev->irq) + ctl->irq != dev->irq) return -EINVAL; return drm_irq_install(dev); case DRM_UNINST_HANDLER: @@ -227,7 +217,7 @@ int drm_control(struct inode *inode, struct file *filp, * Wait for VBLANK. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param data user argument, pointing to a drm_wait_vblank structure. * \return zero on success or a negative number on failure. @@ -242,31 +232,25 @@ int drm_control(struct inode *inode, struct file *filp, * * If a signal is not requested, then calls vblank_wait(). */ -int drm_wait_vblank(DRM_IOCTL_ARGS) +int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - union drm_wait_vblank __user *argp = (void __user *)data; - union drm_wait_vblank vblwait; + union drm_wait_vblank *vblwait = data; struct timeval now; int ret = 0; unsigned int flags, seq; - if (!dev->irq) + if ((!dev->irq) || (!dev->irq_enabled)) return -EINVAL; - if (copy_from_user(&vblwait, argp, sizeof(vblwait))) - return -EFAULT; - - if (vblwait.request.type & + if (vblwait->request.type & ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) { DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n", - vblwait.request.type, + vblwait->request.type, (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)); return -EINVAL; } - flags = vblwait.request.type & _DRM_VBLANK_FLAGS_MASK; + flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK; if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ? DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL)) @@ -275,10 +259,10 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2 : &dev->vbl_received); - switch (vblwait.request.type & _DRM_VBLANK_TYPES_MASK) { + switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) { case _DRM_VBLANK_RELATIVE: - vblwait.request.sequence += seq; - vblwait.request.type &= ~_DRM_VBLANK_RELATIVE; + vblwait->request.sequence += seq; + vblwait->request.type &= ~_DRM_VBLANK_RELATIVE; case _DRM_VBLANK_ABSOLUTE: break; default: @@ -286,8 +270,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) } if ((flags & _DRM_VBLANK_NEXTONMISS) && - (seq - vblwait.request.sequence) <= (1<<23)) { - vblwait.request.sequence = seq + 1; + (seq - vblwait->request.sequence) <= (1<<23)) { + vblwait->request.sequence = seq + 1; } if (flags & _DRM_VBLANK_SIGNAL) { @@ -303,12 +287,13 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) * that case */ list_for_each_entry(vbl_sig, vbl_sigs, head) { - if (vbl_sig->sequence == vblwait.request.sequence - && vbl_sig->info.si_signo == vblwait.request.signal + if (vbl_sig->sequence == vblwait->request.sequence + && vbl_sig->info.si_signo == + vblwait->request.signal && vbl_sig->task == current) { spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - vblwait.reply.sequence = seq; + vblwait->reply.sequence = seq; goto done; } } @@ -330,8 +315,8 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) memset((void *)vbl_sig, 0, sizeof(*vbl_sig)); - vbl_sig->sequence = vblwait.request.sequence; - vbl_sig->info.si_signo = vblwait.request.signal; + vbl_sig->sequence = vblwait->request.sequence; + vbl_sig->info.si_signo = vblwait->request.signal; vbl_sig->task = current; spin_lock_irqsave(&dev->vbl_lock, irqflags); @@ -340,25 +325,22 @@ int drm_wait_vblank(DRM_IOCTL_ARGS) spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - vblwait.reply.sequence = seq; + vblwait->reply.sequence = seq; } else { if (flags & _DRM_VBLANK_SECONDARY) { if (dev->driver->vblank_wait2) - ret = dev->driver->vblank_wait2(dev, &vblwait.request.sequence); + ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence); } else if (dev->driver->vblank_wait) ret = dev->driver->vblank_wait(dev, - &vblwait.request.sequence); + &vblwait->request.sequence); do_gettimeofday(&now); - vblwait.reply.tval_sec = now.tv_sec; - vblwait.reply.tval_usec = now.tv_usec; + vblwait->reply.tval_sec = now.tv_sec; + vblwait->reply.tval_usec = now.tv_usec; } done: - if (copy_to_user(argp, &vblwait, sizeof(vblwait))) - return -EFAULT; - return ret; } diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c index c0534b5a8b78..c6b73e744d67 100644 --- a/drivers/char/drm/drm_lock.c +++ b/drivers/char/drm/drm_lock.c @@ -41,39 +41,33 @@ static int drm_notifier(void *priv); * Lock ioctl. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_lock structure. * \return zero on success or negative number on failure. * * Add the current task to the lock wait queue, and attempt to take to lock. */ -int drm_lock(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; DECLARE_WAITQUEUE(entry, current); - struct drm_lock lock; + struct drm_lock *lock = data; int ret = 0; - ++priv->lock_count; + ++file_priv->lock_count; - if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock))) - return -EFAULT; - - if (lock.context == DRM_KERNEL_CONTEXT) { + if (lock->context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", - current->pid, lock.context); + current->pid, lock->context); return -EINVAL; } DRM_DEBUG("%d (pid %d) requests lock (0x%08x), flags = 0x%08x\n", - lock.context, current->pid, - dev->lock.hw_lock->lock, lock.flags); + lock->context, current->pid, + dev->lock.hw_lock->lock, lock->flags); if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE)) - if (lock.context < 0) + if (lock->context < 0) return -EINVAL; add_wait_queue(&dev->lock.lock_queue, &entry); @@ -87,8 +81,8 @@ int drm_lock(struct inode *inode, struct file *filp, ret = -EINTR; break; } - if (drm_lock_take(&dev->lock, lock.context)) { - dev->lock.filp = filp; + if (drm_lock_take(&dev->lock, lock->context)) { + dev->lock.file_priv = file_priv; dev->lock.lock_time = jiffies; atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); break; /* Got lock */ @@ -107,7 +101,8 @@ int drm_lock(struct inode *inode, struct file *filp, __set_current_state(TASK_RUNNING); remove_wait_queue(&dev->lock.lock_queue, &entry); - DRM_DEBUG( "%d %s\n", lock.context, ret ? "interrupted" : "has lock" ); + DRM_DEBUG("%d %s\n", lock->context, + ret ? "interrupted" : "has lock"); if (ret) return ret; sigemptyset(&dev->sigmask); @@ -115,24 +110,26 @@ int drm_lock(struct inode *inode, struct file *filp, sigaddset(&dev->sigmask, SIGTSTP); sigaddset(&dev->sigmask, SIGTTIN); sigaddset(&dev->sigmask, SIGTTOU); - dev->sigdata.context = lock.context; + dev->sigdata.context = lock->context; dev->sigdata.lock = dev->lock.hw_lock; block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); - if (dev->driver->dma_ready && (lock.flags & _DRM_LOCK_READY)) + if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY)) dev->driver->dma_ready(dev); - if (dev->driver->dma_quiescent && (lock.flags & _DRM_LOCK_QUIESCENT)) { + if (dev->driver->dma_quiescent && (lock->flags & _DRM_LOCK_QUIESCENT)) + { if (dev->driver->dma_quiescent(dev)) { - DRM_DEBUG("%d waiting for DMA quiescent\n", lock.context); - return DRM_ERR(EBUSY); + DRM_DEBUG("%d waiting for DMA quiescent\n", + lock->context); + return -EBUSY; } } if (dev->driver->kernel_context_switch && - dev->last_context != lock.context) { + dev->last_context != lock->context) { dev->driver->kernel_context_switch(dev, dev->last_context, - lock.context); + lock->context); } return 0; @@ -142,27 +139,21 @@ int drm_lock(struct inode *inode, struct file *filp, * Unlock ioctl. * * \param inode device inode. - * \param filp file pointer. + * \param file_priv DRM file private. * \param cmd command. * \param arg user argument, pointing to a drm_lock structure. * \return zero on success or negative number on failure. * * Transfer and free the lock. */ -int drm_unlock(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_lock lock; + struct drm_lock *lock = data; unsigned long irqflags; - if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock))) - return -EFAULT; - - if (lock.context == DRM_KERNEL_CONTEXT) { + if (lock->context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", - current->pid, lock.context); + current->pid, lock->context); return -EINVAL; } @@ -184,7 +175,7 @@ int drm_unlock(struct inode *inode, struct file *filp, if (dev->driver->kernel_context_switch_unlock) dev->driver->kernel_context_switch_unlock(dev); else { - if (drm_lock_free(&dev->lock,lock.context)) { + if (drm_lock_free(&dev->lock,lock->context)) { /* FIXME: Should really bail out here. */ } } @@ -257,7 +248,7 @@ static int drm_lock_transfer(struct drm_lock_data *lock_data, unsigned int old, new, prev; volatile unsigned int *lock = &lock_data->hw_lock->lock; - lock_data->filp = NULL; + lock_data->file_priv = NULL; do { old = *lock; new = context | _DRM_LOCK_HELD; @@ -390,13 +381,11 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) EXPORT_SYMBOL(drm_idlelock_release); -int drm_i_have_hw_lock(struct file *filp) +int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) { - DRM_DEVICE; - - return (priv->lock_count && dev->lock.hw_lock && + return (file_priv->lock_count && dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && - dev->lock.filp == filp); + dev->lock.file_priv == file_priv); } EXPORT_SYMBOL(drm_i_have_hw_lock); diff --git a/drivers/char/drm/drm_os_linux.h b/drivers/char/drm/drm_os_linux.h index 0b8d3433386d..114e54e0f61b 100644 --- a/drivers/char/drm/drm_os_linux.h +++ b/drivers/char/drm/drm_os_linux.h @@ -6,11 +6,6 @@ #include <linux/interrupt.h> /* For task queue support */ #include <linux/delay.h> -/** File pointer type */ -#define DRMFILE struct file * -/** Ioctl arguments */ -#define DRM_IOCTL_ARGS struct inode *inode, struct file *filp, unsigned int cmd, unsigned long data -#define DRM_ERR(d) -(d) /** Current process ID */ #define DRM_CURRENTPID current->pid #define DRM_SUSER(p) capable(CAP_SYS_ADMIN) @@ -33,9 +28,6 @@ #define DRM_WRITEMEMORYBARRIER() wmb() /** Read/write memory barrier */ #define DRM_MEMORYBARRIER() mb() -/** DRM device local declaration */ -#define DRM_DEVICE struct drm_file *priv = filp->private_data; \ - struct drm_device *dev = priv->head->dev /** IRQ handler arguments and return type and values */ #define DRM_IRQ_ARGS int irq, void *arg @@ -94,8 +86,6 @@ static __inline__ int mtrr_del(int reg, unsigned long base, unsigned long size) #define DRM_GET_USER_UNCHECKED(val, uaddr) \ __get_user(val, uaddr) -#define DRM_GET_PRIV_WITH_RETURN(_priv, _filp) _priv = _filp->private_data - #define DRM_HZ HZ #define DRM_WAIT_ON( ret, queue, timeout, condition ) \ diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h index 30b200b01314..f3593974496c 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h @@ -236,10 +236,8 @@ {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3118, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_PRO_GROUP_A}, \ {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ - {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ - {0x1106, 0x3304, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3344, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3343, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ {0x1106, 0x3230, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VIA_DX9_0}, \ diff --git a/drivers/char/drm/drm_scatter.c b/drivers/char/drm/drm_scatter.c index 067d25daaf17..eb7fa437355e 100644 --- a/drivers/char/drm/drm_scatter.c +++ b/drivers/char/drm/drm_scatter.c @@ -62,13 +62,8 @@ void drm_sg_cleanup(struct drm_sg_mem * entry) # define ScatterHandle(x) (unsigned int)(x) #endif -int drm_sg_alloc(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_scatter_gather __user *argp = (void __user *)arg; - struct drm_scatter_gather request; struct drm_sg_mem *entry; unsigned long pages, i, j; @@ -80,17 +75,13 @@ int drm_sg_alloc(struct inode *inode, struct file *filp, if (dev->sg) return -EINVAL; - if (copy_from_user(&request, argp, sizeof(request))) - return -EFAULT; - entry = drm_alloc(sizeof(*entry), DRM_MEM_SGLISTS); if (!entry) return -ENOMEM; memset(entry, 0, sizeof(*entry)); - - pages = (request.size + PAGE_SIZE - 1) / PAGE_SIZE; - DRM_DEBUG("sg size=%ld pages=%ld\n", request.size, pages); + pages = (request->size + PAGE_SIZE - 1) / PAGE_SIZE; + DRM_DEBUG("sg size=%ld pages=%ld\n", request->size, pages); entry->pages = pages; entry->pagelist = drm_alloc(pages * sizeof(*entry->pagelist), @@ -142,12 +133,7 @@ int drm_sg_alloc(struct inode *inode, struct file *filp, SetPageReserved(entry->pagelist[j]); } - request.handle = entry->handle; - - if (copy_to_user(argp, &request, sizeof(request))) { - drm_sg_cleanup(entry); - return -EFAULT; - } + request->handle = entry->handle; dev->sg = entry; @@ -197,27 +183,31 @@ int drm_sg_alloc(struct inode *inode, struct file *filp, drm_sg_cleanup(entry); return -ENOMEM; } +EXPORT_SYMBOL(drm_sg_alloc); + -int drm_sg_free(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +int drm_sg_alloc_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - struct drm_scatter_gather request; + struct drm_scatter_gather *request = data; + + return drm_sg_alloc(dev, request); + +} + +int drm_sg_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) +{ + struct drm_scatter_gather *request = data; struct drm_sg_mem *entry; if (!drm_core_check_feature(dev, DRIVER_SG)) return -EINVAL; - if (copy_from_user(&request, - (struct drm_scatter_gather __user *) arg, - sizeof(request))) - return -EFAULT; - entry = dev->sg; dev->sg = NULL; - if (!entry || entry->handle != request.handle) + if (!entry || entry->handle != request->handle) return -EINVAL; DRM_DEBUG("sg free virtual = %p\n", entry->virtual); diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c index 68e36e51ba0c..e8d50af58201 100644 --- a/drivers/char/drm/drm_vm.c +++ b/drivers/char/drm/drm_vm.c @@ -463,7 +463,7 @@ static void drm_vm_close(struct vm_area_struct *vma) /** * mmap DMA memory. * - * \param filp file pointer. + * \param file_priv DRM file private. * \param vma virtual memory area. * \return zero on success or a negative number on failure. * @@ -533,7 +533,7 @@ EXPORT_SYMBOL(drm_core_get_reg_ofs); /** * mmap DMA memory. * - * \param filp file pointer. + * \param file_priv DRM file private. * \param vma virtual memory area. * \return zero on success or a negative number on failure. * diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c index cb449999d0ef..8e841bdee6dc 100644 --- a/drivers/char/drm/i810_dma.c +++ b/drivers/char/drm/i810_dma.c @@ -120,10 +120,9 @@ static const struct file_operations i810_buffer_fops = { .fasync = drm_fasync, }; -static int i810_map_buffer(struct drm_buf * buf, struct file *filp) +static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = file_priv->head->dev; drm_i810_buf_priv_t *buf_priv = buf->dev_private; drm_i810_private_t *dev_priv = dev->dev_private; const struct file_operations *old_fops; @@ -133,14 +132,14 @@ static int i810_map_buffer(struct drm_buf * buf, struct file *filp) return -EINVAL; down_write(¤t->mm->mmap_sem); - old_fops = filp->f_op; - filp->f_op = &i810_buffer_fops; + old_fops = file_priv->filp->f_op; + file_priv->filp->f_op = &i810_buffer_fops; dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, + buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE, MAP_SHARED, buf->bus_address); dev_priv->mmap_buffer = NULL; - filp->f_op = old_fops; + file_priv->filp->f_op = old_fops; if (IS_ERR(buf_priv->virtual)) { /* Real error */ DRM_ERROR("mmap error\n"); @@ -173,7 +172,7 @@ static int i810_unmap_buffer(struct drm_buf * buf) } static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d, - struct file *filp) + struct drm_file *file_priv) { struct drm_buf *buf; drm_i810_buf_priv_t *buf_priv; @@ -186,13 +185,13 @@ static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d, return retcode; } - retcode = i810_map_buffer(buf, filp); + retcode = i810_map_buffer(buf, file_priv); if (retcode) { i810_freelist_put(dev, buf); DRM_ERROR("mapbuf failed, retcode %d\n", retcode); return retcode; } - buf->filp = filp; + buf->file_priv = file_priv; buf_priv = buf->dev_private; d->granted = 1; d->request_idx = buf->idx; @@ -380,7 +379,7 @@ static int i810_dma_initialize(struct drm_device * dev, i810_dma_cleanup(dev); DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } dev_priv->ring.virtual_start = dev_priv->ring.map.handle; @@ -430,99 +429,29 @@ static int i810_dma_initialize(struct drm_device * dev, return 0; } -/* i810 DRM version 1.1 used a smaller init structure with different - * ordering of values than is currently used (drm >= 1.2). There is - * no defined way to detect the XFree version to correct this problem, - * however by checking using this procedure we can detect the correct - * thing to do. - * - * #1 Read the Smaller init structure from user-space - * #2 Verify the overlay_physical is a valid physical address, or NULL - * If it isn't then we have a v1.1 client. Fix up params. - * If it is, then we have a 1.2 client... get the rest of the data. - */ -static int i810_dma_init_compat(drm_i810_init_t * init, unsigned long arg) +static int i810_dma_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - - /* Get v1.1 init data */ - if (copy_from_user(init, (drm_i810_pre12_init_t __user *) arg, - sizeof(drm_i810_pre12_init_t))) { - return -EFAULT; - } - - if ((!init->overlay_physical) || (init->overlay_physical > 4096)) { - - /* This is a v1.2 client, just get the v1.2 init data */ - DRM_INFO("Using POST v1.2 init.\n"); - if (copy_from_user(init, (drm_i810_init_t __user *) arg, - sizeof(drm_i810_init_t))) { - return -EFAULT; - } - } else { - - /* This is a v1.1 client, fix the params */ - DRM_INFO("Using PRE v1.2 init.\n"); - init->pitch_bits = init->h; - init->pitch = init->w; - init->h = init->overlay_physical; - init->w = init->overlay_offset; - init->overlay_physical = 0; - init->overlay_offset = 0; - } - - return 0; -} - -static int i810_dma_init(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) -{ - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i810_private_t *dev_priv; - drm_i810_init_t init; + drm_i810_init_t *init = data; int retcode = 0; - /* Get only the init func */ - if (copy_from_user - (&init, (void __user *)arg, sizeof(drm_i810_init_func_t))) - return -EFAULT; - - switch (init.func) { - case I810_INIT_DMA: - /* This case is for backward compatibility. It - * handles XFree 4.1.0 and 4.2.0, and has to - * do some parameter checking as described below. - * It will someday go away. - */ - retcode = i810_dma_init_compat(&init, arg); - if (retcode) - return retcode; - - dev_priv = drm_alloc(sizeof(drm_i810_private_t), - DRM_MEM_DRIVER); - if (dev_priv == NULL) - return -ENOMEM; - retcode = i810_dma_initialize(dev, dev_priv, &init); - break; - - default: + switch (init->func) { case I810_INIT_DMA_1_4: DRM_INFO("Using v1.4 init.\n"); - if (copy_from_user(&init, (drm_i810_init_t __user *) arg, - sizeof(drm_i810_init_t))) { - return -EFAULT; - } dev_priv = drm_alloc(sizeof(drm_i810_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return -ENOMEM; - retcode = i810_dma_initialize(dev, dev_priv, &init); + retcode = i810_dma_initialize(dev, dev_priv, init); break; case I810_CLEANUP_DMA: DRM_INFO("DMA Cleanup\n"); retcode = i810_dma_cleanup(dev); break; + default: + return -EINVAL; } return retcode; @@ -968,7 +897,8 @@ static int i810_flush_queue(struct drm_device * dev) } /* Must be called with the lock held */ -static void i810_reclaim_buffers(struct drm_device * dev, struct file *filp) +static void i810_reclaim_buffers(struct drm_device * dev, + struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; int i; @@ -986,7 +916,7 @@ static void i810_reclaim_buffers(struct drm_device * dev, struct file *filp) struct drm_buf *buf = dma->buflist[i]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; - if (buf->filp == filp && buf_priv) { + if (buf->file_priv == file_priv && buf_priv) { int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE); @@ -998,47 +928,38 @@ static void i810_reclaim_buffers(struct drm_device * dev, struct file *filp) } } -static int i810_flush_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_flush_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); i810_flush_queue(dev); return 0; } -static int i810_dma_vertex(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_dma_vertex(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; struct drm_device_dma *dma = dev->dma; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - drm_i810_vertex_t vertex; - - if (copy_from_user - (&vertex, (drm_i810_vertex_t __user *) arg, sizeof(vertex))) - return -EFAULT; + drm_i810_vertex_t *vertex = data; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); DRM_DEBUG("i810 dma vertex, idx %d used %d discard %d\n", - vertex.idx, vertex.used, vertex.discard); + vertex->idx, vertex->used, vertex->discard); - if (vertex.idx < 0 || vertex.idx > dma->buf_count) + if (vertex->idx < 0 || vertex->idx > dma->buf_count) return -EINVAL; i810_dma_dispatch_vertex(dev, - dma->buflist[vertex.idx], - vertex.discard, vertex.used); + dma->buflist[vertex->idx], + vertex->discard, vertex->used); - atomic_add(vertex.used, &dev->counts[_DRM_STAT_SECONDARY]); + atomic_add(vertex->used, &dev->counts[_DRM_STAT_SECONDARY]); atomic_inc(&dev->counts[_DRM_STAT_DMA]); sarea_priv->last_enqueue = dev_priv->counter - 1; sarea_priv->last_dispatch = (int)hw_status[5]; @@ -1046,48 +967,37 @@ static int i810_dma_vertex(struct inode *inode, struct file *filp, return 0; } -static int i810_clear_bufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_clear_bufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - drm_i810_clear_t clear; + drm_i810_clear_t *clear = data; - if (copy_from_user - (&clear, (drm_i810_clear_t __user *) arg, sizeof(clear))) - return -EFAULT; - - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); /* GH: Someone's doing nasty things... */ if (!dev->dev_private) { return -EINVAL; } - i810_dma_dispatch_clear(dev, clear.flags, - clear.clear_color, clear.clear_depth); + i810_dma_dispatch_clear(dev, clear->flags, + clear->clear_color, clear->clear_depth); return 0; } -static int i810_swap_bufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_swap_bufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - DRM_DEBUG("i810_swap_bufs\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); i810_dma_dispatch_swap(dev); return 0; } -static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +static int i810_getage(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) @@ -1097,46 +1007,39 @@ static int i810_getage(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -static int i810_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +static int i810_getbuf(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; int retcode = 0; - drm_i810_dma_t d; + drm_i810_dma_t *d = data; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - if (copy_from_user(&d, (drm_i810_dma_t __user *) arg, sizeof(d))) - return -EFAULT; - - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - d.granted = 0; + d->granted = 0; - retcode = i810_dma_get_buffer(dev, &d, filp); + retcode = i810_dma_get_buffer(dev, d, file_priv); DRM_DEBUG("i810_dma: %d returning %d, granted = %d\n", - current->pid, retcode, d.granted); + current->pid, retcode, d->granted); - if (copy_to_user((void __user *) arg, &d, sizeof(d))) - return -EFAULT; sarea_priv->last_dispatch = (int)hw_status[5]; return retcode; } -static int i810_copybuf(struct inode *inode, - struct file *filp, unsigned int cmd, unsigned long arg) +static int i810_copybuf(struct drm_device *dev, void *data, + struct drm_file *file_priv) { /* Never copy - 2.4.x doesn't need it */ return 0; } -static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +static int i810_docopy(struct drm_device *dev, void *data, + struct drm_file *file_priv) { /* Never copy - 2.4.x doesn't need it */ return 0; @@ -1202,30 +1105,25 @@ static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, ADVANCE_LP_RING(); } -static int i810_dma_mc(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_dma_mc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; struct drm_device_dma *dma = dev->dma; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) dev_priv->sarea_priv; - drm_i810_mc_t mc; - - if (copy_from_user(&mc, (drm_i810_mc_t __user *) arg, sizeof(mc))) - return -EFAULT; + drm_i810_mc_t *mc = data; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - if (mc.idx >= dma->buf_count || mc.idx < 0) + if (mc->idx >= dma->buf_count || mc->idx < 0) return -EINVAL; - i810_dma_dispatch_mc(dev, dma->buflist[mc.idx], mc.used, - mc.last_render); + i810_dma_dispatch_mc(dev, dma->buflist[mc->idx], mc->used, + mc->last_render); - atomic_add(mc.used, &dev->counts[_DRM_STAT_SECONDARY]); + atomic_add(mc->used, &dev->counts[_DRM_STAT_SECONDARY]); atomic_inc(&dev->counts[_DRM_STAT_DMA]); sarea_priv->last_enqueue = dev_priv->counter - 1; sarea_priv->last_dispatch = (int)hw_status[5]; @@ -1233,52 +1131,41 @@ static int i810_dma_mc(struct inode *inode, struct file *filp, return 0; } -static int i810_rstatus(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_rstatus(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; return (int)(((u32 *) (dev_priv->hw_status_page))[4]); } -static int i810_ov0_info(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_ov0_info(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - drm_i810_overlay_t data; + drm_i810_overlay_t *ov = data; + + ov->offset = dev_priv->overlay_offset; + ov->physical = dev_priv->overlay_physical; - data.offset = dev_priv->overlay_offset; - data.physical = dev_priv->overlay_physical; - if (copy_to_user - ((drm_i810_overlay_t __user *) arg, &data, sizeof(data))) - return -EFAULT; return 0; } -static int i810_fstatus(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_fstatus(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - LOCK_TEST_WITH_RETURN(dev, filp); - + LOCK_TEST_WITH_RETURN(dev, file_priv); return I810_READ(0x30008); } -static int i810_ov0_flip(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_ov0_flip(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i810_private_t *dev_priv = (drm_i810_private_t *) dev->dev_private; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); //Tell the overlay to update I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000); @@ -1310,16 +1197,14 @@ static int i810_do_cleanup_pageflip(struct drm_device * dev) return 0; } -static int i810_flip_bufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i810_flip_bufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i810_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv->page_flipping) i810_do_init_pageflip(dev); @@ -1345,7 +1230,7 @@ void i810_driver_lastclose(struct drm_device * dev) i810_dma_cleanup(dev); } -void i810_driver_preclose(struct drm_device * dev, DRMFILE filp) +void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { if (dev->dev_private) { drm_i810_private_t *dev_priv = dev->dev_private; @@ -1355,9 +1240,10 @@ void i810_driver_preclose(struct drm_device * dev, DRMFILE filp) } } -void i810_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) +void i810_driver_reclaim_buffers_locked(struct drm_device * dev, + struct drm_file *file_priv) { - i810_reclaim_buffers(dev, filp); + i810_reclaim_buffers(dev, file_priv); } int i810_driver_dma_quiescent(struct drm_device * dev) @@ -1366,22 +1252,22 @@ int i810_driver_dma_quiescent(struct drm_device * dev) return 0; } -drm_ioctl_desc_t i810_ioctls[] = { - [DRM_IOCTL_NR(DRM_I810_INIT)] = {i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_I810_VERTEX)] = {i810_dma_vertex, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_CLEAR)] = {i810_clear_bufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_FLUSH)] = {i810_flush_ioctl, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_GETAGE)] = {i810_getage, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_GETBUF)] = {i810_getbuf, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_SWAP)] = {i810_swap_bufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_COPY)] = {i810_copybuf, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_DOCOPY)] = {i810_docopy, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_OV0INFO)] = {i810_ov0_info, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_FSTATUS)] = {i810_fstatus, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_OV0FLIP)] = {i810_ov0_flip, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_MC)] = {i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_I810_RSTATUS)] = {i810_rstatus, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I810_FLIP)] = {i810_flip_bufs, DRM_AUTH} +struct drm_ioctl_desc i810_ioctls[] = { + DRM_IOCTL_DEF(DRM_I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_I810_VERTEX, i810_dma_vertex, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_CLEAR, i810_clear_bufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_FLUSH, i810_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_GETAGE, i810_getage, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_GETBUF, i810_getbuf, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_SWAP, i810_swap_bufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_COPY, i810_copybuf, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_DOCOPY, i810_docopy, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_OV0INFO, i810_ov0_info, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_FSTATUS, i810_fstatus, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_OV0FLIP, i810_ov0_flip, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_MC, i810_dma_mc, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_I810_RSTATUS, i810_rstatus, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I810_FLIP, i810_flip_bufs, DRM_AUTH) }; int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); diff --git a/drivers/char/drm/i810_drm.h b/drivers/char/drm/i810_drm.h index 614977dbce45..7a10bb6f2c0f 100644 --- a/drivers/char/drm/i810_drm.h +++ b/drivers/char/drm/i810_drm.h @@ -102,13 +102,8 @@ typedef enum _drm_i810_init_func { /* This is the init structure after v1.2 */ typedef struct _drm_i810_init { drm_i810_init_func_t func; -#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) - int ring_map_idx; - int buffer_map_idx; -#else unsigned int mmio_offset; unsigned int buffers_offset; -#endif int sarea_priv_offset; unsigned int ring_start; unsigned int ring_end; diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h index 648833844c7f..0af45872f67e 100644 --- a/drivers/char/drm/i810_drv.h +++ b/drivers/char/drm/i810_drv.h @@ -117,15 +117,16 @@ typedef struct drm_i810_private { /* i810_dma.c */ extern int i810_driver_dma_quiescent(struct drm_device * dev); extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev, - struct file *filp); + struct drm_file *file_priv); extern int i810_driver_load(struct drm_device *, unsigned long flags); extern void i810_driver_lastclose(struct drm_device * dev); -extern void i810_driver_preclose(struct drm_device * dev, DRMFILE filp); +extern void i810_driver_preclose(struct drm_device * dev, + struct drm_file *file_priv); extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev, - struct file *filp); + struct drm_file *file_priv); extern int i810_driver_device_is_agp(struct drm_device * dev); -extern drm_ioctl_desc_t i810_ioctls[]; +extern struct drm_ioctl_desc i810_ioctls[]; extern int i810_max_ioctl; #define I810_BASE(reg) ((unsigned long) \ diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c index dc20c1a7834e..43a1f78712d6 100644 --- a/drivers/char/drm/i830_dma.c +++ b/drivers/char/drm/i830_dma.c @@ -122,10 +122,9 @@ static const struct file_operations i830_buffer_fops = { .fasync = drm_fasync, }; -static int i830_map_buffer(struct drm_buf * buf, struct file *filp) +static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; + struct drm_device *dev = file_priv->head->dev; drm_i830_buf_priv_t *buf_priv = buf->dev_private; drm_i830_private_t *dev_priv = dev->dev_private; const struct file_operations *old_fops; @@ -136,13 +135,13 @@ static int i830_map_buffer(struct drm_buf * buf, struct file *filp) return -EINVAL; down_write(¤t->mm->mmap_sem); - old_fops = filp->f_op; - filp->f_op = &i830_buffer_fops; + old_fops = file_priv->filp->f_op; + file_priv->filp->f_op = &i830_buffer_fops; dev_priv->mmap_buffer = buf; - virtual = do_mmap(filp, 0, buf->total, PROT_READ | PROT_WRITE, + virtual = do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE, MAP_SHARED, buf->bus_address); dev_priv->mmap_buffer = NULL; - filp->f_op = old_fops; + file_priv->filp->f_op = old_fops; if (IS_ERR((void *)virtual)) { /* ugh */ /* Real error */ DRM_ERROR("mmap error\n"); @@ -177,7 +176,7 @@ static int i830_unmap_buffer(struct drm_buf * buf) } static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d, - struct file *filp) + struct drm_file *file_priv) { struct drm_buf *buf; drm_i830_buf_priv_t *buf_priv; @@ -190,13 +189,13 @@ static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d, return retcode; } - retcode = i830_map_buffer(buf, filp); + retcode = i830_map_buffer(buf, file_priv); if (retcode) { i830_freelist_put(dev, buf); DRM_ERROR("mapbuf failed, retcode %d\n", retcode); return retcode; } - buf->filp = filp; + buf->file_priv = file_priv; buf_priv = buf->dev_private; d->granted = 1; d->request_idx = buf->idx; @@ -389,7 +388,7 @@ static int i830_dma_initialize(struct drm_device * dev, i830_dma_cleanup(dev); DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } dev_priv->ring.virtual_start = dev_priv->ring.map.handle; @@ -451,25 +450,20 @@ static int i830_dma_initialize(struct drm_device * dev, return 0; } -static int i830_dma_init(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i830_dma_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i830_private_t *dev_priv; - drm_i830_init_t init; + drm_i830_init_t *init = data; int retcode = 0; - if (copy_from_user(&init, (void *__user)arg, sizeof(init))) - return -EFAULT; - - switch (init.func) { + switch (init->func) { case I830_INIT_DMA: dev_priv = drm_alloc(sizeof(drm_i830_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return -ENOMEM; - retcode = i830_dma_initialize(dev, dev_priv, &init); + retcode = i830_dma_initialize(dev, dev_priv, init); break; case I830_CLEANUP_DMA: retcode = i830_dma_cleanup(dev); @@ -1248,7 +1242,7 @@ static int i830_flush_queue(struct drm_device * dev) } /* Must be called with the lock held */ -static void i830_reclaim_buffers(struct drm_device * dev, struct file *filp) +static void i830_reclaim_buffers(struct drm_device * dev, struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; int i; @@ -1266,7 +1260,7 @@ static void i830_reclaim_buffers(struct drm_device * dev, struct file *filp) struct drm_buf *buf = dma->buflist[i]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; - if (buf->filp == filp && buf_priv) { + if (buf->file_priv == file_priv && buf_priv) { int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE); @@ -1278,45 +1272,36 @@ static void i830_reclaim_buffers(struct drm_device * dev, struct file *filp) } } -static int i830_flush_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i830_flush_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); i830_flush_queue(dev); return 0; } -static int i830_dma_vertex(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i830_dma_vertex(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; struct drm_device_dma *dma = dev->dma; drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) dev_priv->sarea_priv; - drm_i830_vertex_t vertex; - - if (copy_from_user - (&vertex, (drm_i830_vertex_t __user *) arg, sizeof(vertex))) - return -EFAULT; + drm_i830_vertex_t *vertex = data; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n", - vertex.idx, vertex.used, vertex.discard); + vertex->idx, vertex->used, vertex->discard); - if (vertex.idx < 0 || vertex.idx > dma->buf_count) + if (vertex->idx < 0 || vertex->idx > dma->buf_count) return -EINVAL; i830_dma_dispatch_vertex(dev, - dma->buflist[vertex.idx], - vertex.discard, vertex.used); + dma->buflist[vertex->idx], + vertex->discard, vertex->used); sarea_priv->last_enqueue = dev_priv->counter - 1; sarea_priv->last_dispatch = (int)hw_status[5]; @@ -1324,39 +1309,30 @@ static int i830_dma_vertex(struct inode *inode, struct file *filp, return 0; } -static int i830_clear_bufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i830_clear_bufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - drm_i830_clear_t clear; - - if (copy_from_user - (&clear, (drm_i830_clear_t __user *) arg, sizeof(clear))) - return -EFAULT; + drm_i830_clear_t *clear = data; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); /* GH: Someone's doing nasty things... */ if (!dev->dev_private) { return -EINVAL; } - i830_dma_dispatch_clear(dev, clear.flags, - clear.clear_color, - clear.clear_depth, clear.clear_depthmask); + i830_dma_dispatch_clear(dev, clear->flags, + clear->clear_color, + clear->clear_depth, clear->clear_depthmask); return 0; } -static int i830_swap_bufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i830_swap_bufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; - DRM_DEBUG("i830_swap_bufs\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); i830_dma_dispatch_swap(dev); return 0; @@ -1386,16 +1362,14 @@ static int i830_do_cleanup_pageflip(struct drm_device * dev) return 0; } -static int i830_flip_bufs(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i830_flip_bufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i830_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv->page_flipping) i830_do_init_pageflip(dev); @@ -1404,11 +1378,9 @@ static int i830_flip_bufs(struct inode *inode, struct file *filp, return 0; } -static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +static int i830_getage(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) @@ -1418,58 +1390,50 @@ static int i830_getage(struct inode *inode, struct file *filp, unsigned int cmd, return 0; } -static int i830_getbuf(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +static int i830_getbuf(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; int retcode = 0; - drm_i830_dma_t d; + drm_i830_dma_t *d = data; drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *) dev_priv->sarea_priv; DRM_DEBUG("getbuf\n"); - if (copy_from_user(&d, (drm_i830_dma_t __user *) arg, sizeof(d))) - return -EFAULT; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - d.granted = 0; + d->granted = 0; - retcode = i830_dma_get_buffer(dev, &d, filp); + retcode = i830_dma_get_buffer(dev, d, file_priv); DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n", - current->pid, retcode, d.granted); + current->pid, retcode, d->granted); - if (copy_to_user((void __user *) arg, &d, sizeof(d))) - return -EFAULT; sarea_priv->last_dispatch = (int)hw_status[5]; return retcode; } -static int i830_copybuf(struct inode *inode, - struct file *filp, unsigned int cmd, unsigned long arg) +static int i830_copybuf(struct drm_device *dev, void *data, + struct drm_file *file_priv) { /* Never copy - 2.4.x doesn't need it */ return 0; } -static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +static int i830_docopy(struct drm_device *dev, void *data, + struct drm_file *file_priv) { return 0; } -static int i830_getparam(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i830_getparam(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i830_private_t *dev_priv = dev->dev_private; - drm_i830_getparam_t param; + drm_i830_getparam_t *param = data; int value; if (!dev_priv) { @@ -1477,11 +1441,7 @@ static int i830_getparam(struct inode *inode, struct file *filp, return -EINVAL; } - if (copy_from_user - (¶m, (drm_i830_getparam_t __user *) arg, sizeof(param))) - return -EFAULT; - - switch (param.param) { + switch (param->param) { case I830_PARAM_IRQ_ACTIVE: value = dev->irq_enabled; break; @@ -1489,7 +1449,7 @@ static int i830_getparam(struct inode *inode, struct file *filp, return -EINVAL; } - if (copy_to_user(param.value, &value, sizeof(int))) { + if (copy_to_user(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } @@ -1497,26 +1457,20 @@ static int i830_getparam(struct inode *inode, struct file *filp, return 0; } -static int i830_setparam(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg) +static int i830_setparam(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i830_private_t *dev_priv = dev->dev_private; - drm_i830_setparam_t param; + drm_i830_setparam_t *param = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return -EINVAL; } - if (copy_from_user - (¶m, (drm_i830_setparam_t __user *) arg, sizeof(param))) - return -EFAULT; - - switch (param.param) { + switch (param->param) { case I830_SETPARAM_USE_MI_BATCHBUFFER_START: - dev_priv->use_mi_batchbuffer_start = param.value; + dev_priv->use_mi_batchbuffer_start = param->value; break; default: return -EINVAL; @@ -1542,7 +1496,7 @@ void i830_driver_lastclose(struct drm_device * dev) i830_dma_cleanup(dev); } -void i830_driver_preclose(struct drm_device * dev, DRMFILE filp) +void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { if (dev->dev_private) { drm_i830_private_t *dev_priv = dev->dev_private; @@ -1552,9 +1506,9 @@ void i830_driver_preclose(struct drm_device * dev, DRMFILE filp) } } -void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) +void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct drm_file *file_priv) { - i830_reclaim_buffers(dev, filp); + i830_reclaim_buffers(dev, file_priv); } int i830_driver_dma_quiescent(struct drm_device * dev) @@ -1563,21 +1517,21 @@ int i830_driver_dma_quiescent(struct drm_device * dev) return 0; } -drm_ioctl_desc_t i830_ioctls[] = { - [DRM_IOCTL_NR(DRM_I830_INIT)] = {i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_I830_VERTEX)] = {i830_dma_vertex, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_CLEAR)] = {i830_clear_bufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_FLUSH)] = {i830_flush_ioctl, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_GETAGE)] = {i830_getage, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_GETBUF)] = {i830_getbuf, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_SWAP)] = {i830_swap_bufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_COPY)] = {i830_copybuf, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_DOCOPY)] = {i830_docopy, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_FLIP)] = {i830_flip_bufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_IRQ_EMIT)] = {i830_irq_emit, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_IRQ_WAIT)] = {i830_irq_wait, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_GETPARAM)] = {i830_getparam, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I830_SETPARAM)] = {i830_setparam, DRM_AUTH} +struct drm_ioctl_desc i830_ioctls[] = { + DRM_IOCTL_DEF(DRM_I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_I830_VERTEX, i830_dma_vertex, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_CLEAR, i830_clear_bufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_FLUSH, i830_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_GETAGE, i830_getage, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_GETBUF, i830_getbuf, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_SWAP, i830_swap_bufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_COPY, i830_copybuf, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_DOCOPY, i830_docopy, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_FLIP, i830_flip_bufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_GETPARAM, i830_getparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I830_SETPARAM, i830_setparam, DRM_AUTH) }; int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h index ddda67956dea..db3a9fa83960 100644 --- a/drivers/char/drm/i830_drv.h +++ b/drivers/char/drm/i830_drv.h @@ -122,24 +122,25 @@ typedef struct drm_i830_private { } drm_i830_private_t; -extern drm_ioctl_desc_t i830_ioctls[]; +extern struct drm_ioctl_desc i830_ioctls[]; extern int i830_max_ioctl; /* i830_irq.c */ -extern int i830_irq_emit(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); -extern int i830_irq_wait(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg); +extern int i830_irq_emit(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int i830_irq_wait(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS); extern void i830_driver_irq_preinstall(struct drm_device * dev); extern void i830_driver_irq_postinstall(struct drm_device * dev); extern void i830_driver_irq_uninstall(struct drm_device * dev); extern int i830_driver_load(struct drm_device *, unsigned long flags); -extern void i830_driver_preclose(struct drm_device * dev, DRMFILE filp); +extern void i830_driver_preclose(struct drm_device * dev, + struct drm_file *file_priv); extern void i830_driver_lastclose(struct drm_device * dev); extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev, - struct file *filp); + struct drm_file *file_priv); extern int i830_driver_dma_quiescent(struct drm_device * dev); extern int i830_driver_device_is_agp(struct drm_device * dev); diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c index a1b5c63c3c3e..76403f4b6200 100644 --- a/drivers/char/drm/i830_irq.c +++ b/drivers/char/drm/i830_irq.c @@ -114,29 +114,23 @@ static int i830_wait_irq(struct drm_device * dev, int irq_nr) /* Needs the lock as it touches the ring. */ -int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i830_irq_emit(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i830_private_t *dev_priv = dev->dev_private; - drm_i830_irq_emit_t emit; + drm_i830_irq_emit_t *emit = data; int result; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return -EINVAL; } - if (copy_from_user - (&emit, (drm_i830_irq_emit_t __user *) arg, sizeof(emit))) - return -EFAULT; - result = i830_emit_irq(dev); - if (copy_to_user(emit.irq_seq, &result, sizeof(int))) { + if (copy_to_user(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); return -EFAULT; } @@ -146,24 +140,18 @@ int i830_irq_emit(struct inode *inode, struct file *filp, unsigned int cmd, /* Doesn't need the hardware lock. */ -int i830_irq_wait(struct inode *inode, struct file *filp, unsigned int cmd, - unsigned long arg) +int i830_irq_wait(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - struct drm_file *priv = filp->private_data; - struct drm_device *dev = priv->head->dev; drm_i830_private_t *dev_priv = dev->dev_private; - drm_i830_irq_wait_t irqwait; + drm_i830_irq_wait_t *irqwait = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return -EINVAL; } - if (copy_from_user(&irqwait, (drm_i830_irq_wait_t __user *) arg, - sizeof(irqwait))) - return -EFAULT; - - return i830_wait_irq(dev, irqwait.irq_seq); + return i830_wait_irq(dev, irqwait->irq_seq); } /* drm_dma.h hooks diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 8e7d713a5a15..e61a43e5b3ac 100644 --- a/drivers/char/drm/i915_dma.c +++ b/drivers/char/drm/i915_dma.c @@ -70,7 +70,7 @@ int i915_wait_ring(struct drm_device * dev, int n, const char *caller) last_head = ring->head; } - return DRM_ERR(EBUSY); + return -EBUSY; } void i915_kernel_lost_context(struct drm_device * dev) @@ -137,7 +137,7 @@ static int i915_initialize(struct drm_device * dev, DRM_ERROR("can not find sarea!\n"); dev->dev_private = (void *)dev_priv; i915_dma_cleanup(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset); @@ -145,7 +145,7 @@ static int i915_initialize(struct drm_device * dev, dev->dev_private = (void *)dev_priv; i915_dma_cleanup(dev); DRM_ERROR("can not find mmio map!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->sarea_priv = (drm_i915_sarea_t *) @@ -169,7 +169,7 @@ static int i915_initialize(struct drm_device * dev, i915_dma_cleanup(dev); DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } dev_priv->ring.virtual_start = dev_priv->ring.map.handle; @@ -200,7 +200,7 @@ static int i915_initialize(struct drm_device * dev, dev->dev_private = (void *)dev_priv; i915_dma_cleanup(dev); DRM_ERROR("Can not allocate hardware status page\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } dev_priv->hw_status_page = dev_priv->status_page_dmah->vaddr; dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr; @@ -221,24 +221,24 @@ static int i915_dma_resume(struct drm_device * dev) if (!dev_priv->sarea) { DRM_ERROR("can not find sarea!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } if (!dev_priv->mmio_map) { DRM_ERROR("can not find mmio map!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } if (dev_priv->ring.map.handle == NULL) { DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } /* Program Hardware Status Page */ if (!dev_priv->hw_status_page) { DRM_ERROR("Can not find hardware status page\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); @@ -251,23 +251,20 @@ static int i915_dma_resume(struct drm_device * dev) return 0; } -static int i915_dma_init(DRM_IOCTL_ARGS) +static int i915_dma_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv; - drm_i915_init_t init; + drm_i915_init_t *init = data; int retcode = 0; - DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data, - sizeof(init)); - - switch (init.func) { + switch (init->func) { case I915_INIT_DMA: dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) - return DRM_ERR(ENOMEM); - retcode = i915_initialize(dev, dev_priv, &init); + return -ENOMEM; + retcode = i915_initialize(dev, dev_priv, init); break; case I915_CLEANUP_DMA: retcode = i915_dma_cleanup(dev); @@ -276,7 +273,7 @@ static int i915_dma_init(DRM_IOCTL_ARGS) retcode = i915_dma_resume(dev); break; default: - retcode = DRM_ERR(EINVAL); + retcode = -EINVAL; break; } @@ -366,7 +363,7 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor RING_LOCALS; if ((dwords+1) * sizeof(int) >= dev_priv->ring.Size - 8) - return DRM_ERR(EINVAL); + return -EINVAL; BEGIN_LP_RING((dwords+1)&~1); @@ -374,17 +371,17 @@ static int i915_emit_cmds(struct drm_device * dev, int __user * buffer, int dwor int cmd, sz; if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) - return DRM_ERR(EINVAL); + return -EINVAL; if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) - return DRM_ERR(EINVAL); + return -EINVAL; OUT_RING(cmd); while (++i, --sz) { if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) { - return DRM_ERR(EINVAL); + return -EINVAL; } OUT_RING(cmd); } @@ -407,13 +404,13 @@ static int i915_emit_box(struct drm_device * dev, RING_LOCALS; if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { - return DRM_ERR(EFAULT); + return -EFAULT; } if (box.y2 <= box.y1 || box.x2 <= box.x1 || box.y2 <= 0 || box.x2 <= 0) { DRM_ERROR("Bad box %d,%d..%d,%d\n", box.x1, box.y1, box.x2, box.y2); - return DRM_ERR(EINVAL); + return -EINVAL; } if (IS_I965G(dev)) { @@ -467,7 +464,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, if (cmd->sz & 0x3) { DRM_ERROR("alignment"); - return DRM_ERR(EINVAL); + return -EINVAL; } i915_kernel_lost_context(dev); @@ -502,7 +499,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, if ((batch->start | batch->used) & 0x7) { DRM_ERROR("alignment"); - return DRM_ERR(EINVAL); + return -EINVAL; } i915_kernel_lost_context(dev); @@ -598,76 +595,69 @@ static int i915_quiescent(struct drm_device * dev) return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__); } -static int i915_flush_ioctl(DRM_IOCTL_ARGS) +static int i915_flush_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; - - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); return i915_quiescent(dev); } -static int i915_batchbuffer(DRM_IOCTL_ARGS) +static int i915_batchbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; - drm_i915_batchbuffer_t batch; + drm_i915_batchbuffer_t *batch = data; int ret; if (!dev_priv->allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(batch, (drm_i915_batchbuffer_t __user *) data, - sizeof(batch)); - DRM_DEBUG("i915 batchbuffer, start %x used %d cliprects %d\n", - batch.start, batch.used, batch.num_cliprects); + batch->start, batch->used, batch->num_cliprects); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - if (batch.num_cliprects && DRM_VERIFYAREA_READ(batch.cliprects, - batch.num_cliprects * + if (batch->num_cliprects && DRM_VERIFYAREA_READ(batch->cliprects, + batch->num_cliprects * sizeof(struct drm_clip_rect))) - return DRM_ERR(EFAULT); + return -EFAULT; - ret = i915_dispatch_batchbuffer(dev, &batch); + ret = i915_dispatch_batchbuffer(dev, batch); sarea_priv->last_dispatch = (int)hw_status[5]; return ret; } -static int i915_cmdbuffer(DRM_IOCTL_ARGS) +static int i915_cmdbuffer(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *) dev_priv->sarea_priv; - drm_i915_cmdbuffer_t cmdbuf; + drm_i915_cmdbuffer_t *cmdbuf = data; int ret; - DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_i915_cmdbuffer_t __user *) data, - sizeof(cmdbuf)); - DRM_DEBUG("i915 cmdbuffer, buf %p sz %d cliprects %d\n", - cmdbuf.buf, cmdbuf.sz, cmdbuf.num_cliprects); + cmdbuf->buf, cmdbuf->sz, cmdbuf->num_cliprects); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - if (cmdbuf.num_cliprects && - DRM_VERIFYAREA_READ(cmdbuf.cliprects, - cmdbuf.num_cliprects * + if (cmdbuf->num_cliprects && + DRM_VERIFYAREA_READ(cmdbuf->cliprects, + cmdbuf->num_cliprects * sizeof(struct drm_clip_rect))) { DRM_ERROR("Fault accessing cliprects\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } - ret = i915_dispatch_cmdbuffer(dev, &cmdbuf); + ret = i915_dispatch_cmdbuffer(dev, cmdbuf); if (ret) { DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); return ret; @@ -677,33 +667,29 @@ static int i915_cmdbuffer(DRM_IOCTL_ARGS) return 0; } -static int i915_flip_bufs(DRM_IOCTL_ARGS) +static int i915_flip_bufs(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; - DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); return i915_dispatch_flip(dev); } -static int i915_getparam(DRM_IOCTL_ARGS) +static int i915_getparam(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_getparam_t param; + drm_i915_getparam_t *param = data; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data, - sizeof(param)); - - switch (param.param) { + switch (param->param) { case I915_PARAM_IRQ_ACTIVE: value = dev->irq ? 1 : 0; break; @@ -714,68 +700,64 @@ static int i915_getparam(DRM_IOCTL_ARGS) value = READ_BREADCRUMB(dev_priv); break; default: - DRM_ERROR("Unknown parameter %d\n", param.param); - return DRM_ERR(EINVAL); + DRM_ERROR("Unknown parameter %d\n", param->param); + return -EINVAL; } - if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { + if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { DRM_ERROR("DRM_COPY_TO_USER failed\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; } -static int i915_setparam(DRM_IOCTL_ARGS) +static int i915_setparam(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_setparam_t param; + drm_i915_setparam_t *param = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data, - sizeof(param)); - - switch (param.param) { + switch (param->param) { case I915_SETPARAM_USE_MI_BATCHBUFFER_START: if (!IS_I965G(dev)) - dev_priv->use_mi_batchbuffer_start = param.value; + dev_priv->use_mi_batchbuffer_start = param->value; break; case I915_SETPARAM_TEX_LRU_LOG_GRANULARITY: - dev_priv->tex_lru_log_granularity = param.value; + dev_priv->tex_lru_log_granularity = param->value; break; case I915_SETPARAM_ALLOW_BATCHBUFFER: - dev_priv->allow_batchbuffer = param.value; + dev_priv->allow_batchbuffer = param->value; break; default: - DRM_ERROR("unknown parameter %d\n", param.param); - return DRM_ERR(EINVAL); + DRM_ERROR("unknown parameter %d\n", param->param); + return -EINVAL; } return 0; } -static int i915_set_status_page(DRM_IOCTL_ARGS) +static int i915_set_status_page(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_hws_addr_t hws; + drm_i915_hws_addr_t *hws = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(hws, (drm_i915_hws_addr_t __user *) data, - sizeof(hws)); - printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws.addr); - dev_priv->status_gfx_addr = hws.addr & (0x1ffff<<12); + printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr); + + dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); - dev_priv->hws_map.offset = dev->agp->agp_info.aper_base + hws.addr; + dev_priv->hws_map.offset = dev->agp->agp_info.aper_base + hws->addr; dev_priv->hws_map.size = 4*1024; dev_priv->hws_map.type = 0; dev_priv->hws_map.flags = 0; @@ -788,7 +770,7 @@ static int i915_set_status_page(DRM_IOCTL_ARGS) dev_priv->status_gfx_addr = 0; DRM_ERROR("can not ioremap virtual address for" " G33 hw status page\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } dev_priv->hw_status_page = dev_priv->hws_map.handle; @@ -821,32 +803,32 @@ void i915_driver_lastclose(struct drm_device * dev) i915_dma_cleanup(dev); } -void i915_driver_preclose(struct drm_device * dev, DRMFILE filp) +void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { if (dev->dev_private) { drm_i915_private_t *dev_priv = dev->dev_private; - i915_mem_release(dev, filp, dev_priv->agp_heap); + i915_mem_release(dev, file_priv, dev_priv->agp_heap); } } -drm_ioctl_desc_t i915_ioctls[] = { - [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_DESTROY_HEAP)] = { i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_I915_SET_VBLANK_PIPE)] = { i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY }, - [DRM_IOCTL_NR(DRM_I915_GET_VBLANK_PIPE)] = { i915_vblank_pipe_get, DRM_AUTH }, - [DRM_IOCTL_NR(DRM_I915_VBLANK_SWAP)] = {i915_vblank_swap, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_I915_HWS_ADDR)] = {i915_set_status_page, DRM_AUTH}, +struct drm_ioctl_desc i915_ioctls[] = { + DRM_IOCTL_DEF(DRM_I915_INIT, i915_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_I915_FLUSH, i915_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_FLIP, i915_flip_bufs, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_BATCHBUFFER, i915_batchbuffer, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_IRQ_EMIT, i915_irq_emit, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_IRQ_WAIT, i915_irq_wait, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_GETPARAM, i915_getparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_SETPARAM, i915_setparam, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_I915_ALLOC, i915_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_FREE, i915_mem_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_INIT_HEAP, i915_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_I915_CMDBUFFER, i915_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_DESTROY_HEAP, i915_mem_destroy_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), + DRM_IOCTL_DEF(DRM_I915_SET_VBLANK_PIPE, i915_vblank_pipe_set, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY ), + DRM_IOCTL_DEF(DRM_I915_GET_VBLANK_PIPE, i915_vblank_pipe_get, DRM_AUTH ), + DRM_IOCTL_DEF(DRM_I915_VBLANK_SWAP, i915_vblank_swap, DRM_AUTH), + DRM_IOCTL_DEF(DRM_I915_HWS_ADDR, i915_set_status_page, DRM_AUTH), }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index 28b98733beb8..e064292e703a 100644 --- a/drivers/char/drm/i915_drv.h +++ b/drivers/char/drm/i915_drv.h @@ -70,7 +70,7 @@ struct mem_block { struct mem_block *prev; int start; int size; - DRMFILE filp; /* 0: free, -1: heap, other: real files */ + struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ }; typedef struct _drm_i915_vbl_swap { @@ -116,21 +116,24 @@ typedef struct drm_i915_private { unsigned int swaps_pending; } drm_i915_private_t; -extern drm_ioctl_desc_t i915_ioctls[]; +extern struct drm_ioctl_desc i915_ioctls[]; extern int i915_max_ioctl; /* i915_dma.c */ extern void i915_kernel_lost_context(struct drm_device * dev); extern int i915_driver_load(struct drm_device *, unsigned long flags); extern void i915_driver_lastclose(struct drm_device * dev); -extern void i915_driver_preclose(struct drm_device * dev, DRMFILE filp); +extern void i915_driver_preclose(struct drm_device *dev, + struct drm_file *file_priv); extern int i915_driver_device_is_agp(struct drm_device * dev); extern long i915_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); /* i915_irq.c */ -extern int i915_irq_emit(DRM_IOCTL_ARGS); -extern int i915_irq_wait(DRM_IOCTL_ARGS); +extern int i915_irq_emit(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int i915_irq_wait(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence); extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence); @@ -138,18 +141,25 @@ extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); extern void i915_driver_irq_preinstall(struct drm_device * dev); extern void i915_driver_irq_postinstall(struct drm_device * dev); extern void i915_driver_irq_uninstall(struct drm_device * dev); -extern int i915_vblank_pipe_set(DRM_IOCTL_ARGS); -extern int i915_vblank_pipe_get(DRM_IOCTL_ARGS); -extern int i915_vblank_swap(DRM_IOCTL_ARGS); +extern int i915_vblank_pipe_set(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int i915_vblank_pipe_get(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int i915_vblank_swap(struct drm_device *dev, void *data, + struct drm_file *file_priv); /* i915_mem.c */ -extern int i915_mem_alloc(DRM_IOCTL_ARGS); -extern int i915_mem_free(DRM_IOCTL_ARGS); -extern int i915_mem_init_heap(DRM_IOCTL_ARGS); -extern int i915_mem_destroy_heap(DRM_IOCTL_ARGS); +extern int i915_mem_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int i915_mem_free(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int i915_mem_init_heap(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int i915_mem_destroy_heap(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern void i915_mem_takedown(struct mem_block **heap); extern void i915_mem_release(struct drm_device * dev, - DRMFILE filp, struct mem_block *heap); + struct drm_file *file_priv, struct mem_block *heap); #define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, (reg)) #define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, (reg), (val)) diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index bb8e9e9c8201..a443f4a202e3 100644 --- a/drivers/char/drm/i915_irq.c +++ b/drivers/char/drm/i915_irq.c @@ -311,7 +311,7 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, READ_BREADCRUMB(dev_priv) >= irq_nr); - if (ret == DRM_ERR(EBUSY)) { + if (ret == -EBUSY) { DRM_ERROR("%s: EBUSY -- rec: %d emitted: %d\n", __FUNCTION__, READ_BREADCRUMB(dev_priv), (int)dev_priv->counter); @@ -330,7 +330,7 @@ static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequ if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, @@ -355,28 +355,25 @@ int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) /* Needs the lock as it touches the ring. */ -int i915_irq_emit(DRM_IOCTL_ARGS) +int i915_irq_emit(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_irq_emit_t emit; + drm_i915_irq_emit_t *emit = data; int result; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(emit, (drm_i915_irq_emit_t __user *) data, - sizeof(emit)); - result = i915_emit_irq(dev); - if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) { + if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; @@ -384,21 +381,18 @@ int i915_irq_emit(DRM_IOCTL_ARGS) /* Doesn't need the hardware lock. */ -int i915_irq_wait(DRM_IOCTL_ARGS) +int i915_irq_wait(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_irq_wait_t irqwait; + drm_i915_irq_wait_t *irqwait = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data, - sizeof(irqwait)); - - return i915_wait_irq(dev, irqwait.irq_seq); + return i915_wait_irq(dev, irqwait->irq_seq); } static void i915_enable_interrupt (struct drm_device *dev) @@ -417,64 +411,60 @@ static void i915_enable_interrupt (struct drm_device *dev) /* Set the vblank monitor pipe */ -int i915_vblank_pipe_set(DRM_IOCTL_ARGS) +int i915_vblank_pipe_set(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_pipe_t pipe; + drm_i915_vblank_pipe_t *pipe = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(pipe, (drm_i915_vblank_pipe_t __user *) data, - sizeof(pipe)); - - if (pipe.pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { + if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { DRM_ERROR("%s called with invalid pipe 0x%x\n", - __FUNCTION__, pipe.pipe); - return DRM_ERR(EINVAL); + __FUNCTION__, pipe->pipe); + return -EINVAL; } - dev_priv->vblank_pipe = pipe.pipe; + dev_priv->vblank_pipe = pipe->pipe; i915_enable_interrupt (dev); return 0; } -int i915_vblank_pipe_get(DRM_IOCTL_ARGS) +int i915_vblank_pipe_get(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_pipe_t pipe; + drm_i915_vblank_pipe_t *pipe = data; u16 flag; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } flag = I915_READ(I915REG_INT_ENABLE_R); - pipe.pipe = 0; + pipe->pipe = 0; if (flag & VSYNC_PIPEA_FLAG) - pipe.pipe |= DRM_I915_VBLANK_PIPE_A; + pipe->pipe |= DRM_I915_VBLANK_PIPE_A; if (flag & VSYNC_PIPEB_FLAG) - pipe.pipe |= DRM_I915_VBLANK_PIPE_B; - DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe, - sizeof(pipe)); + pipe->pipe |= DRM_I915_VBLANK_PIPE_B; + return 0; } /** * Schedule buffer swap at given vertical blank. */ -int i915_vblank_swap(DRM_IOCTL_ARGS) +int i915_vblank_swap(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_swap_t swap; + drm_i915_vblank_swap_t *swap = data; drm_i915_vbl_swap_t *vbl_swap; unsigned int pipe, seqtype, curseq; unsigned long irqflags; @@ -482,38 +472,35 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __func__); - return DRM_ERR(EINVAL); + return -EINVAL; } if (dev_priv->sarea_priv->rotation) { DRM_DEBUG("Rotation not supported\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data, - sizeof(swap)); - - if (swap.seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | + if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) { - DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype); - return DRM_ERR(EINVAL); + DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype); + return -EINVAL; } - pipe = (swap.seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; + pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0; - seqtype = swap.seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); + seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE); if (!(dev_priv->vblank_pipe & (1 << pipe))) { DRM_ERROR("Invalid pipe %d\n", pipe); - return DRM_ERR(EINVAL); + return -EINVAL; } spin_lock_irqsave(&dev->drw_lock, irqflags); - if (!drm_get_drawable_info(dev, swap.drawable)) { + if (!drm_get_drawable_info(dev, swap->drawable)) { spin_unlock_irqrestore(&dev->drw_lock, irqflags); - DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable); - return DRM_ERR(EINVAL); + DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable); + return -EINVAL; } spin_unlock_irqrestore(&dev->drw_lock, irqflags); @@ -521,14 +508,14 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received); if (seqtype == _DRM_VBLANK_RELATIVE) - swap.sequence += curseq; + swap->sequence += curseq; - if ((curseq - swap.sequence) <= (1<<23)) { - if (swap.seqtype & _DRM_VBLANK_NEXTONMISS) { - swap.sequence = curseq + 1; + if ((curseq - swap->sequence) <= (1<<23)) { + if (swap->seqtype & _DRM_VBLANK_NEXTONMISS) { + swap->sequence = curseq + 1; } else { DRM_DEBUG("Missed target sequence\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -537,9 +524,9 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) list_for_each(list, &dev_priv->vbl_swaps.head) { vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head); - if (vbl_swap->drw_id == swap.drawable && + if (vbl_swap->drw_id == swap->drawable && vbl_swap->pipe == pipe && - vbl_swap->sequence == swap.sequence) { + vbl_swap->sequence == swap->sequence) { spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); DRM_DEBUG("Already scheduled\n"); return 0; @@ -550,21 +537,21 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) if (dev_priv->swaps_pending >= 100) { DRM_DEBUG("Too many swaps queued\n"); - return DRM_ERR(EBUSY); + return -EBUSY; } - vbl_swap = drm_calloc(1, sizeof(vbl_swap), DRM_MEM_DRIVER); + vbl_swap = drm_calloc(1, sizeof(*vbl_swap), DRM_MEM_DRIVER); if (!vbl_swap) { DRM_ERROR("Failed to allocate memory to queue swap\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } DRM_DEBUG("\n"); - vbl_swap->drw_id = swap.drawable; + vbl_swap->drw_id = swap->drawable; vbl_swap->pipe = pipe; - vbl_swap->sequence = swap.sequence; + vbl_swap->sequence = swap->sequence; spin_lock_irqsave(&dev_priv->swaps_lock, irqflags); @@ -573,9 +560,6 @@ int i915_vblank_swap(DRM_IOCTL_ARGS) spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags); - DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_swap_t __user *) data, swap, - sizeof(swap)); - return 0; } diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c index 50b4bacef0e0..56fb9b30a5d7 100644 --- a/drivers/char/drm/i915_mem.c +++ b/drivers/char/drm/i915_mem.c @@ -89,7 +89,7 @@ static void mark_block(struct drm_device * dev, struct mem_block *p, int in_use) */ static struct mem_block *split_block(struct mem_block *p, int start, int size, - DRMFILE filp) + struct drm_file *file_priv) { /* Maybe cut off the start of an existing block */ if (start > p->start) { @@ -99,7 +99,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size, goto out; newblock->start = start; newblock->size = p->size - (start - p->start); - newblock->filp = NULL; + newblock->file_priv = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; @@ -116,7 +116,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size, goto out; newblock->start = start + size; newblock->size = p->size - size; - newblock->filp = NULL; + newblock->file_priv = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; @@ -126,20 +126,20 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size, out: /* Our block is in the middle */ - p->filp = filp; + p->file_priv = file_priv; return p; } static struct mem_block *alloc_block(struct mem_block *heap, int size, - int align2, DRMFILE filp) + int align2, struct drm_file *file_priv) { struct mem_block *p; int mask = (1 << align2) - 1; for (p = heap->next; p != heap; p = p->next) { int start = (p->start + mask) & ~mask; - if (p->filp == NULL && start + size <= p->start + p->size) - return split_block(p, start, size, filp); + if (p->file_priv == NULL && start + size <= p->start + p->size) + return split_block(p, start, size, file_priv); } return NULL; @@ -158,12 +158,12 @@ static struct mem_block *find_block(struct mem_block *heap, int start) static void free_block(struct mem_block *p) { - p->filp = NULL; + p->file_priv = NULL; - /* Assumes a single contiguous range. Needs a special filp in + /* Assumes a single contiguous range. Needs a special file_priv in * 'heap' to stop it being subsumed. */ - if (p->next->filp == NULL) { + if (p->next->file_priv == NULL) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; @@ -171,7 +171,7 @@ static void free_block(struct mem_block *p) drm_free(q, sizeof(*q), DRM_MEM_BUFLISTS); } - if (p->prev->filp == NULL) { + if (p->prev->file_priv == NULL) { struct mem_block *q = p->prev; q->size += p->size; q->next = p->next; @@ -197,18 +197,19 @@ static int init_heap(struct mem_block **heap, int start, int size) blocks->start = start; blocks->size = size; - blocks->filp = NULL; + blocks->file_priv = NULL; blocks->next = blocks->prev = *heap; memset(*heap, 0, sizeof(**heap)); - (*heap)->filp = (DRMFILE) - 1; + (*heap)->file_priv = (struct drm_file *) - 1; (*heap)->next = (*heap)->prev = blocks; return 0; } /* Free all blocks associated with the releasing file. */ -void i915_mem_release(struct drm_device * dev, DRMFILE filp, struct mem_block *heap) +void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv, + struct mem_block *heap) { struct mem_block *p; @@ -216,17 +217,17 @@ void i915_mem_release(struct drm_device * dev, DRMFILE filp, struct mem_block *h return; for (p = heap->next; p != heap; p = p->next) { - if (p->filp == filp) { - p->filp = NULL; + if (p->file_priv == file_priv) { + p->file_priv = NULL; mark_block(dev, p, 0); } } - /* Assumes a single contiguous range. Needs a special filp in + /* Assumes a single contiguous range. Needs a special file_priv in * 'heap' to stop it being subsumed. */ for (p = heap->next; p != heap; p = p->next) { - while (p->filp == NULL && p->next->filp == NULL) { + while (p->file_priv == NULL && p->next->file_priv == NULL) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; @@ -267,129 +268,117 @@ static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region) /* IOCTL HANDLERS */ -int i915_mem_alloc(DRM_IOCTL_ARGS) +int i915_mem_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_alloc_t alloc; + drm_i915_mem_alloc_t *alloc = data; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data, - sizeof(alloc)); - - heap = get_heap(dev_priv, alloc.region); + heap = get_heap(dev_priv, alloc->region); if (!heap || !*heap) - return DRM_ERR(EFAULT); + return -EFAULT; /* Make things easier on ourselves: all allocations at least * 4k aligned. */ - if (alloc.alignment < 12) - alloc.alignment = 12; + if (alloc->alignment < 12) + alloc->alignment = 12; - block = alloc_block(*heap, alloc.size, alloc.alignment, filp); + block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); if (!block) - return DRM_ERR(ENOMEM); + return -ENOMEM; mark_block(dev, block, 1); - if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) { + if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, + sizeof(int))) { DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; } -int i915_mem_free(DRM_IOCTL_ARGS) +int i915_mem_free(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_free_t memfree; + drm_i915_mem_free_t *memfree = data; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data, - sizeof(memfree)); - - heap = get_heap(dev_priv, memfree.region); + heap = get_heap(dev_priv, memfree->region); if (!heap || !*heap) - return DRM_ERR(EFAULT); + return -EFAULT; - block = find_block(*heap, memfree.region_offset); + block = find_block(*heap, memfree->region_offset); if (!block) - return DRM_ERR(EFAULT); + return -EFAULT; - if (block->filp != filp) - return DRM_ERR(EPERM); + if (block->file_priv != file_priv) + return -EPERM; mark_block(dev, block, 0); free_block(block); return 0; } -int i915_mem_init_heap(DRM_IOCTL_ARGS) +int i915_mem_init_heap(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_init_heap_t initheap; + drm_i915_mem_init_heap_t *initheap = data; struct mem_block **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(initheap, - (drm_i915_mem_init_heap_t __user *) data, - sizeof(initheap)); - - heap = get_heap(dev_priv, initheap.region); + heap = get_heap(dev_priv, initheap->region); if (!heap) - return DRM_ERR(EFAULT); + return -EFAULT; if (*heap) { DRM_ERROR("heap already initialized?"); - return DRM_ERR(EFAULT); + return -EFAULT; } - return init_heap(heap, initheap.start, initheap.size); + return init_heap(heap, initheap->start, initheap->size); } -int i915_mem_destroy_heap( DRM_IOCTL_ARGS ) +int i915_mem_destroy_heap( struct drm_device *dev, void *data, + struct drm_file *file_priv ) { - DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_destroy_heap_t destroyheap; + drm_i915_mem_destroy_heap_t *destroyheap = data; struct mem_block **heap; if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data, - sizeof(destroyheap) ); - - heap = get_heap( dev_priv, destroyheap.region ); + heap = get_heap( dev_priv, destroyheap->region ); if (!heap) { DRM_ERROR("get_heap failed"); - return DRM_ERR(EFAULT); + return -EFAULT; } if (!*heap) { DRM_ERROR("heap not initialized?"); - return DRM_ERR(EFAULT); + return -EFAULT; } i915_mem_takedown( heap ); diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c index 9c73a6e3861b..c567c34cda78 100644 --- a/drivers/char/drm/mga_dma.c +++ b/drivers/char/drm/mga_dma.c @@ -71,7 +71,7 @@ int mga_do_wait_for_idle(drm_mga_private_t * dev_priv) DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x\n", status); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } static int mga_do_dma_reset(drm_mga_private_t * dev_priv) @@ -256,7 +256,7 @@ static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_pr dev_priv->head = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); if (dev_priv->head == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; memset(dev_priv->head, 0, sizeof(drm_mga_freelist_t)); SET_AGE(&dev_priv->head->age, MGA_BUFFER_USED, 0); @@ -267,7 +267,7 @@ static int mga_freelist_init(struct drm_device * dev, drm_mga_private_t * dev_pr entry = drm_alloc(sizeof(drm_mga_freelist_t), DRM_MEM_DRIVER); if (entry == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; memset(entry, 0, sizeof(drm_mga_freelist_t)); @@ -399,7 +399,7 @@ int mga_driver_load(struct drm_device * dev, unsigned long flags) dev_priv = drm_alloc(sizeof(drm_mga_private_t), DRM_MEM_DRIVER); if (!dev_priv) - return DRM_ERR(ENOMEM); + return -ENOMEM; dev->dev_private = (void *)dev_priv; memset(dev_priv, 0, sizeof(drm_mga_private_t)); @@ -578,7 +578,7 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev, DRM_ERROR("failed to ioremap agp regions! (%p, %p, %p)\n", dev_priv->warp->handle, dev_priv->primary->handle, dev->agp_buffer_map->handle); - return DRM_ERR(ENOMEM); + return -ENOMEM; } dev_priv->dma_access = MGA_PAGPXFER; @@ -622,7 +622,7 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev, if (dev->dma == NULL) { DRM_ERROR("dev->dma is NULL\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } /* Make drm_addbufs happy by not trying to create a mapping for less @@ -656,7 +656,7 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev, if (err != 0) { DRM_ERROR("Unable to allocate primary DMA region: %d\n", err); - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (dev_priv->primary->size != dma_bs->primary_size) { @@ -759,36 +759,30 @@ static int mga_do_dma_bootstrap(struct drm_device * dev, return err; } -int mga_dma_bootstrap(DRM_IOCTL_ARGS) +int mga_dma_bootstrap(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; - drm_mga_dma_bootstrap_t bootstrap; + drm_mga_dma_bootstrap_t *bootstrap = data; int err; static const int modes[] = { 0, 1, 2, 2, 4, 4, 4, 4 }; const drm_mga_private_t *const dev_priv = (drm_mga_private_t *) dev->dev_private; - DRM_COPY_FROM_USER_IOCTL(bootstrap, - (drm_mga_dma_bootstrap_t __user *) data, - sizeof(bootstrap)); - - err = mga_do_dma_bootstrap(dev, &bootstrap); + err = mga_do_dma_bootstrap(dev, bootstrap); if (err) { mga_do_cleanup_dma(dev, FULL_CLEANUP); return err; } if (dev_priv->agp_textures != NULL) { - bootstrap.texture_handle = dev_priv->agp_textures->offset; - bootstrap.texture_size = dev_priv->agp_textures->size; + bootstrap->texture_handle = dev_priv->agp_textures->offset; + bootstrap->texture_size = dev_priv->agp_textures->size; } else { - bootstrap.texture_handle = 0; - bootstrap.texture_size = 0; + bootstrap->texture_handle = 0; + bootstrap->texture_size = 0; } - bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07]; - DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data, - bootstrap, sizeof(bootstrap)); + bootstrap->agp_mode = modes[bootstrap->agp_mode & 0x07]; return err; } @@ -826,7 +820,7 @@ static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init) dev_priv->sarea = drm_getsarea(dev); if (!dev_priv->sarea) { DRM_ERROR("failed to find sarea!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } if (!dev_priv->used_new_dma_init) { @@ -837,29 +831,29 @@ static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init) dev_priv->status = drm_core_findmap(dev, init->status_offset); if (!dev_priv->status) { DRM_ERROR("failed to find status page!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio) { DRM_ERROR("failed to find mmio region!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->warp = drm_core_findmap(dev, init->warp_offset); if (!dev_priv->warp) { DRM_ERROR("failed to find warp microcode region!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->primary = drm_core_findmap(dev, init->primary_offset); if (!dev_priv->primary) { DRM_ERROR("failed to find primary dma region!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("failed to find dma buffer region!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } drm_core_ioremap(dev_priv->warp, dev); @@ -877,7 +871,7 @@ static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init) ((dev->agp_buffer_map == NULL) || (dev->agp_buffer_map->handle == NULL)))) { DRM_ERROR("failed to ioremap agp regions!\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } ret = mga_warp_install_microcode(dev_priv); @@ -927,7 +921,7 @@ static int mga_do_init_dma(struct drm_device * dev, drm_mga_init_t * init) if (mga_freelist_init(dev, dev_priv) < 0) { DRM_ERROR("could not initialize freelist\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } return 0; @@ -1007,20 +1001,17 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup) return 0; } -int mga_dma_init(DRM_IOCTL_ARGS) +int mga_dma_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; - drm_mga_init_t init; + drm_mga_init_t *init = data; int err; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data, - sizeof(init)); + LOCK_TEST_WITH_RETURN(dev, file_priv); - switch (init.func) { + switch (init->func) { case MGA_INIT_DMA: - err = mga_do_init_dma(dev, &init); + err = mga_do_init_dma(dev, init); if (err) { (void)mga_do_cleanup_dma(dev, FULL_CLEANUP); } @@ -1029,36 +1020,33 @@ int mga_dma_init(DRM_IOCTL_ARGS) return mga_do_cleanup_dma(dev, FULL_CLEANUP); } - return DRM_ERR(EINVAL); + return -EINVAL; } /* ================================================================ * Primary DMA stream management */ -int mga_dma_flush(DRM_IOCTL_ARGS) +int mga_dma_flush(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - struct drm_lock lock; - - LOCK_TEST_WITH_RETURN(dev, filp); + struct drm_lock *lock = data; - DRM_COPY_FROM_USER_IOCTL(lock, (struct drm_lock __user *) data, - sizeof(lock)); + LOCK_TEST_WITH_RETURN(dev, file_priv); DRM_DEBUG("%s%s%s\n", - (lock.flags & _DRM_LOCK_FLUSH) ? "flush, " : "", - (lock.flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "", - (lock.flags & _DRM_LOCK_QUIESCENT) ? "idle, " : ""); + (lock->flags & _DRM_LOCK_FLUSH) ? "flush, " : "", + (lock->flags & _DRM_LOCK_FLUSH_ALL) ? "flush all, " : "", + (lock->flags & _DRM_LOCK_QUIESCENT) ? "idle, " : ""); WRAP_WAIT_WITH_RETURN(dev_priv); - if (lock.flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) { + if (lock->flags & (_DRM_LOCK_FLUSH | _DRM_LOCK_FLUSH_ALL)) { mga_do_dma_flush(dev_priv); } - if (lock.flags & _DRM_LOCK_QUIESCENT) { + if (lock->flags & _DRM_LOCK_QUIESCENT) { #if MGA_DMA_DEBUG int ret = mga_do_wait_for_idle(dev_priv); if (ret < 0) @@ -1072,12 +1060,12 @@ int mga_dma_flush(DRM_IOCTL_ARGS) } } -int mga_dma_reset(DRM_IOCTL_ARGS) +int mga_dma_reset(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); return mga_do_dma_reset(dev_priv); } @@ -1086,7 +1074,8 @@ int mga_dma_reset(DRM_IOCTL_ARGS) * DMA buffer management */ -static int mga_dma_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d) +static int mga_dma_get_buffers(struct drm_device * dev, + struct drm_file *file_priv, struct drm_dma * d) { struct drm_buf *buf; int i; @@ -1094,61 +1083,56 @@ static int mga_dma_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm for (i = d->granted_count; i < d->request_count; i++) { buf = mga_freelist_get(dev); if (!buf) - return DRM_ERR(EAGAIN); + return -EAGAIN; - buf->filp = filp; + buf->file_priv = file_priv; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return DRM_ERR(EFAULT); + return -EFAULT; if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return DRM_ERR(EFAULT); + return -EFAULT; d->granted_count++; } return 0; } -int mga_dma_buffers(DRM_IOCTL_ARGS) +int mga_dma_buffers(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; struct drm_device_dma *dma = dev->dma; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - struct drm_dma __user *argp = (void __user *)data; - struct drm_dma d; + struct drm_dma *d = data; int ret = 0; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); + LOCK_TEST_WITH_RETURN(dev, file_priv); /* Please don't send us buffers. */ - if (d.send_count != 0) { + if (d->send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - DRM_CURRENTPID, d.send_count); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, d->send_count); + return -EINVAL; } /* We'll send you buffers. */ - if (d.request_count < 0 || d.request_count > dma->buf_count) { + if (d->request_count < 0 || d->request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - DRM_CURRENTPID, d.request_count, dma->buf_count); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, d->request_count, dma->buf_count); + return -EINVAL; } WRAP_TEST_WITH_RETURN(dev_priv); - d.granted_count = 0; + d->granted_count = 0; - if (d.request_count) { - ret = mga_dma_get_buffers(filp, dev, &d); + if (d->request_count) { + ret = mga_dma_get_buffers(dev, file_priv, d); } - DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); - return ret; } diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h index 49253affa475..cd94c04e31c0 100644 --- a/drivers/char/drm/mga_drv.h +++ b/drivers/char/drm/mga_drv.h @@ -148,15 +148,20 @@ typedef struct drm_mga_private { unsigned int agp_size; } drm_mga_private_t; -extern drm_ioctl_desc_t mga_ioctls[]; +extern struct drm_ioctl_desc mga_ioctls[]; extern int mga_max_ioctl; /* mga_dma.c */ -extern int mga_dma_bootstrap(DRM_IOCTL_ARGS); -extern int mga_dma_init(DRM_IOCTL_ARGS); -extern int mga_dma_flush(DRM_IOCTL_ARGS); -extern int mga_dma_reset(DRM_IOCTL_ARGS); -extern int mga_dma_buffers(DRM_IOCTL_ARGS); +extern int mga_dma_bootstrap(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int mga_dma_init(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int mga_dma_flush(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int mga_dma_reset(struct drm_device *dev, void *data, + struct drm_file *file_priv); +extern int mga_dma_buffers(struct drm_device *dev, void *data, + struct drm_file *file_priv); extern int mga_driver_load(struct drm_device *dev, unsigned long flags); extern int mga_driver_unload(struct drm_device * dev); extern void mga_driver_lastclose(struct drm_device * dev); @@ -245,7 +250,7 @@ do { \ dev_priv->prim.high_mark ) { \ if ( MGA_DMA_DEBUG ) \ DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ - return DRM_ERR(EBUSY); \ + return -EBUSY; \ } \ } \ } while (0) @@ -256,7 +261,7 @@ do { \ if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \ if ( MGA_DMA_DEBUG ) \ DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ - return DRM_ERR(EBUSY); \ + return -EBUSY; \ } \ mga_do_dma_wrap_end( dev_priv ); \ } \ diff --git a/drivers/char/drm/mga_state.c b/drivers/char/drm/mga_state.c index d448b0aef33c..5ec8b61c5d45 100644 --- a/drivers/char/drm/mga_state.c +++ b/drivers/char/drm/mga_state.c @@ -392,7 +392,7 @@ static int mga_verify_context(drm_mga_private_t * dev_priv) ctx->dstorg, dev_priv->front_offset, dev_priv->back_offset); ctx->dstorg = 0; - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; @@ -411,7 +411,7 @@ static int mga_verify_tex(drm_mga_private_t * dev_priv, int unit) if (org == (MGA_TEXORGMAP_SYSMEM | MGA_TEXORGACC_PCI)) { DRM_ERROR("*** bad TEXORG: 0x%x, unit %d\n", tex->texorg, unit); tex->texorg = 0; - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; @@ -453,13 +453,13 @@ static int mga_verify_iload(drm_mga_private_t * dev_priv, dstorg + length > (dev_priv->texture_offset + dev_priv->texture_size)) { DRM_ERROR("*** bad iload DSTORG: 0x%x\n", dstorg); - return DRM_ERR(EINVAL); + return -EINVAL; } if (length & MGA_ILOAD_MASK) { DRM_ERROR("*** bad iload length: 0x%x\n", length & MGA_ILOAD_MASK); - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; @@ -471,7 +471,7 @@ static int mga_verify_blit(drm_mga_private_t * dev_priv, if ((srcorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM) || (dstorg & 0x3) == (MGA_SRCACC_PCI | MGA_SRCMAP_SYSMEM)) { DRM_ERROR("*** bad blit: src=0x%x dst=0x%x\n", srcorg, dstorg); - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; } @@ -828,24 +828,20 @@ static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit * */ -static int mga_dma_clear(DRM_IOCTL_ARGS) +static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_clear_t clear; + drm_mga_clear_t *clear = data; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(clear, (drm_mga_clear_t __user *) data, - sizeof(clear)); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; WRAP_TEST_WITH_RETURN(dev_priv); - mga_dma_dispatch_clear(dev, &clear); + mga_dma_dispatch_clear(dev, clear); /* Make sure we restore the 3D state next time. */ @@ -854,13 +850,12 @@ static int mga_dma_clear(DRM_IOCTL_ARGS) return 0; } -static int mga_dma_swap(DRM_IOCTL_ARGS) +static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; @@ -876,37 +871,32 @@ static int mga_dma_swap(DRM_IOCTL_ARGS) return 0; } -static int mga_dma_vertex(DRM_IOCTL_ARGS) +static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; drm_mga_buf_priv_t *buf_priv; - drm_mga_vertex_t vertex; - - LOCK_TEST_WITH_RETURN(dev, filp); + drm_mga_vertex_t *vertex = data; - DRM_COPY_FROM_USER_IOCTL(vertex, - (drm_mga_vertex_t __user *) data, - sizeof(vertex)); + LOCK_TEST_WITH_RETURN(dev, file_priv); - if (vertex.idx < 0 || vertex.idx > dma->buf_count) - return DRM_ERR(EINVAL); - buf = dma->buflist[vertex.idx]; + if (vertex->idx < 0 || vertex->idx > dma->buf_count) + return -EINVAL; + buf = dma->buflist[vertex->idx]; buf_priv = buf->dev_private; - buf->used = vertex.used; - buf_priv->discard = vertex.discard; + buf->used = vertex->used; + buf_priv->discard = vertex->discard; if (!mga_verify_state(dev_priv)) { - if (vertex.discard) { + if (vertex->discard) { if (buf_priv->dispatched == 1) AGE_BUFFER(buf_priv); buf_priv->dispatched = 0; mga_freelist_put(dev, buf); } - return DRM_ERR(EINVAL); + return -EINVAL; } WRAP_TEST_WITH_RETURN(dev_priv); @@ -916,82 +906,73 @@ static int mga_dma_vertex(DRM_IOCTL_ARGS) return 0; } -static int mga_dma_indices(DRM_IOCTL_ARGS) +static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; drm_mga_buf_priv_t *buf_priv; - drm_mga_indices_t indices; + drm_mga_indices_t *indices = data; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_COPY_FROM_USER_IOCTL(indices, - (drm_mga_indices_t __user *) data, - sizeof(indices)); + if (indices->idx < 0 || indices->idx > dma->buf_count) + return -EINVAL; - if (indices.idx < 0 || indices.idx > dma->buf_count) - return DRM_ERR(EINVAL); - - buf = dma->buflist[indices.idx]; + buf = dma->buflist[indices->idx]; buf_priv = buf->dev_private; - buf_priv->discard = indices.discard; + buf_priv->discard = indices->discard; if (!mga_verify_state(dev_priv)) { - if (indices.discard) { + if (indices->discard) { if (buf_priv->dispatched == 1) AGE_BUFFER(buf_priv); buf_priv->dispatched = 0; mga_freelist_put(dev, buf); } - return DRM_ERR(EINVAL); + return -EINVAL; } WRAP_TEST_WITH_RETURN(dev_priv); - mga_dma_dispatch_indices(dev, buf, indices.start, indices.end); + mga_dma_dispatch_indices(dev, buf, indices->start, indices->end); return 0; } -static int mga_dma_iload(DRM_IOCTL_ARGS) +static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; struct drm_device_dma *dma = dev->dma; drm_mga_private_t *dev_priv = dev->dev_private; struct drm_buf *buf; drm_mga_buf_priv_t *buf_priv; - drm_mga_iload_t iload; + drm_mga_iload_t *iload = data; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(iload, (drm_mga_iload_t __user *) data, - sizeof(iload)); + LOCK_TEST_WITH_RETURN(dev, file_priv); #if 0 if (mga_do_wait_for_idle(dev_priv) < 0) { if (MGA_DMA_DEBUG) DRM_INFO("%s: -EBUSY\n", __FUNCTION__); - return DRM_ERR(EBUSY); + return -EBUSY; } #endif - if (iload.idx < 0 || iload.idx > dma->buf_count) - return DRM_ERR(EINVAL); + if (iload->idx < 0 || iload->idx > dma->buf_count) + return -EINVAL; - buf = dma->buflist[iload.idx]; + buf = dma->buflist[iload->idx]; buf_priv = buf->dev_private; - if (mga_verify_iload(dev_priv, iload.dstorg, iload.length)) { + if (mga_verify_iload(dev_priv, iload->dstorg, iload->length)) { mga_freelist_put(dev, buf); - return DRM_ERR(EINVAL); + return -EINVAL; } WRAP_TEST_WITH_RETURN(dev_priv); - mga_dma_dispatch_iload(dev, buf, iload.dstorg, iload.length); + mga_dma_dispatch_iload(dev, buf, iload->dstorg, iload->length); /* Make sure we restore the 3D state next time. */ @@ -1000,28 +981,24 @@ static int mga_dma_iload(DRM_IOCTL_ARGS) return 0; } -static int mga_dma_blit(DRM_IOCTL_ARGS) +static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_mga_blit_t blit; + drm_mga_blit_t *blit = data; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(blit, (drm_mga_blit_t __user *) data, - sizeof(blit)); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; - if (mga_verify_blit(dev_priv, blit.srcorg, blit.dstorg)) - return DRM_ERR(EINVAL); + if (mga_verify_blit(dev_priv, blit->srcorg, blit->dstorg)) + return -EINVAL; WRAP_TEST_WITH_RETURN(dev_priv); - mga_dma_dispatch_blit(dev, &blit); + mga_dma_dispatch_blit(dev, blit); /* Make sure we restore the 3D state next time. */ @@ -1030,24 +1007,20 @@ static int mga_dma_blit(DRM_IOCTL_ARGS) return 0; } -static int mga_getparam(DRM_IOCTL_ARGS) +static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_getparam_t param; + drm_mga_getparam_t *param = data; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(param, (drm_mga_getparam_t __user *) data, - sizeof(param)); - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); - switch (param.param) { + switch (param->param) { case MGA_PARAM_IRQ_NR: value = dev->irq; break; @@ -1055,36 +1028,35 @@ static int mga_getparam(DRM_IOCTL_ARGS) value = dev_priv->chipset; break; default: - return DRM_ERR(EINVAL); + return -EINVAL; } - if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { + if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; } -static int mga_set_fence(DRM_IOCTL_ARGS) +static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; - u32 temp; + u32 *fence = data; DMA_LOCALS; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); - /* I would normal do this assignment in the declaration of temp, + /* I would normal do this assignment in the declaration of fence, * but dev_priv may be NULL. */ - temp = dev_priv->next_fence_to_post; + *fence = dev_priv->next_fence_to_post; dev_priv->next_fence_to_post++; BEGIN_DMA(1); @@ -1093,53 +1065,40 @@ static int mga_set_fence(DRM_IOCTL_ARGS) MGA_DMAPAD, 0x00000000, MGA_SOFTRAP, 0x00000000); ADVANCE_DMA(); - if (DRM_COPY_TO_USER((u32 __user *) data, &temp, sizeof(u32))) { - DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); - } - return 0; } -static int mga_wait_fence(DRM_IOCTL_ARGS) +static int mga_wait_fence(struct drm_device *dev, void *data, struct drm_file * +file_priv) { - DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; - u32 fence; + u32 *fence = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(fence, (u32 __user *) data, sizeof(u32)); - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); - mga_driver_fence_wait(dev, &fence); - - if (DRM_COPY_TO_USER((u32 __user *) data, &fence, sizeof(u32))) { - DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); - } - + mga_driver_fence_wait(dev, fence); return 0; } -drm_ioctl_desc_t mga_ioctls[] = { - [DRM_IOCTL_NR(DRM_MGA_INIT)] = {mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_MGA_FLUSH)] = {mga_dma_flush, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_RESET)] = {mga_dma_reset, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_SWAP)] = {mga_dma_swap, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_CLEAR)] = {mga_dma_clear, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_VERTEX)] = {mga_dma_vertex, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_INDICES)] = {mga_dma_indices, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_ILOAD)] = {mga_dma_iload, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_BLIT)] = {mga_dma_blit, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_GETPARAM)] = {mga_getparam, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_SET_FENCE)] = {mga_set_fence, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_WAIT_FENCE)] = {mga_wait_fence, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_MGA_DMA_BOOTSTRAP)] = {mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, +struct drm_ioctl_desc mga_ioctls[] = { + DRM_IOCTL_DEF(DRM_MGA_INIT, mga_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_MGA_FLUSH, mga_dma_flush, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_RESET, mga_dma_reset, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_SWAP, mga_dma_swap, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_CLEAR, mga_dma_clear, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_VERTEX, mga_dma_vertex, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_INDICES, mga_dma_indices, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_ILOAD, mga_dma_iload, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_BLIT, mga_dma_blit, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_GETPARAM, mga_getparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_SET_FENCE, mga_set_fence, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_WAIT_FENCE, mga_wait_fence, DRM_AUTH), + DRM_IOCTL_DEF(DRM_MGA_DMA_BOOTSTRAP, mga_dma_bootstrap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), }; int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c index d67f4925fbac..651b93c8ab5d 100644 --- a/drivers/char/drm/mga_warp.c +++ b/drivers/char/drm/mga_warp.c @@ -141,7 +141,7 @@ int mga_warp_install_microcode(drm_mga_private_t * dev_priv) if (size > dev_priv->warp->size) { DRM_ERROR("microcode too large! (%u > %lu)\n", size, dev_priv->warp->size); - return DRM_ERR(ENOMEM); + return -ENOMEM; } switch (dev_priv->chipset) { @@ -151,7 +151,7 @@ int mga_warp_install_microcode(drm_mga_private_t * dev_priv) case MGA_CARD_TYPE_G200: return mga_warp_install_g200_microcode(dev_priv); default: - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -177,7 +177,7 @@ int mga_warp_init(drm_mga_private_t * dev_priv) MGA_WRITE(MGA_WVRTXSZ, 7); break; default: - return DRM_ERR(EINVAL); + return -EINVAL; } MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE | @@ -186,7 +186,7 @@ int mga_warp_init(drm_mga_private_t * dev_priv) if (wmisc != WMISC_EXPECTED) { DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n", wmisc, WMISC_EXPECTED); - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c index b163ed09bd81..7d550aba165e 100644 --- a/drivers/char/drm/r128_cce.c +++ b/drivers/char/drm/r128_cce.c @@ -129,7 +129,7 @@ static int r128_do_pixcache_flush(drm_r128_private_t * dev_priv) #if R128_FIFO_DEBUG DRM_ERROR("failed!\n"); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries) @@ -146,7 +146,7 @@ static int r128_do_wait_for_fifo(drm_r128_private_t * dev_priv, int entries) #if R128_FIFO_DEBUG DRM_ERROR("failed!\n"); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv) @@ -168,7 +168,7 @@ static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv) #if R128_FIFO_DEBUG DRM_ERROR("failed!\n"); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } /* ================================================================ @@ -227,7 +227,7 @@ int r128_do_cce_idle(drm_r128_private_t * dev_priv) DRM_ERROR("failed!\n"); r128_status(dev_priv); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } /* Start the Concurrent Command Engine. @@ -355,7 +355,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) dev_priv = drm_alloc(sizeof(drm_r128_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; memset(dev_priv, 0, sizeof(drm_r128_private_t)); @@ -365,7 +365,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_ERROR("PCI GART memory not allocated!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->usec_timeout = init->usec_timeout; @@ -374,7 +374,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_DEBUG("TIMEOUT problem!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->cce_mode = init->cce_mode; @@ -394,7 +394,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_DEBUG("Bad cce_mode!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } switch (init->cce_mode) { @@ -461,7 +461,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_ERROR("could not find sarea!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); @@ -469,21 +469,21 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_ERROR("could not find mmio region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->cce_ring = drm_core_findmap(dev, init->ring_offset); if (!dev_priv->cce_ring) { DRM_ERROR("could not find cce ring region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); if (!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); @@ -491,7 +491,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_ERROR("could not find dma buffer region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } if (!dev_priv->is_pci) { @@ -501,7 +501,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_ERROR("could not find agp texture region!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -520,7 +520,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_ERROR("Could not ioremap agp regions!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(ENOMEM); + return -ENOMEM; } } else #endif @@ -567,7 +567,7 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init) DRM_ERROR("failed to init PCI GART!\n"); dev->dev_private = (void *)dev_priv; r128_do_cleanup_cce(dev); - return DRM_ERR(ENOMEM); + return -ENOMEM; } R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr); #if __OS_HAS_AGP @@ -625,35 +625,30 @@ int r128_do_cleanup_cce(struct drm_device * dev) return 0; } -int r128_cce_init(DRM_IOCTL_ARGS) +int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_r128_init_t init; + drm_r128_init_t *init = data; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_COPY_FROM_USER_IOCTL(init, (drm_r128_init_t __user *) data, - sizeof(init)); - - switch (init.func) { + switch (init->func) { case R128_INIT_CCE: - return r128_do_init_cce(dev, &init); + return r128_do_init_cce(dev, init); case R128_CLEANUP_CCE: return r128_do_cleanup_cce(dev); } - return DRM_ERR(EINVAL); + return -EINVAL; } -int r128_cce_start(DRM_IOCTL_ARGS) +int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { DRM_DEBUG("%s while CCE running\n", __FUNCTION__); @@ -668,30 +663,26 @@ int r128_cce_start(DRM_IOCTL_ARGS) /* Stop the CCE. The engine must have been idled before calling this * routine. */ -int r128_cce_stop(DRM_IOCTL_ARGS) +int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_cce_stop_t stop; + drm_r128_cce_stop_t *stop = data; int ret; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *) data, - sizeof(stop)); + LOCK_TEST_WITH_RETURN(dev, file_priv); /* Flush any pending CCE commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ - if (stop.flush) { + if (stop->flush) { r128_do_cce_flush(dev_priv); } /* If we fail to make the engine go idle, we return an error * code so that the DRM ioctl wrapper can try again. */ - if (stop.idle) { + if (stop->idle) { ret = r128_do_cce_idle(dev_priv); if (ret) return ret; @@ -711,17 +702,16 @@ int r128_cce_stop(DRM_IOCTL_ARGS) /* Just reset the CCE ring. Called as part of an X Server engine reset. */ -int r128_cce_reset(DRM_IOCTL_ARGS) +int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_DEBUG("%s called before init done\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } r128_do_cce_reset(dev_priv); @@ -732,13 +722,12 @@ int r128_cce_reset(DRM_IOCTL_ARGS) return 0; } -int r128_cce_idle(DRM_IOCTL_ARGS) +int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (dev_priv->cce_running) { r128_do_cce_flush(dev_priv); @@ -747,19 +736,18 @@ int r128_cce_idle(DRM_IOCTL_ARGS) return r128_do_cce_idle(dev_priv); } -int r128_engine_reset(DRM_IOCTL_ARGS) +int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); return r128_do_engine_reset(dev); } -int r128_fullscreen(DRM_IOCTL_ARGS) +int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) { - return DRM_ERR(EINVAL); + return -EINVAL; } /* ================================================================ @@ -780,7 +768,7 @@ static int r128_freelist_init(struct drm_device * dev) dev_priv->head = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); if (dev_priv->head == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t)); dev_priv->head->age = R128_BUFFER_USED; @@ -791,7 +779,7 @@ static int r128_freelist_init(struct drm_device * dev) entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); if (!entry) - return DRM_ERR(ENOMEM); + return -ENOMEM; entry->age = R128_BUFFER_FREE; entry->buf = buf; @@ -828,7 +816,7 @@ static struct drm_buf *r128_freelist_get(struct drm_device * dev) for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; - if (buf->filp == 0) + if (buf->file_priv == 0) return buf; } @@ -883,10 +871,12 @@ int r128_wait_ring(drm_r128_private_t * dev_priv, int n) /* FIXME: This is being ignored... */ DRM_ERROR("failed!\n"); - return DRM_ERR(EBUSY); + return -EBUSY; } -static int r128_cce_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d) +static int r128_cce_get_buffers(struct drm_device * dev, + struct drm_file *file_priv, + struct drm_dma * d) { int i; struct drm_buf *buf; @@ -894,57 +884,51 @@ static int r128_cce_get_buffers(DRMFILE filp, struct drm_device * dev, struct dr for (i = d->granted_count; i < d->request_count; i++) { buf = r128_freelist_get(dev); if (!buf) - return DRM_ERR(EAGAIN); + return -EAGAIN; - buf->filp = filp; + buf->file_priv = file_priv; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return DRM_ERR(EFAULT); + return -EFAULT; if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return DRM_ERR(EFAULT); + return -EFAULT; d->granted_count++; } return 0; } -int r128_cce_buffers(DRM_IOCTL_ARGS) +int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; struct drm_device_dma *dma = dev->dma; int ret = 0; - struct drm_dma __user *argp = (void __user *)data; - struct drm_dma d; + struct drm_dma *d = data; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); + LOCK_TEST_WITH_RETURN(dev, file_priv); /* Please don't send us buffers. */ - if (d.send_count != 0) { + if (d->send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - DRM_CURRENTPID, d.send_count); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, d->send_count); + return -EINVAL; } /* We'll send you buffers. */ - if (d.request_count < 0 || d.request_count > dma->buf_count) { + if (d->request_count < 0 || d->request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - DRM_CURRENTPID, d.request_count, dma->buf_count); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, d->request_count, dma->buf_count); + return -EINVAL; } - d.granted_count = 0; + d->granted_count = 0; - if (d.request_count) { - ret = r128_cce_get_buffers(filp, dev, &d); + if (d->request_count) { + ret = r128_cce_get_buffers(dev, file_priv, d); } - DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); - return ret; } diff --git a/drivers/char/drm/r128_drm.h b/drivers/char/drm/r128_drm.h index e94a39c6e327..8d8878b55f55 100644 --- a/drivers/char/drm/r128_drm.h +++ b/drivers/char/drm/r128_drm.h @@ -222,11 +222,7 @@ typedef struct drm_r128_init { R128_INIT_CCE = 0x01, R128_CLEANUP_CCE = 0x02 } func; -#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) - int sarea_priv_offset; -#else unsigned long sarea_priv_offset; -#endif int is_pci; int cce_mode; int cce_secure; @@ -240,21 +236,12 @@ typedef struct drm_r128_init { unsigned int depth_offset, depth_pitch; unsigned int span_offset; -#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) - unsigned int fb_offset; - unsigned int mmio_offset; - unsigned int ring_offset; - unsigned int ring_rptr_offset; - unsigned int buffers_offset; - unsigned int agp_textures_offset; -#else unsigned long fb_offset; unsigned long mmio_offset; unsigned long ring_offset; unsigned long ring_rptr_offset; unsigned long buffers_offset; unsigned long agp_textures_offset; -#endif } drm_r128_init_t; typedef struct drm_r128_cce_stop { @@ -264,15 +251,10 @@ typedef struct drm_r128_cce_stop { typedef struct drm_r128_clear { unsigned int flags; -#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0) - int x, y, w, h; -#endif unsigned int clear_color; unsigned int clear_depth; -#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0) unsigned int color_mask; unsigned int depth_mask; -#endif } drm_r128_clear_t; typedef struct drm_r128_vertex { diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h index 72249fb2fd1c..250d2aa46581 100644 --- a/drivers/char/drm/r128_drv.h +++ b/drivers/char/drm/r128_drv.h @@ -129,18 +129,18 @@ typedef struct drm_r128_buf_priv { drm_r128_freelist_t *list_entry; } drm_r128_buf_priv_t; -extern drm_ioctl_desc_t r128_ioctls[]; +extern struct drm_ioctl_desc r128_ioctls[]; extern int r128_max_ioctl; /* r128_cce.c */ -extern int r128_cce_init(DRM_IOCTL_ARGS); -extern int r128_cce_start(DRM_IOCTL_ARGS); -extern int r128_cce_stop(DRM_IOCTL_ARGS); -extern int r128_cce_reset(DRM_IOCTL_ARGS); -extern int r128_cce_idle(DRM_IOCTL_ARGS); -extern int r128_engine_reset(DRM_IOCTL_ARGS); -extern int r128_fullscreen(DRM_IOCTL_ARGS); -extern int r128_cce_buffers(DRM_IOCTL_ARGS); +extern int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void r128_freelist_reset(struct drm_device * dev); @@ -156,7 +156,8 @@ extern void r128_driver_irq_preinstall(struct drm_device * dev); extern void r128_driver_irq_postinstall(struct drm_device * dev); extern void r128_driver_irq_uninstall(struct drm_device * dev); extern void r128_driver_lastclose(struct drm_device * dev); -extern void r128_driver_preclose(struct drm_device * dev, DRMFILE filp); +extern void r128_driver_preclose(struct drm_device * dev, + struct drm_file *file_priv); extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); @@ -428,7 +429,7 @@ do { \ DRM_UDELAY(1); \ } \ DRM_ERROR( "ring space check failed!\n" ); \ - return DRM_ERR(EBUSY); \ + return -EBUSY; \ } \ __ring_space_done: \ ; \ diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c index 7b334fb7d649..b7f483cac6d4 100644 --- a/drivers/char/drm/r128_state.c +++ b/drivers/char/drm/r128_state.c @@ -776,8 +776,9 @@ static void r128_cce_dispatch_indices(struct drm_device * dev, sarea_priv->nbox = 0; } -static int r128_cce_dispatch_blit(DRMFILE filp, - struct drm_device * dev, drm_r128_blit_t * blit) +static int r128_cce_dispatch_blit(struct drm_device * dev, + struct drm_file *file_priv, + drm_r128_blit_t * blit) { drm_r128_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; @@ -809,7 +810,7 @@ static int r128_cce_dispatch_blit(DRMFILE filp, break; default: DRM_ERROR("invalid blit format %d\n", blit->format); - return DRM_ERR(EINVAL); + return -EINVAL; } /* Flush the pixel cache, and mark the contents as Read Invalid. @@ -829,14 +830,14 @@ static int r128_cce_dispatch_blit(DRMFILE filp, buf = dma->buflist[blit->idx]; buf_priv = buf->dev_private; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->filp); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", blit->idx); - return DRM_ERR(EINVAL); + return -EINVAL; } buf_priv->discard = 1; @@ -900,22 +901,22 @@ static int r128_cce_dispatch_write_span(struct drm_device * dev, count = depth->n; if (count > 4096 || count <= 0) - return DRM_ERR(EMSGSIZE); + return -EMSGSIZE; if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) { - return DRM_ERR(EFAULT); + return -EFAULT; } if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) { - return DRM_ERR(EFAULT); + return -EFAULT; } buffer_size = depth->n * sizeof(u32); buffer = drm_alloc(buffer_size, DRM_MEM_BUFS); if (buffer == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { drm_free(buffer, buffer_size, DRM_MEM_BUFS); - return DRM_ERR(EFAULT); + return -EFAULT; } mask_size = depth->n * sizeof(u8); @@ -923,12 +924,12 @@ static int r128_cce_dispatch_write_span(struct drm_device * dev, mask = drm_alloc(mask_size, DRM_MEM_BUFS); if (mask == NULL) { drm_free(buffer, buffer_size, DRM_MEM_BUFS); - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) { drm_free(buffer, buffer_size, DRM_MEM_BUFS); drm_free(mask, mask_size, DRM_MEM_BUFS); - return DRM_ERR(EFAULT); + return -EFAULT; } for (i = 0; i < count; i++, x++) { @@ -996,28 +997,28 @@ static int r128_cce_dispatch_write_pixels(struct drm_device * dev, count = depth->n; if (count > 4096 || count <= 0) - return DRM_ERR(EMSGSIZE); + return -EMSGSIZE; xbuf_size = count * sizeof(*x); ybuf_size = count * sizeof(*y); x = drm_alloc(xbuf_size, DRM_MEM_BUFS); if (x == NULL) { - return DRM_ERR(ENOMEM); + return -ENOMEM; } y = drm_alloc(ybuf_size, DRM_MEM_BUFS); if (y == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); - return DRM_ERR(EFAULT); + return -EFAULT; } if (DRM_COPY_FROM_USER(y, depth->y, xbuf_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); - return DRM_ERR(EFAULT); + return -EFAULT; } buffer_size = depth->n * sizeof(u32); @@ -1025,13 +1026,13 @@ static int r128_cce_dispatch_write_pixels(struct drm_device * dev, if (buffer == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); drm_free(buffer, buffer_size, DRM_MEM_BUFS); - return DRM_ERR(EFAULT); + return -EFAULT; } if (depth->mask) { @@ -1041,14 +1042,14 @@ static int r128_cce_dispatch_write_pixels(struct drm_device * dev, drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); drm_free(buffer, buffer_size, DRM_MEM_BUFS); - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (DRM_COPY_FROM_USER(mask, depth->mask, mask_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); drm_free(buffer, buffer_size, DRM_MEM_BUFS); drm_free(mask, mask_size, DRM_MEM_BUFS); - return DRM_ERR(EFAULT); + return -EFAULT; } for (i = 0; i < count; i++) { @@ -1115,13 +1116,13 @@ static int r128_cce_dispatch_read_span(struct drm_device * dev, count = depth->n; if (count > 4096 || count <= 0) - return DRM_ERR(EMSGSIZE); + return -EMSGSIZE; if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) { - return DRM_ERR(EFAULT); + return -EFAULT; } if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) { - return DRM_ERR(EFAULT); + return -EFAULT; } BEGIN_RING(7); @@ -1159,7 +1160,7 @@ static int r128_cce_dispatch_read_pixels(struct drm_device * dev, count = depth->n; if (count > 4096 || count <= 0) - return DRM_ERR(EMSGSIZE); + return -EMSGSIZE; if (count > dev_priv->depth_pitch) { count = dev_priv->depth_pitch; @@ -1169,22 +1170,22 @@ static int r128_cce_dispatch_read_pixels(struct drm_device * dev, ybuf_size = count * sizeof(*y); x = drm_alloc(xbuf_size, DRM_MEM_BUFS); if (x == NULL) { - return DRM_ERR(ENOMEM); + return -ENOMEM; } y = drm_alloc(ybuf_size, DRM_MEM_BUFS); if (y == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (DRM_COPY_FROM_USER(x, depth->x, xbuf_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); - return DRM_ERR(EFAULT); + return -EFAULT; } if (DRM_COPY_FROM_USER(y, depth->y, ybuf_size)) { drm_free(x, xbuf_size, DRM_MEM_BUFS); drm_free(y, ybuf_size, DRM_MEM_BUFS); - return DRM_ERR(EFAULT); + return -EFAULT; } for (i = 0; i < count; i++) { @@ -1241,25 +1242,21 @@ static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple) * IOCTL functions */ -static int r128_cce_clear(DRM_IOCTL_ARGS) +static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_r128_clear_t clear; + drm_r128_clear_t *clear = data; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(clear, (drm_r128_clear_t __user *) data, - sizeof(clear)); + LOCK_TEST_WITH_RETURN(dev, file_priv); RING_SPACE_TEST_WITH_RETURN(dev_priv); if (sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS) sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; - r128_cce_dispatch_clear(dev, &clear); + r128_cce_dispatch_clear(dev, clear); COMMIT_RING(); /* Make sure we restore the 3D state next time. @@ -1309,13 +1306,12 @@ static int r128_do_cleanup_pageflip(struct drm_device * dev) * They can & should be intermixed to support multiple 3d windows. */ -static int r128_cce_flip(DRM_IOCTL_ARGS) +static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -1328,14 +1324,13 @@ static int r128_cce_flip(DRM_IOCTL_ARGS) return 0; } -static int r128_cce_swap(DRM_IOCTL_ARGS) +static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -1350,58 +1345,54 @@ static int r128_cce_swap(DRM_IOCTL_ARGS) return 0; } -static int r128_cce_vertex(DRM_IOCTL_ARGS) +static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; drm_r128_buf_priv_t *buf_priv; - drm_r128_vertex_t vertex; + drm_r128_vertex_t *vertex = data; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(vertex, (drm_r128_vertex_t __user *) data, - sizeof(vertex)); - DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", - DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard); + DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); - if (vertex.idx < 0 || vertex.idx >= dma->buf_count) { + if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", - vertex.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + vertex->idx, dma->buf_count - 1); + return -EINVAL; } - if (vertex.prim < 0 || - vertex.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { - DRM_ERROR("buffer prim %d\n", vertex.prim); - return DRM_ERR(EINVAL); + if (vertex->prim < 0 || + vertex->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { + DRM_ERROR("buffer prim %d\n", vertex->prim); + return -EINVAL; } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - buf = dma->buflist[vertex.idx]; + buf = dma->buflist[vertex->idx]; buf_priv = buf->dev_private; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->filp); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex.idx); - return DRM_ERR(EINVAL); + DRM_ERROR("sending pending buffer %d\n", vertex->idx); + return -EINVAL; } - buf->used = vertex.count; - buf_priv->prim = vertex.prim; - buf_priv->discard = vertex.discard; + buf->used = vertex->count; + buf_priv->prim = vertex->prim; + buf_priv->discard = vertex->discard; r128_cce_dispatch_vertex(dev, buf); @@ -1409,134 +1400,123 @@ static int r128_cce_vertex(DRM_IOCTL_ARGS) return 0; } -static int r128_cce_indices(DRM_IOCTL_ARGS) +static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; drm_r128_buf_priv_t *buf_priv; - drm_r128_indices_t elts; + drm_r128_indices_t *elts = data; int count; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(elts, (drm_r128_indices_t __user *) data, - sizeof(elts)); - DRM_DEBUG("pid=%d buf=%d s=%d e=%d d=%d\n", DRM_CURRENTPID, - elts.idx, elts.start, elts.end, elts.discard); + elts->idx, elts->start, elts->end, elts->discard); - if (elts.idx < 0 || elts.idx >= dma->buf_count) { + if (elts->idx < 0 || elts->idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", - elts.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + elts->idx, dma->buf_count - 1); + return -EINVAL; } - if (elts.prim < 0 || elts.prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { - DRM_ERROR("buffer prim %d\n", elts.prim); - return DRM_ERR(EINVAL); + if (elts->prim < 0 || + elts->prim > R128_CCE_VC_CNTL_PRIM_TYPE_TRI_TYPE2) { + DRM_ERROR("buffer prim %d\n", elts->prim); + return -EINVAL; } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - buf = dma->buflist[elts.idx]; + buf = dma->buflist[elts->idx]; buf_priv = buf->dev_private; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->filp); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", elts.idx); - return DRM_ERR(EINVAL); + DRM_ERROR("sending pending buffer %d\n", elts->idx); + return -EINVAL; } - count = (elts.end - elts.start) / sizeof(u16); - elts.start -= R128_INDEX_PRIM_OFFSET; + count = (elts->end - elts->start) / sizeof(u16); + elts->start -= R128_INDEX_PRIM_OFFSET; - if (elts.start & 0x7) { - DRM_ERROR("misaligned buffer 0x%x\n", elts.start); - return DRM_ERR(EINVAL); + if (elts->start & 0x7) { + DRM_ERROR("misaligned buffer 0x%x\n", elts->start); + return -EINVAL; } - if (elts.start < buf->used) { - DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used); - return DRM_ERR(EINVAL); + if (elts->start < buf->used) { + DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); + return -EINVAL; } - buf->used = elts.end; - buf_priv->prim = elts.prim; - buf_priv->discard = elts.discard; + buf->used = elts->end; + buf_priv->prim = elts->prim; + buf_priv->discard = elts->discard; - r128_cce_dispatch_indices(dev, buf, elts.start, elts.end, count); + r128_cce_dispatch_indices(dev, buf, elts->start, elts->end, count); COMMIT_RING(); return 0; } -static int r128_cce_blit(DRM_IOCTL_ARGS) +static int r128_cce_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; struct drm_device_dma *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_blit_t blit; + drm_r128_blit_t *blit = data; int ret; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(blit, (drm_r128_blit_t __user *) data, - sizeof(blit)); + LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit.idx); + DRM_DEBUG("pid=%d index=%d\n", DRM_CURRENTPID, blit->idx); - if (blit.idx < 0 || blit.idx >= dma->buf_count) { + if (blit->idx < 0 || blit->idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", - blit.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + blit->idx, dma->buf_count - 1); + return -EINVAL; } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - ret = r128_cce_dispatch_blit(filp, dev, &blit); + ret = r128_cce_dispatch_blit(dev, file_priv, blit); COMMIT_RING(); return ret; } -static int r128_cce_depth(DRM_IOCTL_ARGS) +static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_depth_t depth; + drm_r128_depth_t *depth = data; int ret; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(depth, (drm_r128_depth_t __user *) data, - sizeof(depth)); + LOCK_TEST_WITH_RETURN(dev, file_priv); RING_SPACE_TEST_WITH_RETURN(dev_priv); - ret = DRM_ERR(EINVAL); - switch (depth.func) { + ret = -EINVAL; + switch (depth->func) { case R128_WRITE_SPAN: - ret = r128_cce_dispatch_write_span(dev, &depth); + ret = r128_cce_dispatch_write_span(dev, depth); break; case R128_WRITE_PIXELS: - ret = r128_cce_dispatch_write_pixels(dev, &depth); + ret = r128_cce_dispatch_write_pixels(dev, depth); break; case R128_READ_SPAN: - ret = r128_cce_dispatch_read_span(dev, &depth); + ret = r128_cce_dispatch_read_span(dev, depth); break; case R128_READ_PIXELS: - ret = r128_cce_dispatch_read_pixels(dev, &depth); + ret = r128_cce_dispatch_read_pixels(dev, depth); break; } @@ -1544,20 +1524,16 @@ static int r128_cce_depth(DRM_IOCTL_ARGS) return ret; } -static int r128_cce_stipple(DRM_IOCTL_ARGS) +static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_stipple_t stipple; + drm_r128_stipple_t *stipple = data; u32 mask[32]; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(stipple, (drm_r128_stipple_t __user *) data, - sizeof(stipple)); + LOCK_TEST_WITH_RETURN(dev, file_priv); - if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32))) - return DRM_ERR(EFAULT); + if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) + return -EFAULT; RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -1567,61 +1543,58 @@ static int r128_cce_stipple(DRM_IOCTL_ARGS) return 0; } -static int r128_cce_indirect(DRM_IOCTL_ARGS) +static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; drm_r128_buf_priv_t *buf_priv; - drm_r128_indirect_t indirect; + drm_r128_indirect_t *indirect = data; #if 0 RING_LOCALS; #endif - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(indirect, (drm_r128_indirect_t __user *) data, - sizeof(indirect)); - DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n", - indirect.idx, indirect.start, indirect.end, indirect.discard); + indirect->idx, indirect->start, indirect->end, + indirect->discard); - if (indirect.idx < 0 || indirect.idx >= dma->buf_count) { + if (indirect->idx < 0 || indirect->idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", - indirect.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + indirect->idx, dma->buf_count - 1); + return -EINVAL; } - buf = dma->buflist[indirect.idx]; + buf = dma->buflist[indirect->idx]; buf_priv = buf->dev_private; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->filp); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", indirect.idx); - return DRM_ERR(EINVAL); + DRM_ERROR("sending pending buffer %d\n", indirect->idx); + return -EINVAL; } - if (indirect.start < buf->used) { + if (indirect->start < buf->used) { DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", - indirect.start, buf->used); - return DRM_ERR(EINVAL); + indirect->start, buf->used); + return -EINVAL; } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - buf->used = indirect.end; - buf_priv->discard = indirect.discard; + buf->used = indirect->end; + buf_priv->discard = indirect->discard; #if 0 /* Wait for the 3D stream to idle before the indirect buffer @@ -1636,46 +1609,42 @@ static int r128_cce_indirect(DRM_IOCTL_ARGS) * X server. This is insecure and is thus only available to * privileged clients. */ - r128_cce_dispatch_indirect(dev, buf, indirect.start, indirect.end); + r128_cce_dispatch_indirect(dev, buf, indirect->start, indirect->end); COMMIT_RING(); return 0; } -static int r128_getparam(DRM_IOCTL_ARGS) +static int r128_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_getparam_t param; + drm_r128_getparam_t *param = data; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(param, (drm_r128_getparam_t __user *) data, - sizeof(param)); - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); - switch (param.param) { + switch (param->param) { case R128_PARAM_IRQ_NR: value = dev->irq; break; default: - return DRM_ERR(EINVAL); + return -EINVAL; } - if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { + if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; } -void r128_driver_preclose(struct drm_device * dev, DRMFILE filp) +void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) { if (dev->dev_private) { drm_r128_private_t *dev_priv = dev->dev_private; @@ -1690,24 +1659,24 @@ void r128_driver_lastclose(struct drm_device * dev) r128_do_cleanup_cce(dev); } -drm_ioctl_desc_t r128_ioctls[] = { - [DRM_IOCTL_NR(DRM_R128_INIT)] = {r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_R128_CCE_START)] = {r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_R128_CCE_STOP)] = {r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_R128_CCE_RESET)] = {r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_R128_CCE_IDLE)] = {r128_cce_idle, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_RESET)] = {r128_engine_reset, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_FULLSCREEN)] = {r128_fullscreen, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_SWAP)] = {r128_cce_swap, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_FLIP)] = {r128_cce_flip, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_CLEAR)] = {r128_cce_clear, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_VERTEX)] = {r128_cce_vertex, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_INDICES)] = {r128_cce_indices, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_BLIT)] = {r128_cce_blit, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_DEPTH)] = {r128_cce_depth, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_STIPPLE)] = {r128_cce_stipple, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_R128_INDIRECT)] = {r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_R128_GETPARAM)] = {r128_getparam, DRM_AUTH}, +struct drm_ioctl_desc r128_ioctls[] = { + DRM_IOCTL_DEF(DRM_R128_INIT, r128_cce_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_R128_CCE_START, r128_cce_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_R128_CCE_STOP, r128_cce_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_R128_CCE_RESET, r128_cce_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_R128_CCE_IDLE, r128_cce_idle, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_RESET, r128_engine_reset, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_FULLSCREEN, r128_fullscreen, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_SWAP, r128_cce_swap, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_FLIP, r128_cce_flip, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_CLEAR, r128_cce_clear, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_VERTEX, r128_cce_vertex, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_INDICES, r128_cce_indices, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_BLIT, r128_cce_blit, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_DEPTH, r128_cce_depth, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_STIPPLE, r128_cce_stipple, DRM_AUTH), + DRM_IOCTL_DEF(DRM_R128_INDIRECT, r128_cce_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_R128_GETPARAM, r128_getparam, DRM_AUTH), }; int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls); diff --git a/drivers/char/drm/r300_cmdbuf.c b/drivers/char/drm/r300_cmdbuf.c index 4e5aca6ba59a..59b2944811c5 100644 --- a/drivers/char/drm/r300_cmdbuf.c +++ b/drivers/char/drm/r300_cmdbuf.c @@ -74,7 +74,7 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, if (DRM_COPY_FROM_USER_UNCHECKED (&box, &cmdbuf->boxes[n + i], sizeof(box))) { DRM_ERROR("copy cliprect faulted\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } box.x1 = @@ -263,7 +263,7 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * DRM_ERROR ("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n", reg, sz); - return DRM_ERR(EINVAL); + return -EINVAL; } for (i = 0; i < sz; i++) { values[i] = ((int *)cmdbuf->buf)[i]; @@ -275,13 +275,13 @@ static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * DRM_ERROR ("Offset failed range check (reg=%04x sz=%d)\n", reg, sz); - return DRM_ERR(EINVAL); + return -EINVAL; } break; default: DRM_ERROR("Register %04x failed check as flag=%02x\n", reg + i * 4, r300_reg_flags[(reg >> 2) + i]); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -317,12 +317,12 @@ static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv, return 0; if (sz * 4 > cmdbuf->bufsz) - return DRM_ERR(EINVAL); + return -EINVAL; if (reg + sz * 4 >= 0x10000) { DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, sz); - return DRM_ERR(EINVAL); + return -EINVAL; } if (r300_check_range(reg, sz)) { @@ -362,7 +362,7 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv, if (!sz) return 0; if (sz * 16 > cmdbuf->bufsz) - return DRM_ERR(EINVAL); + return -EINVAL; BEGIN_RING(5 + sz * 4); /* Wait for VAP to come to senses.. */ @@ -391,7 +391,7 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv, RING_LOCALS; if (8 * 4 > cmdbuf->bufsz) - return DRM_ERR(EINVAL); + return -EINVAL; BEGIN_RING(10); OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8)); @@ -421,7 +421,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, if ((count + 1) > MAX_ARRAY_PACKET) { DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", count); - return DRM_ERR(EINVAL); + return -EINVAL; } memset(payload, 0, MAX_ARRAY_PACKET * 4); memcpy(payload, cmdbuf->buf + 4, (count + 1) * 4); @@ -437,7 +437,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, DRM_ERROR ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", k, i); - return DRM_ERR(EINVAL); + return -EINVAL; } k++; i++; @@ -448,7 +448,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, DRM_ERROR ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", k, i); - return DRM_ERR(EINVAL); + return -EINVAL; } k++; i++; @@ -458,7 +458,7 @@ static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, DRM_ERROR ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", k, i, narrays, count + 1); - return DRM_ERR(EINVAL); + return -EINVAL; } /* all clear, output packet */ @@ -492,7 +492,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, ret = !radeon_check_offset(dev_priv, offset); if (ret) { DRM_ERROR("Invalid bitblt first offset is %08X\n", offset); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -502,7 +502,7 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, ret = !radeon_check_offset(dev_priv, offset); if (ret) { DRM_ERROR("Invalid bitblt second offset is %08X\n", offset); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -530,12 +530,12 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, if ((cmd[1] & 0x8000ffff) != 0x80000810) { DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); - return DRM_ERR(EINVAL); + return -EINVAL; } ret = !radeon_check_offset(dev_priv, cmd[2]); if (ret) { DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); - return DRM_ERR(EINVAL); + return -EINVAL; } BEGIN_RING(count+2); @@ -557,7 +557,7 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, RING_LOCALS; if (4 > cmdbuf->bufsz) - return DRM_ERR(EINVAL); + return -EINVAL; /* Fixme !! This simply emits a packet without much checking. We need to be smarter. */ @@ -568,7 +568,7 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, /* Is it packet 3 ? */ if ((header >> 30) != 0x3) { DRM_ERROR("Not a packet3 header (0x%08x)\n", header); - return DRM_ERR(EINVAL); + return -EINVAL; } count = (header >> 16) & 0x3fff; @@ -578,7 +578,7 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, DRM_ERROR ("Expected packet3 of length %d but have only %d bytes left\n", (count + 2) * 4, cmdbuf->bufsz); - return DRM_ERR(EINVAL); + return -EINVAL; } /* Is it a packet type we know about ? */ @@ -600,7 +600,7 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, break; default: DRM_ERROR("Unknown packet3 header (0x%08x)\n", header); - return DRM_ERR(EINVAL); + return -EINVAL; } BEGIN_RING(count + 2); @@ -664,7 +664,7 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv, DRM_ERROR("bad packet3 type %i at %p\n", header.packet3.packet, cmdbuf->buf - sizeof(header)); - return DRM_ERR(EINVAL); + return -EINVAL; } n += R300_SIMULTANEOUS_CLIPRECTS; @@ -726,11 +726,11 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, if (cmdbuf->bufsz < (sizeof(u64) + header.scratch.n_bufs * sizeof(buf_idx))) { - return DRM_ERR(EINVAL); + return -EINVAL; } if (header.scratch.reg >= 5) { - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->scratch_ages[header.scratch.reg]++; @@ -745,21 +745,21 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, buf_idx *= 2; /* 8 bytes per buf */ if (DRM_COPY_TO_USER(ref_age_base + buf_idx, &dev_priv->scratch_ages[header.scratch.reg], sizeof(u32))) { - return DRM_ERR(EINVAL); + return -EINVAL; } if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { - return DRM_ERR(EINVAL); + return -EINVAL; } if (h_pending == 0) { - return DRM_ERR(EINVAL); + return -EINVAL; } h_pending--; if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { - return DRM_ERR(EINVAL); + return -EINVAL; } cmdbuf->buf += sizeof(buf_idx); @@ -780,8 +780,7 @@ static int r300_scratch(drm_radeon_private_t *dev_priv, * Called by the ioctl handler function radeon_cp_cmdbuf. */ int r300_do_cp_cmdbuf(struct drm_device *dev, - DRMFILE filp, - struct drm_file *filp_priv, + struct drm_file *file_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -879,15 +878,16 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, if (idx < 0 || idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", idx, dma->buf_count - 1); - ret = DRM_ERR(EINVAL); + ret = -EINVAL; goto cleanup; } buf = dma->buflist[idx]; - if (buf->filp != filp || buf->pending) { + if (buf->file_priv != file_priv || buf->pending) { DRM_ERROR("bad buffer %p %p %d\n", - buf->filp, filp, buf->pending); - ret = DRM_ERR(EINVAL); + buf->file_priv, file_priv, + buf->pending); + ret = -EINVAL; goto cleanup; } @@ -924,7 +924,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, DRM_ERROR("bad cmd_type %i at %p\n", header.header.cmd_type, cmdbuf->buf - sizeof(header)); - ret = DRM_ERR(EINVAL); + ret = -EINVAL; goto cleanup; } } diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c index af5790f8fd53..335423c5c186 100644 --- a/drivers/char/drm/radeon_cp.c +++ b/drivers/char/drm/radeon_cp.c @@ -889,7 +889,7 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) @@ -910,7 +910,7 @@ static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) @@ -936,7 +936,7 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } /* ================================================================ @@ -1394,7 +1394,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { @@ -1409,7 +1409,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) { DRM_ERROR("PCI GART memory not allocated!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->usec_timeout = init->usec_timeout; @@ -1417,7 +1417,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { DRM_DEBUG("TIMEOUT problem!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } /* Enable vblank on CRTC1 for older X servers @@ -1446,7 +1446,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } switch (init->fb_bpp) { @@ -1515,27 +1515,27 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) if (!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset); if (!dev_priv->cp_ring) { DRM_ERROR("could not find cp ring region!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset); if (!dev_priv->ring_rptr) { DRM_ERROR("could not find ring read pointer!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev->agp_buffer_token = init->buffers_offset; dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset); if (!dev->agp_buffer_map) { DRM_ERROR("could not find dma buffer region!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } if (init->gart_textures_offset) { @@ -1544,7 +1544,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) if (!dev_priv->gart_textures) { DRM_ERROR("could not find GART texture region!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -1562,7 +1562,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) !dev->agp_buffer_map->handle) { DRM_ERROR("could not find ioremap agp regions!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } } else #endif @@ -1710,14 +1710,14 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init) DRM_ERROR ("Cannot use PCI Express without GART in FB memory\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } } if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) { DRM_ERROR("failed to init PCI GART!\n"); radeon_do_cleanup_cp(dev); - return DRM_ERR(ENOMEM); + return -ENOMEM; } /* Turn on PCI GART */ @@ -1797,7 +1797,7 @@ static int radeon_do_resume_cp(struct drm_device * dev) if (!dev_priv) { DRM_ERROR("Called with no initialization\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } DRM_DEBUG("Starting radeon_do_resume_cp()\n"); @@ -1823,38 +1823,33 @@ static int radeon_do_resume_cp(struct drm_device * dev) return 0; } -int radeon_cp_init(DRM_IOCTL_ARGS) +int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_radeon_init_t init; + drm_radeon_init_t *init = data; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_COPY_FROM_USER_IOCTL(init, (drm_radeon_init_t __user *) data, - sizeof(init)); - - if (init.func == RADEON_INIT_R300_CP) + if (init->func == RADEON_INIT_R300_CP) r300_init_reg_flags(); - switch (init.func) { + switch (init->func) { case RADEON_INIT_CP: case RADEON_INIT_R200_CP: case RADEON_INIT_R300_CP: - return radeon_do_init_cp(dev, &init); + return radeon_do_init_cp(dev, init); case RADEON_CLEANUP_CP: return radeon_do_cleanup_cp(dev); } - return DRM_ERR(EINVAL); + return -EINVAL; } -int radeon_cp_start(DRM_IOCTL_ARGS) +int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (dev_priv->cp_running) { DRM_DEBUG("%s while CP running\n", __FUNCTION__); @@ -1874,18 +1869,14 @@ int radeon_cp_start(DRM_IOCTL_ARGS) /* Stop the CP. The engine must have been idled before calling this * routine. */ -int radeon_cp_stop(DRM_IOCTL_ARGS) +int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_cp_stop_t stop; + drm_radeon_cp_stop_t *stop = data; int ret; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(stop, (drm_radeon_cp_stop_t __user *) data, - sizeof(stop)); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv->cp_running) return 0; @@ -1893,14 +1884,14 @@ int radeon_cp_stop(DRM_IOCTL_ARGS) /* Flush any pending CP commands. This ensures any outstanding * commands are exectuted by the engine before we turn it off. */ - if (stop.flush) { + if (stop->flush) { radeon_do_cp_flush(dev_priv); } /* If we fail to make the engine go idle, we return an error * code so that the DRM ioctl wrapper can try again. */ - if (stop.idle) { + if (stop->idle) { ret = radeon_do_cp_idle(dev_priv); if (ret) return ret; @@ -1963,17 +1954,16 @@ void radeon_do_release(struct drm_device * dev) /* Just reset the CP ring. Called as part of an X Server engine reset. */ -int radeon_cp_reset(DRM_IOCTL_ARGS) +int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_DEBUG("%s called before init done\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } radeon_do_cp_reset(dev_priv); @@ -1984,32 +1974,29 @@ int radeon_cp_reset(DRM_IOCTL_ARGS) return 0; } -int radeon_cp_idle(DRM_IOCTL_ARGS) +int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); return radeon_do_cp_idle(dev_priv); } /* Added by Charl P. Botha to call radeon_do_resume_cp(). */ -int radeon_cp_resume(DRM_IOCTL_ARGS) +int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; return radeon_do_resume_cp(dev); } -int radeon_engine_reset(DRM_IOCTL_ARGS) +int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); return radeon_do_engine_reset(dev); } @@ -2020,7 +2007,7 @@ int radeon_engine_reset(DRM_IOCTL_ARGS) /* KW: Deprecated to say the least: */ -int radeon_fullscreen(DRM_IOCTL_ARGS) +int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) { return 0; } @@ -2066,8 +2053,9 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev) for (i = start; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; - if (buf->filp == 0 || (buf->pending && - buf_priv->age <= done_age)) { + if (buf->file_priv == NULL || (buf->pending && + buf_priv->age <= + done_age)) { dev_priv->stats.requested_bufs++; buf->pending = 0; return buf; @@ -2106,8 +2094,9 @@ struct drm_buf *radeon_freelist_get(struct drm_device * dev) for (i = start; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; - if (buf->filp == 0 || (buf->pending && - buf_priv->age <= done_age)) { + if (buf->file_priv == 0 || (buf->pending && + buf_priv->age <= + done_age)) { dev_priv->stats.requested_bufs++; buf->pending = 0; return buf; @@ -2167,10 +2156,11 @@ int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n) radeon_status(dev_priv); DRM_ERROR("failed!\n"); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } -static int radeon_cp_get_buffers(DRMFILE filp, struct drm_device * dev, +static int radeon_cp_get_buffers(struct drm_device *dev, + struct drm_file *file_priv, struct drm_dma * d) { int i; @@ -2179,58 +2169,52 @@ static int radeon_cp_get_buffers(DRMFILE filp, struct drm_device * dev, for (i = d->granted_count; i < d->request_count; i++) { buf = radeon_freelist_get(dev); if (!buf) - return DRM_ERR(EBUSY); /* NOTE: broken client */ + return -EBUSY; /* NOTE: broken client */ - buf->filp = filp; + buf->file_priv = file_priv; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return DRM_ERR(EFAULT); + return -EFAULT; if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return DRM_ERR(EFAULT); + return -EFAULT; d->granted_count++; } return 0; } -int radeon_cp_buffers(DRM_IOCTL_ARGS) +int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; struct drm_device_dma *dma = dev->dma; int ret = 0; - struct drm_dma __user *argp = (void __user *)data; - struct drm_dma d; + struct drm_dma *d = data; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); + LOCK_TEST_WITH_RETURN(dev, file_priv); /* Please don't send us buffers. */ - if (d.send_count != 0) { + if (d->send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - DRM_CURRENTPID, d.send_count); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, d->send_count); + return -EINVAL; } /* We'll send you buffers. */ - if (d.request_count < 0 || d.request_count > dma->buf_count) { + if (d->request_count < 0 || d->request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - DRM_CURRENTPID, d.request_count, dma->buf_count); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, d->request_count, dma->buf_count); + return -EINVAL; } - d.granted_count = 0; + d->granted_count = 0; - if (d.request_count) { - ret = radeon_cp_get_buffers(filp, dev, &d); + if (d->request_count) { + ret = radeon_cp_get_buffers(dev, file_priv, d); } - DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); - return ret; } @@ -2241,7 +2225,7 @@ int radeon_driver_load(struct drm_device *dev, unsigned long flags) dev_priv = drm_alloc(sizeof(drm_radeon_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; memset(dev_priv, 0, sizeof(drm_radeon_private_t)); dev->dev_private = (void *)dev_priv; diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h index 3b3d9357201c..e4077bc212b3 100644 --- a/drivers/char/drm/radeon_drv.h +++ b/drivers/char/drm/radeon_drv.h @@ -188,7 +188,7 @@ struct mem_block { struct mem_block *prev; int start; int size; - DRMFILE filp; /* 0: free, -1: heap, other: real files */ + struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ }; struct radeon_surface { @@ -203,7 +203,7 @@ struct radeon_virt_surface { u32 lower; u32 upper; u32 flags; - DRMFILE filp; + struct drm_file *file_priv; }; typedef struct drm_radeon_private { @@ -307,7 +307,7 @@ typedef struct drm_radeon_kcmd_buffer { } drm_radeon_kcmd_buffer_t; extern int radeon_no_wb; -extern drm_ioctl_desc_t radeon_ioctls[]; +extern struct drm_ioctl_desc radeon_ioctls[]; extern int radeon_max_ioctl; /* Check whether the given hardware address is inside the framebuffer or the @@ -326,15 +326,15 @@ static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv, } /* radeon_cp.c */ -extern int radeon_cp_init(DRM_IOCTL_ARGS); -extern int radeon_cp_start(DRM_IOCTL_ARGS); -extern int radeon_cp_stop(DRM_IOCTL_ARGS); -extern int radeon_cp_reset(DRM_IOCTL_ARGS); -extern int radeon_cp_idle(DRM_IOCTL_ARGS); -extern int radeon_cp_resume(DRM_IOCTL_ARGS); -extern int radeon_engine_reset(DRM_IOCTL_ARGS); -extern int radeon_fullscreen(DRM_IOCTL_ARGS); -extern int radeon_cp_buffers(DRM_IOCTL_ARGS); +extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void radeon_freelist_reset(struct drm_device * dev); extern struct drm_buf *radeon_freelist_get(struct drm_device * dev); @@ -347,15 +347,16 @@ extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags); extern int radeon_presetup(struct drm_device *dev); extern int radeon_driver_postcleanup(struct drm_device *dev); -extern int radeon_mem_alloc(DRM_IOCTL_ARGS); -extern int radeon_mem_free(DRM_IOCTL_ARGS); -extern int radeon_mem_init_heap(DRM_IOCTL_ARGS); +extern int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void radeon_mem_takedown(struct mem_block **heap); -extern void radeon_mem_release(DRMFILE filp, struct mem_block *heap); +extern void radeon_mem_release(struct drm_file *file_priv, + struct mem_block *heap); /* radeon_irq.c */ -extern int radeon_irq_emit(DRM_IOCTL_ARGS); -extern int radeon_irq_wait(DRM_IOCTL_ARGS); +extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); extern void radeon_do_release(struct drm_device * dev); extern int radeon_driver_vblank_wait(struct drm_device * dev, @@ -372,7 +373,7 @@ extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value); extern int radeon_driver_load(struct drm_device *dev, unsigned long flags); extern int radeon_driver_unload(struct drm_device *dev); extern int radeon_driver_firstopen(struct drm_device *dev); -extern void radeon_driver_preclose(struct drm_device * dev, DRMFILE filp); +extern void radeon_driver_preclose(struct drm_device * dev, struct drm_file *file_priv); extern void radeon_driver_postclose(struct drm_device * dev, struct drm_file * filp); extern void radeon_driver_lastclose(struct drm_device * dev); extern int radeon_driver_open(struct drm_device * dev, struct drm_file * filp_priv); @@ -382,8 +383,8 @@ extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, /* r300_cmdbuf.c */ extern void r300_init_reg_flags(void); -extern int r300_do_cp_cmdbuf(struct drm_device * dev, DRMFILE filp, - struct drm_file * filp_priv, +extern int r300_do_cp_cmdbuf(struct drm_device * dev, + struct drm_file *file_priv, drm_radeon_kcmd_buffer_t * cmdbuf); /* Flags for stats.boxes diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c index ad8a0ac7182e..f89e57665b64 100644 --- a/drivers/char/drm/radeon_irq.c +++ b/drivers/char/drm/radeon_irq.c @@ -155,7 +155,7 @@ int radeon_driver_vblank_do_wait(struct drm_device * dev, unsigned int *sequence atomic_t *counter; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } if (crtc == DRM_RADEON_VBLANK_CRTC1) { @@ -165,7 +165,7 @@ int radeon_driver_vblank_do_wait(struct drm_device * dev, unsigned int *sequence counter = &dev->vbl_received2; ack |= RADEON_CRTC2_VBLANK_STAT; } else - return DRM_ERR(EINVAL); + return -EINVAL; radeon_acknowledge_irqs(dev_priv, ack); @@ -196,28 +196,24 @@ int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) /* Needs the lock as it touches the ring. */ -int radeon_irq_emit(DRM_IOCTL_ARGS) +int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_irq_emit_t emit; + drm_radeon_irq_emit_t *emit = data; int result; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(emit, (drm_radeon_irq_emit_t __user *) data, - sizeof(emit)); - result = radeon_emit_irq(dev); - if (DRM_COPY_TO_USER(emit.irq_seq, &result, sizeof(int))) { + if (DRM_COPY_TO_USER(emit->irq_seq, &result, sizeof(int))) { DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; @@ -225,21 +221,17 @@ int radeon_irq_emit(DRM_IOCTL_ARGS) /* Doesn't need the hardware lock. */ -int radeon_irq_wait(DRM_IOCTL_ARGS) +int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_irq_wait_t irqwait; + drm_radeon_irq_wait_t *irqwait = data; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_radeon_irq_wait_t __user *) data, - sizeof(irqwait)); - - return radeon_wait_irq(dev, irqwait.irq_seq); + return radeon_wait_irq(dev, irqwait->irq_seq); } static void radeon_enable_interrupt(struct drm_device *dev) @@ -320,7 +312,7 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->vblank_crtc = (unsigned int)value; radeon_enable_interrupt(dev); diff --git a/drivers/char/drm/radeon_mem.c b/drivers/char/drm/radeon_mem.c index 517cad8b6e3a..a29acfe2f973 100644 --- a/drivers/char/drm/radeon_mem.c +++ b/drivers/char/drm/radeon_mem.c @@ -39,7 +39,7 @@ */ static struct mem_block *split_block(struct mem_block *p, int start, int size, - DRMFILE filp) + struct drm_file *file_priv) { /* Maybe cut off the start of an existing block */ if (start > p->start) { @@ -49,7 +49,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size, goto out; newblock->start = start; newblock->size = p->size - (start - p->start); - newblock->filp = NULL; + newblock->file_priv = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; @@ -66,7 +66,7 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size, goto out; newblock->start = start + size; newblock->size = p->size - size; - newblock->filp = NULL; + newblock->file_priv = NULL; newblock->next = p->next; newblock->prev = p; p->next->prev = newblock; @@ -76,20 +76,20 @@ static struct mem_block *split_block(struct mem_block *p, int start, int size, out: /* Our block is in the middle */ - p->filp = filp; + p->file_priv = file_priv; return p; } static struct mem_block *alloc_block(struct mem_block *heap, int size, - int align2, DRMFILE filp) + int align2, struct drm_file *file_priv) { struct mem_block *p; int mask = (1 << align2) - 1; list_for_each(p, heap) { int start = (p->start + mask) & ~mask; - if (p->filp == 0 && start + size <= p->start + p->size) - return split_block(p, start, size, filp); + if (p->file_priv == 0 && start + size <= p->start + p->size) + return split_block(p, start, size, file_priv); } return NULL; @@ -108,12 +108,12 @@ static struct mem_block *find_block(struct mem_block *heap, int start) static void free_block(struct mem_block *p) { - p->filp = NULL; + p->file_priv = NULL; - /* Assumes a single contiguous range. Needs a special filp in + /* Assumes a single contiguous range. Needs a special file_priv in * 'heap' to stop it being subsumed. */ - if (p->next->filp == 0) { + if (p->next->file_priv == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; @@ -121,7 +121,7 @@ static void free_block(struct mem_block *p) drm_free(q, sizeof(*q), DRM_MEM_BUFS); } - if (p->prev->filp == 0) { + if (p->prev->file_priv == 0) { struct mem_block *q = p->prev; q->size += p->size; q->next = p->next; @@ -137,28 +137,28 @@ static int init_heap(struct mem_block **heap, int start, int size) struct mem_block *blocks = drm_alloc(sizeof(*blocks), DRM_MEM_BUFS); if (!blocks) - return DRM_ERR(ENOMEM); + return -ENOMEM; *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS); if (!*heap) { drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS); - return DRM_ERR(ENOMEM); + return -ENOMEM; } blocks->start = start; blocks->size = size; - blocks->filp = NULL; + blocks->file_priv = NULL; blocks->next = blocks->prev = *heap; memset(*heap, 0, sizeof(**heap)); - (*heap)->filp = (DRMFILE) - 1; + (*heap)->file_priv = (struct drm_file *) - 1; (*heap)->next = (*heap)->prev = blocks; return 0; } /* Free all blocks associated with the releasing file. */ -void radeon_mem_release(DRMFILE filp, struct mem_block *heap) +void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap) { struct mem_block *p; @@ -166,15 +166,15 @@ void radeon_mem_release(DRMFILE filp, struct mem_block *heap) return; list_for_each(p, heap) { - if (p->filp == filp) - p->filp = NULL; + if (p->file_priv == file_priv) + p->file_priv = NULL; } - /* Assumes a single contiguous range. Needs a special filp in + /* Assumes a single contiguous range. Needs a special file_priv in * 'heap' to stop it being subsumed. */ list_for_each(p, heap) { - while (p->filp == 0 && p->next->filp == 0) { + while (p->file_priv == 0 && p->next->file_priv == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; @@ -217,98 +217,86 @@ static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region) } } -int radeon_mem_alloc(DRM_IOCTL_ARGS) +int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_alloc_t alloc; + drm_radeon_mem_alloc_t *alloc = data; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_mem_alloc_t __user *) data, - sizeof(alloc)); - - heap = get_heap(dev_priv, alloc.region); + heap = get_heap(dev_priv, alloc->region); if (!heap || !*heap) - return DRM_ERR(EFAULT); + return -EFAULT; /* Make things easier on ourselves: all allocations at least * 4k aligned. */ - if (alloc.alignment < 12) - alloc.alignment = 12; + if (alloc->alignment < 12) + alloc->alignment = 12; - block = alloc_block(*heap, alloc.size, alloc.alignment, filp); + block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); if (!block) - return DRM_ERR(ENOMEM); + return -ENOMEM; - if (DRM_COPY_TO_USER(alloc.region_offset, &block->start, sizeof(int))) { + if (DRM_COPY_TO_USER(alloc->region_offset, &block->start, + sizeof(int))) { DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; } -int radeon_mem_free(DRM_IOCTL_ARGS) +int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_free_t memfree; + drm_radeon_mem_free_t *memfree = data; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data, - sizeof(memfree)); - - heap = get_heap(dev_priv, memfree.region); + heap = get_heap(dev_priv, memfree->region); if (!heap || !*heap) - return DRM_ERR(EFAULT); + return -EFAULT; - block = find_block(*heap, memfree.region_offset); + block = find_block(*heap, memfree->region_offset); if (!block) - return DRM_ERR(EFAULT); + return -EFAULT; - if (block->filp != filp) - return DRM_ERR(EPERM); + if (block->file_priv != file_priv) + return -EPERM; free_block(block); return 0; } -int radeon_mem_init_heap(DRM_IOCTL_ARGS) +int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_init_heap_t initheap; + drm_radeon_mem_init_heap_t *initheap = data; struct mem_block **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - DRM_COPY_FROM_USER_IOCTL(initheap, - (drm_radeon_mem_init_heap_t __user *) data, - sizeof(initheap)); - - heap = get_heap(dev_priv, initheap.region); + heap = get_heap(dev_priv, initheap->region); if (!heap) - return DRM_ERR(EFAULT); + return -EFAULT; if (*heap) { DRM_ERROR("heap already initialized?"); - return DRM_ERR(EFAULT); + return -EFAULT; } - return init_heap(heap, initheap.start, initheap.size); + return init_heap(heap, initheap->start, initheap->size); } diff --git a/drivers/char/drm/radeon_state.c b/drivers/char/drm/radeon_state.c index 3ddf86f2abf0..69c9f2febf43 100644 --- a/drivers/char/drm/radeon_state.c +++ b/drivers/char/drm/radeon_state.c @@ -39,7 +39,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * dev_priv, - struct drm_file * filp_priv, + struct drm_file * file_priv, u32 *offset) { u64 off = *offset; @@ -71,7 +71,7 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * * magic offset we get from SETPARAM or calculated from fb_location */ if (off < (dev_priv->fb_size + dev_priv->gart_size)) { - radeon_priv = filp_priv->driver_priv; + radeon_priv = file_priv->driver_priv; off += radeon_priv->radeon_fb_delta; } @@ -85,29 +85,29 @@ static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * *offset = off; return 0; } - return DRM_ERR(EINVAL); + return -EINVAL; } static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * dev_priv, - struct drm_file * filp_priv, + struct drm_file *file_priv, int id, u32 *data) { switch (id) { case RADEON_EMIT_PP_MISC: - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) { DRM_ERROR("Invalid depth buffer offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } break; case RADEON_EMIT_PP_CNTL: - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) { DRM_ERROR("Invalid colour buffer offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } break; @@ -117,20 +117,20 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * case R200_EMIT_PP_TXOFFSET_3: case R200_EMIT_PP_TXOFFSET_4: case R200_EMIT_PP_TXOFFSET_5: - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &data[0])) { DRM_ERROR("Invalid R200 texture offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } break; case RADEON_EMIT_PP_TXFILTER_0: case RADEON_EMIT_PP_TXFILTER_1: case RADEON_EMIT_PP_TXFILTER_2: - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) { DRM_ERROR("Invalid R100 texture offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } break; @@ -143,11 +143,11 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * int i; for (i = 0; i < 5; i++) { if (radeon_check_and_fixup_offset(dev_priv, - filp_priv, + file_priv, &data[i])) { DRM_ERROR ("Invalid R200 cubic texture offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } } break; @@ -159,11 +159,11 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * int i; for (i = 0; i < 5; i++) { if (radeon_check_and_fixup_offset(dev_priv, - filp_priv, + file_priv, &data[i])) { DRM_ERROR ("Invalid R100 cubic texture offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } } } @@ -256,7 +256,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * default: DRM_ERROR("Unknown state packet ID %d\n", id); - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; @@ -264,7 +264,7 @@ static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * dev_priv, - struct drm_file *filp_priv, + struct drm_file *file_priv, drm_radeon_kcmd_buffer_t * cmdbuf, unsigned int *cmdsz) @@ -277,12 +277,12 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * if ((cmd[0] & 0xc0000000) != RADEON_CP_PACKET3) { DRM_ERROR("Not a type 3 packet\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } if (4 * *cmdsz > cmdbuf->bufsz) { DRM_ERROR("Packet size larger than size of data provided\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } switch(cmd[0] & 0xff00) { @@ -307,7 +307,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * /* safe but r200 only */ if (dev_priv->microcode_version != UCODE_R200) { DRM_ERROR("Invalid 3d packet for r100-class chip\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } break; @@ -317,7 +317,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * if (count > 18) { /* 12 arrays max */ DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", count); - return DRM_ERR(EINVAL); + return -EINVAL; } /* carefully check packet contents */ @@ -326,22 +326,25 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * i = 2; while ((k < narrays) && (i < (count + 2))) { i++; /* skip attribute field */ - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { + if (radeon_check_and_fixup_offset(dev_priv, file_priv, + &cmd[i])) { DRM_ERROR ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", k, i); - return DRM_ERR(EINVAL); + return -EINVAL; } k++; i++; if (k == narrays) break; /* have one more to process, they come in pairs */ - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { + if (radeon_check_and_fixup_offset(dev_priv, + file_priv, &cmd[i])) + { DRM_ERROR ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", k, i); - return DRM_ERR(EINVAL); + return -EINVAL; } k++; i++; @@ -351,33 +354,33 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * DRM_ERROR ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", k, i, narrays, count + 1); - return DRM_ERR(EINVAL); + return -EINVAL; } break; case RADEON_3D_RNDR_GEN_INDX_PRIM: if (dev_priv->microcode_version != UCODE_R100) { DRM_ERROR("Invalid 3d packet for r200-class chip\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) { + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) { DRM_ERROR("Invalid rndr_gen_indx offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } break; case RADEON_CP_INDX_BUFFER: if (dev_priv->microcode_version != UCODE_R200) { DRM_ERROR("Invalid 3d packet for r100-class chip\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } if ((cmd[1] & 0x8000ffff) != 0x80000810) { DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); - return DRM_ERR(EINVAL); + return -EINVAL; } - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) { + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) { DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); - return DRM_ERR(EINVAL); + return -EINVAL; } break; @@ -389,9 +392,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { offset = cmd[2] << 10; if (radeon_check_and_fixup_offset - (dev_priv, filp_priv, &offset)) { + (dev_priv, file_priv, &offset)) { DRM_ERROR("Invalid first packet offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10; } @@ -400,9 +403,9 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * (cmd[1] & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { offset = cmd[3] << 10; if (radeon_check_and_fixup_offset - (dev_priv, filp_priv, &offset)) { + (dev_priv, file_priv, &offset)) { DRM_ERROR("Invalid second packet offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; } @@ -410,7 +413,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * default: DRM_ERROR("Invalid packet type %x\n", cmd[0] & 0xff00); - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; @@ -439,7 +442,7 @@ static __inline__ void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv, /* Emit 1.1 state */ static int radeon_emit_state(drm_radeon_private_t * dev_priv, - struct drm_file * filp_priv, + struct drm_file *file_priv, drm_radeon_context_regs_t * ctx, drm_radeon_texture_regs_t * tex, unsigned int dirty) @@ -448,16 +451,16 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv, DRM_DEBUG("dirty=0x%08x\n", dirty); if (dirty & RADEON_UPLOAD_CONTEXT) { - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &ctx->rb3d_depthoffset)) { DRM_ERROR("Invalid depth buffer offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &ctx->rb3d_coloroffset)) { DRM_ERROR("Invalid depth buffer offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } BEGIN_RING(14); @@ -543,10 +546,10 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv, } if (dirty & RADEON_UPLOAD_TEX0) { - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex[0].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 0\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } BEGIN_RING(9); @@ -563,10 +566,10 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv, } if (dirty & RADEON_UPLOAD_TEX1) { - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex[1].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 1\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } BEGIN_RING(9); @@ -583,10 +586,10 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv, } if (dirty & RADEON_UPLOAD_TEX2) { - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex[2].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 2\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } BEGIN_RING(9); @@ -608,7 +611,7 @@ static int radeon_emit_state(drm_radeon_private_t * dev_priv, /* Emit 1.2 state */ static int radeon_emit_state2(drm_radeon_private_t * dev_priv, - struct drm_file * filp_priv, + struct drm_file *file_priv, drm_radeon_state_t * state) { RING_LOCALS; @@ -621,7 +624,7 @@ static int radeon_emit_state2(drm_radeon_private_t * dev_priv, ADVANCE_RING(); } - return radeon_emit_state(dev_priv, filp_priv, &state->context, + return radeon_emit_state(dev_priv, file_priv, &state->context, state->tex, state->dirty); } @@ -1646,13 +1649,12 @@ static void radeon_cp_dispatch_indices(struct drm_device * dev, #define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE -static int radeon_cp_dispatch_texture(DRMFILE filp, - struct drm_device * dev, +static int radeon_cp_dispatch_texture(struct drm_device * dev, + struct drm_file *file_priv, drm_radeon_texture_t * tex, drm_radeon_tex_image_t * image) { drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_file *filp_priv; struct drm_buf *buf; u32 format; u32 *buffer; @@ -1664,11 +1666,9 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, u32 offset; RING_LOCALS; - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); - - if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) { + if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) { DRM_ERROR("Invalid destination offset\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; @@ -1711,11 +1711,11 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, break; default: DRM_ERROR("invalid texture format %d\n", tex->format); - return DRM_ERR(EINVAL); + return -EINVAL; } spitch = blit_width >> 6; if (spitch == 0 && image->height > 1) - return DRM_ERR(EINVAL); + return -EINVAL; texpitch = tex->pitch; if ((texpitch << 22) & RADEON_DST_TILE_MICRO) { @@ -1760,8 +1760,8 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, if (!buf) { DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n"); if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) - return DRM_ERR(EFAULT); - return DRM_ERR(EAGAIN); + return -EFAULT; + return -EAGAIN; } /* Dispatch the indirect buffer. @@ -1774,7 +1774,7 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, do { \ if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\ DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \ - return DRM_ERR(EFAULT); \ + return -EFAULT; \ } \ } while(0) @@ -1841,7 +1841,7 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, } #undef RADEON_COPY_MT - buf->filp = filp; + buf->file_priv = file_priv; buf->used = size; offset = dev_priv->gart_buffers_offset + buf->offset; BEGIN_RING(9); @@ -1861,6 +1861,7 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, OUT_RING((image->width << 16) | height); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); + COMMIT_RING(); radeon_cp_discard_buffer(dev, buf); @@ -1878,6 +1879,8 @@ static int radeon_cp_dispatch_texture(DRMFILE filp, RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); + COMMIT_RING(); + return 0; } @@ -1929,7 +1932,8 @@ static void radeon_apply_surface_regs(int surf_index, * not always be available. */ static int alloc_surface(drm_radeon_surface_alloc_t *new, - drm_radeon_private_t *dev_priv, DRMFILE filp) + drm_radeon_private_t *dev_priv, + struct drm_file *file_priv) { struct radeon_virt_surface *s; int i; @@ -1959,7 +1963,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, /* find a virtual surface */ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) - if (dev_priv->virt_surfaces[i].filp == 0) + if (dev_priv->virt_surfaces[i].file_priv == 0) break; if (i == 2 * RADEON_MAX_SURFACES) { return -1; @@ -1977,7 +1981,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; - s->filp = filp; + s->file_priv = file_priv; dev_priv->surfaces[i].refcount++; dev_priv->surfaces[i].lower = s->lower; radeon_apply_surface_regs(s->surface_index, dev_priv); @@ -1993,7 +1997,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; - s->filp = filp; + s->file_priv = file_priv; dev_priv->surfaces[i].refcount++; dev_priv->surfaces[i].upper = s->upper; radeon_apply_surface_regs(s->surface_index, dev_priv); @@ -2009,7 +2013,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; - s->filp = filp; + s->file_priv = file_priv; dev_priv->surfaces[i].refcount = 1; dev_priv->surfaces[i].lower = s->lower; dev_priv->surfaces[i].upper = s->upper; @@ -2023,7 +2027,8 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, return -1; } -static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv, +static int free_surface(struct drm_file *file_priv, + drm_radeon_private_t * dev_priv, int lower) { struct radeon_virt_surface *s; @@ -2031,8 +2036,9 @@ static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv, /* find the virtual surface */ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { s = &(dev_priv->virt_surfaces[i]); - if (s->filp) { - if ((lower == s->lower) && (filp == s->filp)) { + if (s->file_priv) { + if ((lower == s->lower) && (file_priv == s->file_priv)) + { if (dev_priv->surfaces[s->surface_index]. lower == s->lower) dev_priv->surfaces[s->surface_index]. @@ -2048,7 +2054,7 @@ static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv, refcount == 0) dev_priv->surfaces[s->surface_index]. flags = 0; - s->filp = NULL; + s->file_priv = NULL; radeon_apply_surface_regs(s->surface_index, dev_priv); return 0; @@ -2058,13 +2064,13 @@ static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv, return 1; } -static void radeon_surfaces_release(DRMFILE filp, +static void radeon_surfaces_release(struct drm_file *file_priv, drm_radeon_private_t * dev_priv) { int i; for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { - if (dev_priv->virt_surfaces[i].filp == filp) - free_surface(filp, dev_priv, + if (dev_priv->virt_surfaces[i].file_priv == file_priv) + free_surface(file_priv, dev_priv, dev_priv->virt_surfaces[i].lower); } } @@ -2072,61 +2078,48 @@ static void radeon_surfaces_release(DRMFILE filp, /* ================================================================ * IOCTL functions */ -static int radeon_surface_alloc(DRM_IOCTL_ARGS) +static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_surface_alloc_t alloc; + drm_radeon_surface_alloc_t *alloc = data; - DRM_COPY_FROM_USER_IOCTL(alloc, - (drm_radeon_surface_alloc_t __user *) data, - sizeof(alloc)); - - if (alloc_surface(&alloc, dev_priv, filp) == -1) - return DRM_ERR(EINVAL); + if (alloc_surface(alloc, dev_priv, file_priv) == -1) + return -EINVAL; else return 0; } -static int radeon_surface_free(DRM_IOCTL_ARGS) +static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_surface_free_t memfree; - - DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data, - sizeof(memfree)); + drm_radeon_surface_free_t *memfree = data; - if (free_surface(filp, dev_priv, memfree.address)) - return DRM_ERR(EINVAL); + if (free_surface(file_priv, dev_priv, memfree->address)) + return -EINVAL; else return 0; } -static int radeon_cp_clear(DRM_IOCTL_ARGS) +static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; - drm_radeon_clear_t clear; + drm_radeon_clear_t *clear = data; drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data, - sizeof(clear)); + LOCK_TEST_WITH_RETURN(dev, file_priv); RING_SPACE_TEST_WITH_RETURN(dev_priv); if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - if (DRM_COPY_FROM_USER(&depth_boxes, clear.depth_boxes, + if (DRM_COPY_FROM_USER(&depth_boxes, clear->depth_boxes, sarea_priv->nbox * sizeof(depth_boxes[0]))) - return DRM_ERR(EFAULT); + return -EFAULT; - radeon_cp_dispatch_clear(dev, &clear, depth_boxes); + radeon_cp_dispatch_clear(dev, clear, depth_boxes); COMMIT_RING(); return 0; @@ -2162,13 +2155,12 @@ static int radeon_do_init_pageflip(struct drm_device * dev) /* Swapping and flipping are different operations, need different ioctls. * They can & should be intermixed to support multiple 3d windows. */ -static int radeon_cp_flip(DRM_IOCTL_ARGS) +static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -2181,14 +2173,13 @@ static int radeon_cp_flip(DRM_IOCTL_ARGS) return 0; } -static int radeon_cp_swap(DRM_IOCTL_ARGS) +static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -2202,64 +2193,57 @@ static int radeon_cp_swap(DRM_IOCTL_ARGS) return 0; } -static int radeon_cp_vertex(DRM_IOCTL_ARGS) +static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_file *filp_priv; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; - drm_radeon_vertex_t vertex; + drm_radeon_vertex_t *vertex = data; drm_radeon_tcl_prim_t prim; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); - - DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex_t __user *) data, - sizeof(vertex)); + LOCK_TEST_WITH_RETURN(dev, file_priv); DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", - DRM_CURRENTPID, vertex.idx, vertex.count, vertex.discard); + DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); - if (vertex.idx < 0 || vertex.idx >= dma->buf_count) { + if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", - vertex.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + vertex->idx, dma->buf_count - 1); + return -EINVAL; } - if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { - DRM_ERROR("buffer prim %d\n", vertex.prim); - return DRM_ERR(EINVAL); + if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { + DRM_ERROR("buffer prim %d\n", vertex->prim); + return -EINVAL; } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - buf = dma->buflist[vertex.idx]; + buf = dma->buflist[vertex->idx]; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->filp); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex.idx); - return DRM_ERR(EINVAL); + DRM_ERROR("sending pending buffer %d\n", vertex->idx); + return -EINVAL; } /* Build up a prim_t record: */ - if (vertex.count) { - buf->used = vertex.count; /* not used? */ + if (vertex->count) { + buf->used = vertex->count; /* not used? */ if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { - if (radeon_emit_state(dev_priv, filp_priv, + if (radeon_emit_state(dev_priv, file_priv, &sarea_priv->context_state, sarea_priv->tex_state, sarea_priv->dirty)) { DRM_ERROR("radeon_emit_state failed\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | @@ -2269,15 +2253,15 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS) } prim.start = 0; - prim.finish = vertex.count; /* unused */ - prim.prim = vertex.prim; - prim.numverts = vertex.count; + prim.finish = vertex->count; /* unused */ + prim.prim = vertex->prim; + prim.numverts = vertex->count; prim.vc_format = dev_priv->sarea_priv->vc_format; radeon_cp_dispatch_vertex(dev, buf, &prim); } - if (vertex.discard) { + if (vertex->discard) { radeon_cp_discard_buffer(dev, buf); } @@ -2285,74 +2269,68 @@ static int radeon_cp_vertex(DRM_IOCTL_ARGS) return 0; } -static int radeon_cp_indices(DRM_IOCTL_ARGS) +static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_file *filp_priv; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; - drm_radeon_indices_t elts; + drm_radeon_indices_t *elts = data; drm_radeon_tcl_prim_t prim; int count; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); - - DRM_COPY_FROM_USER_IOCTL(elts, (drm_radeon_indices_t __user *) data, - sizeof(elts)); + LOCK_TEST_WITH_RETURN(dev, file_priv); DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n", - DRM_CURRENTPID, elts.idx, elts.start, elts.end, elts.discard); + DRM_CURRENTPID, elts->idx, elts->start, elts->end, + elts->discard); - if (elts.idx < 0 || elts.idx >= dma->buf_count) { + if (elts->idx < 0 || elts->idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", - elts.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + elts->idx, dma->buf_count - 1); + return -EINVAL; } - if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { - DRM_ERROR("buffer prim %d\n", elts.prim); - return DRM_ERR(EINVAL); + if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { + DRM_ERROR("buffer prim %d\n", elts->prim); + return -EINVAL; } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - buf = dma->buflist[elts.idx]; + buf = dma->buflist[elts->idx]; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->filp); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", elts.idx); - return DRM_ERR(EINVAL); + DRM_ERROR("sending pending buffer %d\n", elts->idx); + return -EINVAL; } - count = (elts.end - elts.start) / sizeof(u16); - elts.start -= RADEON_INDEX_PRIM_OFFSET; + count = (elts->end - elts->start) / sizeof(u16); + elts->start -= RADEON_INDEX_PRIM_OFFSET; - if (elts.start & 0x7) { - DRM_ERROR("misaligned buffer 0x%x\n", elts.start); - return DRM_ERR(EINVAL); + if (elts->start & 0x7) { + DRM_ERROR("misaligned buffer 0x%x\n", elts->start); + return -EINVAL; } - if (elts.start < buf->used) { - DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used); - return DRM_ERR(EINVAL); + if (elts->start < buf->used) { + DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); + return -EINVAL; } - buf->used = elts.end; + buf->used = elts->end; if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { - if (radeon_emit_state(dev_priv, filp_priv, + if (radeon_emit_state(dev_priv, file_priv, &sarea_priv->context_state, sarea_priv->tex_state, sarea_priv->dirty)) { DRM_ERROR("radeon_emit_state failed\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | @@ -2363,15 +2341,15 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS) /* Build up a prim_t record: */ - prim.start = elts.start; - prim.finish = elts.end; - prim.prim = elts.prim; + prim.start = elts->start; + prim.finish = elts->end; + prim.prim = elts->prim; prim.offset = 0; /* offset from start of dma buffers */ prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ prim.vc_format = dev_priv->sarea_priv->vc_format; radeon_cp_dispatch_indices(dev, buf, &prim); - if (elts.discard) { + if (elts->discard) { radeon_cp_discard_buffer(dev, buf); } @@ -2379,52 +2357,43 @@ static int radeon_cp_indices(DRM_IOCTL_ARGS) return 0; } -static int radeon_cp_texture(DRM_IOCTL_ARGS) +static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_texture_t tex; + drm_radeon_texture_t *tex = data; drm_radeon_tex_image_t image; int ret; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data, - sizeof(tex)); + LOCK_TEST_WITH_RETURN(dev, file_priv); - if (tex.image == NULL) { + if (tex->image == NULL) { DRM_ERROR("null texture image!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } if (DRM_COPY_FROM_USER(&image, - (drm_radeon_tex_image_t __user *) tex.image, + (drm_radeon_tex_image_t __user *) tex->image, sizeof(image))) - return DRM_ERR(EFAULT); + return -EFAULT; RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image); + ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image); - COMMIT_RING(); return ret; } -static int radeon_cp_stipple(DRM_IOCTL_ARGS) +static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_stipple_t stipple; + drm_radeon_stipple_t *stipple = data; u32 mask[32]; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data, - sizeof(stipple)); + LOCK_TEST_WITH_RETURN(dev, file_priv); - if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32))) - return DRM_ERR(EFAULT); + if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) + return -EFAULT; RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -2434,52 +2403,48 @@ static int radeon_cp_stipple(DRM_IOCTL_ARGS) return 0; } -static int radeon_cp_indirect(DRM_IOCTL_ARGS) +static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; - drm_radeon_indirect_t indirect; + drm_radeon_indirect_t *indirect = data; RING_LOCALS; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(indirect, - (drm_radeon_indirect_t __user *) data, - sizeof(indirect)); + LOCK_TEST_WITH_RETURN(dev, file_priv); DRM_DEBUG("indirect: idx=%d s=%d e=%d d=%d\n", - indirect.idx, indirect.start, indirect.end, indirect.discard); + indirect->idx, indirect->start, indirect->end, + indirect->discard); - if (indirect.idx < 0 || indirect.idx >= dma->buf_count) { + if (indirect->idx < 0 || indirect->idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", - indirect.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + indirect->idx, dma->buf_count - 1); + return -EINVAL; } - buf = dma->buflist[indirect.idx]; + buf = dma->buflist[indirect->idx]; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->filp); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", indirect.idx); - return DRM_ERR(EINVAL); + DRM_ERROR("sending pending buffer %d\n", indirect->idx); + return -EINVAL; } - if (indirect.start < buf->used) { + if (indirect->start < buf->used) { DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", - indirect.start, buf->used); - return DRM_ERR(EINVAL); + indirect->start, buf->used); + return -EINVAL; } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - buf->used = indirect.end; + buf->used = indirect->end; /* Wait for the 3D stream to idle before the indirect buffer * containing 2D acceleration commands is processed. @@ -2494,8 +2459,8 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS) * X server. This is insecure and is thus only available to * privileged clients. */ - radeon_cp_dispatch_indirect(dev, buf, indirect.start, indirect.end); - if (indirect.discard) { + radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); + if (indirect->discard) { radeon_cp_discard_buffer(dev, buf); } @@ -2503,71 +2468,64 @@ static int radeon_cp_indirect(DRM_IOCTL_ARGS) return 0; } -static int radeon_cp_vertex2(DRM_IOCTL_ARGS) +static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_file *filp_priv; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf; - drm_radeon_vertex2_t vertex; + drm_radeon_vertex2_t *vertex = data; int i; unsigned char laststate; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); - - DRM_COPY_FROM_USER_IOCTL(vertex, (drm_radeon_vertex2_t __user *) data, - sizeof(vertex)); + LOCK_TEST_WITH_RETURN(dev, file_priv); DRM_DEBUG("pid=%d index=%d discard=%d\n", - DRM_CURRENTPID, vertex.idx, vertex.discard); + DRM_CURRENTPID, vertex->idx, vertex->discard); - if (vertex.idx < 0 || vertex.idx >= dma->buf_count) { + if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { DRM_ERROR("buffer index %d (of %d max)\n", - vertex.idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + vertex->idx, dma->buf_count - 1); + return -EINVAL; } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - buf = dma->buflist[vertex.idx]; + buf = dma->buflist[vertex->idx]; - if (buf->filp != filp) { + if (buf->file_priv != file_priv) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->filp); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, buf->file_priv); + return -EINVAL; } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex.idx); - return DRM_ERR(EINVAL); + DRM_ERROR("sending pending buffer %d\n", vertex->idx); + return -EINVAL; } if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) - return DRM_ERR(EINVAL); + return -EINVAL; - for (laststate = 0xff, i = 0; i < vertex.nr_prims; i++) { + for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) { drm_radeon_prim_t prim; drm_radeon_tcl_prim_t tclprim; - if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim))) - return DRM_ERR(EFAULT); + if (DRM_COPY_FROM_USER(&prim, &vertex->prim[i], sizeof(prim))) + return -EFAULT; if (prim.stateidx != laststate) { drm_radeon_state_t state; if (DRM_COPY_FROM_USER(&state, - &vertex.state[prim.stateidx], + &vertex->state[prim.stateidx], sizeof(state))) - return DRM_ERR(EFAULT); + return -EFAULT; - if (radeon_emit_state2(dev_priv, filp_priv, &state)) { + if (radeon_emit_state2(dev_priv, file_priv, &state)) { DRM_ERROR("radeon_emit_state2 failed\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } laststate = prim.stateidx; @@ -2594,7 +2552,7 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS) sarea_priv->nbox = 0; } - if (vertex.discard) { + if (vertex->discard) { radeon_cp_discard_buffer(dev, buf); } @@ -2603,7 +2561,7 @@ static int radeon_cp_vertex2(DRM_IOCTL_ARGS) } static int radeon_emit_packets(drm_radeon_private_t * dev_priv, - struct drm_file * filp_priv, + struct drm_file *file_priv, drm_radeon_cmd_header_t header, drm_radeon_kcmd_buffer_t *cmdbuf) { @@ -2613,19 +2571,19 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv, RING_LOCALS; if (id >= RADEON_MAX_STATE_PACKETS) - return DRM_ERR(EINVAL); + return -EINVAL; sz = packet[id].len; reg = packet[id].start; if (sz * sizeof(int) > cmdbuf->bufsz) { DRM_ERROR("Packet size provided larger than data provided\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } - if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) { + if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) { DRM_ERROR("Packet verification failed\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } BEGIN_RING(sz + 1); @@ -2713,7 +2671,7 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, if (!sz) return 0; if (sz * 4 > cmdbuf->bufsz) - return DRM_ERR(EINVAL); + return -EINVAL; BEGIN_RING(5 + sz); OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); @@ -2729,7 +2687,7 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, } static int radeon_emit_packet3(struct drm_device * dev, - struct drm_file * filp_priv, + struct drm_file *file_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -2739,7 +2697,7 @@ static int radeon_emit_packet3(struct drm_device * dev, DRM_DEBUG("\n"); - if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv, + if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, cmdbuf, &cmdsz))) { DRM_ERROR("Packet verification failed\n"); return ret; @@ -2755,7 +2713,7 @@ static int radeon_emit_packet3(struct drm_device * dev, } static int radeon_emit_packet3_cliprect(struct drm_device *dev, - struct drm_file *filp_priv, + struct drm_file *file_priv, drm_radeon_kcmd_buffer_t *cmdbuf, int orig_nbox) { @@ -2769,7 +2727,7 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev, DRM_DEBUG("\n"); - if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv, + if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, cmdbuf, &cmdsz))) { DRM_ERROR("Packet verification failed\n"); return ret; @@ -2781,7 +2739,7 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev, do { if (i < cmdbuf->nbox) { if (DRM_COPY_FROM_USER(&box, &boxes[i], sizeof(box))) - return DRM_ERR(EFAULT); + return -EFAULT; /* FIXME The second and subsequent times round * this loop, send a WAIT_UNTIL_3D_IDLE before * calling emit_clip_rect(). This fixes a @@ -2839,62 +2797,54 @@ static int radeon_emit_wait(struct drm_device * dev, int flags) ADVANCE_RING(); break; default: - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; } -static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) +static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_file *filp_priv; struct drm_device_dma *dma = dev->dma; struct drm_buf *buf = NULL; int idx; - drm_radeon_kcmd_buffer_t cmdbuf; + drm_radeon_kcmd_buffer_t *cmdbuf = data; drm_radeon_cmd_header_t header; int orig_nbox, orig_bufsz; char *kbuf = NULL; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); - - DRM_COPY_FROM_USER_IOCTL(cmdbuf, - (drm_radeon_cmd_buffer_t __user *) data, - sizeof(cmdbuf)); + LOCK_TEST_WITH_RETURN(dev, file_priv); RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) { - return DRM_ERR(EINVAL); + if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) { + return -EINVAL; } /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid * races between checking values and using those values in other code, * and simply to avoid a lot of function calls to copy in data. */ - orig_bufsz = cmdbuf.bufsz; + orig_bufsz = cmdbuf->bufsz; if (orig_bufsz != 0) { - kbuf = drm_alloc(cmdbuf.bufsz, DRM_MEM_DRIVER); + kbuf = drm_alloc(cmdbuf->bufsz, DRM_MEM_DRIVER); if (kbuf == NULL) - return DRM_ERR(ENOMEM); - if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, - cmdbuf.bufsz)) { + return -ENOMEM; + if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf, + cmdbuf->bufsz)) { drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); - return DRM_ERR(EFAULT); + return -EFAULT; } - cmdbuf.buf = kbuf; + cmdbuf->buf = kbuf; } - orig_nbox = cmdbuf.nbox; + orig_nbox = cmdbuf->nbox; if (dev_priv->microcode_version == UCODE_R300) { int temp; - temp = r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf); + temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); if (orig_bufsz != 0) drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); @@ -2903,17 +2853,17 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) } /* microcode_version != r300 */ - while (cmdbuf.bufsz >= sizeof(header)) { + while (cmdbuf->bufsz >= sizeof(header)) { - header.i = *(int *)cmdbuf.buf; - cmdbuf.buf += sizeof(header); - cmdbuf.bufsz -= sizeof(header); + header.i = *(int *)cmdbuf->buf; + cmdbuf->buf += sizeof(header); + cmdbuf->bufsz -= sizeof(header); switch (header.header.cmd_type) { case RADEON_CMD_PACKET: DRM_DEBUG("RADEON_CMD_PACKET\n"); if (radeon_emit_packets - (dev_priv, filp_priv, header, &cmdbuf)) { + (dev_priv, file_priv, header, cmdbuf)) { DRM_ERROR("radeon_emit_packets failed\n"); goto err; } @@ -2921,7 +2871,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) case RADEON_CMD_SCALARS: DRM_DEBUG("RADEON_CMD_SCALARS\n"); - if (radeon_emit_scalars(dev_priv, header, &cmdbuf)) { + if (radeon_emit_scalars(dev_priv, header, cmdbuf)) { DRM_ERROR("radeon_emit_scalars failed\n"); goto err; } @@ -2929,7 +2879,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) case RADEON_CMD_VECTORS: DRM_DEBUG("RADEON_CMD_VECTORS\n"); - if (radeon_emit_vectors(dev_priv, header, &cmdbuf)) { + if (radeon_emit_vectors(dev_priv, header, cmdbuf)) { DRM_ERROR("radeon_emit_vectors failed\n"); goto err; } @@ -2945,9 +2895,10 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) } buf = dma->buflist[idx]; - if (buf->filp != filp || buf->pending) { + if (buf->file_priv != file_priv || buf->pending) { DRM_ERROR("bad buffer %p %p %d\n", - buf->filp, filp, buf->pending); + buf->file_priv, file_priv, + buf->pending); goto err; } @@ -2956,7 +2907,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) case RADEON_CMD_PACKET3: DRM_DEBUG("RADEON_CMD_PACKET3\n"); - if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) { + if (radeon_emit_packet3(dev, file_priv, cmdbuf)) { DRM_ERROR("radeon_emit_packet3 failed\n"); goto err; } @@ -2965,7 +2916,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) case RADEON_CMD_PACKET3_CLIP: DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); if (radeon_emit_packet3_cliprect - (dev, filp_priv, &cmdbuf, orig_nbox)) { + (dev, file_priv, cmdbuf, orig_nbox)) { DRM_ERROR("radeon_emit_packet3_clip failed\n"); goto err; } @@ -2973,7 +2924,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) case RADEON_CMD_SCALARS2: DRM_DEBUG("RADEON_CMD_SCALARS2\n"); - if (radeon_emit_scalars2(dev_priv, header, &cmdbuf)) { + if (radeon_emit_scalars2(dev_priv, header, cmdbuf)) { DRM_ERROR("radeon_emit_scalars2 failed\n"); goto err; } @@ -2988,7 +2939,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) break; case RADEON_CMD_VECLINEAR: DRM_DEBUG("RADEON_CMD_VECLINEAR\n"); - if (radeon_emit_veclinear(dev_priv, header, &cmdbuf)) { + if (radeon_emit_veclinear(dev_priv, header, cmdbuf)) { DRM_ERROR("radeon_emit_veclinear failed\n"); goto err; } @@ -2997,7 +2948,7 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) default: DRM_ERROR("bad cmd_type %d at %p\n", header.header.cmd_type, - cmdbuf.buf - sizeof(header)); + cmdbuf->buf - sizeof(header)); goto err; } } @@ -3012,22 +2963,18 @@ static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) err: if (orig_bufsz != 0) drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); - return DRM_ERR(EINVAL); + return -EINVAL; } -static int radeon_cp_getparam(DRM_IOCTL_ARGS) +static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_getparam_t param; + drm_radeon_getparam_t *param = data; int value; - DRM_COPY_FROM_USER_IOCTL(param, (drm_radeon_getparam_t __user *) data, - sizeof(param)); - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); - switch (param.param) { + switch (param->param) { case RADEON_PARAM_GART_BUFFER_OFFSET: value = dev_priv->gart_buffers_offset; break; @@ -3074,7 +3021,7 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) break; case RADEON_PARAM_SCRATCH_OFFSET: if (!dev_priv->writeback_works) - return DRM_ERR(EINVAL); + return -EINVAL; value = RADEON_SCRATCH_REG_OFFSET; break; case RADEON_PARAM_CARD_TYPE: @@ -3089,43 +3036,37 @@ static int radeon_cp_getparam(DRM_IOCTL_ARGS) value = radeon_vblank_crtc_get(dev); break; default: - DRM_DEBUG("Invalid parameter %d\n", param.param); - return DRM_ERR(EINVAL); + DRM_DEBUG("Invalid parameter %d\n", param->param); + return -EINVAL; } - if (DRM_COPY_TO_USER(param.value, &value, sizeof(int))) { + if (DRM_COPY_TO_USER(param->value, &value, sizeof(int))) { DRM_ERROR("copy_to_user\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } return 0; } -static int radeon_cp_setparam(DRM_IOCTL_ARGS) +static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_file *filp_priv; - drm_radeon_setparam_t sp; + drm_radeon_setparam_t *sp = data; struct drm_radeon_driver_file_fields *radeon_priv; - DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); - - DRM_COPY_FROM_USER_IOCTL(sp, (drm_radeon_setparam_t __user *) data, - sizeof(sp)); - - switch (sp.param) { + switch (sp->param) { case RADEON_SETPARAM_FB_LOCATION: - radeon_priv = filp_priv->driver_priv; - radeon_priv->radeon_fb_delta = dev_priv->fb_location - sp.value; + radeon_priv = file_priv->driver_priv; + radeon_priv->radeon_fb_delta = dev_priv->fb_location - + sp->value; break; case RADEON_SETPARAM_SWITCH_TILING: - if (sp.value == 0) { + if (sp->value == 0) { DRM_DEBUG("color tiling disabled\n"); dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO; dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO; dev_priv->sarea_priv->tiling_enabled = 0; - } else if (sp.value == 1) { + } else if (sp->value == 1) { DRM_DEBUG("color tiling enabled\n"); dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO; dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO; @@ -3133,23 +3074,23 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) } break; case RADEON_SETPARAM_PCIGART_LOCATION: - dev_priv->pcigart_offset = sp.value; + dev_priv->pcigart_offset = sp->value; dev_priv->pcigart_offset_set = 1; break; case RADEON_SETPARAM_NEW_MEMMAP: - dev_priv->new_memmap = sp.value; + dev_priv->new_memmap = sp->value; break; case RADEON_SETPARAM_PCIGART_TABLE_SIZE: - dev_priv->gart_info.table_size = sp.value; + dev_priv->gart_info.table_size = sp->value; if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; break; case RADEON_SETPARAM_VBLANK_CRTC: - return radeon_vblank_crtc_set(dev, sp.value); + return radeon_vblank_crtc_set(dev, sp->value); break; default: - DRM_DEBUG("Invalid parameter %d\n", sp.param); - return DRM_ERR(EINVAL); + DRM_DEBUG("Invalid parameter %d\n", sp->param); + return -EINVAL; } return 0; @@ -3162,14 +3103,14 @@ static int radeon_cp_setparam(DRM_IOCTL_ARGS) * * DRM infrastructure takes care of reclaiming dma buffers. */ -void radeon_driver_preclose(struct drm_device *dev, DRMFILE filp) +void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) { if (dev->dev_private) { drm_radeon_private_t *dev_priv = dev->dev_private; dev_priv->page_flipping = 0; - radeon_mem_release(filp, dev_priv->gart_heap); - radeon_mem_release(filp, dev_priv->fb_heap); - radeon_surfaces_release(filp, dev_priv); + radeon_mem_release(file_priv, dev_priv->gart_heap); + radeon_mem_release(file_priv, dev_priv->fb_heap); + radeon_surfaces_release(file_priv, dev_priv); } } @@ -3186,7 +3127,7 @@ void radeon_driver_lastclose(struct drm_device *dev) radeon_do_release(dev); } -int radeon_driver_open(struct drm_device *dev, struct drm_file *filp_priv) +int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_radeon_driver_file_fields *radeon_priv; @@ -3199,7 +3140,7 @@ int radeon_driver_open(struct drm_device *dev, struct drm_file *filp_priv) if (!radeon_priv) return -ENOMEM; - filp_priv->driver_priv = radeon_priv; + file_priv->driver_priv = radeon_priv; if (dev_priv) radeon_priv->radeon_fb_delta = dev_priv->fb_location; @@ -3208,42 +3149,42 @@ int radeon_driver_open(struct drm_device *dev, struct drm_file *filp_priv) return 0; } -void radeon_driver_postclose(struct drm_device *dev, struct drm_file *filp_priv) +void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) { struct drm_radeon_driver_file_fields *radeon_priv = - filp_priv->driver_priv; + file_priv->driver_priv; drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES); } -drm_ioctl_desc_t radeon_ioctls[] = { - [DRM_IOCTL_NR(DRM_RADEON_CP_INIT)] = {radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_RADEON_CP_START)] = {radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_RADEON_CP_STOP)] = {radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_RADEON_CP_RESET)] = {radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_RADEON_CP_IDLE)] = {radeon_cp_idle, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_CP_RESUME)] = {radeon_cp_resume, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_RESET)] = {radeon_engine_reset, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_FULLSCREEN)] = {radeon_fullscreen, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_SWAP)] = {radeon_cp_swap, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_CLEAR)] = {radeon_cp_clear, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_VERTEX)] = {radeon_cp_vertex, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_INDICES)] = {radeon_cp_indices, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_TEXTURE)] = {radeon_cp_texture, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_STIPPLE)] = {radeon_cp_stipple, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_INDIRECT)] = {radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_RADEON_VERTEX2)] = {radeon_cp_vertex2, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_CMDBUF)] = {radeon_cp_cmdbuf, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_GETPARAM)] = {radeon_cp_getparam, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_FLIP)] = {radeon_cp_flip, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_ALLOC)] = {radeon_mem_alloc, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_FREE)] = {radeon_mem_free, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_INIT_HEAP)] = {radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_RADEON_IRQ_EMIT)] = {radeon_irq_emit, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_IRQ_WAIT)] = {radeon_irq_wait, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_SETPARAM)] = {radeon_cp_setparam, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_SURF_ALLOC)] = {radeon_surface_alloc, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_RADEON_SURF_FREE)] = {radeon_surface_free, DRM_AUTH} +struct drm_ioctl_desc radeon_ioctls[] = { + DRM_IOCTL_DEF(DRM_RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_RESET, radeon_engine_reset, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_SWAP, radeon_cp_swap, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_CLEAR, radeon_cp_clear, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_INDICES, radeon_cp_indices, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_FLIP, radeon_cp_flip, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_FREE, radeon_mem_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH) }; int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); diff --git a/drivers/char/drm/savage_bci.c b/drivers/char/drm/savage_bci.c index 18c7235f6b73..59484d56b333 100644 --- a/drivers/char/drm/savage_bci.c +++ b/drivers/char/drm/savage_bci.c @@ -60,7 +60,7 @@ savage_bci_wait_fifo_shadow(drm_savage_private_t * dev_priv, unsigned int n) DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x, threshold=0x%08x\n", status, threshold); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } static int @@ -81,7 +81,7 @@ savage_bci_wait_fifo_s3d(drm_savage_private_t * dev_priv, unsigned int n) DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x\n", status); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } static int @@ -102,7 +102,7 @@ savage_bci_wait_fifo_s4(drm_savage_private_t * dev_priv, unsigned int n) DRM_ERROR("failed!\n"); DRM_INFO(" status=0x%08x\n", status); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } /* @@ -136,7 +136,7 @@ savage_bci_wait_event_shadow(drm_savage_private_t * dev_priv, uint16_t e) DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } static int @@ -158,7 +158,7 @@ savage_bci_wait_event_reg(drm_savage_private_t * dev_priv, uint16_t e) DRM_INFO(" status=0x%08x, e=0x%04x\n", status, e); #endif - return DRM_ERR(EBUSY); + return -EBUSY; } uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv, @@ -301,7 +301,7 @@ static int savage_dma_init(drm_savage_private_t * dev_priv) dev_priv->dma_pages = drm_alloc(sizeof(drm_savage_dma_page_t) * dev_priv->nr_dma_pages, DRM_MEM_DRIVER); if (dev_priv->dma_pages == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; for (i = 0; i < dev_priv->nr_dma_pages; ++i) { SET_AGE(&dev_priv->dma_pages[i].age, 0, 0); @@ -541,7 +541,7 @@ int savage_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv = drm_alloc(sizeof(drm_savage_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; memset(dev_priv, 0, sizeof(drm_savage_private_t)); dev->dev_private = (void *)dev_priv; @@ -682,16 +682,16 @@ static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init) if (init->fb_bpp != 16 && init->fb_bpp != 32) { DRM_ERROR("invalid frame buffer bpp %d!\n", init->fb_bpp); - return DRM_ERR(EINVAL); + return -EINVAL; } if (init->depth_bpp != 16 && init->depth_bpp != 32) { DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp); - return DRM_ERR(EINVAL); + return -EINVAL; } if (init->dma_type != SAVAGE_DMA_AGP && init->dma_type != SAVAGE_DMA_PCI) { DRM_ERROR("invalid dma memory type %d!\n", init->dma_type); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->cob_size = init->cob_size; @@ -715,14 +715,14 @@ static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init) if (!dev_priv->sarea) { DRM_ERROR("could not find sarea!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } if (init->status_offset != 0) { dev_priv->status = drm_core_findmap(dev, init->status_offset); if (!dev_priv->status) { DRM_ERROR("could not find shadow status region!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } } else { dev_priv->status = NULL; @@ -734,13 +734,13 @@ static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init) if (!dev->agp_buffer_map) { DRM_ERROR("could not find DMA buffer region!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } drm_core_ioremap(dev->agp_buffer_map, dev); if (!dev->agp_buffer_map) { DRM_ERROR("failed to ioremap DMA buffer region!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(ENOMEM); + return -ENOMEM; } } if (init->agp_textures_offset) { @@ -749,7 +749,7 @@ static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init) if (!dev_priv->agp_textures) { DRM_ERROR("could not find agp texture region!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } } else { dev_priv->agp_textures = NULL; @@ -760,39 +760,39 @@ static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init) DRM_ERROR("command DMA not supported on " "Savage3D/MX/IX.\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } if (dev->dma && dev->dma->buflist) { DRM_ERROR("command and vertex DMA not supported " "at the same time.\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->cmd_dma = drm_core_findmap(dev, init->cmd_dma_offset); if (!dev_priv->cmd_dma) { DRM_ERROR("could not find command DMA region!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } if (dev_priv->dma_type == SAVAGE_DMA_AGP) { if (dev_priv->cmd_dma->type != _DRM_AGP) { DRM_ERROR("AGP command DMA region is not a " "_DRM_AGP map!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } drm_core_ioremap(dev_priv->cmd_dma, dev); if (!dev_priv->cmd_dma->handle) { DRM_ERROR("failed to ioremap command " "DMA region!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(ENOMEM); + return -ENOMEM; } } else if (dev_priv->cmd_dma->type != _DRM_CONSISTENT) { DRM_ERROR("PCI command DMA region is not a " "_DRM_CONSISTENT map!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(EINVAL); + return -EINVAL; } } else { dev_priv->cmd_dma = NULL; @@ -809,7 +809,7 @@ static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init) if (!dev_priv->fake_dma.handle) { DRM_ERROR("could not allocate faked DMA buffer!\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(ENOMEM); + return -ENOMEM; } dev_priv->cmd_dma = &dev_priv->fake_dma; dev_priv->dma_flush = savage_fake_dma_flush; @@ -886,13 +886,13 @@ static int savage_do_init_bci(struct drm_device * dev, drm_savage_init_t * init) if (savage_freelist_init(dev) < 0) { DRM_ERROR("could not initialize freelist\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (savage_dma_init(dev_priv) < 0) { DRM_ERROR("could not initialize command DMA\n"); savage_do_cleanup_bci(dev); - return DRM_ERR(ENOMEM); + return -ENOMEM; } return 0; @@ -928,51 +928,41 @@ static int savage_do_cleanup_bci(struct drm_device * dev) return 0; } -static int savage_bci_init(DRM_IOCTL_ARGS) +static int savage_bci_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_savage_init_t init; + drm_savage_init_t *init = data; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *) data, - sizeof(init)); - - switch (init.func) { + switch (init->func) { case SAVAGE_INIT_BCI: - return savage_do_init_bci(dev, &init); + return savage_do_init_bci(dev, init); case SAVAGE_CLEANUP_BCI: return savage_do_cleanup_bci(dev); } - return DRM_ERR(EINVAL); + return -EINVAL; } -static int savage_bci_event_emit(DRM_IOCTL_ARGS) +static int savage_bci_event_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; - drm_savage_event_emit_t event; + drm_savage_event_emit_t *event = data; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_COPY_FROM_USER_IOCTL(event, (drm_savage_event_emit_t __user *) data, - sizeof(event)); + event->count = savage_bci_emit_event(dev_priv, event->flags); + event->count |= dev_priv->event_wrap << 16; - event.count = savage_bci_emit_event(dev_priv, event.flags); - event.count |= dev_priv->event_wrap << 16; - DRM_COPY_TO_USER_IOCTL((drm_savage_event_emit_t __user *) data, - event, sizeof(event)); return 0; } -static int savage_bci_event_wait(DRM_IOCTL_ARGS) +static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; - drm_savage_event_wait_t event; + drm_savage_event_wait_t *event = data; unsigned int event_e, hw_e; unsigned int event_w, hw_w; @@ -990,8 +980,8 @@ static int savage_bci_event_wait(DRM_IOCTL_ARGS) if (hw_e > dev_priv->event_counter) hw_w--; /* hardware hasn't passed the last wrap yet */ - event_e = event.count & 0xffff; - event_w = event.count >> 16; + event_e = event->count & 0xffff; + event_w = event->count >> 16; /* Don't need to wait if * - event counter wrapped since the event was emitted or @@ -1007,7 +997,9 @@ static int savage_bci_event_wait(DRM_IOCTL_ARGS) * DMA buffer management */ -static int savage_bci_get_buffers(DRMFILE filp, struct drm_device *dev, struct drm_dma *d) +static int savage_bci_get_buffers(struct drm_device *dev, + struct drm_file *file_priv, + struct drm_dma *d) { struct drm_buf *buf; int i; @@ -1015,61 +1007,56 @@ static int savage_bci_get_buffers(DRMFILE filp, struct drm_device *dev, struct d for (i = d->granted_count; i < d->request_count; i++) { buf = savage_freelist_get(dev); if (!buf) - return DRM_ERR(EAGAIN); + return -EAGAIN; - buf->filp = filp; + buf->file_priv = file_priv; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return DRM_ERR(EFAULT); + return -EFAULT; if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return DRM_ERR(EFAULT); + return -EFAULT; d->granted_count++; } return 0; } -int savage_bci_buffers(DRM_IOCTL_ARGS) +int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; struct drm_device_dma *dma = dev->dma; - struct drm_dma d; + struct drm_dma *d = data; int ret = 0; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(d, (struct drm_dma __user *) data, sizeof(d)); + LOCK_TEST_WITH_RETURN(dev, file_priv); /* Please don't send us buffers. */ - if (d.send_count != 0) { + if (d->send_count != 0) { DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - DRM_CURRENTPID, d.send_count); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, d->send_count); + return -EINVAL; } /* We'll send you buffers. */ - if (d.request_count < 0 || d.request_count > dma->buf_count) { + if (d->request_count < 0 || d->request_count > dma->buf_count) { DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - DRM_CURRENTPID, d.request_count, dma->buf_count); - return DRM_ERR(EINVAL); + DRM_CURRENTPID, d->request_count, dma->buf_count); + return -EINVAL; } - d.granted_count = 0; + d->granted_count = 0; - if (d.request_count) { - ret = savage_bci_get_buffers(filp, dev, &d); + if (d->request_count) { + ret = savage_bci_get_buffers(dev, file_priv, d); } - DRM_COPY_TO_USER_IOCTL((struct drm_dma __user *) data, d, sizeof(d)); - return ret; } -void savage_reclaim_buffers(struct drm_device *dev, DRMFILE filp) +void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) { struct drm_device_dma *dma = dev->dma; drm_savage_private_t *dev_priv = dev->dev_private; @@ -1088,7 +1075,7 @@ void savage_reclaim_buffers(struct drm_device *dev, DRMFILE filp) struct drm_buf *buf = dma->buflist[i]; drm_savage_buf_priv_t *buf_priv = buf->dev_private; - if (buf->filp == filp && buf_priv && + if (buf->file_priv == file_priv && buf_priv && buf_priv->next == NULL && buf_priv->prev == NULL) { uint16_t event; DRM_DEBUG("reclaimed from client\n"); @@ -1098,14 +1085,14 @@ void savage_reclaim_buffers(struct drm_device *dev, DRMFILE filp) } } - drm_core_reclaim_buffers(dev, filp); + drm_core_reclaim_buffers(dev, file_priv); } -drm_ioctl_desc_t savage_ioctls[] = { - [DRM_IOCTL_NR(DRM_SAVAGE_BCI_INIT)] = {savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_SAVAGE_BCI_CMDBUF)] = {savage_bci_cmdbuf, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_EMIT)] = {savage_bci_event_emit, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_SAVAGE_BCI_EVENT_WAIT)] = {savage_bci_event_wait, DRM_AUTH}, +struct drm_ioctl_desc savage_ioctls[] = { + DRM_IOCTL_DEF(DRM_SAVAGE_BCI_INIT, savage_bci_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_SAVAGE_BCI_CMDBUF, savage_bci_cmdbuf, DRM_AUTH), + DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_EMIT, savage_bci_event_emit, DRM_AUTH), + DRM_IOCTL_DEF(DRM_SAVAGE_BCI_EVENT_WAIT, savage_bci_event_wait, DRM_AUTH), }; int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls); diff --git a/drivers/char/drm/savage_drv.h b/drivers/char/drm/savage_drv.h index 5fd54de4280e..df2aac6636f7 100644 --- a/drivers/char/drm/savage_drv.h +++ b/drivers/char/drm/savage_drv.h @@ -104,7 +104,7 @@ enum savage_family { S3_LAST }; -extern drm_ioctl_desc_t savage_ioctls[]; +extern struct drm_ioctl_desc savage_ioctls[]; extern int savage_max_ioctl; #define S3_SAVAGE3D_SERIES(chip) ((chip>=S3_SAVAGE3D) && (chip<=S3_SAVAGE_MX)) @@ -197,8 +197,8 @@ typedef struct drm_savage_private { } drm_savage_private_t; /* ioctls */ -extern int savage_bci_cmdbuf(DRM_IOCTL_ARGS); -extern int savage_bci_buffers(DRM_IOCTL_ARGS); +extern int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); /* BCI functions */ extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv, @@ -212,7 +212,8 @@ extern int savage_driver_load(struct drm_device *dev, unsigned long chipset); extern int savage_driver_firstopen(struct drm_device *dev); extern void savage_driver_lastclose(struct drm_device *dev); extern int savage_driver_unload(struct drm_device *dev); -extern void savage_reclaim_buffers(struct drm_device * dev, DRMFILE filp); +extern void savage_reclaim_buffers(struct drm_device *dev, + struct drm_file *file_priv); /* state functions */ extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, diff --git a/drivers/char/drm/savage_state.c b/drivers/char/drm/savage_state.c index 77497841478a..bf8e0e10fe21 100644 --- a/drivers/char/drm/savage_state.c +++ b/drivers/char/drm/savage_state.c @@ -83,7 +83,7 @@ static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit, { if ((addr & 6) != 2) { /* reserved bits */ DRM_ERROR("bad texAddr%d %08x (reserved bits)\n", unit, addr); - return DRM_ERR(EINVAL); + return -EINVAL; } if (!(addr & 1)) { /* local */ addr &= ~7; @@ -92,13 +92,13 @@ static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit, DRM_ERROR ("bad texAddr%d %08x (local addr out of range)\n", unit, addr); - return DRM_ERR(EINVAL); + return -EINVAL; } } else { /* AGP */ if (!dev_priv->agp_textures) { DRM_ERROR("bad texAddr%d %08x (AGP not available)\n", unit, addr); - return DRM_ERR(EINVAL); + return -EINVAL; } addr &= ~7; if (addr < dev_priv->agp_textures->offset || @@ -107,7 +107,7 @@ static int savage_verify_texaddr(drm_savage_private_t * dev_priv, int unit, DRM_ERROR ("bad texAddr%d %08x (AGP addr out of range)\n", unit, addr); - return DRM_ERR(EINVAL); + return -EINVAL; } } return 0; @@ -133,7 +133,7 @@ static int savage_verify_state_s3d(drm_savage_private_t * dev_priv, start + count - 1 > SAVAGE_DESTTEXRWWATERMARK_S3D) { DRM_ERROR("invalid register range (0x%04x-0x%04x)\n", start, start + count - 1); - return DRM_ERR(EINVAL); + return -EINVAL; } SAVE_STATE_MASK(SAVAGE_SCSTART_S3D, s3d.new_scstart, @@ -165,7 +165,7 @@ static int savage_verify_state_s4(drm_savage_private_t * dev_priv, start + count - 1 > SAVAGE_TEXBLENDCOLOR_S4) { DRM_ERROR("invalid register range (0x%04x-0x%04x)\n", start, start + count - 1); - return DRM_ERR(EINVAL); + return -EINVAL; } SAVE_STATE_MASK(SAVAGE_DRAWCTRL0_S4, s4.new_drawctrl0, @@ -289,7 +289,7 @@ static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv, if (!dmabuf) { DRM_ERROR("called without dma buffers!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } if (!n) @@ -303,7 +303,7 @@ static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv, if (n % 3 != 0) { DRM_ERROR("wrong number of vertices %u in TRILIST\n", n); - return DRM_ERR(EINVAL); + return -EINVAL; } break; case SAVAGE_PRIM_TRISTRIP: @@ -312,18 +312,18 @@ static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv, DRM_ERROR ("wrong number of vertices %u in TRIFAN/STRIP\n", n); - return DRM_ERR(EINVAL); + return -EINVAL; } break; default: DRM_ERROR("invalid primitive type %u\n", prim); - return DRM_ERR(EINVAL); + return -EINVAL; } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip != 0) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return DRM_ERR(EINVAL); + return -EINVAL; } } else { unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) - @@ -331,18 +331,18 @@ static int savage_dispatch_dma_prim(drm_savage_private_t * dev_priv, (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1); if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return DRM_ERR(EINVAL); + return -EINVAL; } if (reorder) { DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } } if (start + n > dmabuf->total / 32) { DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n", start, start + n - 1, dmabuf->total / 32); - return DRM_ERR(EINVAL); + return -EINVAL; } /* Vertex DMA doesn't work with command DMA at the same time, @@ -440,7 +440,7 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, if (n % 3 != 0) { DRM_ERROR("wrong number of vertices %u in TRILIST\n", n); - return DRM_ERR(EINVAL); + return -EINVAL; } break; case SAVAGE_PRIM_TRISTRIP: @@ -449,24 +449,24 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, DRM_ERROR ("wrong number of vertices %u in TRIFAN/STRIP\n", n); - return DRM_ERR(EINVAL); + return -EINVAL; } break; default: DRM_ERROR("invalid primitive type %u\n", prim); - return DRM_ERR(EINVAL); + return -EINVAL; } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip > SAVAGE_SKIP_ALL_S3D) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return DRM_ERR(EINVAL); + return -EINVAL; } vtx_size = 8; /* full vertex */ } else { if (skip > SAVAGE_SKIP_ALL_S4) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return DRM_ERR(EINVAL); + return -EINVAL; } vtx_size = 10; /* full vertex */ } @@ -478,13 +478,13 @@ static int savage_dispatch_vb_prim(drm_savage_private_t * dev_priv, if (vtx_size > vb_stride) { DRM_ERROR("vertex size greater than vb stride (%u > %u)\n", vtx_size, vb_stride); - return DRM_ERR(EINVAL); + return -EINVAL; } if (start + n > vb_size / (vb_stride * 4)) { DRM_ERROR("vertex indices (%u-%u) out of range (0-%u)\n", start, start + n - 1, vb_size / (vb_stride * 4)); - return DRM_ERR(EINVAL); + return -EINVAL; } prim <<= 25; @@ -547,7 +547,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, if (!dmabuf) { DRM_ERROR("called without dma buffers!\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } if (!n) @@ -560,7 +560,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of indices %u in TRILIST\n", n); - return DRM_ERR(EINVAL); + return -EINVAL; } break; case SAVAGE_PRIM_TRISTRIP: @@ -568,18 +568,18 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, if (n < 3) { DRM_ERROR ("wrong number of indices %u in TRIFAN/STRIP\n", n); - return DRM_ERR(EINVAL); + return -EINVAL; } break; default: DRM_ERROR("invalid primitive type %u\n", prim); - return DRM_ERR(EINVAL); + return -EINVAL; } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip != 0) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return DRM_ERR(EINVAL); + return -EINVAL; } } else { unsigned int size = 10 - (skip & 1) - (skip >> 1 & 1) - @@ -587,11 +587,11 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, (skip >> 5 & 1) - (skip >> 6 & 1) - (skip >> 7 & 1); if (skip > SAVAGE_SKIP_ALL_S4 || size != 8) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return DRM_ERR(EINVAL); + return -EINVAL; } if (reorder) { DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -628,7 +628,7 @@ static int savage_dispatch_dma_idx(drm_savage_private_t * dev_priv, if (idx[i] > dmabuf->total / 32) { DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", i, idx[i], dmabuf->total / 32); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -698,7 +698,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, case SAVAGE_PRIM_TRILIST: if (n % 3 != 0) { DRM_ERROR("wrong number of indices %u in TRILIST\n", n); - return DRM_ERR(EINVAL); + return -EINVAL; } break; case SAVAGE_PRIM_TRISTRIP: @@ -706,24 +706,24 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, if (n < 3) { DRM_ERROR ("wrong number of indices %u in TRIFAN/STRIP\n", n); - return DRM_ERR(EINVAL); + return -EINVAL; } break; default: DRM_ERROR("invalid primitive type %u\n", prim); - return DRM_ERR(EINVAL); + return -EINVAL; } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip > SAVAGE_SKIP_ALL_S3D) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return DRM_ERR(EINVAL); + return -EINVAL; } vtx_size = 8; /* full vertex */ } else { if (skip > SAVAGE_SKIP_ALL_S4) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return DRM_ERR(EINVAL); + return -EINVAL; } vtx_size = 10; /* full vertex */ } @@ -735,7 +735,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, if (vtx_size > vb_stride) { DRM_ERROR("vertex size greater than vb stride (%u > %u)\n", vtx_size, vb_stride); - return DRM_ERR(EINVAL); + return -EINVAL; } prim <<= 25; @@ -748,7 +748,7 @@ static int savage_dispatch_vb_idx(drm_savage_private_t * dev_priv, if (idx[i] > vb_size / (vb_stride * 4)) { DRM_ERROR("idx[%u]=%u out of range (0-%u)\n", i, idx[i], vb_size / (vb_stride * 4)); - return DRM_ERR(EINVAL); + return -EINVAL; } } @@ -942,7 +942,7 @@ static int savage_dispatch_draw(drm_savage_private_t * dev_priv, DRM_ERROR("IMPLEMENTATION ERROR: " "non-drawing-command %d\n", cmd_header.cmd.cmd); - return DRM_ERR(EINVAL); + return -EINVAL; } if (ret != 0) @@ -953,13 +953,12 @@ static int savage_dispatch_draw(drm_savage_private_t * dev_priv, return 0; } -int savage_bci_cmdbuf(DRM_IOCTL_ARGS) +int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; struct drm_buf *dmabuf; - drm_savage_cmdbuf_t cmdbuf; + drm_savage_cmdbuf_t *cmdbuf = data; drm_savage_cmd_header_t *kcmd_addr = NULL; drm_savage_cmd_header_t *first_draw_cmd; unsigned int *kvb_addr = NULL; @@ -969,19 +968,16 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *) data, - sizeof(cmdbuf)); + LOCK_TEST_WITH_RETURN(dev, file_priv); if (dma && dma->buflist) { - if (cmdbuf.dma_idx > dma->buf_count) { + if (cmdbuf->dma_idx > dma->buf_count) { DRM_ERROR ("vertex buffer index %u out of range (0-%u)\n", - cmdbuf.dma_idx, dma->buf_count - 1); - return DRM_ERR(EINVAL); + cmdbuf->dma_idx, dma->buf_count - 1); + return -EINVAL; } - dmabuf = dma->buflist[cmdbuf.dma_idx]; + dmabuf = dma->buflist[cmdbuf->dma_idx]; } else { dmabuf = NULL; } @@ -991,47 +987,47 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) * COPY_FROM_USER_UNCHECKED when done in other drivers, and is correct * for locking on FreeBSD. */ - if (cmdbuf.size) { - kcmd_addr = drm_alloc(cmdbuf.size * 8, DRM_MEM_DRIVER); + if (cmdbuf->size) { + kcmd_addr = drm_alloc(cmdbuf->size * 8, DRM_MEM_DRIVER); if (kcmd_addr == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; - if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf.cmd_addr, - cmdbuf.size * 8)) + if (DRM_COPY_FROM_USER(kcmd_addr, cmdbuf->cmd_addr, + cmdbuf->size * 8)) { - drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER); - return DRM_ERR(EFAULT); + drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER); + return -EFAULT; } - cmdbuf.cmd_addr = kcmd_addr; + cmdbuf->cmd_addr = kcmd_addr; } - if (cmdbuf.vb_size) { - kvb_addr = drm_alloc(cmdbuf.vb_size, DRM_MEM_DRIVER); + if (cmdbuf->vb_size) { + kvb_addr = drm_alloc(cmdbuf->vb_size, DRM_MEM_DRIVER); if (kvb_addr == NULL) { - ret = DRM_ERR(ENOMEM); + ret = -ENOMEM; goto done; } - if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr, - cmdbuf.vb_size)) { - ret = DRM_ERR(EFAULT); + if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf->vb_addr, + cmdbuf->vb_size)) { + ret = -EFAULT; goto done; } - cmdbuf.vb_addr = kvb_addr; + cmdbuf->vb_addr = kvb_addr; } - if (cmdbuf.nbox) { - kbox_addr = drm_alloc(cmdbuf.nbox * sizeof(struct drm_clip_rect), + if (cmdbuf->nbox) { + kbox_addr = drm_alloc(cmdbuf->nbox * sizeof(struct drm_clip_rect), DRM_MEM_DRIVER); if (kbox_addr == NULL) { - ret = DRM_ERR(ENOMEM); + ret = -ENOMEM; goto done; } - if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr, - cmdbuf.nbox * sizeof(struct drm_clip_rect))) { - ret = DRM_ERR(EFAULT); + if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf->box_addr, + cmdbuf->nbox * sizeof(struct drm_clip_rect))) { + ret = -EFAULT; goto done; } - cmdbuf.box_addr = kbox_addr; + cmdbuf->box_addr = kbox_addr; } /* Make sure writes to DMA buffers are finished before sending @@ -1044,10 +1040,10 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) i = 0; first_draw_cmd = NULL; - while (i < cmdbuf.size) { + while (i < cmdbuf->size) { drm_savage_cmd_header_t cmd_header; - cmd_header = *(drm_savage_cmd_header_t *)cmdbuf.cmd_addr; - cmdbuf.cmd_addr++; + cmd_header = *(drm_savage_cmd_header_t *)cmdbuf->cmd_addr; + cmdbuf->cmd_addr++; i++; /* Group drawing commands with same state to minimize @@ -1057,28 +1053,28 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) case SAVAGE_CMD_DMA_IDX: case SAVAGE_CMD_VB_IDX: j = (cmd_header.idx.count + 3) / 4; - if (i + j > cmdbuf.size) { + if (i + j > cmdbuf->size) { DRM_ERROR("indexed drawing command extends " "beyond end of command buffer\n"); DMA_FLUSH(); - return DRM_ERR(EINVAL); + return -EINVAL; } /* fall through */ case SAVAGE_CMD_DMA_PRIM: case SAVAGE_CMD_VB_PRIM: if (!first_draw_cmd) - first_draw_cmd = cmdbuf.cmd_addr - 1; - cmdbuf.cmd_addr += j; + first_draw_cmd = cmdbuf->cmd_addr - 1; + cmdbuf->cmd_addr += j; i += j; break; default: if (first_draw_cmd) { ret = savage_dispatch_draw( dev_priv, first_draw_cmd, - cmdbuf.cmd_addr - 1, - dmabuf, cmdbuf.vb_addr, cmdbuf.vb_size, - cmdbuf.vb_stride, - cmdbuf.nbox, cmdbuf.box_addr); + cmdbuf->cmd_addr - 1, + dmabuf, cmdbuf->vb_addr, cmdbuf->vb_size, + cmdbuf->vb_stride, + cmdbuf->nbox, cmdbuf->box_addr); if (ret != 0) return ret; first_draw_cmd = NULL; @@ -1090,40 +1086,42 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) switch (cmd_header.cmd.cmd) { case SAVAGE_CMD_STATE: j = (cmd_header.state.count + 1) / 2; - if (i + j > cmdbuf.size) { + if (i + j > cmdbuf->size) { DRM_ERROR("command SAVAGE_CMD_STATE extends " "beyond end of command buffer\n"); DMA_FLUSH(); - ret = DRM_ERR(EINVAL); + ret = -EINVAL; goto done; } ret = savage_dispatch_state(dev_priv, &cmd_header, - (const uint32_t *)cmdbuf.cmd_addr); - cmdbuf.cmd_addr += j; + (const uint32_t *)cmdbuf->cmd_addr); + cmdbuf->cmd_addr += j; i += j; break; case SAVAGE_CMD_CLEAR: - if (i + 1 > cmdbuf.size) { + if (i + 1 > cmdbuf->size) { DRM_ERROR("command SAVAGE_CMD_CLEAR extends " "beyond end of command buffer\n"); DMA_FLUSH(); - ret = DRM_ERR(EINVAL); + ret = -EINVAL; goto done; } ret = savage_dispatch_clear(dev_priv, &cmd_header, - cmdbuf.cmd_addr, - cmdbuf.nbox, cmdbuf.box_addr); - cmdbuf.cmd_addr++; + cmdbuf->cmd_addr, + cmdbuf->nbox, + cmdbuf->box_addr); + cmdbuf->cmd_addr++; i++; break; case SAVAGE_CMD_SWAP: - ret = savage_dispatch_swap(dev_priv, cmdbuf.nbox, - cmdbuf.box_addr); + ret = savage_dispatch_swap(dev_priv, cmdbuf->nbox, + cmdbuf->box_addr); break; default: - DRM_ERROR("invalid command 0x%x\n", cmd_header.cmd.cmd); + DRM_ERROR("invalid command 0x%x\n", + cmd_header.cmd.cmd); DMA_FLUSH(); - ret = DRM_ERR(EINVAL); + ret = -EINVAL; goto done; } @@ -1135,9 +1133,9 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) if (first_draw_cmd) { ret = savage_dispatch_draw ( - dev_priv, first_draw_cmd, cmdbuf.cmd_addr, dmabuf, - cmdbuf.vb_addr, cmdbuf.vb_size, cmdbuf.vb_stride, - cmdbuf.nbox, cmdbuf.box_addr); + dev_priv, first_draw_cmd, cmdbuf->cmd_addr, dmabuf, + cmdbuf->vb_addr, cmdbuf->vb_size, cmdbuf->vb_stride, + cmdbuf->nbox, cmdbuf->box_addr); if (ret != 0) { DMA_FLUSH(); goto done; @@ -1146,7 +1144,7 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) DMA_FLUSH(); - if (dmabuf && cmdbuf.discard) { + if (dmabuf && cmdbuf->discard) { drm_savage_buf_priv_t *buf_priv = dmabuf->dev_private; uint16_t event; event = savage_bci_emit_event(dev_priv, SAVAGE_WAIT_3D); @@ -1156,9 +1154,9 @@ int savage_bci_cmdbuf(DRM_IOCTL_ARGS) done: /* If we didn't need to allocate them, these'll be NULL */ - drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER); - drm_free(kvb_addr, cmdbuf.vb_size, DRM_MEM_DRIVER); - drm_free(kbox_addr, cmdbuf.nbox * sizeof(struct drm_clip_rect), + drm_free(kcmd_addr, cmdbuf->size * 8, DRM_MEM_DRIVER); + drm_free(kvb_addr, cmdbuf->vb_size, DRM_MEM_DRIVER); + drm_free(kbox_addr, cmdbuf->nbox * sizeof(struct drm_clip_rect), DRM_MEM_DRIVER); return ret; diff --git a/drivers/char/drm/sis_drv.c b/drivers/char/drm/sis_drv.c index 1912f5857051..7dacc64e9b56 100644 --- a/drivers/char/drm/sis_drv.c +++ b/drivers/char/drm/sis_drv.c @@ -42,7 +42,7 @@ static int sis_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv = drm_calloc(1, sizeof(drm_sis_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; dev->dev_private = (void *)dev_priv; dev_priv->chipset = chipset; diff --git a/drivers/char/drm/sis_drv.h b/drivers/char/drm/sis_drv.h index 5630df874353..ef940bad63f7 100644 --- a/drivers/char/drm/sis_drv.h +++ b/drivers/char/drm/sis_drv.h @@ -63,10 +63,11 @@ typedef struct drm_sis_private { } drm_sis_private_t; extern int sis_idle(struct drm_device *dev); -extern void sis_reclaim_buffers_locked(struct drm_device *dev, struct file *filp); +extern void sis_reclaim_buffers_locked(struct drm_device *dev, + struct drm_file *file_priv); extern void sis_lastclose(struct drm_device *dev); -extern drm_ioctl_desc_t sis_ioctls[]; +extern struct drm_ioctl_desc sis_ioctls[]; extern int sis_max_ioctl; #endif diff --git a/drivers/char/drm/sis_mm.c b/drivers/char/drm/sis_mm.c index 441bbdbf1510..8c66838ff515 100644 --- a/drivers/char/drm/sis_mm.c +++ b/drivers/char/drm/sis_mm.c @@ -82,15 +82,12 @@ static unsigned long sis_sman_mm_offset(void *private, void *ref) #endif /* CONFIG_FB_SIS */ -static int sis_fb_init(DRM_IOCTL_ARGS) +static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_sis_private_t *dev_priv = dev->dev_private; - drm_sis_fb_t fb; + drm_sis_fb_t *fb = data; int ret; - DRM_COPY_FROM_USER_IOCTL(fb, (drm_sis_fb_t __user *) data, sizeof(fb)); - mutex_lock(&dev->struct_mutex); #if defined(CONFIG_FB_SIS) { @@ -105,7 +102,7 @@ static int sis_fb_init(DRM_IOCTL_ARGS) } #else ret = drm_sman_set_range(&dev_priv->sman, VIDEO_TYPE, 0, - fb.size >> SIS_MM_ALIGN_SHIFT); + fb->size >> SIS_MM_ALIGN_SHIFT); #endif if (ret) { @@ -115,98 +112,87 @@ static int sis_fb_init(DRM_IOCTL_ARGS) } dev_priv->vram_initialized = 1; - dev_priv->vram_offset = fb.offset; + dev_priv->vram_offset = fb->offset; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); + DRM_DEBUG("offset = %u, size = %u", fb->offset, fb->size); return 0; } -static int sis_drm_alloc(struct drm_device *dev, struct drm_file * priv, - unsigned long data, int pool) +static int sis_drm_alloc(struct drm_device *dev, struct drm_file *file_priv, + void *data, int pool) { drm_sis_private_t *dev_priv = dev->dev_private; - drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data; - drm_sis_mem_t mem; + drm_sis_mem_t *mem = data; int retval = 0; struct drm_memblock_item *item; - DRM_COPY_FROM_USER_IOCTL(mem, argp, sizeof(mem)); - mutex_lock(&dev->struct_mutex); if (0 == ((pool == 0) ? dev_priv->vram_initialized : dev_priv->agp_initialized)) { DRM_ERROR ("Attempt to allocate from uninitialized memory manager.\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } - mem.size = (mem.size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT; - item = drm_sman_alloc(&dev_priv->sman, pool, mem.size, 0, - (unsigned long)priv); + mem->size = (mem->size + SIS_MM_ALIGN_MASK) >> SIS_MM_ALIGN_SHIFT; + item = drm_sman_alloc(&dev_priv->sman, pool, mem->size, 0, + (unsigned long)file_priv); mutex_unlock(&dev->struct_mutex); if (item) { - mem.offset = ((pool == 0) ? + mem->offset = ((pool == 0) ? dev_priv->vram_offset : dev_priv->agp_offset) + (item->mm-> offset(item->mm, item->mm_info) << SIS_MM_ALIGN_SHIFT); - mem.free = item->user_hash.key; - mem.size = mem.size << SIS_MM_ALIGN_SHIFT; + mem->free = item->user_hash.key; + mem->size = mem->size << SIS_MM_ALIGN_SHIFT; } else { - mem.offset = 0; - mem.size = 0; - mem.free = 0; - retval = DRM_ERR(ENOMEM); + mem->offset = 0; + mem->size = 0; + mem->free = 0; + retval = -ENOMEM; } - DRM_COPY_TO_USER_IOCTL(argp, mem, sizeof(mem)); - - DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem.size, - mem.offset); + DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size, + mem->offset); return retval; } -static int sis_drm_free(DRM_IOCTL_ARGS) +static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_sis_private_t *dev_priv = dev->dev_private; - drm_sis_mem_t mem; + drm_sis_mem_t *mem = data; int ret; - DRM_COPY_FROM_USER_IOCTL(mem, (drm_sis_mem_t __user *) data, - sizeof(mem)); - mutex_lock(&dev->struct_mutex); - ret = drm_sman_free_key(&dev_priv->sman, mem.free); + ret = drm_sman_free_key(&dev_priv->sman, mem->free); mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("free = 0x%lx\n", mem.free); + DRM_DEBUG("free = 0x%lx\n", mem->free); return ret; } -static int sis_fb_alloc(DRM_IOCTL_ARGS) +static int sis_fb_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; - return sis_drm_alloc(dev, priv, data, VIDEO_TYPE); + return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE); } -static int sis_ioctl_agp_init(DRM_IOCTL_ARGS) +static int sis_ioctl_agp_init(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; drm_sis_private_t *dev_priv = dev->dev_private; - drm_sis_agp_t agp; + drm_sis_agp_t *agp = data; int ret; dev_priv = dev->dev_private; - DRM_COPY_FROM_USER_IOCTL(agp, (drm_sis_agp_t __user *) data, - sizeof(agp)); mutex_lock(&dev->struct_mutex); ret = drm_sman_set_range(&dev_priv->sman, AGP_TYPE, 0, - agp.size >> SIS_MM_ALIGN_SHIFT); + agp->size >> SIS_MM_ALIGN_SHIFT); if (ret) { DRM_ERROR("AGP memory manager initialisation error\n"); @@ -215,18 +201,18 @@ static int sis_ioctl_agp_init(DRM_IOCTL_ARGS) } dev_priv->agp_initialized = 1; - dev_priv->agp_offset = agp.offset; + dev_priv->agp_offset = agp->offset; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + DRM_DEBUG("offset = %u, size = %u", agp->offset, agp->size); return 0; } -static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS) +static int sis_ioctl_agp_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; - return sis_drm_alloc(dev, priv, data, AGP_TYPE); + return sis_drm_alloc(dev, file_priv, data, AGP_TYPE); } static drm_local_map_t *sis_reg_init(struct drm_device *dev) @@ -314,13 +300,13 @@ void sis_lastclose(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); } -void sis_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) +void sis_reclaim_buffers_locked(struct drm_device * dev, + struct drm_file *file_priv) { drm_sis_private_t *dev_priv = dev->dev_private; - struct drm_file *priv = filp->private_data; mutex_lock(&dev->struct_mutex); - if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) { + if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) { mutex_unlock(&dev->struct_mutex); return; } @@ -329,20 +315,18 @@ void sis_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) dev->driver->dma_quiescent(dev); } - drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv); + drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); mutex_unlock(&dev->struct_mutex); return; } -drm_ioctl_desc_t sis_ioctls[] = { - [DRM_IOCTL_NR(DRM_SIS_FB_ALLOC)] = {sis_fb_alloc, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_SIS_FB_FREE)] = {sis_drm_free, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_SIS_AGP_INIT)] = - {sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY}, - [DRM_IOCTL_NR(DRM_SIS_AGP_ALLOC)] = {sis_ioctl_agp_alloc, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_SIS_AGP_FREE)] = {sis_drm_free, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_SIS_FB_INIT)] = - {sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY} +struct drm_ioctl_desc sis_ioctls[] = { + DRM_IOCTL_DEF(DRM_SIS_FB_ALLOC, sis_fb_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_SIS_FB_FREE, sis_drm_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_SIS_AGP_INIT, sis_ioctl_agp_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), + DRM_IOCTL_DEF(DRM_SIS_AGP_ALLOC, sis_ioctl_agp_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_SIS_AGP_FREE, sis_drm_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_SIS_FB_INIT, sis_fb_init, DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), }; int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls); diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c index 7ff2b623c2d4..75d6b748c2c0 100644 --- a/drivers/char/drm/via_dma.c +++ b/drivers/char/drm/via_dma.c @@ -175,24 +175,24 @@ static int via_initialize(struct drm_device * dev, { if (!dev_priv || !dev_priv->mmio) { DRM_ERROR("via_dma_init called before via_map_init\n"); - return DRM_ERR(EFAULT); + return -EFAULT; } if (dev_priv->ring.virtual_start != NULL) { DRM_ERROR("%s called again without calling cleanup\n", __FUNCTION__); - return DRM_ERR(EFAULT); + return -EFAULT; } if (!dev->agp || !dev->agp->base) { DRM_ERROR("%s called with no agp memory available\n", __FUNCTION__); - return DRM_ERR(EFAULT); + return -EFAULT; } if (dev_priv->chipset == VIA_DX9_0) { DRM_ERROR("AGP DMA is not supported on this chip\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } dev_priv->ring.map.offset = dev->agp->base + init->offset; @@ -207,7 +207,7 @@ static int via_initialize(struct drm_device * dev, via_dma_cleanup(dev); DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); - return DRM_ERR(ENOMEM); + return -ENOMEM; } dev_priv->ring.virtual_start = dev_priv->ring.map.handle; @@ -227,35 +227,31 @@ static int via_initialize(struct drm_device * dev, return 0; } -static int via_dma_init(DRM_IOCTL_ARGS) +static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - drm_via_dma_init_t init; + drm_via_dma_init_t *init = data; int retcode = 0; - DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t __user *) data, - sizeof(init)); - - switch (init.func) { + switch (init->func) { case VIA_INIT_DMA: if (!DRM_SUSER(DRM_CURPROC)) - retcode = DRM_ERR(EPERM); + retcode = -EPERM; else - retcode = via_initialize(dev, dev_priv, &init); + retcode = via_initialize(dev, dev_priv, init); break; case VIA_CLEANUP_DMA: if (!DRM_SUSER(DRM_CURPROC)) - retcode = DRM_ERR(EPERM); + retcode = -EPERM; else retcode = via_dma_cleanup(dev); break; case VIA_DMA_INITIALIZED: retcode = (dev_priv->ring.virtual_start != NULL) ? - 0 : DRM_ERR(EFAULT); + 0 : -EFAULT; break; default: - retcode = DRM_ERR(EINVAL); + retcode = -EINVAL; break; } @@ -273,15 +269,15 @@ static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * if (dev_priv->ring.virtual_start == NULL) { DRM_ERROR("%s called without initializing AGP ring buffer.\n", __FUNCTION__); - return DRM_ERR(EFAULT); + return -EFAULT; } if (cmd->size > VIA_PCI_BUF_SIZE) { - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) - return DRM_ERR(EFAULT); + return -EFAULT; /* * Running this function on AGP memory is dead slow. Therefore @@ -297,7 +293,7 @@ static int via_dispatch_cmdbuffer(struct drm_device * dev, drm_via_cmdbuffer_t * vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size); if (vb == NULL) { - return DRM_ERR(EAGAIN); + return -EAGAIN; } memcpy(vb, dev_priv->pci_buf, cmd->size); @@ -321,34 +317,30 @@ int via_driver_dma_quiescent(struct drm_device * dev) drm_via_private_t *dev_priv = dev->dev_private; if (!via_wait_idle(dev_priv)) { - return DRM_ERR(EBUSY); + return -EBUSY; } return 0; } -static int via_flush_ioctl(DRM_IOCTL_ARGS) +static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); return via_driver_dma_quiescent(dev); } -static int via_cmdbuffer(DRM_IOCTL_ARGS) +static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_via_cmdbuffer_t cmdbuf; + drm_via_cmdbuffer_t *cmdbuf = data; int ret; - LOCK_TEST_WITH_RETURN(dev, filp); - - DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data, - sizeof(cmdbuf)); + LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size); + DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf->buf, + cmdbuf->size); - ret = via_dispatch_cmdbuffer(dev, &cmdbuf); + ret = via_dispatch_cmdbuffer(dev, cmdbuf); if (ret) { return ret; } @@ -363,10 +355,10 @@ static int via_dispatch_pci_cmdbuffer(struct drm_device * dev, int ret; if (cmd->size > VIA_PCI_BUF_SIZE) { - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) - return DRM_ERR(EFAULT); + return -EFAULT; if ((ret = via_verify_command_stream((uint32_t *) dev_priv->pci_buf, @@ -380,21 +372,17 @@ static int via_dispatch_pci_cmdbuffer(struct drm_device * dev, return ret; } -static int via_pci_cmdbuffer(DRM_IOCTL_ARGS) +static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_via_cmdbuffer_t cmdbuf; + drm_via_cmdbuffer_t *cmdbuf = data; int ret; - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); - DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data, - sizeof(cmdbuf)); + DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf->buf, + cmdbuf->size); - DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf, - cmdbuf.size); - - ret = via_dispatch_pci_cmdbuffer(dev, &cmdbuf); + ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf); if (ret) { return ret; } @@ -653,80 +641,74 @@ static void via_cmdbuf_reset(drm_via_private_t * dev_priv) * User interface to the space and lag functions. */ -static int via_cmdbuf_size(DRM_IOCTL_ARGS) +static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_via_cmdbuf_size_t d_siz; + drm_via_cmdbuf_size_t *d_siz = data; int ret = 0; uint32_t tmp_size, count; drm_via_private_t *dev_priv; DRM_DEBUG("via cmdbuf_size\n"); - LOCK_TEST_WITH_RETURN(dev, filp); + LOCK_TEST_WITH_RETURN(dev, file_priv); dev_priv = (drm_via_private_t *) dev->dev_private; if (dev_priv->ring.virtual_start == NULL) { DRM_ERROR("%s called without initializing AGP ring buffer.\n", __FUNCTION__); - return DRM_ERR(EFAULT); + return -EFAULT; } - DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t __user *) data, - sizeof(d_siz)); - count = 1000000; - tmp_size = d_siz.size; - switch (d_siz.func) { + tmp_size = d_siz->size; + switch (d_siz->func) { case VIA_CMDBUF_SPACE: - while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size) + while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz->size) && count--) { - if (!d_siz.wait) { + if (!d_siz->wait) { break; } } if (!count) { DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n"); - ret = DRM_ERR(EAGAIN); + ret = -EAGAIN; } break; case VIA_CMDBUF_LAG: - while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size) + while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz->size) && count--) { - if (!d_siz.wait) { + if (!d_siz->wait) { break; } } if (!count) { DRM_ERROR("VIA_CMDBUF_LAG timed out.\n"); - ret = DRM_ERR(EAGAIN); + ret = -EAGAIN; } break; default: - ret = DRM_ERR(EFAULT); + ret = -EFAULT; } - d_siz.size = tmp_size; + d_siz->size = tmp_size; - DRM_COPY_TO_USER_IOCTL((drm_via_cmdbuf_size_t __user *) data, d_siz, - sizeof(d_siz)); return ret; } -drm_ioctl_desc_t via_ioctls[] = { - [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, DRM_AUTH|DRM_MASTER}, - [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, DRM_AUTH|DRM_MASTER}, - [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, DRM_AUTH|DRM_MASTER}, - [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_DMA_BLIT)] = {via_dma_blit, DRM_AUTH}, - [DRM_IOCTL_NR(DRM_VIA_BLIT_SYNC)] = {via_dma_blit_sync, DRM_AUTH} +struct drm_ioctl_desc via_ioctls[] = { + DRM_IOCTL_DEF(DRM_VIA_ALLOCMEM, via_mem_alloc, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_FREEMEM, via_mem_free, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_AGP_INIT, via_agp_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF(DRM_VIA_FB_INIT, via_fb_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF(DRM_VIA_MAP_INIT, via_map_init, DRM_AUTH|DRM_MASTER), + DRM_IOCTL_DEF(DRM_VIA_DEC_FUTEX, via_decoder_futex, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_DMA_INIT, via_dma_init, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CMDBUFFER, via_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_FLUSH, via_flush_ioctl, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_PCICMD, via_pci_cmdbuffer, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_CMDBUF_SIZE, via_cmdbuf_size, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_WAIT_IRQ, via_wait_irq, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_DMA_BLIT, via_dma_blit, DRM_AUTH), + DRM_IOCTL_DEF(DRM_VIA_BLIT_SYNC, via_dma_blit_sync, DRM_AUTH) }; int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls); diff --git a/drivers/char/drm/via_dmablit.c b/drivers/char/drm/via_dmablit.c index 3dd1ed3d1bf5..c6fd16f3cb43 100644 --- a/drivers/char/drm/via_dmablit.c +++ b/drivers/char/drm/via_dmablit.c @@ -237,7 +237,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) first_pfn + 1; if (NULL == (vsg->pages = vmalloc(sizeof(struct page *) * vsg->num_pages))) - return DRM_ERR(ENOMEM); + return -ENOMEM; memset(vsg->pages, 0, sizeof(struct page *) * vsg->num_pages); down_read(¤t->mm->mmap_sem); ret = get_user_pages(current, current->mm, @@ -251,7 +251,7 @@ via_lock_all_dma_pages(drm_via_sg_info_t *vsg, drm_via_dmablit_t *xfer) if (ret < 0) return ret; vsg->state = dr_via_pages_locked; - return DRM_ERR(EINVAL); + return -EINVAL; } vsg->state = dr_via_pages_locked; DRM_DEBUG("DMA pages locked\n"); @@ -274,13 +274,13 @@ via_alloc_desc_pages(drm_via_sg_info_t *vsg) vsg->descriptors_per_page; if (NULL == (vsg->desc_pages = kcalloc(vsg->num_desc_pages, sizeof(void *), GFP_KERNEL))) - return DRM_ERR(ENOMEM); + return -ENOMEM; vsg->state = dr_via_desc_pages_alloc; for (i=0; i<vsg->num_desc_pages; ++i) { if (NULL == (vsg->desc_pages[i] = (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL))) - return DRM_ERR(ENOMEM); + return -ENOMEM; } DRM_DEBUG("Allocated %d pages for %d descriptors.\n", vsg->num_desc_pages, vsg->num_desc); @@ -593,7 +593,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli if (xfer->num_lines <= 0 || xfer->line_length <= 0) { DRM_ERROR("Zero size bitblt.\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } /* @@ -606,7 +606,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli if ((xfer->mem_stride - xfer->line_length) >= PAGE_SIZE) { DRM_ERROR("Too large system memory stride. Stride: %d, " "Length: %d\n", xfer->mem_stride, xfer->line_length); - return DRM_ERR(EINVAL); + return -EINVAL; } if ((xfer->mem_stride == xfer->line_length) && @@ -624,7 +624,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli if (xfer->num_lines > 2048 || (xfer->num_lines*xfer->mem_stride > (2048*2048*4))) { DRM_ERROR("Too large PCI DMA bitblt.\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } /* @@ -635,7 +635,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli if (xfer->mem_stride < xfer->line_length || abs(xfer->fb_stride) < xfer->line_length) { DRM_ERROR("Invalid frame-buffer / memory stride.\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } /* @@ -648,7 +648,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli if ((((unsigned long)xfer->mem_addr & 3) != ((unsigned long)xfer->fb_addr & 3)) || ((xfer->num_lines > 1) && ((xfer->mem_stride & 3) != (xfer->fb_stride & 3)))) { DRM_ERROR("Invalid DRM bitblt alignment.\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } #else if ((((unsigned long)xfer->mem_addr & 15) || @@ -656,7 +656,7 @@ via_build_sg_info(struct drm_device *dev, drm_via_sg_info_t *vsg, drm_via_dmabli ((xfer->num_lines > 1) && ((xfer->mem_stride & 15) || (xfer->fb_stride & 3)))) { DRM_ERROR("Invalid DRM bitblt alignment.\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } #endif @@ -696,7 +696,7 @@ via_dmablit_grab_slot(drm_via_blitq_t *blitq, int engine) DRM_WAIT_ON(ret, blitq->busy_queue, DRM_HZ, blitq->num_free > 0); if (ret) { - return (DRM_ERR(EINTR) == ret) ? DRM_ERR(EAGAIN) : ret; + return (-EINTR == ret) ? -EAGAIN : ret; } spin_lock_irqsave(&blitq->blit_lock, irqsave); @@ -740,7 +740,7 @@ via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer) if (dev_priv == NULL) { DRM_ERROR("Called without initialization.\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } engine = (xfer->to_fb) ? 0 : 1; @@ -750,7 +750,7 @@ via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer) } if (NULL == (vsg = kmalloc(sizeof(*vsg), GFP_KERNEL))) { via_dmablit_release_slot(blitq); - return DRM_ERR(ENOMEM); + return -ENOMEM; } if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) { via_dmablit_release_slot(blitq); @@ -781,21 +781,18 @@ via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer) */ int -via_dma_blit_sync( DRM_IOCTL_ARGS ) +via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv ) { - drm_via_blitsync_t sync; + drm_via_blitsync_t *sync = data; int err; - DRM_DEVICE; - DRM_COPY_FROM_USER_IOCTL(sync, (drm_via_blitsync_t *)data, sizeof(sync)); - - if (sync.engine >= VIA_NUM_BLIT_ENGINES) - return DRM_ERR(EINVAL); + if (sync->engine >= VIA_NUM_BLIT_ENGINES) + return -EINVAL; - err = via_dmablit_sync(dev, sync.sync_handle, sync.engine); + err = via_dmablit_sync(dev, sync->sync_handle, sync->engine); - if (DRM_ERR(EINTR) == err) - err = DRM_ERR(EAGAIN); + if (-EINTR == err) + err = -EAGAIN; return err; } @@ -808,17 +805,12 @@ via_dma_blit_sync( DRM_IOCTL_ARGS ) */ int -via_dma_blit( DRM_IOCTL_ARGS ) +via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv ) { - drm_via_dmablit_t xfer; + drm_via_dmablit_t *xfer = data; int err; - DRM_DEVICE; - - DRM_COPY_FROM_USER_IOCTL(xfer, (drm_via_dmablit_t __user *)data, sizeof(xfer)); - - err = via_dmablit(dev, &xfer); - DRM_COPY_TO_USER_IOCTL((void __user *)data, xfer, sizeof(xfer)); + err = via_dmablit(dev, xfer); return err; } diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h index 576711564a11..2daae81874cd 100644 --- a/drivers/char/drm/via_drv.h +++ b/drivers/char/drm/via_drv.h @@ -110,18 +110,18 @@ enum via_family { #define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg) #define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val) -extern drm_ioctl_desc_t via_ioctls[]; +extern struct drm_ioctl_desc via_ioctls[]; extern int via_max_ioctl; -extern int via_fb_init(DRM_IOCTL_ARGS); -extern int via_mem_alloc(DRM_IOCTL_ARGS); -extern int via_mem_free(DRM_IOCTL_ARGS); -extern int via_agp_init(DRM_IOCTL_ARGS); -extern int via_map_init(DRM_IOCTL_ARGS); -extern int via_decoder_futex(DRM_IOCTL_ARGS); -extern int via_wait_irq(DRM_IOCTL_ARGS); -extern int via_dma_blit_sync( DRM_IOCTL_ARGS ); -extern int via_dma_blit( DRM_IOCTL_ARGS ); +extern int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int via_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv); +extern int via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv ); +extern int via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv ); extern int via_driver_load(struct drm_device *dev, unsigned long chipset); extern int via_driver_unload(struct drm_device *dev); @@ -144,7 +144,7 @@ extern void via_init_futex(drm_via_private_t * dev_priv); extern void via_cleanup_futex(drm_via_private_t * dev_priv); extern void via_release_futex(drm_via_private_t * dev_priv, int context); -extern void via_reclaim_buffers_locked(struct drm_device *dev, struct file *filp); +extern void via_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv); extern void via_lastclose(struct drm_device *dev); extern void via_dmablit_handler(struct drm_device *dev, int engine, int from_irq); diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c index 8dc99b5fbab6..9c1d52bc92d7 100644 --- a/drivers/char/drm/via_irq.c +++ b/drivers/char/drm/via_irq.c @@ -205,13 +205,13 @@ via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequenc if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } if (irq >= drm_via_irq_num) { DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, irq); - return DRM_ERR(EINVAL); + return -EINVAL; } real_irq = dev_priv->irq_map[irq]; @@ -219,7 +219,7 @@ via_driver_irq_wait(struct drm_device * dev, unsigned int irq, int force_sequenc if (real_irq < 0) { DRM_ERROR("%s Video IRQ %d not available on this hardware.\n", __FUNCTION__, irq); - return DRM_ERR(EINVAL); + return -EINVAL; } masks = dev_priv->irq_masks; @@ -331,11 +331,9 @@ void via_driver_irq_uninstall(struct drm_device * dev) } } -int via_wait_irq(DRM_IOCTL_ARGS) +int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_via_irqwait_t __user *argp = (void __user *)data; - drm_via_irqwait_t irqwait; + drm_via_irqwait_t *irqwait = data; struct timeval now; int ret = 0; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; @@ -343,42 +341,39 @@ int via_wait_irq(DRM_IOCTL_ARGS) int force_sequence; if (!dev->irq) - return DRM_ERR(EINVAL); + return -EINVAL; - DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait)); - if (irqwait.request.irq >= dev_priv->num_irqs) { + if (irqwait->request.irq >= dev_priv->num_irqs) { DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, - irqwait.request.irq); - return DRM_ERR(EINVAL); + irqwait->request.irq); + return -EINVAL; } - cur_irq += irqwait.request.irq; + cur_irq += irqwait->request.irq; - switch (irqwait.request.type & ~VIA_IRQ_FLAGS_MASK) { + switch (irqwait->request.type & ~VIA_IRQ_FLAGS_MASK) { case VIA_IRQ_RELATIVE: - irqwait.request.sequence += atomic_read(&cur_irq->irq_received); - irqwait.request.type &= ~_DRM_VBLANK_RELATIVE; + irqwait->request.sequence += atomic_read(&cur_irq->irq_received); + irqwait->request.type &= ~_DRM_VBLANK_RELATIVE; case VIA_IRQ_ABSOLUTE: break; default: - return DRM_ERR(EINVAL); + return -EINVAL; } - if (irqwait.request.type & VIA_IRQ_SIGNAL) { + if (irqwait->request.type & VIA_IRQ_SIGNAL) { DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n", __FUNCTION__); - return DRM_ERR(EINVAL); + return -EINVAL; } - force_sequence = (irqwait.request.type & VIA_IRQ_FORCE_SEQUENCE); + force_sequence = (irqwait->request.type & VIA_IRQ_FORCE_SEQUENCE); - ret = via_driver_irq_wait(dev, irqwait.request.irq, force_sequence, - &irqwait.request.sequence); + ret = via_driver_irq_wait(dev, irqwait->request.irq, force_sequence, + &irqwait->request.sequence); do_gettimeofday(&now); - irqwait.reply.tval_sec = now.tv_sec; - irqwait.reply.tval_usec = now.tv_usec; - - DRM_COPY_TO_USER_IOCTL(argp, irqwait, sizeof(irqwait)); + irqwait->reply.tval_sec = now.tv_sec; + irqwait->reply.tval_usec = now.tv_usec; return ret; } diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c index 7fb9d2a2cce2..10091507a0dc 100644 --- a/drivers/char/drm/via_map.c +++ b/drivers/char/drm/via_map.c @@ -75,19 +75,15 @@ int via_do_cleanup_map(struct drm_device * dev) return 0; } -int via_map_init(DRM_IOCTL_ARGS) +int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_via_init_t init; + drm_via_init_t *init = data; DRM_DEBUG("%s\n", __FUNCTION__); - DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t __user *) data, - sizeof(init)); - - switch (init.func) { + switch (init->func) { case VIA_INIT_MAP: - return via_do_init_map(dev, &init); + return via_do_init_map(dev, init); case VIA_CLEANUP_MAP: return via_do_cleanup_map(dev); } @@ -102,7 +98,7 @@ int via_driver_load(struct drm_device *dev, unsigned long chipset) dev_priv = drm_calloc(1, sizeof(drm_via_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) - return DRM_ERR(ENOMEM); + return -ENOMEM; dev->dev_private = (void *)dev_priv; diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c index 85d56acd9d82..9afc1684348d 100644 --- a/drivers/char/drm/via_mm.c +++ b/drivers/char/drm/via_mm.c @@ -33,18 +33,15 @@ #define VIA_MM_ALIGN_SHIFT 4 #define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1) -int via_agp_init(DRM_IOCTL_ARGS) +int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_via_agp_t agp; + drm_via_agp_t *agp = data; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; int ret; - DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data, - sizeof(agp)); mutex_lock(&dev->struct_mutex); ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_AGP, 0, - agp.size >> VIA_MM_ALIGN_SHIFT); + agp->size >> VIA_MM_ALIGN_SHIFT); if (ret) { DRM_ERROR("AGP memory manager initialisation error\n"); @@ -53,25 +50,22 @@ int via_agp_init(DRM_IOCTL_ARGS) } dev_priv->agp_initialized = 1; - dev_priv->agp_offset = agp.offset; + dev_priv->agp_offset = agp->offset; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("offset = %u, size = %u", agp.offset, agp.size); + DRM_DEBUG("offset = %u, size = %u", agp->offset, agp->size); return 0; } -int via_fb_init(DRM_IOCTL_ARGS) +int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_via_fb_t fb; + drm_via_fb_t *fb = data; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; int ret; - DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb)); - mutex_lock(&dev->struct_mutex); ret = drm_sman_set_range(&dev_priv->sman, VIA_MEM_VIDEO, 0, - fb.size >> VIA_MM_ALIGN_SHIFT); + fb->size >> VIA_MM_ALIGN_SHIFT); if (ret) { DRM_ERROR("VRAM memory manager initialisation error\n"); @@ -80,10 +74,10 @@ int via_fb_init(DRM_IOCTL_ARGS) } dev_priv->vram_initialized = 1; - dev_priv->vram_offset = fb.offset; + dev_priv->vram_offset = fb->offset; mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("offset = %u, size = %u", fb.offset, fb.size); + DRM_DEBUG("offset = %u, size = %u", fb->offset, fb->size); return 0; @@ -121,80 +115,71 @@ void via_lastclose(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); } -int via_mem_alloc(DRM_IOCTL_ARGS) +int via_mem_alloc(struct drm_device *dev, void *data, + struct drm_file *file_priv) { - DRM_DEVICE; - - drm_via_mem_t mem; + drm_via_mem_t *mem = data; int retval = 0; struct drm_memblock_item *item; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; unsigned long tmpSize; - DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, - sizeof(mem)); - - if (mem.type > VIA_MEM_AGP) { + if (mem->type > VIA_MEM_AGP) { DRM_ERROR("Unknown memory type allocation\n"); - return DRM_ERR(EINVAL); + return -EINVAL; } mutex_lock(&dev->struct_mutex); - if (0 == ((mem.type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized : + if (0 == ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_initialized : dev_priv->agp_initialized)) { DRM_ERROR ("Attempt to allocate from uninitialized memory manager.\n"); mutex_unlock(&dev->struct_mutex); - return DRM_ERR(EINVAL); + return -EINVAL; } - tmpSize = (mem.size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; - item = drm_sman_alloc(&dev_priv->sman, mem.type, tmpSize, 0, - (unsigned long)priv); + tmpSize = (mem->size + VIA_MM_ALIGN_MASK) >> VIA_MM_ALIGN_SHIFT; + item = drm_sman_alloc(&dev_priv->sman, mem->type, tmpSize, 0, + (unsigned long)file_priv); mutex_unlock(&dev->struct_mutex); if (item) { - mem.offset = ((mem.type == VIA_MEM_VIDEO) ? + mem->offset = ((mem->type == VIA_MEM_VIDEO) ? dev_priv->vram_offset : dev_priv->agp_offset) + (item->mm-> offset(item->mm, item->mm_info) << VIA_MM_ALIGN_SHIFT); - mem.index = item->user_hash.key; + mem->index = item->user_hash.key; } else { - mem.offset = 0; - mem.size = 0; - mem.index = 0; + mem->offset = 0; + mem->size = 0; + mem->index = 0; DRM_DEBUG("Video memory allocation failed\n"); - retval = DRM_ERR(ENOMEM); + retval = -ENOMEM; } - DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, sizeof(mem)); return retval; } -int via_mem_free(DRM_IOCTL_ARGS) +int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; drm_via_private_t *dev_priv = dev->dev_private; - drm_via_mem_t mem; + drm_via_mem_t *mem = data; int ret; - DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, - sizeof(mem)); - mutex_lock(&dev->struct_mutex); - ret = drm_sman_free_key(&dev_priv->sman, mem.index); + ret = drm_sman_free_key(&dev_priv->sman, mem->index); mutex_unlock(&dev->struct_mutex); - DRM_DEBUG("free = 0x%lx\n", mem.index); + DRM_DEBUG("free = 0x%lx\n", mem->index); return ret; } -void via_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) +void via_reclaim_buffers_locked(struct drm_device * dev, + struct drm_file *file_priv) { drm_via_private_t *dev_priv = dev->dev_private; - struct drm_file *priv = filp->private_data; mutex_lock(&dev->struct_mutex); - if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) { + if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)file_priv)) { mutex_unlock(&dev->struct_mutex); return; } @@ -203,7 +188,7 @@ void via_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) dev->driver->dma_quiescent(dev); } - drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv); + drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); mutex_unlock(&dev->struct_mutex); return; } diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c index 832d48356e91..46a579198747 100644 --- a/drivers/char/drm/via_verifier.c +++ b/drivers/char/drm/via_verifier.c @@ -1026,12 +1026,12 @@ via_verify_command_stream(const uint32_t * buf, unsigned int size, case state_error: default: *hc_state = saved_state; - return DRM_ERR(EINVAL); + return -EINVAL; } } if (state == state_error) { *hc_state = saved_state; - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; } @@ -1082,11 +1082,11 @@ via_parse_command_stream(struct drm_device * dev, const uint32_t * buf, break; case state_error: default: - return DRM_ERR(EINVAL); + return -EINVAL; } } if (state == state_error) { - return DRM_ERR(EINVAL); + return -EINVAL; } return 0; } diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c index 300ac61b09ed..c15e75b54cb1 100644 --- a/drivers/char/drm/via_video.c +++ b/drivers/char/drm/via_video.c @@ -65,10 +65,9 @@ void via_release_futex(drm_via_private_t * dev_priv, int context) } } -int via_decoder_futex(DRM_IOCTL_ARGS) +int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv) { - DRM_DEVICE; - drm_via_futex_t fx; + drm_via_futex_t *fx = data; volatile int *lock; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; drm_via_sarea_t *sAPriv = dev_priv->sarea_priv; @@ -76,21 +75,18 @@ int via_decoder_futex(DRM_IOCTL_ARGS) DRM_DEBUG("%s\n", __FUNCTION__); - DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t __user *) data, - sizeof(fx)); - - if (fx.lock > VIA_NR_XVMC_LOCKS) + if (fx->lock > VIA_NR_XVMC_LOCKS) return -EFAULT; - lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx.lock); + lock = (volatile int *)XVMCLOCKPTR(sAPriv, fx->lock); - switch (fx.func) { + switch (fx->func) { case VIA_FUTEX_WAIT: - DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock], - (fx.ms / 10) * (DRM_HZ / 100), *lock != fx.val); + DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx->lock], + (fx->ms / 10) * (DRM_HZ / 100), *lock != fx->val); return ret; case VIA_FUTEX_WAKE: - DRM_WAKEUP(&(dev_priv->decoder_queue[fx.lock])); + DRM_WAKEUP(&(dev_priv->decoder_queue[fx->lock])); return 0; } return 0; diff --git a/drivers/fc4/fc.c b/drivers/fc4/fc.c index 22b62b3cd14e..82de9e1adb1e 100644 --- a/drivers/fc4/fc.c +++ b/drivers/fc4/fc.c @@ -427,15 +427,10 @@ static inline void fcp_scsi_receive(fc_channel *fc, int token, int status, fc_hd memcpy(SCpnt->sense_buffer, ((char *)(rsp+1)), sense_len); } - if (fcmd->data) { - if (SCpnt->use_sg) - dma_unmap_sg(fc->dev, (struct scatterlist *)SCpnt->request_buffer, - SCpnt->use_sg, - SCpnt->sc_data_direction); - else - dma_unmap_single(fc->dev, fcmd->data, SCpnt->request_bufflen, - SCpnt->sc_data_direction); - } + if (fcmd->data) + dma_unmap_sg(fc->dev, scsi_sglist(SCpnt), + scsi_sg_count(SCpnt), + SCpnt->sc_data_direction); break; default: host_status=DID_ERROR; /* FIXME */ @@ -793,10 +788,14 @@ static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt, fcp_cntl = FCP_CNTL_QTYPE_SIMPLE; } else fcp_cntl = FCP_CNTL_QTYPE_UNTAGGED; - if (!SCpnt->request_bufflen && !SCpnt->use_sg) { + + if (!scsi_bufflen(SCpnt)) { cmd->fcp_cntl = fcp_cntl; fcmd->data = (dma_addr_t)NULL; } else { + struct scatterlist *sg; + int nents; + switch (SCpnt->cmnd[0]) { case WRITE_6: case WRITE_10: @@ -805,22 +804,12 @@ static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt, default: cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break; } - if (!SCpnt->use_sg) { - cmd->fcp_data_len = SCpnt->request_bufflen; - fcmd->data = dma_map_single (fc->dev, (char *)SCpnt->request_buffer, - SCpnt->request_bufflen, - SCpnt->sc_data_direction); - } else { - struct scatterlist *sg = (struct scatterlist *)SCpnt->request_buffer; - int nents; - - FCD(("XXX: Use_sg %d %d\n", SCpnt->use_sg, sg->length)) - nents = dma_map_sg (fc->dev, sg, SCpnt->use_sg, - SCpnt->sc_data_direction); - if (nents > 1) printk ("%s: SG for nents %d (use_sg %d) not handled yet\n", fc->name, nents, SCpnt->use_sg); - fcmd->data = sg_dma_address(sg); - cmd->fcp_data_len = sg_dma_len(sg); - } + + sg = scsi_sglist(SCpnt); + nents = dma_map_sg(fc->dev, sg, scsi_sg_count(SCpnt), + SCpnt->sc_data_direction); + fcmd->data = sg_dma_address(sg); + cmd->fcp_data_len = sg_dma_len(sg); } memcpy (cmd->fcp_cdb, SCpnt->cmnd, SCpnt->cmd_len); memset (cmd->fcp_cdb+SCpnt->cmd_len, 0, sizeof(cmd->fcp_cdb)-SCpnt->cmd_len); diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 8503197a8131..a702e2f6da7d 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -229,9 +229,15 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd if (get_user(len, (int __user *)arg)) return -EFAULT; - if (copy_to_user(*((__u8 **)(user_arg + - sizeof(__u32))), - dev->hid->rdesc, len)) + + if (len > HID_MAX_DESCRIPTOR_SIZE - 1) + return -EINVAL; + + if (copy_to_user(user_arg + offsetof( + struct hidraw_report_descriptor, + value[0]), + dev->hid->rdesc, + min(dev->hid->rsize, len))) return -EFAULT; return 0; } diff --git a/drivers/infiniband/ulp/srp/Kconfig b/drivers/infiniband/ulp/srp/Kconfig index 3432dce29520..c74ee9633041 100644 --- a/drivers/infiniband/ulp/srp/Kconfig +++ b/drivers/infiniband/ulp/srp/Kconfig @@ -1,6 +1,7 @@ config INFINIBAND_SRP tristate "InfiniBand SCSI RDMA Protocol" depends on SCSI + select SCSI_SRP_ATTRS ---help--- Support for the SCSI RDMA Protocol over InfiniBand. This allows you to access storage devices that speak SRP over diff --git a/drivers/infiniband/ulp/srp/ib_srp.c b/drivers/infiniband/ulp/srp/ib_srp.c index 9ccc63886d92..950228fb009f 100644 --- a/drivers/infiniband/ulp/srp/ib_srp.c +++ b/drivers/infiniband/ulp/srp/ib_srp.c @@ -47,6 +47,7 @@ #include <scsi/scsi_device.h> #include <scsi/scsi_dbg.h> #include <scsi/srp.h> +#include <scsi/scsi_transport_srp.h> #include <rdma/ib_cache.h> @@ -86,6 +87,8 @@ static void srp_remove_one(struct ib_device *device); static void srp_completion(struct ib_cq *cq, void *target_ptr); static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event); +static struct scsi_transport_template *ib_srp_transport_template; + static struct ib_client srp_client = { .name = "srp", .add = srp_add_one, @@ -420,6 +423,7 @@ static void srp_remove_work(struct work_struct *work) list_del(&target->list); spin_unlock(&target->srp_host->target_lock); + srp_remove_host(target->scsi_host); scsi_remove_host(target->scsi_host); ib_destroy_cm_id(target->cm_id); srp_free_target_ib(target); @@ -1544,12 +1548,24 @@ static struct scsi_host_template srp_template = { static int srp_add_target(struct srp_host *host, struct srp_target_port *target) { + struct srp_rport_identifiers ids; + struct srp_rport *rport; + sprintf(target->target_name, "SRP.T10:%016llX", (unsigned long long) be64_to_cpu(target->id_ext)); if (scsi_add_host(target->scsi_host, host->dev->dev->dma_device)) return -ENODEV; + memcpy(ids.port_id, &target->id_ext, 8); + memcpy(ids.port_id + 8, &target->ioc_guid, 8); + ids.roles = SRP_RPORT_ROLE_TARGET; + rport = srp_rport_add(target->scsi_host, &ids); + if (IS_ERR(rport)) { + scsi_remove_host(target->scsi_host); + return PTR_ERR(rport); + } + spin_lock(&host->target_lock); list_add_tail(&target->list, &host->target_list); spin_unlock(&host->target_lock); @@ -1775,6 +1791,7 @@ static ssize_t srp_create_target(struct class_device *class_dev, if (!target_host) return -ENOMEM; + target_host->transportt = ib_srp_transport_template; target_host->max_lun = SRP_MAX_LUN; target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb; @@ -2054,10 +2071,18 @@ static void srp_remove_one(struct ib_device *device) kfree(srp_dev); } +static struct srp_function_template ib_srp_transport_functions = { +}; + static int __init srp_init_module(void) { int ret; + ib_srp_transport_template = + srp_attach_transport(&ib_srp_transport_functions); + if (!ib_srp_transport_template) + return -ENOMEM; + srp_template.sg_tablesize = srp_sg_tablesize; srp_max_iu_len = (sizeof (struct srp_cmd) + sizeof (struct srp_indirect_buf) + @@ -2066,6 +2091,7 @@ static int __init srp_init_module(void) ret = class_register(&srp_class); if (ret) { printk(KERN_ERR PFX "couldn't register class infiniband_srp\n"); + srp_release_transport(ib_srp_transport_template); return ret; } @@ -2074,6 +2100,7 @@ static int __init srp_init_module(void) ret = ib_register_client(&srp_client); if (ret) { printk(KERN_ERR PFX "couldn't register IB client\n"); + srp_release_transport(ib_srp_transport_template); ib_sa_unregister_client(&srp_sa_client); class_unregister(&srp_class); return ret; @@ -2087,6 +2114,7 @@ static void __exit srp_cleanup_module(void) ib_unregister_client(&srp_client); ib_sa_unregister_client(&srp_sa_client); class_unregister(&srp_class); + srp_release_transport(ib_srp_transport_template); } module_init(srp_init_module); diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h index ad0813843adc..3b0bc4bda5f2 100644 --- a/drivers/kvm/kvm.h +++ b/drivers/kvm/kvm.h @@ -624,6 +624,16 @@ void kvm_mmu_unload(struct kvm_vcpu *vcpu); int kvm_hypercall(struct kvm_vcpu *vcpu, struct kvm_run *run); +static inline void kvm_guest_enter(void) +{ + current->flags |= PF_VCPU; +} + +static inline void kvm_guest_exit(void) +{ + current->flags &= ~PF_VCPU; +} + static inline int kvm_mmu_page_fault(struct kvm_vcpu *vcpu, gva_t gva, u32 error_code) { diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c index 353e58527d15..af2d288c881d 100644 --- a/drivers/kvm/kvm_main.c +++ b/drivers/kvm/kvm_main.c @@ -2046,6 +2046,7 @@ again: kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run); vcpu->guest_mode = 1; + kvm_guest_enter(); if (vcpu->requests) if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests)) @@ -2053,6 +2054,7 @@ again: kvm_x86_ops->run(vcpu, kvm_run); + kvm_guest_exit(); vcpu->guest_mode = 0; local_irq_enable(); diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index f55cc03a75c9..a34a11d2fef2 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -1,15 +1,19 @@ -menu "Fusion MPT device support" +menuconfig FUSION + bool "Fusion MPT device support" depends on PCI + ---help--- + Say Y here to get to see options for Fusion Message + Passing Technology (MPT) drivers. + This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and disabled. -config FUSION - bool - default n +if FUSION config FUSION_SPI tristate "Fusion MPT ScsiHost drivers for SPI" depends on PCI && SCSI - select FUSION select SCSI_SPI_ATTRS ---help--- SCSI HOST support for a parallel SCSI host adapters. @@ -20,11 +24,11 @@ config FUSION_SPI LSI53C1020A LSI53C1030 LSI53C1035 + ATTO UL4D config FUSION_FC tristate "Fusion MPT ScsiHost drivers for FC" depends on PCI && SCSI - select FUSION select SCSI_FC_ATTRS ---help--- SCSI HOST support for a Fiber Channel host adapters. @@ -37,12 +41,13 @@ config FUSION_FC LSIFC929 LSIFC929X LSIFC929XL + LSIFC949X + LSIFC949E Brocade FC 410/420 config FUSION_SAS tristate "Fusion MPT ScsiHost drivers for SAS" depends on PCI && SCSI - select FUSION select SCSI_SAS_ATTRS ---help--- SCSI HOST support for a SAS host adapters. @@ -53,10 +58,10 @@ config FUSION_SAS LSISAS1068 LSISAS1064E LSISAS1068E + LSISAS1078 config FUSION_MAX_SGE int "Maximum number of scatter gather entries (16 - 128)" - depends on FUSION default "128" range 16 128 help @@ -104,7 +109,6 @@ config FUSION_LAN config FUSION_LOGGING bool "Fusion MPT logging facility" - depends on FUSION ---help--- This turns on a logging facility that can be used to debug a number of Fusion MPT related problems. @@ -113,7 +117,7 @@ config FUSION_LOGGING echo [level] > /sys/class/scsi_host/host#/debug_level - There are various debug levels that an be found in the source: + There are various debug levels that can be found in the source: file:drivers/message/fusion/mptdebug.h -endmenu +endif # FUSION diff --git a/drivers/message/fusion/lsi/mpi.h b/drivers/message/fusion/lsi/mpi.h index 6a92e3d118fe..1acbdd61b670 100644 --- a/drivers/message/fusion/lsi/mpi.h +++ b/drivers/message/fusion/lsi/mpi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Logic Corporation. + * Copyright (c) 2000-2007 LSI Corporation. * * * Name: mpi.h diff --git a/drivers/message/fusion/lsi/mpi_cnfg.h b/drivers/message/fusion/lsi/mpi_cnfg.h index eda769730e39..2bd8adae0f00 100644 --- a/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/drivers/message/fusion/lsi/mpi_cnfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Logic Corporation. + * Copyright (c) 2000-2007 LSI Corporation. * * * Name: mpi_cnfg.h diff --git a/drivers/message/fusion/lsi/mpi_fc.h b/drivers/message/fusion/lsi/mpi_fc.h index 51a6aeb990ba..627acfbb8623 100644 --- a/drivers/message/fusion/lsi/mpi_fc.h +++ b/drivers/message/fusion/lsi/mpi_fc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 LSI Logic Corporation. + * Copyright (c) 2000-2004 LSI Corporation. * * * Name: mpi_fc.h diff --git a/drivers/message/fusion/lsi/mpi_history.txt b/drivers/message/fusion/lsi/mpi_history.txt index a1f479057ea3..241592ab13ad 100644 --- a/drivers/message/fusion/lsi/mpi_history.txt +++ b/drivers/message/fusion/lsi/mpi_history.txt @@ -3,7 +3,7 @@ MPI Header File Change History ============================== - Copyright (c) 2000-2007 LSI Logic Corporation. + Copyright (c) 2000-2007 LSI Corporation. --------------------------------------- Header Set Release Version: 01.05.16 diff --git a/drivers/message/fusion/lsi/mpi_init.h b/drivers/message/fusion/lsi/mpi_init.h index 3a02615f12d6..a9e3693601a7 100644 --- a/drivers/message/fusion/lsi/mpi_init.h +++ b/drivers/message/fusion/lsi/mpi_init.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Logic Corporation. + * Copyright (c) 2000-2007 LSI Corporation. * * * Name: mpi_init.h diff --git a/drivers/message/fusion/lsi/mpi_ioc.h b/drivers/message/fusion/lsi/mpi_ioc.h index b1893d185bc4..5cbb6bd048e1 100644 --- a/drivers/message/fusion/lsi/mpi_ioc.h +++ b/drivers/message/fusion/lsi/mpi_ioc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Logic Corporation. + * Copyright (c) 2000-2007 LSI Corporation. * * * Name: mpi_ioc.h diff --git a/drivers/message/fusion/lsi/mpi_lan.h b/drivers/message/fusion/lsi/mpi_lan.h index dc0b52ae83dd..03253b53b785 100644 --- a/drivers/message/fusion/lsi/mpi_lan.h +++ b/drivers/message/fusion/lsi/mpi_lan.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 LSI Logic Corporation. + * Copyright (c) 2000-2004 LSI Corporation. * * * Name: mpi_lan.h diff --git a/drivers/message/fusion/lsi/mpi_log_fc.h b/drivers/message/fusion/lsi/mpi_log_fc.h index dc98d46f9071..e4dafcefeecd 100644 --- a/drivers/message/fusion/lsi/mpi_log_fc.h +++ b/drivers/message/fusion/lsi/mpi_log_fc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved. + * Copyright (c) 2000-2001 LSI Corporation. All rights reserved. * * NAME: fc_log.h * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips diff --git a/drivers/message/fusion/lsi/mpi_log_sas.h b/drivers/message/fusion/lsi/mpi_log_sas.h index 635bbe04513e..6be1f6b65777 100644 --- a/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/drivers/message/fusion/lsi/mpi_log_sas.h @@ -1,6 +1,6 @@ /*************************************************************************** * * - * Copyright 2003 LSI Logic Corporation. All rights reserved. * + * Copyright 2003 LSI Corporation. All rights reserved. * * * * Description * * ------------ * diff --git a/drivers/message/fusion/lsi/mpi_raid.h b/drivers/message/fusion/lsi/mpi_raid.h index 32819b1ec8ec..2856108421d7 100644 --- a/drivers/message/fusion/lsi/mpi_raid.h +++ b/drivers/message/fusion/lsi/mpi_raid.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2007 LSI Logic Corporation. + * Copyright (c) 2001-2007 LSI Corporation. * * * Name: mpi_raid.h diff --git a/drivers/message/fusion/lsi/mpi_sas.h b/drivers/message/fusion/lsi/mpi_sas.h index 8e990a0fa7a2..33fca83cefc2 100644 --- a/drivers/message/fusion/lsi/mpi_sas.h +++ b/drivers/message/fusion/lsi/mpi_sas.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2006 LSI Logic Corporation. + * Copyright (c) 2004-2006 LSI Corporation. * * * Name: mpi_sas.h diff --git a/drivers/message/fusion/lsi/mpi_targ.h b/drivers/message/fusion/lsi/mpi_targ.h index 20b667315773..ff8c37d3fdcb 100644 --- a/drivers/message/fusion/lsi/mpi_targ.h +++ b/drivers/message/fusion/lsi/mpi_targ.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 LSI Logic Corporation. + * Copyright (c) 2000-2004 LSI Corporation. * * * Name: mpi_targ.h diff --git a/drivers/message/fusion/lsi/mpi_tool.h b/drivers/message/fusion/lsi/mpi_tool.h index aa9053da1f58..8834ae6ce0f2 100644 --- a/drivers/message/fusion/lsi/mpi_tool.h +++ b/drivers/message/fusion/lsi/mpi_tool.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 LSI Logic Corporation. + * Copyright (c) 2001-2005 LSI Corporation. * * * Name: mpi_tool.h diff --git a/drivers/message/fusion/lsi/mpi_type.h b/drivers/message/fusion/lsi/mpi_type.h index 32cc9b1151b8..08dad9c1e446 100644 --- a/drivers/message/fusion/lsi/mpi_type.h +++ b/drivers/message/fusion/lsi/mpi_type.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 LSI Logic Corporation. + * Copyright (c) 2000-2004 LSI Corporation. * * * Name: mpi_type.h diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index 414c109f4cf5..52fb216dfe74 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -2,10 +2,10 @@ * linux/drivers/message/fusion/mptbase.c * This is the Fusion MPT base driver which supports multiple * (SCSI + LAN) specialized protocol drivers. - * For use with LSI Logic PCI chip/adapter(s) - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * For use with LSI PCI chip/adapter(s) + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -102,8 +102,6 @@ static int mfcounter = 0; /* * Public data... */ -int mpt_lan_index = -1; -int mpt_stm_index = -1; struct proc_dir_entry *mpt_proc_root_dir; @@ -125,11 +123,14 @@ static MPT_EVHANDLER MptEvHandlers[MPT_MAX_PROTOCOL_DRIVERS]; static MPT_RESETHANDLER MptResetHandlers[MPT_MAX_PROTOCOL_DRIVERS]; static struct mpt_pci_driver *MptDeviceDriverHandlers[MPT_MAX_PROTOCOL_DRIVERS]; -static int mpt_base_index = -1; -static int last_drv_idx = -1; - static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq); +/* + * Driver Callback Index's + */ +static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS; +static u8 last_drv_idx; + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* * Forward protos... @@ -235,6 +236,23 @@ static int mpt_set_debug_level(const char *val, struct kernel_param *kp) return 0; } +/** + * mpt_get_cb_idx - obtain cb_idx for registered driver + * @dclass: class driver enum + * + * Returns cb_idx, or zero means it wasn't found + **/ +static u8 +mpt_get_cb_idx(MPT_DRIVER_CLASS dclass) +{ + u8 cb_idx; + + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) + if (MptDriverClass[cb_idx] == dclass) + return cb_idx; + return 0; +} + /* * Process turbo (context) reply... */ @@ -243,8 +261,8 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) { MPT_FRAME_HDR *mf = NULL; MPT_FRAME_HDR *mr = NULL; - int req_idx = 0; - int cb_idx; + u16 req_idx = 0; + u8 cb_idx; dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa)); @@ -256,7 +274,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) mf = MPT_INDEX_2_MFPTR(ioc, req_idx); break; case MPI_CONTEXT_REPLY_TYPE_LAN: - cb_idx = mpt_lan_index; + cb_idx = mpt_get_cb_idx(MPTLAN_DRIVER); /* * Blind set of mf to NULL here was fatal * after lan_reply says "freeme" @@ -277,7 +295,7 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); break; case MPI_CONTEXT_REPLY_TYPE_SCSI_TARGET: - cb_idx = mpt_stm_index; + cb_idx = mpt_get_cb_idx(MPTSTM_DRIVER); mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); break; default: @@ -286,8 +304,8 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) } /* Check for (valid) IO callback! */ - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || - MptCallbacks[cb_idx] == NULL) { + if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || + MptCallbacks[cb_idx] == NULL) { printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", __FUNCTION__, ioc->name, cb_idx); goto out; @@ -304,8 +322,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) { MPT_FRAME_HDR *mf; MPT_FRAME_HDR *mr; - int req_idx; - int cb_idx; + u16 req_idx; + u8 cb_idx; int freeme; u32 reply_dma_low; @@ -331,7 +349,7 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got non-TURBO reply=%p req_idx=%x cb_idx=%x Function=%x\n", ioc->name, mr, req_idx, cb_idx, mr->u.hdr.Function)); - DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr) + DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mr); /* Check/log IOC log info */ @@ -350,8 +368,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) mpt_iocstatus_info(ioc, (u32)ioc_stat, mf); /* Check for (valid) IO callback! */ - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || - MptCallbacks[cb_idx] == NULL) { + if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || + MptCallbacks[cb_idx] == NULL) { printk(MYIOC_s_WARN_FMT "%s: Invalid cb_idx (%d)!\n", __FUNCTION__, ioc->name, cb_idx); freeme = 0; @@ -433,8 +451,9 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) #ifdef CONFIG_FUSION_LOGGING if ((ioc->debug_level & MPT_DEBUG_MSG_FRAME) && !(reply->u.hdr.MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY)) { - dmfprintk(ioc, printk(KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf)); - DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf) + dmfprintk(ioc, printk(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n", + ioc->name, mf)); + DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf); } #endif @@ -499,8 +518,8 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) u16 status; status = le16_to_cpu(pReply->IOCStatus) & MPI_IOCSTATUS_MASK; - dcprintk(ioc, printk(KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n", - status, le32_to_cpu(pReply->IOCLogInfo))); + dcprintk(ioc, printk(MYIOC_s_NOTE_FMT " IOCStatus=%04xh, IOCLogInfo=%08xh\n", + ioc->name, status, le32_to_cpu(pReply->IOCLogInfo))); pCfg->status = status; if (status == MPI_IOCSTATUS_SUCCESS) { @@ -563,28 +582,27 @@ mpt_base_reply(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *reply) * in order to register separate callbacks; one for "normal" SCSI IO; * one for MptScsiTaskMgmt requests; one for Scan/DV requests. * - * Returns a positive integer valued "handle" in the - * range (and S.O.D. order) {N,...,7,6,5,...,1} if successful. - * Any non-positive return value (including zero!) should be considered - * an error by the caller. + * Returns u8 valued "handle" in the range (and S.O.D. order) + * {N,...,7,6,5,...,1} if successful. + * A return value of MPT_MAX_PROTOCOL_DRIVERS (including zero!) should be + * considered an error by the caller. */ -int +u8 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) { - int i; - - last_drv_idx = -1; + u8 cb_idx; + last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS; /* * Search for empty callback slot in this order: {N,...,7,6,5,...,1} * (slot/handle 0 is reserved!) */ - for (i = MPT_MAX_PROTOCOL_DRIVERS-1; i; i--) { - if (MptCallbacks[i] == NULL) { - MptCallbacks[i] = cbfunc; - MptDriverClass[i] = dclass; - MptEvHandlers[i] = NULL; - last_drv_idx = i; + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + if (MptCallbacks[cb_idx] == NULL) { + MptCallbacks[cb_idx] = cbfunc; + MptDriverClass[cb_idx] = dclass; + MptEvHandlers[cb_idx] = NULL; + last_drv_idx = cb_idx; break; } } @@ -601,9 +619,9 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) * module is unloaded. */ void -mpt_deregister(int cb_idx) +mpt_deregister(u8 cb_idx) { - if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) { + if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) { MptCallbacks[cb_idx] = NULL; MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER; MptEvHandlers[cb_idx] = NULL; @@ -625,9 +643,9 @@ mpt_deregister(int cb_idx) * Returns 0 for success. */ int -mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc) +mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc) { - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return -1; MptEvHandlers[cb_idx] = ev_cbfunc; @@ -645,9 +663,9 @@ mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc) * or when its module is unloaded. */ void -mpt_event_deregister(int cb_idx) +mpt_event_deregister(u8 cb_idx) { - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; MptEvHandlers[cb_idx] = NULL; @@ -665,9 +683,9 @@ mpt_event_deregister(int cb_idx) * Returns 0 for success. */ int -mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func) +mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func) { - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return -1; MptResetHandlers[cb_idx] = reset_func; @@ -684,9 +702,9 @@ mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func) * or when its module is unloaded. */ void -mpt_reset_deregister(int cb_idx) +mpt_reset_deregister(u8 cb_idx) { - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; MptResetHandlers[cb_idx] = NULL; @@ -699,12 +717,12 @@ mpt_reset_deregister(int cb_idx) * @cb_idx: MPT protocol driver index */ int -mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) +mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx) { MPT_ADAPTER *ioc; const struct pci_device_id *id; - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return -EINVAL; MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; @@ -726,12 +744,12 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) * @cb_idx: MPT protocol driver index */ void -mpt_device_driver_deregister(int cb_idx) +mpt_device_driver_deregister(u8 cb_idx) { struct mpt_pci_driver *dd_cbfunc; MPT_ADAPTER *ioc; - if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; dd_cbfunc = MptDeviceDriverHandlers[cb_idx]; @@ -749,14 +767,14 @@ mpt_device_driver_deregister(int cb_idx) /** * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024) * allocated per MPT adapter. - * @handle: Handle of registered MPT protocol driver + * @cb_idx: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * * Returns pointer to a MPT request frame or %NULL if none are available * or IOC is not active. */ MPT_FRAME_HDR* -mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) +mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc) { MPT_FRAME_HDR *mf; unsigned long flags; @@ -766,7 +784,8 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) #ifdef MFCNT if (!ioc->active) - printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n"); + printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame " + "returning NULL!\n", ioc->name); #endif /* If interrupts are not attached, do not return a request frame */ @@ -781,13 +800,14 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) u.frame.linkage.list); list_del(&mf->u.frame.linkage.list); mf->u.frame.linkage.arg1 = 0; - mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ req_idx = req_offset / ioc->req_sz; mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; - ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */ + /* Default, will be changed if necessary in SG generation */ + ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; #ifdef MFCNT ioc->mfcnt++; #endif @@ -798,14 +818,17 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) #ifdef MFCNT if (mf == NULL) - printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth); + printk(MYIOC_s_WARN_FMT "IOC Active. No free Msg Frames! " + "Count 0x%x Max 0x%x\n", ioc->name, ioc->mfcnt, + ioc->req_depth); mfcounter++; if (mfcounter == PRINT_MF_COUNT) - printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth); + printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name, + ioc->mfcnt, ioc->req_depth); #endif - dmfprintk(ioc, printk(KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n", - ioc->name, handle, ioc->id, mf)); + dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n", + ioc->name, cb_idx, ioc->id, mf)); return mf; } @@ -813,7 +836,7 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) /** * mpt_put_msg_frame - Send a protocol specific MPT request frame * to a IOC. - * @handle: Handle of registered MPT protocol driver + * @cb_idx: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * @@ -821,14 +844,14 @@ mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) * specific MPT adapter. */ void -mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) +mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) { u32 mf_dma_addr; int req_offset; u16 req_idx; /* Request index */ /* ensure values are reset properly! */ - mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ req_idx = req_offset / ioc->req_sz; @@ -838,10 +861,44 @@ mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf); mf_dma_addr = (ioc->req_frames_low_dma + req_offset) | ioc->RequestNB[req_idx]; - dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, ioc->RequestNB[req_idx])); + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d " + "RequestNB=%x\n", ioc->name, mf_dma_addr, req_idx, + ioc->RequestNB[req_idx])); CHIPREG_WRITE32(&ioc->chip->RequestFifo, mf_dma_addr); } +/** + * mpt_put_msg_frame_hi_pri - Send a protocol specific MPT request frame + * to a IOC using hi priority request queue. + * @cb_idx: Handle of registered MPT protocol driver + * @ioc: Pointer to MPT adapter structure + * @mf: Pointer to MPT request frame + * + * This routine posts a MPT request frame to the request post FIFO of a + * specific MPT adapter. + **/ +void +mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) +{ + u32 mf_dma_addr; + int req_offset; + u16 req_idx; /* Request index */ + + /* ensure values are reset properly! */ + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; + req_offset = (u8 *)mf - (u8 *)ioc->req_frames; + req_idx = req_offset / ioc->req_sz; + mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(req_idx); + mf->u.frame.hwhdr.msgctxu.fld.rsvd = 0; + + DBG_DUMP_PUT_MSG_FRAME(ioc, (u32 *)mf); + + mf_dma_addr = (ioc->req_frames_low_dma + req_offset); + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mf_dma_addr=%x req_idx=%d\n", + ioc->name, mf_dma_addr, req_idx)); + CHIPREG_WRITE32(&ioc->chip->RequestHiPriFifo, mf_dma_addr); +} + /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_free_msg_frame - Place MPT request frame back on FreeQ. @@ -899,7 +956,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_send_handshake_request - Send MPT request via doorbell handshake method. - * @handle: Handle of registered MPT protocol driver + * @cb_idx: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @reqBytes: Size of the request in bytes * @req: Pointer to MPT request frame @@ -914,7 +971,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) * Returns 0 for success, non-zero for failure. */ int -mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) +mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) { int r = 0; u8 *req_as_bytes; @@ -934,7 +991,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, if (reqBytes >= 12 && ii >= 0 && ii < ioc->req_depth) { MPT_FRAME_HDR *mf = (MPT_FRAME_HDR*)req; mf->u.frame.hwhdr.msgctxu.fld.req_idx = cpu_to_le16(ii); - mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = cb_idx; } /* Make sure there are no doorbells */ @@ -953,7 +1010,7 @@ mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) return -5; - dhsprintk(ioc, printk(KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", + dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n", ioc->name, ii)); CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); @@ -1395,11 +1452,13 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) { MPT_ADAPTER *ioc; u8 __iomem *mem; + u8 __iomem *pmem; unsigned long mem_phys; unsigned long port; u32 msize; u32 psize; int ii; + u8 cb_idx; int r = -ENODEV; u8 revision; u8 pcixcmd; @@ -1408,35 +1467,39 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) struct proc_dir_entry *dent, *ent; #endif + if (mpt_debug_level) + printk(KERN_INFO MYNAM ": mpt_debug_level=%xh\n", mpt_debug_level); + + if (pci_enable_device(pdev)) + return r; + ioc = kzalloc(sizeof(MPT_ADAPTER), GFP_ATOMIC); if (ioc == NULL) { printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; } - ioc->debug_level = mpt_debug_level; - if (mpt_debug_level) - printk(KERN_INFO MYNAM ": mpt_debug_level=%xh\n", mpt_debug_level); - - if (pci_enable_device(pdev)) - return r; + ioc->id = mpt_ids++; + sprintf(ioc->name, "ioc%d", ioc->id); - dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n")); + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name)); if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { - dprintk(ioc, printk(KERN_INFO MYNAM - ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); + dprintk(ioc, printk(MYIOC_s_INFO_FMT + ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", ioc->name)); } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { - printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); + printk(MYIOC_s_WARN_FMT ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n", + ioc->name); + kfree(ioc); return r; } if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { - dprintk(ioc, printk(KERN_INFO MYNAM - ": Using 64 bit consistent mask\n")); + dprintk(ioc, printk(MYIOC_s_INFO_FMT + ": Using 64 bit consistent mask\n", ioc->name)); } else { - dprintk(ioc, printk(KERN_INFO MYNAM - ": Not using 64 bit consistent mask\n")); + dprintk(ioc, printk(MYIOC_s_INFO_FMT + ": Not using 64 bit consistent mask\n", ioc->name)); } ioc->alloc_total = sizeof(MPT_ADAPTER); @@ -1475,7 +1538,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /* Find lookup slot. */ INIT_LIST_HEAD(&ioc->list); - ioc->id = mpt_ids++; mem_phys = msize = 0; port = psize = 0; @@ -1501,25 +1563,23 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) /*mem = ioremap(mem_phys, msize);*/ mem = ioremap(mem_phys, msize); if (mem == NULL) { - printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n"); + printk(MYIOC_s_ERR_FMT "Unable to map adapter memory!\n", ioc->name); kfree(ioc); return -EINVAL; } ioc->memmap = mem; - dinitprintk(ioc, printk(KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys)); + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n", ioc->name, mem, mem_phys)); - dinitprintk(ioc, printk(KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n", - &ioc->facts, &ioc->pfacts[0])); + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n", + ioc->name, &ioc->facts, &ioc->pfacts[0])); ioc->mem_phys = mem_phys; ioc->chip = (SYSIF_REGS __iomem *)mem; /* Save Port IO values in case we need to do downloadboot */ - { - u8 *pmem = (u8*)port; - ioc->pio_mem_phys = port; - ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; - } + ioc->pio_mem_phys = port; + pmem = (u8 __iomem *)port; + ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); mpt_get_product_name(pdev->vendor, pdev->device, revision, ioc->prod_name); @@ -1591,8 +1651,6 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) if (ioc->errata_flag_1064) pci_disable_io_access(pdev); - sprintf(ioc->name, "ioc%d", ioc->id); - spin_lock_init(&ioc->FreeQlock); /* Disable all! */ @@ -1609,9 +1667,8 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) if ((r = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_BRINGUP, CAN_SLEEP)) != 0){ - printk(KERN_WARNING MYNAM - ": WARNING - %s did not initialize properly! (%d)\n", - ioc->name, r); + printk(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n", + ioc->name, r); list_del(&ioc->list); if (ioc->alt_ioc) @@ -1623,10 +1680,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) } /* call per device driver probe entry point */ - for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { - if(MptDeviceDriverHandlers[ii] && - MptDeviceDriverHandlers[ii]->probe) { - MptDeviceDriverHandlers[ii]->probe(pdev,id); + for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) { + if(MptDeviceDriverHandlers[cb_idx] && + MptDeviceDriverHandlers[cb_idx]->probe) { + MptDeviceDriverHandlers[cb_idx]->probe(pdev,id); } } @@ -1663,7 +1720,7 @@ mpt_detach(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); char pname[32]; - int ii; + u8 cb_idx; sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); remove_proc_entry(pname, NULL); @@ -1673,10 +1730,10 @@ mpt_detach(struct pci_dev *pdev) remove_proc_entry(pname, NULL); /* call per device driver remove entry point */ - for(ii=0; ii<MPT_MAX_PROTOCOL_DRIVERS; ii++) { - if(MptDeviceDriverHandlers[ii] && - MptDeviceDriverHandlers[ii]->remove) { - MptDeviceDriverHandlers[ii]->remove(pdev); + for(cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) { + if(MptDeviceDriverHandlers[cb_idx] && + MptDeviceDriverHandlers[cb_idx]->remove) { + MptDeviceDriverHandlers[cb_idx]->remove(pdev); } } @@ -1788,7 +1845,7 @@ mpt_resume(struct pci_dev *pdev) #endif static int -mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase) +mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase) { if ((MptDriverClass[index] == MPTSPI_DRIVER && ioc->bus_type != SPI) || @@ -1830,14 +1887,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) int hard; int rc=0; int ii; + u8 cb_idx; int handlers; int ret = 0; int reset_alt_ioc_active = 0; int irq_allocated = 0; u8 *a; - printk(KERN_INFO MYNAM ": Initiating %s %s\n", - ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); + printk(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name, + reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); /* Disable reply interrupts (also blocks FreeQ) */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); @@ -1858,21 +1916,19 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((hard_reset_done = MakeIocReady(ioc, hard, sleepFlag)) < 0) { if (hard_reset_done == -4) { - printk(KERN_WARNING MYNAM ": %s Owned by PEER..skipping!\n", - ioc->name); + printk(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n", + ioc->name); if (reset_alt_ioc_active && ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt, FreeQ) */ - dprintk(ioc, printk(KERN_INFO MYNAM - ": alt-%s reply irq re-enabled\n", - ioc->alt_ioc->name)); + dprintk(ioc, printk(MYIOC_s_INFO_FMT + "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name)); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ioc->alt_ioc->active = 1; } } else { - printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", - ioc->name); + printk(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name); } return -1; } @@ -1884,9 +1940,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((rc = MakeIocReady(ioc->alt_ioc, 0, sleepFlag)) == 0) alt_ioc_ready = 1; else - printk(KERN_WARNING MYNAM - ": alt-%s: Not ready WARNING!\n", - ioc->alt_ioc->name); + printk(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name); } for (ii=0; ii<5; ii++) { @@ -1897,7 +1951,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (ii == 5) { - dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Retry IocFacts failed rc=%x\n", ioc->name, rc)); + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Retry IocFacts failed rc=%x\n", ioc->name, rc)); ret = -2; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { MptDisplayIocCapabilities(ioc); @@ -1906,14 +1961,14 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (alt_ioc_ready) { if ((rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason)) != 0) { dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); + "Initial Alt IocFacts failed rc=%x\n", ioc->name, rc)); /* Retry - alt IOC was initialized once */ rc = GetIocFacts(ioc->alt_ioc, sleepFlag, reason); } if (rc) { dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc)); + "Retry Alt IocFacts failed rc=%x\n", ioc->name, rc)); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } else if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { @@ -1931,13 +1986,12 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (ioc->pcidev->irq) { if (mpt_msi_enable && !pci_enable_msi(ioc->pcidev)) printk(MYIOC_s_INFO_FMT "PCI-MSI enabled\n", - ioc->name); + ioc->name); rc = request_irq(ioc->pcidev->irq, mpt_interrupt, - IRQF_SHARED, ioc->name, ioc); + IRQF_SHARED, ioc->name, ioc); if (rc < 0) { printk(MYIOC_s_ERR_FMT "Unable to allocate " - "interrupt %d!\n", ioc->name, - ioc->pcidev->irq); + "interrupt %d!\n", ioc->name, ioc->pcidev->irq); if (mpt_msi_enable) pci_disable_msi(ioc->pcidev); return -EBUSY; @@ -1946,8 +2000,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ioc->pci_irq = ioc->pcidev->irq; pci_set_master(ioc->pcidev); /* ?? */ pci_set_drvdata(ioc->pcidev, ioc); - dprintk(ioc, printk(KERN_INFO MYNAM ": %s installed at interrupt " - "%d\n", ioc->name, ioc->pcidev->irq)); + dprintk(ioc, printk(MYIOC_s_INFO_FMT "installed at interrupt " + "%d\n", ioc->name, ioc->pcidev->irq)); } } @@ -1966,8 +2020,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) ret = -4; // NEW! if (alt_ioc_ready && ((rc = PrimeIocFifos(ioc->alt_ioc)) != 0)) { - printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", - ioc->alt_ioc->name, rc); + printk(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n", + ioc->alt_ioc->name, rc); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } @@ -1976,16 +2030,15 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if ((rc = SendIocInit(ioc->alt_ioc, sleepFlag)) != 0) { alt_ioc_ready = 0; reset_alt_ioc_active = 0; - printk(KERN_WARNING MYNAM - ": alt-%s: (%d) init failure WARNING!\n", - ioc->alt_ioc->name, rc); + printk(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n", + ioc->alt_ioc->name, rc); } } if (reason == MPT_HOSTEVENT_IOC_BRINGUP){ if (ioc->upload_fw) { ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "firmware upload required!\n", ioc->name)); + "firmware upload required!\n", ioc->name)); /* Controller is not operational, cannot do upload */ @@ -2001,12 +2054,13 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) * mpt_diag_reset) */ ddlprintk(ioc, printk(MYIOC_s_DEBUG_FMT - ": mpt_upload: alt_%s has cached_fw=%p \n", - ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); + "mpt_upload: alt_%s has cached_fw=%p \n", + ioc->name, ioc->alt_ioc->name, ioc->alt_ioc->cached_fw)); ioc->alt_ioc->cached_fw = NULL; } } else { - printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); + printk(MYIOC_s_WARN_FMT + "firmware upload failure!\n", ioc->name); ret = -5; } } @@ -2021,8 +2075,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) if (reset_alt_ioc_active && ioc->alt_ioc) { /* (re)Enable alt-IOC! (reply interrupt) */ - dinitprintk(ioc, printk(KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", - ioc->alt_ioc->name)); + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n", + ioc->alt_ioc->name)); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ioc->alt_ioc->active = 1; } @@ -2075,10 +2129,8 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) (void) GetLanConfigPages(ioc); a = (u8*)&ioc->lan_cnfg_page1.HardwareAddressLow; dprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "LanAddr = %02X:%02X:%02X:" - "%02X:%02X:%02X\n", - ioc->name, a[5], a[4], - a[3], a[2], a[1], a[0] )); + "LanAddr = %02X:%02X:%02X:%02X:%02X:%02X\n", + ioc->name, a[5], a[4], a[3], a[2], a[1], a[0])); } } else { @@ -2114,20 +2166,20 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) */ if (hard_reset_done) { rc = handlers = 0; - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if ((ret == 0) && MptResetHandlers[ii]) { + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + if ((ret == 0) && MptResetHandlers[cb_idx]) { dprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "Calling IOC post_reset handler #%d\n", - ioc->name, ii)); - rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET); + "Calling IOC post_reset handler #%d\n", + ioc->name, cb_idx)); + rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET); handlers++; } - if (alt_ioc_ready && MptResetHandlers[ii]) { + if (alt_ioc_ready && MptResetHandlers[cb_idx]) { drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "Calling alt-%s post_reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); - rc += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_POST_RESET); + "Calling IOC post_reset handler #%d\n", + ioc->alt_ioc->name, cb_idx)); + rc += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_POST_RESET); handlers++; } } @@ -2166,8 +2218,8 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PCI device %s devfn=%x/%x," " searching for devfn match on %x or %x\n", - ioc->name, pci_name(pdev), pdev->bus->number, - pdev->devfn, func-1, func+1)); + ioc->name, pci_name(pdev), pdev->bus->number, + pdev->devfn, func-1, func+1)); peer = pci_get_slot(pdev->bus, PCI_DEVFN(slot,func-1)); if (!peer) { @@ -2181,15 +2233,15 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) if (_pcidev == peer) { /* Paranoia checks */ if (ioc->alt_ioc != NULL) { - printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", + printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n", ioc->name, ioc->alt_ioc->name); break; } else if (ioc_srch->alt_ioc != NULL) { - printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", + printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n", ioc_srch->name, ioc_srch->alt_ioc->name); break; } - dprintk(ioc, printk(KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n", + dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n", ioc->name, ioc_srch->name)); ioc_srch->alt_ioc = ioc; ioc->alt_ioc = ioc_srch; @@ -2210,10 +2262,11 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) int ret; if (ioc->cached_fw != NULL) { - ddlprintk(ioc, printk(KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); + ddlprintk(ioc, printk(MYIOC_s_INFO_FMT + "mpt_adapter_disable: Pushing FW onto adapter\n", ioc->name)); if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { - printk(KERN_WARNING MYNAM - ": firmware downloadboot failure (%d)!\n", ret); + printk(MYIOC_s_WARN_FMT "firmware downloadboot failure (%d)!\n", + ioc->name, ret); } } @@ -2225,8 +2278,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) if (ioc->alloc != NULL) { sz = ioc->alloc_sz; - dexitprintk(ioc, printk(KERN_INFO MYNAM ": %s.free @ %p, sz=%d bytes\n", - ioc->name, ioc->alloc, ioc->alloc_sz)); + dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n", + ioc->name, ioc->alloc, ioc->alloc_sz)); pci_free_consistent(ioc->pcidev, sz, ioc->alloc, ioc->alloc_dma); ioc->reply_frames = NULL; @@ -2286,15 +2339,14 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) if (ioc->HostPageBuffer != NULL) { if((ret = mpt_host_page_access_control(ioc, MPI_DB_HPBAC_FREE_BUFFER, NO_SLEEP)) != 0) { - printk(KERN_ERR MYNAM - ": %s: host page buffers free failed (%d)!\n", - __FUNCTION__, ret); + printk(MYIOC_s_ERR_FMT + "host page buffers free failed (%d)!\n", + ioc->name, ret); } - dexitprintk(ioc, printk(KERN_INFO MYNAM ": %s HostPageBuffer free @ %p, sz=%d bytes\n", + dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free @ %p, sz=%d bytes\n", ioc->name, ioc->HostPageBuffer, ioc->HostPageBuffer_sz)); pci_free_consistent(ioc->pcidev, ioc->HostPageBuffer_sz, - ioc->HostPageBuffer, - ioc->HostPageBuffer_dma); + ioc->HostPageBuffer, ioc->HostPageBuffer_dma); ioc->HostPageBuffer = NULL; ioc->HostPageBuffer_sz = 0; ioc->alloc_total -= ioc->HostPageBuffer_sz; @@ -2336,7 +2388,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) #if defined(CONFIG_MTRR) && 0 if (ioc->mtrr_reg > 0) { mtrr_del(ioc->mtrr_reg, 0, 0); - dprintk(ioc, printk(KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name)); + dprintk(ioc, printk(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name)); } #endif @@ -2344,8 +2396,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) list_del(&ioc->list); sz_last = ioc->alloc_total; - dprintk(ioc, printk(KERN_INFO MYNAM ": %s: free'd %d of %d bytes\n", - ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); + dprintk(ioc, printk(MYIOC_s_INFO_FMT "free'd %d of %d bytes\n", + ioc->name, sz_first-sz_last+(int)sizeof(*ioc), sz_first)); if (ioc->alt_ioc) ioc->alt_ioc->alt_ioc = NULL; @@ -2424,7 +2476,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) /* Get current [raw] IOC state */ ioc_state = mpt_GetIocState(ioc, 0); - dhsprintk(ioc, printk(KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state)); + dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state)); /* * Check to see if IOC got left/stuck in doorbell handshake @@ -2446,9 +2498,9 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) if ((ioc_state & MPI_IOC_STATE_MASK) == MPI_IOC_STATE_FAULT) { statefault = 2; printk(MYIOC_s_WARN_FMT "IOC is in FAULT state!!!\n", - ioc->name); - printk(KERN_WARNING " FAULT code = %04xh\n", - ioc_state & MPI_DOORBELL_DATA_MASK); + ioc->name); + printk(MYIOC_s_WARN_FMT " FAULT code = %04xh\n", + ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK); } /* @@ -2464,9 +2516,9 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) * Else, fall through to KickStart case */ whoinit = (ioc_state & MPI_DOORBELL_WHO_INIT_MASK) >> MPI_DOORBELL_WHO_INIT_SHIFT; - dinitprintk(ioc, printk(KERN_INFO MYNAM - ": whoinit 0x%x statefault %d force %d\n", - whoinit, statefault, force)); + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT + "whoinit 0x%x statefault %d force %d\n", + ioc->name, whoinit, statefault, force)); if (whoinit == MPI_WHOINIT_PCI_PEER) return -4; else { @@ -2549,7 +2601,6 @@ mpt_GetIocState(MPT_ADAPTER *ioc, int cooked) /* Get! */ s = CHIPREG_READ32(&ioc->chip->Doorbell); -// dprintk((MYIOC_s_INFO_FMT "raw state = %08x\n", ioc->name, s)); sc = s & MPI_IOC_STATE_MASK; /* Save! */ @@ -2581,9 +2632,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { - printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n", - ioc->name, - ioc->last_state ); + printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n", + ioc->name, ioc->last_state ); return -44; } @@ -2703,8 +2753,8 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) } ioc->NBShiftFactor = shiftFactor; dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n", - ioc->name, vv, shiftFactor, r)); + "NB_for_64_byte_frame=%x NBShiftFactor=%x BlockSize=%x\n", + ioc->name, vv, shiftFactor, r)); if (reason == MPT_HOSTEVENT_IOC_BRINGUP) { /* @@ -2757,9 +2807,8 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { - printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n", - ioc->name, - ioc->last_state ); + printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n", + ioc->name, ioc->last_state ); return -4; } @@ -2934,7 +2983,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) state = mpt_GetIocState(ioc, 1); count++; } - dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n", ioc->name, count)); ioc->aen_event_read_flag=0; @@ -3027,10 +3076,9 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) int sz; sz = ioc->facts.FWImageSize; - dinitprintk(ioc, printk(KERN_INFO MYNAM "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", - ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); - pci_free_consistent(ioc->pcidev, sz, - ioc->cached_fw, ioc->cached_fw_dma); + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "free_fw_memory: FW Image @ %p[%p], sz=%d[%x] bytes\n", + ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); + pci_free_consistent(ioc->pcidev, sz, ioc->cached_fw, ioc->cached_fw_dma); ioc->cached_fw = NULL; return; @@ -3054,7 +3102,6 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) static int mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) { - u8 request[ioc->req_sz]; u8 reply[sizeof(FWUploadReply_t)]; FWUpload_t *prequest; FWUploadReply_t *preply; @@ -3071,8 +3118,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) mpt_alloc_fw_memory(ioc, sz); - dinitprintk(ioc, printk(KERN_INFO MYNAM ": FW Image @ %p[%p], sz=%d[%x] bytes\n", - ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Image @ %p[%p], sz=%d[%x] bytes\n", + ioc->name, ioc->cached_fw, (void *)(ulong)ioc->cached_fw_dma, sz, sz)); if (ioc->cached_fw == NULL) { /* Major Failure. @@ -3080,11 +3127,16 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) return -ENOMEM; } - prequest = (FWUpload_t *)&request; - preply = (FWUploadReply_t *)&reply; + prequest = (sleepFlag == NO_SLEEP) ? kzalloc(ioc->req_sz, GFP_ATOMIC) : + kzalloc(ioc->req_sz, GFP_KERNEL); + if (!prequest) { + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "fw upload failed " + "while allocating memory \n", ioc->name)); + mpt_free_fw_memory(ioc); + return -ENOMEM; + } - /* Destination... */ - memset(prequest, 0, ioc->req_sz); + preply = (FWUploadReply_t *)&reply; reply_sz = sizeof(reply); memset(preply, 0, reply_sz); @@ -3096,21 +3148,22 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) ptcsge->DetailsLength = 12; ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT; ptcsge->ImageSize = cpu_to_le32(sz); + ptcsge++; sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + sizeof(FWUploadTCSGE_t); flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ | sz; - mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma); + mpt_add_sge((char *)ptcsge, flagsLength, ioc->cached_fw_dma); sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - dinitprintk(ioc, printk(KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n", - prequest, sgeoffset)); - DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest) + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": Sending FW Upload (req @ %p) sgeoffset=%d \n", + ioc->name, prequest, sgeoffset)); + DBG_DUMP_FW_REQUEST_FRAME(ioc, (u32 *)prequest); ii = mpt_handshake_req_reply_wait(ioc, sgeoffset, (u32*)prequest, reply_sz, (u16*)preply, 65 /*seconds*/, sleepFlag); - dinitprintk(ioc, printk(KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii)); + dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii)); cmdStatus = -EFAULT; if (ii == 0) { @@ -3135,6 +3188,7 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) ioc->name)); mpt_free_fw_memory(ioc); } + kfree(prequest); return cmdStatus; } @@ -3381,7 +3435,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) u32 ioc_state=0; int cnt,cntdn; - dinitprintk(ioc, printk(KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name)); if (ioc->bus_type == SPI) { /* Always issue a Msg Unit Reset first. This will clear some * SCSI bus hang conditions. @@ -3400,7 +3454,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) return hard_reset_done; dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Diagnostic reset successful!\n", - ioc->name)); + ioc->name)); cntdn = ((sleepFlag == CAN_SLEEP) ? HZ : 1000) * 2; /* 2 seconds */ for (cnt=0; cnt<cntdn; cnt++) { @@ -3417,8 +3471,8 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) } } - printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n", - ioc->name, ioc_state); + dinitprintk(ioc, printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n", + ioc->name, mpt_GetIocState(ioc, 0))); return -1; } @@ -3560,20 +3614,20 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) * MptResetHandlers[] registered yet. */ { - int ii; + u8 cb_idx; int r = 0; - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if (MptResetHandlers[ii]) { + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + if (MptResetHandlers[cb_idx]) { dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC pre_reset handler #%d\n", - ioc->name, ii)); - r += mpt_signal_reset(ii, ioc, MPT_IOC_PRE_RESET); + ioc->name, cb_idx)); + r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET); if (ioc->alt_ioc) { dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s pre_reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); - r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET); + ioc->name, ioc->alt_ioc->name, cb_idx)); + r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET); } } } @@ -3606,8 +3660,8 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) } if ((count = mpt_downloadboot(ioc, (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) { - printk(KERN_WARNING MYNAM - ": firmware downloadboot failure (%d)!\n", count); + printk(MYIOC_s_WARN_FMT + "firmware downloadboot failure (%d)!\n", ioc->name, count); } } else { @@ -3750,8 +3804,8 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) if (sleepFlag != CAN_SLEEP) count *= 10; - printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n", - ioc->name, (int)((count+5)/HZ)); + printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", + ioc->name, (int)((count+5)/HZ)); return -ETIME; } @@ -4144,7 +4198,7 @@ mpt_handshake_req_reply_wait(MPT_ADAPTER *ioc, int reqBytes, u32 *req, } dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handshake request frame (@%p) header\n", ioc->name, req)); - DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req) + DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)req); dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "HandShake request post done, WaitCnt=%d%s\n", ioc->name, t, failcnt ? " - MISSING DOORBELL ACK!" : "")); @@ -4349,7 +4403,7 @@ WaitForDoorbellReply(MPT_ADAPTER *ioc, int howlong, int sleepFlag) #endif dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got Handshake reply:\n", ioc->name)); - DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply) + DBG_DUMP_REPLY_FRAME(ioc, (u32 *)mptReply); dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "WaitForDoorbell REPLY WaitCnt=%d (sz=%d)\n", ioc->name, t, u16cnt/2)); @@ -4824,8 +4878,8 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) if ( (pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_QAS) == 0 ) { ioc->spi_data.noQas |= MPT_TARGET_NO_NEGO_QAS; - ddvprintk(ioc, printk(KERN_INFO MYNAM - " :%s noQas due to Capabilities=%x\n", + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "noQas due to Capabilities=%x\n", ioc->name, pPP0->Capabilities)); } ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; @@ -4888,6 +4942,38 @@ mpt_GetScsiPortSettings(MPT_ADAPTER *ioc, int portnum) /* Nvram data is left with INVALID mark */ rc = 1; + } else if (ioc->pcidev->vendor == PCI_VENDOR_ID_ATTO) { + + /* This is an ATTO adapter, read Page2 accordingly + */ + ATTO_SCSIPortPage2_t *pPP2 = (ATTO_SCSIPortPage2_t *) pbuf; + ATTODeviceInfo_t *pdevice = NULL; + u16 ATTOFlags; + + /* Save the Port Page 2 data + * (reformat into a 32bit quantity) + */ + for (ii=0; ii < MPT_MAX_SCSI_DEVICES; ii++) { + pdevice = &pPP2->DeviceSettings[ii]; + ATTOFlags = le16_to_cpu(pdevice->ATTOFlags); + data = 0; + + /* Translate ATTO device flags to LSI format + */ + if (ATTOFlags & ATTOFLAG_DISC) + data |= (MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE); + if (ATTOFlags & ATTOFLAG_ID_ENB) + data |= (MPI_SCSIPORTPAGE2_DEVICE_ID_SCAN_ENABLE); + if (ATTOFlags & ATTOFLAG_LUN_ENB) + data |= (MPI_SCSIPORTPAGE2_DEVICE_LUN_SCAN_ENABLE); + if (ATTOFlags & ATTOFLAG_TAGGED) + data |= (MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE); + if (!(ATTOFlags & ATTOFLAG_WIDE_ENB)) + data |= (MPI_SCSIPORTPAGE2_DEVICE_WIDE_DISABLE); + + data = (data << 16) | (pdevice->Period << 8) | 10; + ioc->spi_data.nvram[ii] = data; + } } else { SCSIPortPage2_t *pPP2 = (SCSIPortPage2_t *) pbuf; MpiDeviceInfo_t *pdevice = NULL; @@ -5701,10 +5787,10 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) CONFIGPARMS *pCfg; unsigned long flags; - dprintk(ioc, printk(KERN_DEBUG MYNAM - ": IOC %s_reset routed to MPT base driver!\n", - reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT + ": IOC %s_reset routed to MPT base driver!\n", + ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); if (reset_phase == MPT_IOC_SETUP_RESET) { ; @@ -5843,7 +5929,7 @@ procmpt_summary_read(char *buf, char **start, off_t offset, int request, int *eo static int procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eof, void *data) { - int ii; + u8 cb_idx; int scsi, fc, sas, lan, ctl, targ, dmp; char *drvname; int len; @@ -5852,10 +5938,10 @@ procmpt_version_read(char *buf, char **start, off_t offset, int request, int *eo len += sprintf(buf+len, " Fusion MPT base driver\n"); scsi = fc = sas = lan = ctl = targ = dmp = 0; - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { drvname = NULL; - if (MptCallbacks[ii]) { - switch (MptDriverClass[ii]) { + if (MptCallbacks[cb_idx]) { + switch (MptDriverClass[cb_idx]) { case MPTSPI_DRIVER: if (!scsi++) drvname = "SPI host"; break; @@ -6099,26 +6185,25 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) * For all other protocol drivers, this is a no-op. */ { - int ii; + u8 cb_idx; int r = 0; - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if (MptResetHandlers[ii]) { + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + if (MptResetHandlers[cb_idx]) { dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n", - ioc->name, ii)); - r += mpt_signal_reset(ii, ioc, MPT_IOC_SETUP_RESET); + ioc->name, cb_idx)); + r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); if (ioc->alt_ioc) { dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling alt-%s setup reset handler #%d\n", - ioc->name, ioc->alt_ioc->name, ii)); - r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET); + ioc->name, ioc->alt_ioc->name, cb_idx)); + r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET); } } } } if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) { - printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n", - rc, ioc->name); + printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc); } ioc->reload_fw = 0; if (ioc->alt_ioc) @@ -6515,6 +6600,7 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply u32 evData0 = 0; // u32 evCtx; int ii; + u8 cb_idx; int r = 0; int handlers = 0; char evStr[EVENT_DESCR_STR_SZ]; @@ -6537,12 +6623,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply evStr)); #ifdef CONFIG_FUSION_LOGGING - devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM - ": Event data:\n")); + devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT + ": Event data:\n", ioc->name)); for (ii = 0; ii < evDataLen; ii++) devtverboseprintk(ioc, printk(" %08x", le32_to_cpu(pEventReply->Data[ii]))); - devtverboseprintk(ioc, printk(KERN_DEBUG "\n")); + devtverboseprintk(ioc, printk("\n")); #endif /* @@ -6595,11 +6681,11 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply /* * Call each currently registered protocol event handler. */ - for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { - if (MptEvHandlers[ii]) { + for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + if (MptEvHandlers[cb_idx]) { devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n", - ioc->name, ii)); - r += (*(MptEvHandlers[ii]))(ioc, pEventReply); + ioc->name, cb_idx)); + r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply); handlers++; } } @@ -7034,8 +7120,8 @@ mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) if (!desc) return; - printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n", - ioc->name, ioc_status, desc, extend_desc); + dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n", + ioc->name, ioc_status, desc, extend_desc)); } /** @@ -7261,7 +7347,8 @@ mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) if (!desc) return; - printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc); + dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n", + ioc->name, status, desc)); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -7283,14 +7370,13 @@ EXPORT_SYMBOL(mpt_device_driver_register); EXPORT_SYMBOL(mpt_device_driver_deregister); EXPORT_SYMBOL(mpt_get_msg_frame); EXPORT_SYMBOL(mpt_put_msg_frame); +EXPORT_SYMBOL(mpt_put_msg_frame_hi_pri); EXPORT_SYMBOL(mpt_free_msg_frame); EXPORT_SYMBOL(mpt_add_sge); EXPORT_SYMBOL(mpt_send_handshake_request); EXPORT_SYMBOL(mpt_verify_adapter); EXPORT_SYMBOL(mpt_GetIocState); EXPORT_SYMBOL(mpt_print_ioc_summary); -EXPORT_SYMBOL(mpt_lan_index); -EXPORT_SYMBOL(mpt_stm_index); EXPORT_SYMBOL(mpt_HardResetHandler); EXPORT_SYMBOL(mpt_config); EXPORT_SYMBOL(mpt_findImVolumes); @@ -7308,16 +7394,16 @@ EXPORT_SYMBOL(mpt_raid_phys_disk_pg0); static int __init fusion_init(void) { - int i; + u8 cb_idx; show_mptmod_ver(my_NAME, my_VERSION); printk(KERN_INFO COPYRIGHT "\n"); - for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) { - MptCallbacks[i] = NULL; - MptDriverClass[i] = MPTUNKNOWN_DRIVER; - MptEvHandlers[i] = NULL; - MptResetHandlers[i] = NULL; + for (cb_idx = 0; cb_idx < MPT_MAX_PROTOCOL_DRIVERS; cb_idx++) { + MptCallbacks[cb_idx] = NULL; + MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER; + MptEvHandlers[cb_idx] = NULL; + MptResetHandlers[cb_idx] = NULL; } /* Register ourselves (mptbase) in order to facilitate diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index 15ff22645844..d7682e083f59 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -3,9 +3,9 @@ * High performance SCSI + LAN / Fibre Channel device drivers. * For use with PCI chip/adapter(s): * LSIFC9xx/LSI409xx Fibre Channel - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -68,15 +68,15 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #ifndef MODULEAUTHOR -#define MODULEAUTHOR "LSI Logic Corporation" +#define MODULEAUTHOR "LSI Corporation" #endif #ifndef COPYRIGHT #define COPYRIGHT "Copyright (c) 1999-2007 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.04.05" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.05" +#define MPT_LINUX_VERSION_COMMON "3.04.06" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.06" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -186,6 +186,7 @@ * MPT drivers. NOTE: Users of these macro defs must * themselves define their own MYNAM. */ +#define MYIOC_s_FMT MYNAM ": %s: " #define MYIOC_s_DEBUG_FMT KERN_DEBUG MYNAM ": %s: " #define MYIOC_s_INFO_FMT KERN_INFO MYNAM ": %s: " #define MYIOC_s_NOTE_FMT KERN_NOTICE MYNAM ": %s: " @@ -194,6 +195,35 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* + * ATTO UL4D associated structures and defines + */ +#define ATTOFLAG_DISC 0x0001 +#define ATTOFLAG_TAGGED 0x0002 +#define ATTOFLAG_WIDE_ENB 0x0008 +#define ATTOFLAG_ID_ENB 0x0010 +#define ATTOFLAG_LUN_ENB 0x0060 + +typedef struct _ATTO_DEVICE_INFO +{ + u8 Offset; /* 00h */ + u8 Period; /* 01h */ + u16 ATTOFlags; /* 02h */ +} ATTO_DEVICE_INFO, MPI_POINTER PTR_ATTO_DEVICE_INFO, + ATTODeviceInfo_t, MPI_POINTER pATTODeviceInfo_t; + +typedef struct _ATTO_CONFIG_PAGE_SCSI_PORT_2 +{ + CONFIG_PAGE_HEADER Header; /* 00h */ + u16 PortFlags; /* 04h */ + u16 Unused1; /* 06h */ + u32 Unused2; /* 08h */ + ATTO_DEVICE_INFO DeviceSettings[16]; /* 0Ch */ +} fATTO_CONFIG_PAGE_SCSI_PORT_2, MPI_POINTER PTR_ATTO_CONFIG_PAGE_SCSI_PORT_2, + ATTO_SCSIPortPage2_t, MPI_POINTER pATTO_SCSIPortPage2_t; + + +/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +/* * MPT protocol driver defs... */ typedef enum { @@ -307,7 +337,8 @@ typedef struct _SYSIF_REGS u32 Reserved2[2]; /* 38-3F reserved for future use */ u32 RequestFifo; /* 40 Request Post/Free FIFO */ u32 ReplyFifo; /* 44 Reply Post/Free FIFO */ - u32 Reserved3[2]; /* 48-4F reserved for future use */ + u32 RequestHiPriFifo; /* 48 Hi Priority Request FIFO */ + u32 Reserved3; /* 4C-4F reserved for future use */ u32 HostIndex; /* 50 Host Index register */ u32 Reserved4[15]; /* 54-8F */ u32 Fubar; /* 90 For Fubar usage */ @@ -649,9 +680,9 @@ typedef struct _MPT_ADAPTER u8 reload_fw; /* Force a FW Reload on next reset */ u8 NBShiftFactor; /* NB Shift Factor based on Block Size (Facts) */ u8 pad1[4]; - int DoneCtx; - int TaskCtx; - int InternalCtx; + u8 DoneCtx; + u8 TaskCtx; + u8 InternalCtx; spinlock_t initializing_hba_lock; int initializing_hba_lock_flag; struct list_head list; @@ -668,10 +699,14 @@ typedef struct _MPT_ADAPTER struct work_struct fc_setup_reset_work; struct list_head fc_rports; + struct work_struct fc_lsc_work; + u8 fc_link_speed[2]; spinlock_t fc_rescan_work_lock; struct work_struct fc_rescan_work; char fc_rescan_work_q_name[KOBJ_NAME_LEN]; struct workqueue_struct *fc_rescan_work_q; + struct scsi_cmnd **ScsiLookup; + spinlock_t scsi_lookup_lock; } MPT_ADAPTER; /* @@ -785,7 +820,6 @@ typedef struct _MPT_SCSI_HOST { MPT_ADAPTER *ioc; int port; u32 pad0; - struct scsi_cmnd **ScsiLookup; MPT_LOCAL_REPLY *pLocal; /* used for internal commands */ struct timer_list timer; /* Pool of memory for holding SCpnts before doing @@ -853,20 +887,21 @@ extern void mpt_detach(struct pci_dev *pdev); extern int mpt_suspend(struct pci_dev *pdev, pm_message_t state); extern int mpt_resume(struct pci_dev *pdev); #endif -extern int mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass); -extern void mpt_deregister(int cb_idx); -extern int mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc); -extern void mpt_event_deregister(int cb_idx); -extern int mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func); -extern void mpt_reset_deregister(int cb_idx); -extern int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx); -extern void mpt_device_driver_deregister(int cb_idx); -extern MPT_FRAME_HDR *mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc); +extern u8 mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass); +extern void mpt_deregister(u8 cb_idx); +extern int mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc); +extern void mpt_event_deregister(u8 cb_idx); +extern int mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func); +extern void mpt_reset_deregister(u8 cb_idx); +extern int mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx); +extern void mpt_device_driver_deregister(u8 cb_idx); +extern MPT_FRAME_HDR *mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc); extern void mpt_free_msg_frame(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); -extern void mpt_put_msg_frame(int handle, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); +extern void mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); +extern void mpt_put_msg_frame_hi_pri(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf); extern void mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr); -extern int mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag); +extern int mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag); extern int mpt_verify_adapter(int iocid, MPT_ADAPTER **iocpp); extern u32 mpt_GetIocState(MPT_ADAPTER *ioc, int cooked); extern void mpt_print_ioc_summary(MPT_ADAPTER *ioc, char *buf, int *size, int len, int showlan); @@ -884,9 +919,6 @@ extern int mpt_raid_phys_disk_pg0(MPT_ADAPTER *ioc, u8 phys_disk_num, pRaidPhys extern struct list_head ioc_list; extern struct proc_dir_entry *mpt_proc_root_dir; -extern int mpt_lan_index; /* needed by mptlan.c */ -extern int mpt_stm_index; /* needed by mptstm.c */ - /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #endif /* } __KERNEL__ */ diff --git a/drivers/message/fusion/mptctl.c b/drivers/message/fusion/mptctl.c index 89695e705bdc..6029509702d3 100644 --- a/drivers/message/fusion/mptctl.c +++ b/drivers/message/fusion/mptctl.c @@ -1,10 +1,10 @@ /* * linux/drivers/message/fusion/mptctl.c * mpt Ioctl driver. - * For use with LSI Logic PCI chip/adapters - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * For use with LSI PCI chip/adapters + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -66,8 +66,8 @@ #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> -#define COPYRIGHT "Copyright (c) 1999-2007 LSI Logic Corporation" -#define MODULEAUTHOR "LSI Logic Corporation" +#define COPYRIGHT "Copyright (c) 1999-2007 LSI Corporation" +#define MODULEAUTHOR "LSI Corporation" #include "mptbase.h" #include "mptctl.h" @@ -83,7 +83,7 @@ MODULE_VERSION(my_VERSION); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static int mptctl_id = -1; +static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS; static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait ); @@ -181,7 +181,6 @@ static inline int mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) { int rc = 0; -// dctlprintk(ioc, printk(KERN_DEBUG MYNAM "::mptctl_syscall_down(%p,%d) called\n", ioc, nonblock)); if (nonblock) { if (!mutex_trylock(&ioc->ioctl->ioctl_mutex)) @@ -190,7 +189,6 @@ mptctl_syscall_down(MPT_ADAPTER *ioc, int nonblock) if (mutex_lock_interruptible(&ioc->ioctl->ioctl_mutex)) rc = -ERESTARTSYS; } -// dctlprintk(ioc, printk(KERN_DEBUG MYNAM "::mptctl_syscall_down return %d\n", rc)); return rc; } @@ -342,7 +340,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) SCSITaskMgmt_t *pScsiTm; MPT_SCSI_HOST *hd; int ii; - int retval; + int retval=0; ioctl->reset &= ~MPTCTL_RESET_OK; @@ -350,7 +348,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) if (ioctl->ioc->sh == NULL) return -EPERM; - hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata; + hd = shost_priv(ioctl->ioc->sh); if (hd == NULL) return -EPERM; @@ -395,12 +393,19 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf); ioctl->wait_done=0; - if ((retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc, - sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { - dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!" - " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, - hd->ioc, mf)); - goto mptctl_bus_reset_done; + + if ((ioctl->ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && + (ioctl->ioc->facts.MsgVersion >= MPI_VERSION_01_05)) + mpt_put_msg_frame_hi_pri(mptctl_id, ioctl->ioc, mf); + else { + retval = mpt_send_handshake_request(mptctl_id, ioctl->ioc, + sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); + if (retval != 0) { + dfailprintk(ioctl->ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!" + " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, + hd->ioc, mf)); + goto mptctl_bus_reset_done; + } } /* Now wait for the command to complete */ @@ -444,7 +449,7 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc) MPT_SCSI_HOST * hd; unsigned long flags; - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + hd = shost_priv(ioc->sh); if (hd == NULL) return; @@ -468,7 +473,7 @@ static int mptctl_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { MPT_IOCTL *ioctl = ioc->ioctl; - dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": IOC %s_reset routed to IOCTL driver!\n",ioc->name, + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOC %s_reset routed to IOCTL driver!\n", ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); @@ -574,7 +579,7 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) MPT_ADAPTER *iocp = NULL; if (copy_from_user(&khdr, uhdr, sizeof(khdr))) { - printk(KERN_ERR "%s::mptctl_ioctl() @%d - " + printk(KERN_ERR MYNAM "%s::mptctl_ioctl() @%d - " "Unable to copy mpt_ioctl_header data @ %p\n", __FILE__, __LINE__, uhdr); return -EFAULT; @@ -587,13 +592,13 @@ __mptctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) iocnumX = khdr.iocnum & 0xFF; if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { - printk(KERN_DEBUG "%s::mptctl_ioctl() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnumX); return -ENODEV; } if (!iocp->active) { - printk(KERN_DEBUG "%s::mptctl_ioctl() @%d - Controller disabled.\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - Controller disabled.\n", __FILE__, __LINE__); return -EFAULT; } @@ -660,14 +665,14 @@ static int mptctl_do_reset(unsigned long arg) MPT_ADAPTER *iocp; if (copy_from_user(&krinfo, urinfo, sizeof(struct mpt_ioctl_diag_reset))) { - printk(KERN_ERR "%s@%d::mptctl_do_reset - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_do_reset - " "Unable to copy mpt_ioctl_diag_reset struct @ %p\n", __FILE__, __LINE__, urinfo); return -EFAULT; } if (mpt_verify_adapter(krinfo.hdr.iocnum, &iocp) < 0) { - printk(KERN_DEBUG "%s@%d::mptctl_do_reset - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n", __FILE__, __LINE__, krinfo.hdr.iocnum); return -ENODEV; /* (-6) No such device or address */ } @@ -676,8 +681,8 @@ static int mptctl_do_reset(unsigned long arg) iocp->name)); if (mpt_HardResetHandler(iocp, CAN_SLEEP) != 0) { - printk (KERN_ERR "%s@%d::mptctl_do_reset - reset failed.\n", - __FILE__, __LINE__); + printk (MYIOC_s_ERR_FMT "%s@%d::mptctl_do_reset - reset failed.\n", + iocp->name, __FILE__, __LINE__); return -1; } @@ -708,7 +713,7 @@ mptctl_fw_download(unsigned long arg) struct mpt_fw_xfer kfwdl; if (copy_from_user(&kfwdl, ufwdl, sizeof(struct mpt_fw_xfer))) { - printk(KERN_ERR "%s@%d::_ioctl_fwdl - " + printk(KERN_ERR MYNAM "%s@%d::_ioctl_fwdl - " "Unable to copy mpt_fw_xfer struct @ %p\n", __FILE__, __LINE__, ufwdl); return -EFAULT; @@ -756,7 +761,8 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) pFWDownloadReply_t ReplyMsg = NULL; if (mpt_verify_adapter(ioc, &iocp) < 0) { - printk(KERN_DEBUG "ioctl_fwdl - ioc%d not found!\n", ioc); + printk(KERN_DEBUG MYNAM "ioctl_fwdl - ioc%d not found!\n", + ioc); return -ENODEV; /* (-6) No such device or address */ } else { @@ -868,9 +874,9 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) mpt_add_sge(sgOut, sgIn->FlagsLength, sgIn->Address); n++; if (copy_from_user(bl->kptr, ufwbuf+fw_bytes_copied, bl->len)) { - printk(KERN_ERR "%s@%d::_ioctl_fwdl - " - "Unable to copy f/w buffer hunk#%d @ %p\n", - __FILE__, __LINE__, n, ufwbuf); + printk(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - " + "Unable to copy f/w buffer hunk#%d @ %p\n", + iocp->name, __FILE__, __LINE__, n, ufwbuf); goto fwdl_out; } fw_bytes_copied += bl->len; @@ -906,21 +912,22 @@ mptctl_do_fw_download(int ioc, char __user *ufwbuf, size_t fwlen) ReplyMsg = (pFWDownloadReply_t)iocp->ioctl->ReplyFrame; iocstat = le16_to_cpu(ReplyMsg->IOCStatus) & MPI_IOCSTATUS_MASK; if (iocstat == MPI_IOCSTATUS_SUCCESS) { - printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name); + printk(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name); return 0; } else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) { - printk(KERN_WARNING MYNAM ": ?Hmmm... %s says it doesn't support F/W download!?!\n", - iocp->name); - printk(KERN_WARNING MYNAM ": (time to go bang on somebodies door)\n"); + printk(MYIOC_s_WARN_FMT "Hmmm... F/W download not supported!?!\n", + iocp->name); + printk(MYIOC_s_WARN_FMT "(time to go bang on somebodies door)\n", + iocp->name); return -EBADRQC; } else if (iocstat == MPI_IOCSTATUS_BUSY) { - printk(KERN_WARNING MYNAM ": Warning! %s says: IOC_BUSY!\n", iocp->name); - printk(KERN_WARNING MYNAM ": (try again later?)\n"); + printk(MYIOC_s_WARN_FMT "IOC_BUSY!\n", iocp->name); + printk(MYIOC_s_WARN_FMT "(try again later?)\n", iocp->name); return -EBUSY; } else { - printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR! %s returned [bad] status = %04xh\n", - iocp->name, iocstat); - printk(KERN_WARNING MYNAM ": (bad VooDoo)\n"); + printk(MYIOC_s_WARN_FMT "ioctl_fwdl() returned [bad] status = %04xh\n", + iocp->name, iocstat); + printk(MYIOC_s_WARN_FMT "(bad VooDoo)\n", iocp->name); return -ENOMSG; } return 0; @@ -970,10 +977,9 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, * structures for the SG elements. */ i = MAX_SGL_BYTES / 8; - buflist = kmalloc(i, GFP_USER); - if (buflist == NULL) + buflist = kzalloc(i, GFP_USER); + if (!buflist) return NULL; - memset(buflist, 0, i); buflist_ent = 0; /* Allocate a single block of memory to store the sg elements and @@ -1008,10 +1014,10 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, if (buflist[buflist_ent].kptr == NULL) { alloc_sz = alloc_sz / 2; if (alloc_sz == 0) { - printk(KERN_WARNING MYNAM "-SG: No can do - " - "not enough memory! :-(\n"); - printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n", - numfrags); + printk(MYIOC_s_WARN_FMT "-SG: No can do - " + "not enough memory! :-(\n", ioc->name); + printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n", + ioc->name, numfrags); goto free_and_fail; } continue; @@ -1034,18 +1040,19 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, /* Need to chain? */ if (fragcnt == sg_spill) { - printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required! :-(\n"); - printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags); + printk(MYIOC_s_WARN_FMT + "-SG: No can do - " "Chain required! :-(\n", ioc->name); + printk(MYIOC_s_WARN_FMT "(freeing %d frags)\n", ioc->name, numfrags); goto free_and_fail; } /* overflow check... */ if (numfrags*8 > MAX_SGL_BYTES){ /* GRRRRR... */ - printk(KERN_WARNING MYNAM "-SG: No can do - " - "too many SG frags! :-(\n"); - printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n", - numfrags); + printk(MYIOC_s_WARN_FMT "-SG: No can do - " + "too many SG frags! :-(\n", ioc->name); + printk(MYIOC_s_WARN_FMT "-SG: (freeing %d frags)\n", + ioc->name, numfrags); goto free_and_fail; } } @@ -1066,8 +1073,6 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, free_and_fail: if (sglbuf != NULL) { - int i; - for (i = 0; i < numfrags; i++) { dma_addr_t dma_addr; u8 *kptr; @@ -1170,7 +1175,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) int cim_rev; u8 revision; struct scsi_device *sdev; - VirtDevice *vdev; + VirtDevice *vdevice; /* Add of PCI INFO results in unaligned access for * IA64 and Sparc. Reset long to int. Return no PCI @@ -1189,13 +1194,13 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) karg = kmalloc(data_size, GFP_KERNEL); if (karg == NULL) { - printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", + printk(KERN_ERR MYNAM "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", __FILE__, __LINE__); return -ENOMEM; } if (copy_from_user(karg, uarg, data_size)) { - printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_getiocinfo - " "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", __FILE__, __LINE__, uarg); kfree(karg); @@ -1204,7 +1209,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) if (((iocnum = mpt_verify_adapter(karg->hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); kfree(karg); return -ENODEV; @@ -1212,9 +1217,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) /* Verify the data transfer size is correct. */ if (karg->hdr.maxDataSize != data_size) { - printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - " "Structure size mismatch. Command not completed.\n", - __FILE__, __LINE__); + ioc->name, __FILE__, __LINE__); kfree(karg); return -EFAULT; } @@ -1265,8 +1270,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) karg->numDevices = 0; if (ioc->sh) { shost_for_each_device(sdev, ioc->sh) { - vdev = sdev->hostdata; - if (vdev->vtarget->tflags & + vdevice = sdev->hostdata; + if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) continue; karg->numDevices++; @@ -1290,9 +1295,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) /* Copy the data from kernel memory to user memory */ if (copy_to_user((char __user *)arg, karg, data_size)) { - printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - " "Unable to write out mpt_ioctl_iocinfo struct @ %p\n", - __FILE__, __LINE__, uarg); + ioc->name, __FILE__, __LINE__, uarg); kfree(karg); return -EFAULT; } @@ -1317,7 +1322,7 @@ mptctl_gettargetinfo (unsigned long arg) struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_targetinfo karg; MPT_ADAPTER *ioc; - VirtDevice *vdev; + VirtDevice *vdevice; char *pmem; int *pdata; int iocnum; @@ -1329,7 +1334,7 @@ mptctl_gettargetinfo (unsigned long arg) struct scsi_device *sdev; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { - printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_gettargetinfo - " "Unable to read in mpt_ioctl_targetinfo struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1337,7 +1342,7 @@ mptctl_gettargetinfo (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1353,8 +1358,8 @@ mptctl_gettargetinfo (unsigned long arg) port = karg.hdr.port; if (maxWordsLeft <= 0) { - printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", - __FILE__, __LINE__); + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n", + ioc->name, __FILE__, __LINE__); return -ENOMEM; } @@ -1372,13 +1377,12 @@ mptctl_gettargetinfo (unsigned long arg) * 15- 8: Bus Number * 7- 0: Target ID */ - pmem = kmalloc(numBytes, GFP_KERNEL); - if (pmem == NULL) { - printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", - __FILE__, __LINE__); + pmem = kzalloc(numBytes, GFP_KERNEL); + if (!pmem) { + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n", + ioc->name, __FILE__, __LINE__); return -ENOMEM; } - memset(pmem, 0, numBytes); pdata = (int *) pmem; /* Get number of devices @@ -1387,13 +1391,13 @@ mptctl_gettargetinfo (unsigned long arg) shost_for_each_device(sdev, ioc->sh) { if (!maxWordsLeft) continue; - vdev = sdev->hostdata; - if (vdev->vtarget->tflags & + vdevice = sdev->hostdata; + if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) continue; - lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun; - *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) + - (vdev->vtarget->id )); + lun = (vdevice->vtarget->raidVolume) ? 0x80 : vdevice->lun; + *pdata = (((u8)lun << 16) + (vdevice->vtarget->channel << 8) + + (vdevice->vtarget->id )); pdata++; numDevices++; --maxWordsLeft; @@ -1405,9 +1409,9 @@ mptctl_gettargetinfo (unsigned long arg) */ if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_targetinfo))) { - printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - __FILE__, __LINE__, uarg); + ioc->name, __FILE__, __LINE__, uarg); kfree(pmem); return -EFAULT; } @@ -1415,9 +1419,9 @@ mptctl_gettargetinfo (unsigned long arg) /* Copy the remaining data from kernel memory to user memory */ if (copy_to_user(uarg->targetInfo, pmem, numBytes)) { - printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - __FILE__, __LINE__, pdata); + ioc->name, __FILE__, __LINE__, pdata); kfree(pmem); return -EFAULT; } @@ -1444,7 +1448,7 @@ mptctl_readtest (unsigned long arg) int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) { - printk(KERN_ERR "%s@%d::mptctl_readtest - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - " "Unable to read in mpt_ioctl_test struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1452,7 +1456,7 @@ mptctl_readtest (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_readtest() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1476,9 +1480,9 @@ mptctl_readtest (unsigned long arg) /* Copy the data from kernel memory to user memory */ if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_test))) { - printk(KERN_ERR "%s@%d::mptctl_readtest - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_readtest - " "Unable to write out mpt_ioctl_test struct @ %p\n", - __FILE__, __LINE__, uarg); + ioc->name, __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1505,7 +1509,7 @@ mptctl_eventquery (unsigned long arg) int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) { - printk(KERN_ERR "%s@%d::mptctl_eventquery - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - " "Unable to read in mpt_ioctl_eventquery struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1513,7 +1517,7 @@ mptctl_eventquery (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_eventquery() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1526,9 +1530,9 @@ mptctl_eventquery (unsigned long arg) /* Copy the data from kernel memory to user memory */ if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_eventquery))) { - printk(KERN_ERR "%s@%d::mptctl_eventquery - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_eventquery - " "Unable to write out mpt_ioctl_eventquery struct @ %p\n", - __FILE__, __LINE__, uarg); + ioc->name, __FILE__, __LINE__, uarg); return -EFAULT; } return 0; @@ -1544,7 +1548,7 @@ mptctl_eventenable (unsigned long arg) int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) { - printk(KERN_ERR "%s@%d::mptctl_eventenable - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - " "Unable to read in mpt_ioctl_eventenable struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1552,7 +1556,7 @@ mptctl_eventenable (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_eventenable() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1563,12 +1567,13 @@ mptctl_eventenable (unsigned long arg) /* Have not yet allocated memory - do so now. */ int sz = MPTCTL_EVENT_LOG_SIZE * sizeof(MPT_IOCTL_EVENTS); - ioc->events = kmalloc(sz, GFP_KERNEL); - if (ioc->events == NULL) { - printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); + ioc->events = kzalloc(sz, GFP_KERNEL); + if (!ioc->events) { + printk(MYIOC_s_ERR_FMT + ": ERROR - Insufficient memory to add adapter!\n", + ioc->name); return -ENOMEM; } - memset(ioc->events, 0, sz); ioc->alloc_total += sz; ioc->eventContext = 0; @@ -1592,7 +1597,7 @@ mptctl_eventreport (unsigned long arg) int numBytes, maxEvents, max; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) { - printk(KERN_ERR "%s@%d::mptctl_eventreport - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_eventreport - " "Unable to read in mpt_ioctl_eventreport struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1600,7 +1605,7 @@ mptctl_eventreport (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_eventreport() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1626,9 +1631,9 @@ mptctl_eventreport (unsigned long arg) */ numBytes = max * sizeof(MPT_IOCTL_EVENTS); if (copy_to_user(uarg->eventData, ioc->events, numBytes)) { - printk(KERN_ERR "%s@%d::mptctl_eventreport - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_eventreport - " "Unable to write out mpt_ioctl_eventreport struct @ %p\n", - __FILE__, __LINE__, ioc->events); + ioc->name, __FILE__, __LINE__, ioc->events); return -EFAULT; } @@ -1646,7 +1651,7 @@ mptctl_replace_fw (unsigned long arg) int newFwSize; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) { - printk(KERN_ERR "%s@%d::mptctl_replace_fw - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1654,7 +1659,7 @@ mptctl_replace_fw (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1684,9 +1689,9 @@ mptctl_replace_fw (unsigned long arg) /* Copy the data from user memory to kernel space */ if (copy_from_user(ioc->cached_fw, uarg->newImage, newFwSize)) { - printk(KERN_ERR "%s@%d::mptctl_replace_fw - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw image " - "@ %p\n", __FILE__, __LINE__, uarg); + "@ %p\n", ioc->name, __FILE__, __LINE__, uarg); mpt_free_fw_memory(ioc); return -EFAULT; } @@ -1720,7 +1725,7 @@ mptctl_mpt_command (unsigned long arg) if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) { - printk(KERN_ERR "%s@%d::mptctl_mpt_command - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_mpt_command - " "Unable to read in mpt_ioctl_command struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1728,7 +1733,7 @@ mptctl_mpt_command (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1769,21 +1774,24 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ulong timeout; struct scsi_device *sdev; + /* bufIn and bufOut are used for user to kernel space transfers + */ bufIn.kptr = bufOut.kptr = NULL; + bufIn.len = bufOut.len = 0; if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } if (!ioc->ioctl) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - " "No memory available during driver init.\n", __FILE__, __LINE__); return -ENOMEM; } else if (ioc->ioctl->status & MPT_IOCTL_STATUS_DID_IOCRESET) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - " "Busy with IOC Reset \n", __FILE__, __LINE__); return -EBUSY; } @@ -1797,9 +1805,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) sz += sizeof(dma_addr_t) + sizeof(u32); if (sz > ioc->req_sz) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "Request frame too large (%d) maximum (%d)\n", - __FILE__, __LINE__, sz, ioc->req_sz); + ioc->name, __FILE__, __LINE__, sz, ioc->req_sz); return -EFAULT; } @@ -1817,9 +1825,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) * Request frame in user space */ if (copy_from_user(mf, mfPtr, karg.dataSgeOffset * 4)) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "Unable to read MF from mpt_ioctl_command struct @ %p\n", - __FILE__, __LINE__, mfPtr); + ioc->name, __FILE__, __LINE__, mfPtr); rc = -EFAULT; goto done_free_mem; } @@ -1870,17 +1878,17 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) id = (ioc->devices_per_bus == 0) ? 256 : ioc->devices_per_bus; if (pScsiReq->TargetID > id) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "Target ID out of bounds. \n", - __FILE__, __LINE__); + ioc->name, __FILE__, __LINE__); rc = -ENODEV; goto done_free_mem; } if (pScsiReq->Bus >= ioc->number_of_buses) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "Target Bus out of bounds. \n", - __FILE__, __LINE__); + ioc->name, __FILE__, __LINE__); rc = -ENODEV; goto done_free_mem; } @@ -1932,9 +1940,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ioc->ioctl->id = pScsiReq->TargetID; } else { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", - __FILE__, __LINE__); + ioc->name, __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } @@ -1951,9 +1959,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) case MPI_FUNCTION_SATA_PASSTHROUGH: if (!ioc->sh) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", - __FILE__, __LINE__); + ioc->name, __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } @@ -2010,9 +2018,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ioc->ioctl->reset = MPTCTL_RESET_OK; ioc->ioctl->id = pScsiReq->TargetID; } else { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", - __FILE__, __LINE__); + ioc->name, __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } @@ -2021,10 +2029,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) case MPI_FUNCTION_SCSI_TASK_MGMT: { MPT_SCSI_HOST *hd = NULL; - if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + if ((ioc->sh == NULL) || ((hd = shost_priv(ioc->sh)) == NULL)) { + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "SCSI driver not loaded or SCSI host not found. \n", - __FILE__, __LINE__); + ioc->name, __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } else if (mptctl_set_tm_flags(hd) != 0) { @@ -2055,9 +2063,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) (pInit->ReplyFrameSize != cpu_to_le16(ioc->reply_sz)) || (pInit->HostMfaHighAddr != high_addr) || (pInit->SenseBufferHighAddr != sense_high)) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n", - __FILE__, __LINE__); + ioc->name, __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } @@ -2088,9 +2096,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) MPI_FUNCTION_LAN_RESET */ - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "Illegal request (function 0x%x) \n", - __FILE__, __LINE__, hdr->Function); + ioc->name, __FILE__, __LINE__, hdr->Function); rc = -EFAULT; goto done_free_mem; } @@ -2103,11 +2111,6 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) psge = (char *) (((int *) mf) + karg.dataSgeOffset); flagsLength = 0; - /* bufIn and bufOut are used for user to kernel space transfers - */ - bufIn.kptr = bufOut.kptr = NULL; - bufIn.len = bufOut.len = 0; - if (karg.dataOutSize > 0) sgSize ++; @@ -2147,11 +2150,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) if (copy_from_user(bufOut.kptr, karg.dataOutBufPtr, bufOut.len)) { - printk(KERN_ERR + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - Unable " "to read user data " "struct @ %p\n", - __FILE__, __LINE__,karg.dataOutBufPtr); + ioc->name, __FILE__, __LINE__,karg.dataOutBufPtr); rc = -EFAULT; goto done_free_mem; } @@ -2187,15 +2190,20 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); - if (mpt_send_handshake_request(mptctl_id, ioc, - sizeof(SCSITaskMgmt_t), (u32*)mf, - CAN_SLEEP) != 0) { - dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "_send_handshake FAILED!" - " (ioc %p, mf %p) \n", ioc->name, - ioc, mf)); - mptctl_free_tm_flags(ioc); - rc = -ENODATA; - goto done_free_mem; + if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && + (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) + mpt_put_msg_frame_hi_pri(mptctl_id, ioc, mf); + else { + rc =mpt_send_handshake_request(mptctl_id, ioc, + sizeof(SCSITaskMgmt_t), (u32*)mf, CAN_SLEEP); + if (rc != 0) { + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT + "_send_handshake FAILED! (ioc %p, mf %p)\n", + ioc->name, ioc, mf)); + mptctl_free_tm_flags(ioc); + rc = -ENODATA; + goto done_free_mem; + } } } else @@ -2233,10 +2241,10 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) if (sz > 0) { if (copy_to_user(karg.replyFrameBufPtr, &ioc->ioctl->ReplyFrame, sz)){ - printk(KERN_ERR + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "Unable to write out reply frame %p\n", - __FILE__, __LINE__, karg.replyFrameBufPtr); + ioc->name, __FILE__, __LINE__, karg.replyFrameBufPtr); rc = -ENODATA; goto done_free_mem; } @@ -2249,9 +2257,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) sz = min(karg.maxSenseBytes, MPT_SENSE_BUFFER_SIZE); if (sz > 0) { if (copy_to_user(karg.senseDataPtr, ioc->ioctl->sense, sz)) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "Unable to write sense data to user %p\n", - __FILE__, __LINE__, + ioc->name, __FILE__, __LINE__, karg.senseDataPtr); rc = -ENODATA; goto done_free_mem; @@ -2267,9 +2275,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) if (copy_to_user(karg.dataInBufPtr, bufIn.kptr, karg.dataInSize)) { - printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " "Unable to write data to user %p\n", - __FILE__, __LINE__, + ioc->name, __FILE__, __LINE__, karg.dataInBufPtr); rc = -ENODATA; } @@ -2340,7 +2348,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) return -EFAULT; if (copy_from_user(&karg, uarg, sizeof(hp_host_info_t))) { - printk(KERN_ERR "%s@%d::mptctl_hp_host_info - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_hp_host_info - " "Unable to read in hp_host_info struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -2348,7 +2356,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -2456,7 +2464,7 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) karg.soft_resets = 0; karg.timeouts = 0; if (ioc->sh != NULL) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + MPT_SCSI_HOST *hd = shost_priv(ioc->sh); if (hd && (cim_rev == 1)) { karg.hard_resets = hd->hard_resets; @@ -2529,9 +2537,9 @@ mptctl_hp_hostinfo(unsigned long arg, unsigned int data_size) /* Copy the data from kernel memory to user memory */ if (copy_to_user((char __user *)arg, &karg, sizeof(hp_host_info_t))) { - printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_hpgethostinfo - " "Unable to write out hp_host_info @ %p\n", - __FILE__, __LINE__, uarg); + ioc->name, __FILE__, __LINE__, uarg); return -EFAULT; } @@ -2567,7 +2575,7 @@ mptctl_hp_targetinfo(unsigned long arg) int tmp, np, rc = 0; if (copy_from_user(&karg, uarg, sizeof(hp_target_info_t))) { - printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - " + printk(KERN_ERR MYNAM "%s@%d::mptctl_hp_targetinfo - " "Unable to read in hp_host_targetinfo struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -2575,11 +2583,11 @@ mptctl_hp_targetinfo(unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", + printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } - dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": mptctl_hp_targetinfo called.\n", + dctlprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mptctl_hp_targetinfo called.\n", ioc->name)); /* There is nothing to do for FCP parts. @@ -2673,16 +2681,16 @@ mptctl_hp_targetinfo(unsigned long arg) pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg3_alloc, page_dma); } } - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + hd = shost_priv(ioc->sh); if (hd != NULL) karg.select_timeouts = hd->sel_timeout[karg.hdr.id]; /* Copy the data from kernel memory to user memory */ if (copy_to_user((char __user *)arg, &karg, sizeof(hp_target_info_t))) { - printk(KERN_ERR "%s@%d::mptctl_hp_target_info - " + printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_hp_target_info - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - __FILE__, __LINE__, uarg); + ioc->name, __FILE__, __LINE__, uarg); return -EFAULT; } @@ -2732,7 +2740,7 @@ compat_mptfwxfer_ioctl(struct file *filp, unsigned int cmd, if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { printk(KERN_DEBUG MYNAM "::compat_mptfwxfer_ioctl @%d - ioc%d not found!\n", - __LINE__, iocnumX); + __LINE__, iocnumX); return -ENODEV; } @@ -2772,7 +2780,7 @@ compat_mpt_command(struct file *filp, unsigned int cmd, if (((iocnum = mpt_verify_adapter(iocnumX, &iocp)) < 0) || (iocp == NULL)) { printk(KERN_DEBUG MYNAM "::compat_mpt_command @%d - ioc%d not found!\n", - __LINE__, iocnumX); + __LINE__, iocnumX); return -ENODEV; } @@ -2853,31 +2861,22 @@ static long compat_mpctl_ioctl(struct file *f, unsigned int cmd, unsigned long a static int mptctl_probe(struct pci_dev *pdev, const struct pci_device_id *id) { - int err; - int sz; - u8 *mem; + MPT_IOCTL *mem; MPT_ADAPTER *ioc = pci_get_drvdata(pdev); /* * Allocate and inite a MPT_IOCTL structure */ - sz = sizeof (MPT_IOCTL); - mem = kmalloc(sz, GFP_KERNEL); - if (mem == NULL) { - err = -ENOMEM; - goto out_fail; + mem = kzalloc(sizeof(MPT_IOCTL), GFP_KERNEL); + if (!mem) { + mptctl_remove(pdev); + return -ENOMEM; } - memset(mem, 0, sz); - ioc->ioctl = (MPT_IOCTL *) mem; + ioc->ioctl = mem; ioc->ioctl->ioc = ioc; mutex_init(&ioc->ioctl->ioctl_mutex); return 0; - -out_fail: - - mptctl_remove(pdev); - return err; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2924,7 +2923,8 @@ static int __init mptctl_init(void) * Install our handler */ ++where; - if ((mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER)) < 0) { + mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER); + if (!mptctl_id || mptctl_id >= MPT_MAX_PROTOCOL_DRIVERS) { printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n"); misc_deregister(&mptctl_miscdev); err = -EBUSY; diff --git a/drivers/message/fusion/mptctl.h b/drivers/message/fusion/mptctl.h index 180b3c156247..2c1890127e15 100644 --- a/drivers/message/fusion/mptctl.h +++ b/drivers/message/fusion/mptctl.h @@ -3,9 +3,9 @@ * Fusion MPT misc device (ioctl) driver. * For use with PCI chip/adapter(s): * LSIFC9xx/LSI409xx Fibre Channel - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c index 8422c25e4a3e..3cdd4e962115 100644 --- a/drivers/message/fusion/mptfc.c +++ b/drivers/message/fusion/mptfc.c @@ -1,9 +1,9 @@ /* * linux/drivers/message/fusion/mptfc.c - * For use with LSI Logic PCI chip/adapter(s) - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * For use with LSI PCI chip/adapter(s) + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -90,9 +90,9 @@ static int max_lun = MPTFC_MAX_LUN; module_param(max_lun, int, 0); MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); -static int mptfcDoneCtx = -1; -static int mptfcTaskCtx = -1; -static int mptfcInternalCtx = -1; /* Used only for internal commands */ +static u8 mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS; +static u8 mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; +static u8 mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; static int mptfc_target_alloc(struct scsi_target *starget); static int mptfc_slave_alloc(struct scsi_device *sdev); @@ -194,37 +194,36 @@ mptfc_block_error_handler(struct scsi_cmnd *SCpnt, struct fc_rport *rport = starget_to_rport(scsi_target(sdev)); unsigned long flags; int ready; + MPT_ADAPTER *ioc; - hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; + hd = shost_priv(SCpnt->device->host); + ioc = hd->ioc; spin_lock_irqsave(shost->host_lock, flags); while ((ready = fc_remote_port_chkready(rport) >> 16) == DID_IMM_RETRY) { spin_unlock_irqrestore(shost->host_lock, flags); - dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT + dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT "mptfc_block_error_handler.%d: %d:%d, port status is " "DID_IMM_RETRY, deferring %s recovery.\n", - ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, - ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no, - SCpnt->device->id,SCpnt->device->lun,caller)); + ioc->name, ioc->sh->host_no, + SCpnt->device->id, SCpnt->device->lun, caller)); msleep(1000); spin_lock_irqsave(shost->host_lock, flags); } spin_unlock_irqrestore(shost->host_lock, flags); if (ready == DID_NO_CONNECT || !SCpnt->device->hostdata) { - dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT + dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT "%s.%d: %d:%d, failing recovery, " - "port state %d, vdev %p.\n", caller, - ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, - ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no, - SCpnt->device->id,SCpnt->device->lun,ready, + "port state %d, vdevice %p.\n", caller, + ioc->name, ioc->sh->host_no, + SCpnt->device->id, SCpnt->device->lun, ready, SCpnt->device->hostdata)); return FAILED; } - dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT + dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT "%s.%d: %d:%d, executing recovery.\n", caller, - ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, - ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no, - SCpnt->device->id,SCpnt->device->lun)); + ioc->name, ioc->sh->host_no, + SCpnt->device->id, SCpnt->device->lun)); return (*func)(SCpnt); } @@ -470,7 +469,7 @@ mptfc_register_dev(MPT_ADAPTER *ioc, int channel, FCDevicePage0_t *pg0) /* * if already mapped, remap here. If not mapped, * target_alloc will allocate vtarget and map, - * slave_alloc will fill in vdev from vtarget. + * slave_alloc will fill in vdevice from vtarget. */ if (ri->starget) { vtarget = ri->starget->hostdata; @@ -602,10 +601,10 @@ mptfc_slave_alloc(struct scsi_device *sdev) { MPT_SCSI_HOST *hd; VirtTarget *vtarget; - VirtDevice *vdev; + VirtDevice *vdevice; struct scsi_target *starget; struct fc_rport *rport; - + MPT_ADAPTER *ioc; starget = scsi_target(sdev); rport = starget_to_rport(starget); @@ -613,31 +612,32 @@ mptfc_slave_alloc(struct scsi_device *sdev) if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; - hd = (MPT_SCSI_HOST *)sdev->host->hostdata; + hd = shost_priv(sdev->host); + ioc = hd->ioc; - vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdev) { + vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdevice) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", - hd->ioc->name, sizeof(VirtDevice)); + ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - sdev->hostdata = vdev; + sdev->hostdata = vdevice; vtarget = starget->hostdata; if (vtarget->num_luns == 0) { - vtarget->ioc_id = hd->ioc->id; + vtarget->ioc_id = ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; } - vdev->vtarget = vtarget; - vdev->lun = sdev->lun; + vdevice->vtarget = vtarget; + vdevice->lun = sdev->lun; vtarget->num_luns++; - mptfc_dump_lun_info(hd->ioc, rport, sdev, vtarget); + mptfc_dump_lun_info(ioc, rport, sdev, vtarget); return 0; } @@ -648,9 +648,9 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) struct mptfc_rport_info *ri; struct fc_rport *rport = starget_to_rport(scsi_target(SCpnt->device)); int err; - VirtDevice *vdev = SCpnt->device->hostdata; + VirtDevice *vdevice = SCpnt->device->hostdata; - if (!vdev || !vdev->vtarget) { + if (!vdevice || !vdevice->vtarget) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; @@ -675,6 +675,50 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) } /* + * mptfc_display_port_link_speed - displaying link speed + * @ioc: Pointer to MPT_ADAPTER structure + * @portnum: IOC Port number + * @pp0dest: port page0 data payload + * + */ +static void +mptfc_display_port_link_speed(MPT_ADAPTER *ioc, int portnum, FCPortPage0_t *pp0dest) +{ + u8 old_speed, new_speed, state; + char *old, *new; + + if (portnum >= 2) + return; + + old_speed = ioc->fc_link_speed[portnum]; + new_speed = pp0dest->CurrentSpeed; + state = pp0dest->PortState; + + if (state != MPI_FCPORTPAGE0_PORTSTATE_OFFLINE && + new_speed != MPI_FCPORTPAGE0_CURRENT_SPEED_UKNOWN) { + + old = old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" : + old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" : + old_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : + "Unknown"; + new = new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_1GBIT ? "1 Gbps" : + new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_2GBIT ? "2 Gbps" : + new_speed == MPI_FCPORTPAGE0_CURRENT_SPEED_4GBIT ? "4 Gbps" : + "Unknown"; + if (old_speed == 0) + printk(MYIOC_s_NOTE_FMT + "FC Link Established, Speed = %s\n", + ioc->name, new); + else if (old_speed != new_speed) + printk(MYIOC_s_WARN_FMT + "FC Link Speed Change, Old Speed = %s, New Speed = %s\n", + ioc->name, old, new); + + ioc->fc_link_speed[portnum] = new_speed; + } +} + +/* * mptfc_GetFcPortPage0 - Fetch FCPort config Page0. * @ioc: Pointer to MPT_ADAPTER structure * @portnum: IOC Port number @@ -773,6 +817,7 @@ mptfc_GetFcPortPage0(MPT_ADAPTER *ioc, int portnum) " complete.\n", ioc->name); } + mptfc_display_port_link_speed(ioc, portnum, pp0dest); } pci_free_consistent(ioc->pcidev, data_sz, (u8 *) ppage0_alloc, page0_dma); @@ -1023,6 +1068,18 @@ mptfc_init_host_attr(MPT_ADAPTER *ioc,int portnum) } static void +mptfc_link_status_change(struct work_struct *work) +{ + MPT_ADAPTER *ioc = + container_of(work, MPT_ADAPTER, fc_rescan_work); + int ii; + + for (ii=0; ii < ioc->facts.NumberOfPorts; ii++) + (void) mptfc_GetFcPortPage0(ioc, ii); + +} + +static void mptfc_setup_reset(struct work_struct *work) { MPT_ADAPTER *ioc = @@ -1163,6 +1220,7 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_lock_init(&ioc->fc_rescan_work_lock); INIT_WORK(&ioc->fc_rescan_work, mptfc_rescan_devices); INIT_WORK(&ioc->fc_setup_reset_work, mptfc_setup_reset); + INIT_WORK(&ioc->fc_lsc_work, mptfc_link_status_change); spin_lock_irqsave(&ioc->FreeQlock, flags); @@ -1218,20 +1276,21 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_unlock_irqrestore(&ioc->FreeQlock, flags); - hd = (MPT_SCSI_HOST *) sh->hostdata; + hd = shost_priv(sh); hd->ioc = ioc; /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); - if (!hd->ScsiLookup) { + ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!ioc->ScsiLookup) { error = -ENOMEM; goto out_mptfc_probe; } + spin_lock_init(&ioc->scsi_lookup_lock); dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n", - ioc->name, hd->ScsiLookup)); + ioc->name, ioc->ScsiLookup)); /* Clear the TM flags */ @@ -1262,8 +1321,8 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->transportt = mptfc_transport_template; error = scsi_add_host (sh, &ioc->pcidev->dev); if(error) { - dprintk(ioc, printk(KERN_ERR MYNAM - "scsi_add_host failed\n")); + dprintk(ioc, printk(MYIOC_s_ERR_FMT + "scsi_add_host failed\n", ioc->name)); goto out_mptfc_probe; } @@ -1325,7 +1384,7 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) ioc->name, event)); if (ioc->sh == NULL || - ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) + ((hd = shost_priv(ioc->sh)) == NULL)) return 1; switch (event) { @@ -1337,6 +1396,14 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) } spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); break; + case MPI_EVENT_LINK_STATUS_CHANGE: + spin_lock_irqsave(&ioc->fc_rescan_work_lock, flags); + if (ioc->fc_rescan_work_q) { + queue_work(ioc->fc_rescan_work_q, + &ioc->fc_lsc_work); + } + spin_unlock_irqrestore(&ioc->fc_rescan_work_lock, flags); + break; default: rc = mptscsih_event_process(ioc,pEvReply); break; diff --git a/drivers/message/fusion/mptlan.c b/drivers/message/fusion/mptlan.c index 3da4c37846ec..7950fc678ed1 100644 --- a/drivers/message/fusion/mptlan.c +++ b/drivers/message/fusion/mptlan.c @@ -1,10 +1,10 @@ /* * linux/drivers/message/fusion/mptlan.c * IP Over Fibre Channel device driver. - * For use with LSI Logic Fibre Channel PCI chip/adapters - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Fibre Channel PCI chip/adapters + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 2000-2007 LSI Logic Corporation + * Copyright (c) 2000-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -154,7 +154,7 @@ static unsigned short mpt_lan_type_trans(struct sk_buff *skb, /* * Fusion MPT LAN private data */ -static int LanCtx = -1; +static u8 LanCtx = MPT_MAX_PROTOCOL_DRIVERS; static u32 max_buckets_out = 127; static u32 tx_max_out_p = 127 - 16; @@ -165,12 +165,6 @@ DEFINE_RWLOCK(bad_naa_lock); #endif /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * Fusion MPT LAN external data - */ -extern int mpt_lan_index; - -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * lan_reply - Handle all data sent from the hardware. * @ioc: Pointer to MPT_ADAPTER structure @@ -1230,6 +1224,8 @@ mpt_lan_post_receive_buckets(struct mpt_lan_priv *priv) } pRecvReq = (LANReceivePostRequest_t *) mf; + i = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); + mpt_dev->RequestNB[i] = 0; count = buckets; if (count > max) count = max; @@ -1351,10 +1347,11 @@ mpt_lan_post_receive_buckets_work(struct work_struct *work) static struct net_device * mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) { - struct net_device *dev = alloc_fcdev(sizeof(struct mpt_lan_priv)); - struct mpt_lan_priv *priv = NULL; + struct net_device *dev; + struct mpt_lan_priv *priv; u8 HWaddr[FC_ALEN], *a; + dev = alloc_fcdev(sizeof(struct mpt_lan_priv)); if (!dev) return NULL; @@ -1366,7 +1363,6 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) priv->mpt_dev = mpt_dev; priv->pnum = pnum; - memset(&priv->post_buckets_task, 0, sizeof(priv->post_buckets_task)); INIT_DELAYED_WORK(&priv->post_buckets_task, mpt_lan_post_receive_buckets_work); priv->post_buckets_active = 0; @@ -1391,8 +1387,6 @@ mpt_register_lan_device (MPT_ADAPTER *mpt_dev, int pnum) spin_lock_init(&priv->txfidx_lock); spin_lock_init(&priv->rxfidx_lock); - memset(&priv->stats, 0, sizeof(priv->stats)); - /* Grab pre-fetched LANPage1 stuff. :-) */ a = (u8 *) &mpt_dev->lan_cnfg_page1.HardwareAddressLow; @@ -1508,9 +1502,6 @@ static int __init mpt_lan_init (void) return -EBUSY; } - /* Set the callback index to be used by driver core for turbo replies */ - mpt_lan_index = LanCtx; - dlprintk((KERN_INFO MYNAM ": assigned context of %d\n", LanCtx)); if (mpt_reset_register(LanCtx, mpt_lan_ioc_reset)) { @@ -1531,10 +1522,9 @@ static void __exit mpt_lan_exit(void) mpt_device_driver_deregister(MPTLAN_DRIVER); mpt_reset_deregister(LanCtx); - if (LanCtx >= 0) { + if (LanCtx) { mpt_deregister(LanCtx); - LanCtx = -1; - mpt_lan_index = 0; + LanCtx = MPT_MAX_PROTOCOL_DRIVERS; } } diff --git a/drivers/message/fusion/mptlan.h b/drivers/message/fusion/mptlan.h index 8d08c2bed24a..bafb67fc8181 100644 --- a/drivers/message/fusion/mptlan.h +++ b/drivers/message/fusion/mptlan.h @@ -1,10 +1,10 @@ /* * linux/drivers/message/fusion/mptlan.h * IP Over Fibre Channel device driver. - * For use with LSI Logic Fibre Channel PCI chip/adapters - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Fibre Channel PCI chip/adapters + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 2000-2007 LSI Logic Corporation + * Copyright (c) 2000-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -75,7 +75,7 @@ #include <asm/io.h> /* Override mptbase.h by pre-defining these! */ -#define MODULEAUTHOR "LSI Logic Corporation" +#define MODULEAUTHOR "LSI Corporation" #include "mptbase.h" diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index b9c69bff218c..e4c94f93de16 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c @@ -1,11 +1,10 @@ /* * linux/drivers/message/fusion/mptsas.c - * For use with LSI Logic PCI chip/adapter(s) - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * For use with LSI PCI chip/adapter(s) + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) - * Copyright (c) 2005-2007 Dell */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -61,6 +60,7 @@ #include "mptbase.h" #include "mptscsih.h" +#include "mptsas.h" #define my_NAME "Fusion MPT SAS Host driver" @@ -89,134 +89,35 @@ static int max_lun = MPTSAS_MAX_LUN; module_param(max_lun, int, 0); MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); -static int mptsasDoneCtx = -1; -static int mptsasTaskCtx = -1; -static int mptsasInternalCtx = -1; /* Used only for internal commands */ -static int mptsasMgmtCtx = -1; +static u8 mptsasDoneCtx = MPT_MAX_PROTOCOL_DRIVERS; +static u8 mptsasTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; +static u8 mptsasInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ +static u8 mptsasMgmtCtx = MPT_MAX_PROTOCOL_DRIVERS; static void mptsas_hotplug_work(struct work_struct *work); -struct mptsas_target_reset_event { - struct list_head list; - EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data; - u8 target_reset_issued; -}; - -enum mptsas_hotplug_action { - MPTSAS_ADD_DEVICE, - MPTSAS_DEL_DEVICE, - MPTSAS_ADD_RAID, - MPTSAS_DEL_RAID, - MPTSAS_ADD_INACTIVE_VOLUME, - MPTSAS_IGNORE_EVENT, -}; - -struct mptsas_hotplug_event { - struct work_struct work; - MPT_ADAPTER *ioc; - enum mptsas_hotplug_action event_type; - u64 sas_address; - u8 channel; - u8 id; - u32 device_info; - u16 handle; - u16 parent_handle; - u8 phy_id; - u8 phys_disk_num_valid; /* hrc (hidden raid component) */ - u8 phys_disk_num; /* hrc - unique index*/ - u8 hidden_raid_component; /* hrc - don't expose*/ -}; - -struct mptsas_discovery_event { - struct work_struct work; - MPT_ADAPTER *ioc; -}; - -/* - * SAS topology structures - * - * The MPT Fusion firmware interface spreads information about the - * SAS topology over many manufacture pages, thus we need some data - * structure to collect it and process it for the SAS transport class. - */ - -struct mptsas_devinfo { - u16 handle; /* unique id to address this device */ - u16 handle_parent; /* unique id to address parent device */ - u16 handle_enclosure; /* enclosure identifier of the enclosure */ - u16 slot; /* physical slot in enclosure */ - u8 phy_id; /* phy number of parent device */ - u8 port_id; /* sas physical port this device - is assoc'd with */ - u8 id; /* logical target id of this device */ - u32 phys_disk_num; /* phys disk id, for csmi-ioctls */ - u8 channel; /* logical bus number of this device */ - u64 sas_address; /* WWN of this device, - SATA is assigned by HBA,expander */ - u32 device_info; /* bitfield detailed info about this device */ -}; - -/* - * Specific details on ports, wide/narrow - */ -struct mptsas_portinfo_details{ - u16 num_phys; /* number of phys belong to this port */ - u64 phy_bitmask; /* TODO, extend support for 255 phys */ - struct sas_rphy *rphy; /* transport layer rphy object */ - struct sas_port *port; /* transport layer port object */ - struct scsi_target *starget; - struct mptsas_portinfo *port_info; -}; - -struct mptsas_phyinfo { - u16 handle; /* unique id to address this */ - u8 phy_id; /* phy index */ - u8 port_id; /* firmware port identifier */ - u8 negotiated_link_rate; /* nego'd link rate for this phy */ - u8 hw_link_rate; /* hardware max/min phys link rate */ - u8 programmed_link_rate; /* programmed max/min phy link rate */ - u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/ - struct mptsas_devinfo identify; /* point to phy device info */ - struct mptsas_devinfo attached; /* point to attached device info */ - struct sas_phy *phy; /* transport layer phy object */ - struct mptsas_portinfo *portinfo; - struct mptsas_portinfo_details * port_details; -}; - -struct mptsas_portinfo { - struct list_head list; - u16 num_phys; /* number of phys */ - struct mptsas_phyinfo *phy_info; -}; - -struct mptsas_enclosure { - u64 enclosure_logical_id; /* The WWN for the enclosure */ - u16 enclosure_handle; /* unique id to address this */ - u16 flags; /* details enclosure management */ - u16 num_slot; /* num slots */ - u16 start_slot; /* first slot */ - u8 start_id; /* starting logical target id */ - u8 start_channel; /* starting logical channel id */ - u8 sep_id; /* SEP device logical target id */ - u8 sep_channel; /* SEP channel logical channel id */ -}; - static void mptsas_print_phy_data(MPT_ADAPTER *ioc, MPI_SAS_IO_UNIT0_PHY_DATA *phy_data) { - dsasprintk(ioc, printk(KERN_DEBUG "---- IO UNIT PAGE 0 ------------\n")); - dsasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n", - le16_to_cpu(phy_data->AttachedDeviceHandle))); - dsasprintk(ioc, printk(KERN_DEBUG "Controller Handle=0x%X\n", - le16_to_cpu(phy_data->ControllerDevHandle))); - dsasprintk(ioc, printk(KERN_DEBUG "Port=0x%X\n", phy_data->Port)); - dsasprintk(ioc, printk(KERN_DEBUG "Port Flags=0x%X\n", phy_data->PortFlags)); - dsasprintk(ioc, printk(KERN_DEBUG "PHY Flags=0x%X\n", phy_data->PhyFlags)); - dsasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n", phy_data->NegotiatedLinkRate)); - dsasprintk(ioc, printk(KERN_DEBUG "Controller PHY Device Info=0x%X\n", - le32_to_cpu(phy_data->ControllerPhyDeviceInfo))); - dsasprintk(ioc, printk(KERN_DEBUG "DiscoveryStatus=0x%X\n\n", - le32_to_cpu(phy_data->DiscoveryStatus))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "---- IO UNIT PAGE 0 ------------\n", ioc->name)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n", + ioc->name, le16_to_cpu(phy_data->AttachedDeviceHandle))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Controller Handle=0x%X\n", + ioc->name, le16_to_cpu(phy_data->ControllerDevHandle))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port=0x%X\n", + ioc->name, phy_data->Port)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Port Flags=0x%X\n", + ioc->name, phy_data->PortFlags)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Flags=0x%X\n", + ioc->name, phy_data->PhyFlags)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n", + ioc->name, phy_data->NegotiatedLinkRate)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Controller PHY Device Info=0x%X\n", ioc->name, + le32_to_cpu(phy_data->ControllerPhyDeviceInfo))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "DiscoveryStatus=0x%X\n\n", + ioc->name, le32_to_cpu(phy_data->DiscoveryStatus))); } static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0) @@ -225,27 +126,41 @@ static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0) memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); - dsasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 0 ------------\n")); - dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Handle=0x%X\n", - le16_to_cpu(pg0->AttachedDevHandle))); - dsasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n", - (unsigned long long)le64_to_cpu(sas_address))); - dsasprintk(ioc, printk(KERN_DEBUG "Attached PHY Identifier=0x%X\n", pg0->AttachedPhyIdentifier)); - dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Info=0x%X\n", - le32_to_cpu(pg0->AttachedDeviceInfo))); - dsasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n", pg0->ProgrammedLinkRate)); - dsasprintk(ioc, printk(KERN_DEBUG "Change Count=0x%X\n", pg0->ChangeCount)); - dsasprintk(ioc, printk(KERN_DEBUG "PHY Info=0x%X\n\n", le32_to_cpu(pg0->PhyInfo))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "---- SAS PHY PAGE 0 ------------\n", ioc->name)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Attached Device Handle=0x%X\n", ioc->name, + le16_to_cpu(pg0->AttachedDevHandle))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n", + ioc->name, (unsigned long long)le64_to_cpu(sas_address))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Attached PHY Identifier=0x%X\n", ioc->name, + pg0->AttachedPhyIdentifier)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Attached Device Info=0x%X\n", + ioc->name, le32_to_cpu(pg0->AttachedDeviceInfo))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n", + ioc->name, pg0->ProgrammedLinkRate)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Change Count=0x%X\n", + ioc->name, pg0->ChangeCount)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Info=0x%X\n\n", + ioc->name, le32_to_cpu(pg0->PhyInfo))); } static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1) { - dsasprintk(ioc, printk(KERN_DEBUG "---- SAS PHY PAGE 1 ------------\n")); - dsasprintk(ioc, printk(KERN_DEBUG "Invalid Dword Count=0x%x\n", pg1->InvalidDwordCount)); - dsasprintk(ioc, printk(KERN_DEBUG "Running Disparity Error Count=0x%x\n", - pg1->RunningDisparityErrorCount)); - dsasprintk(ioc, printk(KERN_DEBUG "Loss Dword Synch Count=0x%x\n", pg1->LossDwordSynchCount)); - dsasprintk(ioc, printk(KERN_DEBUG "PHY Reset Problem Count=0x%x\n\n", pg1->PhyResetProblemCount)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "---- SAS PHY PAGE 1 ------------\n", ioc->name)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Invalid Dword Count=0x%x\n", + ioc->name, pg1->InvalidDwordCount)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Running Disparity Error Count=0x%x\n", ioc->name, + pg1->RunningDisparityErrorCount)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Loss Dword Synch Count=0x%x\n", ioc->name, + pg1->LossDwordSynchCount)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "PHY Reset Problem Count=0x%x\n\n", ioc->name, + pg1->PhyResetProblemCount)); } static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0) @@ -254,37 +169,53 @@ static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0) memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); - dsasprintk(ioc, printk(KERN_DEBUG "---- SAS DEVICE PAGE 0 ---------\n")); - dsasprintk(ioc, printk(KERN_DEBUG "Handle=0x%X\n" ,le16_to_cpu(pg0->DevHandle))); - dsasprintk(ioc, printk(KERN_DEBUG "Parent Handle=0x%X\n" ,le16_to_cpu(pg0->ParentDevHandle))); - dsasprintk(ioc, printk(KERN_DEBUG "Enclosure Handle=0x%X\n", le16_to_cpu(pg0->EnclosureHandle))); - dsasprintk(ioc, printk(KERN_DEBUG "Slot=0x%X\n", le16_to_cpu(pg0->Slot))); - dsasprintk(ioc, printk(KERN_DEBUG "SAS Address=0x%llX\n", (unsigned long long) - le64_to_cpu(sas_address))); - dsasprintk(ioc, printk(KERN_DEBUG "Target ID=0x%X\n", pg0->TargetID)); - dsasprintk(ioc, printk(KERN_DEBUG "Bus=0x%X\n", pg0->Bus)); - /* The PhyNum field specifies the PHY number of the parent - * device this device is linked to - */ - dsasprintk(ioc, printk(KERN_DEBUG "Parent Phy Num=0x%X\n", pg0->PhyNum)); - dsasprintk(ioc, printk(KERN_DEBUG "Access Status=0x%X\n", le16_to_cpu(pg0->AccessStatus))); - dsasprintk(ioc, printk(KERN_DEBUG "Device Info=0x%X\n", le32_to_cpu(pg0->DeviceInfo))); - dsasprintk(ioc, printk(KERN_DEBUG "Flags=0x%X\n", le16_to_cpu(pg0->Flags))); - dsasprintk(ioc, printk(KERN_DEBUG "Physical Port=0x%X\n\n", pg0->PhysicalPort)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "---- SAS DEVICE PAGE 0 ---------\n", ioc->name)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Handle=0x%X\n", + ioc->name, le16_to_cpu(pg0->DevHandle))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Handle=0x%X\n", + ioc->name, le16_to_cpu(pg0->ParentDevHandle))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Enclosure Handle=0x%X\n", + ioc->name, le16_to_cpu(pg0->EnclosureHandle))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Slot=0x%X\n", + ioc->name, le16_to_cpu(pg0->Slot))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "SAS Address=0x%llX\n", + ioc->name, (unsigned long long)le64_to_cpu(sas_address))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Target ID=0x%X\n", + ioc->name, pg0->TargetID)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Bus=0x%X\n", + ioc->name, pg0->Bus)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Parent Phy Num=0x%X\n", + ioc->name, pg0->PhyNum)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Access Status=0x%X\n", + ioc->name, le16_to_cpu(pg0->AccessStatus))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Device Info=0x%X\n", + ioc->name, le32_to_cpu(pg0->DeviceInfo))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Flags=0x%X\n", + ioc->name, le16_to_cpu(pg0->Flags))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n\n", + ioc->name, pg0->PhysicalPort)); } static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1) { - dsasprintk(ioc, printk(KERN_DEBUG "---- SAS EXPANDER PAGE 1 ------------\n")); - dsasprintk(ioc, printk(KERN_DEBUG "Physical Port=0x%X\n", pg1->PhysicalPort)); - dsasprintk(ioc, printk(KERN_DEBUG "PHY Identifier=0x%X\n", pg1->PhyIdentifier)); - dsasprintk(ioc, printk(KERN_DEBUG "Negotiated Link Rate=0x%X\n", pg1->NegotiatedLinkRate)); - dsasprintk(ioc, printk(KERN_DEBUG "Programmed Link Rate=0x%X\n", pg1->ProgrammedLinkRate)); - dsasprintk(ioc, printk(KERN_DEBUG "Hardware Link Rate=0x%X\n", pg1->HwLinkRate)); - dsasprintk(ioc, printk(KERN_DEBUG "Owner Device Handle=0x%X\n", - le16_to_cpu(pg1->OwnerDevHandle))); - dsasprintk(ioc, printk(KERN_DEBUG "Attached Device Handle=0x%X\n\n", - le16_to_cpu(pg1->AttachedDevHandle))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "---- SAS EXPANDER PAGE 1 ------------\n", ioc->name)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Physical Port=0x%X\n", + ioc->name, pg1->PhysicalPort)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "PHY Identifier=0x%X\n", + ioc->name, pg1->PhyIdentifier)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Negotiated Link Rate=0x%X\n", + ioc->name, pg1->NegotiatedLinkRate)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Programmed Link Rate=0x%X\n", + ioc->name, pg1->ProgrammedLinkRate)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hardware Link Rate=0x%X\n", + ioc->name, pg1->HwLinkRate)); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Owner Device Handle=0x%X\n", + ioc->name, le16_to_cpu(pg1->OwnerDevHandle))); + dsasprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Attached Device Handle=0x%X\n\n", ioc->name, + le16_to_cpu(pg1->AttachedDevHandle))); } static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) @@ -354,8 +285,8 @@ mptsas_port_delete(MPT_ADAPTER *ioc, struct mptsas_portinfo_details * port_detai port_info = port_details->port_info; phy_info = port_info->phy_info; - dsaswideprintk(ioc, printk(KERN_DEBUG "%s: [%p]: num_phys=%02d " - "bitmask=0x%016llX\n", __FUNCTION__, port_details, + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d " + "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details, port_details->num_phys, (unsigned long long) port_details->phy_bitmask)); @@ -382,14 +313,15 @@ mptsas_set_rphy(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_rp { if (phy_info->port_details) { phy_info->port_details->rphy = rphy; - dsaswideprintk(ioc, printk(KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy)); + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n", + ioc->name, rphy)); } if (rphy) { dsaswideprintk(ioc, dev_printk(KERN_DEBUG, - &rphy->dev, "add:")); - dsaswideprintk(ioc, printk(KERN_DEBUG "rphy=%p release=%p\n", - rphy, rphy->dev.release)); + &rphy->dev, MYIOC_s_FMT "add:", ioc->name)); + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rphy=%p release=%p\n", + ioc->name, rphy, rphy->dev.release)); } } @@ -410,9 +342,9 @@ mptsas_set_port(MPT_ADAPTER *ioc, struct mptsas_phyinfo *phy_info, struct sas_po if (port) { dsaswideprintk(ioc, dev_printk(KERN_DEBUG, - &port->dev, "add:")); - dsaswideprintk(ioc, printk(KERN_DEBUG "port=%p release=%p\n", - port, port->dev.release)); + &port->dev, MYIOC_s_FMT "add:", ioc->name)); + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n", + ioc->name, port, port->dev.release)); } } @@ -463,9 +395,9 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) * Removing a phy from a port, letting the last * phy be removed by firmware events. */ - dsaswideprintk(ioc, printk(KERN_DEBUG - "%s: [%p]: deleting phy = %d\n", - __FUNCTION__, port_details, i)); + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "%s: [%p]: deleting phy = %d\n", + ioc->name, __FUNCTION__, port_details, i)); port_details->num_phys--; port_details->phy_bitmask &= ~ (1 << phy_info->phy_id); memset(&phy_info->attached, 0, sizeof(struct mptsas_devinfo)); @@ -479,8 +411,8 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) phy_info = port_info->phy_info; for (i = 0 ; i < port_info->num_phys ; i++, phy_info++) { sas_address = phy_info->attached.sas_address; - dsaswideprintk(ioc, printk(KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n", - i, (unsigned long long)sas_address)); + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n", + ioc->name, i, (unsigned long long)sas_address)); if (!sas_address) continue; port_details = phy_info->port_details; @@ -498,9 +430,9 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) port_details->phy_bitmask |= (1 << phy_info->phy_id); phy_info->sas_port_add_phy=1; - dsaswideprintk(ioc, printk(KERN_DEBUG "\t\tForming port\n\t\t" + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t" "phy_id=%d sas_address=0x%018llX\n", - i, (unsigned long long)sas_address)); + ioc->name, i, (unsigned long long)sas_address)); phy_info->port_details = port_details; } @@ -515,9 +447,9 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) continue; if (phy_info_cmp->port_details == port_details ) continue; - dsaswideprintk(ioc, printk(KERN_DEBUG + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tphy_id=%d sas_address=0x%018llX\n", - j, (unsigned long long) + ioc->name, j, (unsigned long long) phy_info_cmp->attached.sas_address)); if (phy_info_cmp->port_details) { port_details->rphy = @@ -549,15 +481,15 @@ mptsas_setup_wide_ports(MPT_ADAPTER *ioc, struct mptsas_portinfo *port_info) port_details = port_info->phy_info[i].port_details; if (!port_details) continue; - dsaswideprintk(ioc, printk(KERN_DEBUG + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "%s: [%p]: phy_id=%02d num_phys=%02d " - "bitmask=0x%016llX\n", __FUNCTION__, + "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details, i, port_details->num_phys, (unsigned long long)port_details->phy_bitmask)); - dsaswideprintk(ioc, printk(KERN_DEBUG"\t\tport = %p rphy=%p\n", - port_details->port, port_details->rphy)); + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "\t\tport = %p rphy=%p\n", + ioc->name, port_details->port, port_details->rphy)); } - dsaswideprintk(ioc, printk(KERN_DEBUG"\n")); + dsaswideprintk(ioc, printk("\n")); mutex_unlock(&ioc->sas_topology_mutex); } @@ -573,15 +505,15 @@ static VirtTarget * mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id) { struct scsi_device *sdev; - VirtDevice *vdev; + VirtDevice *vdevice; VirtTarget *vtarget = NULL; shost_for_each_device(sdev, ioc->sh) { - if ((vdev = sdev->hostdata) == NULL) + if ((vdevice = sdev->hostdata) == NULL) continue; - if (vdev->vtarget->id == id && - vdev->vtarget->channel == channel) - vtarget = vdev->vtarget; + if (vdevice->vtarget->id == id && + vdevice->vtarget->channel == channel) + vtarget = vdevice->vtarget; } return vtarget; } @@ -623,13 +555,7 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); - if (mpt_send_handshake_request(ioc->TaskCtx, ioc, - sizeof(SCSITaskMgmt_t), (u32 *)mf, NO_SLEEP)) { - mpt_free_msg_frame(ioc, mf); - dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "%s, tm handshake failed @%d!!\n", - ioc->name,__FUNCTION__, __LINE__)); - return 0; - } + mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); return 1; } @@ -649,7 +575,7 @@ static void mptsas_target_reset_queue(MPT_ADAPTER *ioc, EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + MPT_SCSI_HOST *hd = shost_priv(ioc->sh); VirtTarget *vtarget = NULL; struct mptsas_target_reset_event *target_reset_list; u8 id, channel; @@ -696,7 +622,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc, static void mptsas_dev_reset_complete(MPT_ADAPTER *ioc) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + MPT_SCSI_HOST *hd = shost_priv(ioc->sh); struct list_head *head = &hd->target_reset_list; struct mptsas_target_reset_event *target_reset_list; struct mptsas_hotplug_event *ev; @@ -813,7 +739,7 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) if (!ioc->sh || !ioc->sh->hostdata) goto out; - hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + hd = shost_priv(ioc->sh); if (!hd->ioc) goto out; @@ -913,19 +839,20 @@ static int mptsas_target_alloc(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(&starget->dev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); VirtTarget *vtarget; u8 id, channel; struct sas_rphy *rphy; struct mptsas_portinfo *p; int i; + MPT_ADAPTER *ioc = hd->ioc; vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); if (!vtarget) return -ENOMEM; vtarget->starget = starget; - vtarget->ioc_id = hd->ioc->id; + vtarget->ioc_id = ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; id = starget->id; channel = 0; @@ -934,15 +861,15 @@ mptsas_target_alloc(struct scsi_target *starget) * RAID volumes placed beyond the last expected port. */ if (starget->channel == MPTSAS_RAID_CHANNEL) { - for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) - if (id == hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) - channel = hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; + for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) + if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) + channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; goto out; } rphy = dev_to_rphy(starget->dev.parent); - mutex_lock(&hd->ioc->sas_topology_mutex); - list_for_each_entry(p, &hd->ioc->sas_topology, list) { + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(p, &ioc->sas_topology, list) { for (i = 0; i < p->num_phys; i++) { if (p->phy_info[i].attached.sas_address != rphy->identify.sas_address) @@ -954,18 +881,18 @@ mptsas_target_alloc(struct scsi_target *starget) /* * Exposing hidden raid components */ - if (mptscsih_is_phys_disk(hd->ioc, channel, id)) { - id = mptscsih_raid_id_to_num(hd->ioc, + if (mptscsih_is_phys_disk(ioc, channel, id)) { + id = mptscsih_raid_id_to_num(ioc, channel, id); vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; p->phy_info[i].attached.phys_disk_num = id; } - mutex_unlock(&hd->ioc->sas_topology_mutex); + mutex_unlock(&ioc->sas_topology_mutex); goto out; } } - mutex_unlock(&hd->ioc->sas_topology_mutex); + mutex_unlock(&ioc->sas_topology_mutex); kfree(vtarget); return -ENXIO; @@ -981,10 +908,11 @@ static void mptsas_target_destroy(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(&starget->dev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); struct sas_rphy *rphy; struct mptsas_portinfo *p; int i; + MPT_ADAPTER *ioc = hd->ioc; if (!starget->hostdata) return; @@ -993,7 +921,7 @@ mptsas_target_destroy(struct scsi_target *starget) goto out; rphy = dev_to_rphy(starget->dev.parent); - list_for_each_entry(p, &hd->ioc->sas_topology, list) { + list_for_each_entry(p, &ioc->sas_topology, list) { for (i = 0; i < p->num_phys; i++) { if (p->phy_info[i].attached.sas_address != rphy->identify.sas_address) @@ -1013,61 +941,62 @@ static int mptsas_slave_alloc(struct scsi_device *sdev) { struct Scsi_Host *host = sdev->host; - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); struct sas_rphy *rphy; struct mptsas_portinfo *p; - VirtDevice *vdev; + VirtDevice *vdevice; struct scsi_target *starget; int i; + MPT_ADAPTER *ioc = hd->ioc; - vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdev) { + vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdevice) { printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n", - hd->ioc->name, sizeof(VirtDevice)); + ioc->name, sizeof(VirtDevice)); return -ENOMEM; } starget = scsi_target(sdev); - vdev->vtarget = starget->hostdata; + vdevice->vtarget = starget->hostdata; if (sdev->channel == MPTSAS_RAID_CHANNEL) goto out; rphy = dev_to_rphy(sdev->sdev_target->dev.parent); - mutex_lock(&hd->ioc->sas_topology_mutex); - list_for_each_entry(p, &hd->ioc->sas_topology, list) { + mutex_lock(&ioc->sas_topology_mutex); + list_for_each_entry(p, &ioc->sas_topology, list) { for (i = 0; i < p->num_phys; i++) { if (p->phy_info[i].attached.sas_address != rphy->identify.sas_address) continue; - vdev->lun = sdev->lun; + vdevice->lun = sdev->lun; /* * Exposing hidden raid components */ - if (mptscsih_is_phys_disk(hd->ioc, + if (mptscsih_is_phys_disk(ioc, p->phy_info[i].attached.channel, p->phy_info[i].attached.id)) sdev->no_uld_attach = 1; - mutex_unlock(&hd->ioc->sas_topology_mutex); + mutex_unlock(&ioc->sas_topology_mutex); goto out; } } - mutex_unlock(&hd->ioc->sas_topology_mutex); + mutex_unlock(&ioc->sas_topology_mutex); - kfree(vdev); + kfree(vdevice); return -ENXIO; out: - vdev->vtarget->num_luns++; - sdev->hostdata = vdev; + vdevice->vtarget->num_luns++; + sdev->hostdata = vdevice; return 0; } static int mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - VirtDevice *vdev = SCpnt->device->hostdata; + VirtDevice *vdevice = SCpnt->device->hostdata; - if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) { + if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; @@ -1239,10 +1168,8 @@ static int mptsas_phy_reset(struct sas_phy *phy, int hard_reset) /* process the completed Reply Message Frame */ reply = (SasIoUnitControlReply_t *)ioc->sas_mgmt.reply; if (reply->IOCStatus != MPI_IOCSTATUS_SUCCESS) { - printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", - __FUNCTION__, - reply->IOCStatus, - reply->IOCLogInfo); + printk(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", + ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo); error = -ENXIO; goto out_unlock; } @@ -1328,16 +1255,16 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, u64 sas_address = 0; if (!rsp) { - printk(KERN_ERR "%s: the smp response space is missing\n", - __FUNCTION__); + printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n", + ioc->name, __FUNCTION__); return -EINVAL; } /* do we need to support multiple segments? */ if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { - printk(KERN_ERR "%s: multiple segments req %u %u, rsp %u %u\n", - __FUNCTION__, req->bio->bi_vcnt, req->data_len, - rsp->bio->bi_vcnt, rsp->data_len); + printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n", + ioc->name, __FUNCTION__, req->bio->bi_vcnt, req->data_len, + rsp->bio->bi_vcnt, rsp->data_len); return -EINVAL; } @@ -1402,7 +1329,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, timeleft = wait_for_completion_timeout(&ioc->sas_mgmt.done, 10 * HZ); if (!timeleft) { - printk(KERN_ERR "%s: smp timeout!\n", __FUNCTION__); + printk(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__); /* On timeout reset the board */ mpt_HardResetHandler(ioc, CAN_SLEEP); ret = -ETIMEDOUT; @@ -1417,8 +1344,8 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, memcpy(req->sense, smprep, sizeof(*smprep)); req->sense_len = sizeof(*smprep); } else { - printk(KERN_ERR "%s: smp passthru reply failed to be returned\n", - __FUNCTION__); + printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n", + ioc->name, __FUNCTION__); ret = -ENXIO; } unmap: @@ -2062,12 +1989,12 @@ static int mptsas_probe_one_phy(struct device *dev, goto out; } mptsas_set_port(ioc, phy_info, port); - dsaswideprintk(ioc, printk(KERN_DEBUG + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_alloc: port=%p dev=%p port_id=%d\n", - port, dev, port->port_identifier)); + ioc->name, port, dev, port->port_identifier)); } - dsaswideprintk(ioc, printk(KERN_DEBUG "sas_port_add_phy: phy_id=%d\n", - phy_info->phy_id)); + dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n", + ioc->name, phy_info->phy_id)); sas_port_add_phy(port, phy_info->phy); phy_info->sas_port_add_phy = 0; } @@ -2369,8 +2296,9 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) expander_sas_address) continue; dsaswideprintk(ioc, - dev_printk(KERN_DEBUG, &port->dev, - "delete port (%d)\n", port->port_identifier)); + dev_printk(KERN_DEBUG, &port->dev, + MYIOC_s_FMT "delete port (%d)\n", ioc->name, + port->port_identifier)); sas_port_delete(port); mptsas_port_delete(ioc, phy_info->port_details); } @@ -2613,7 +2541,7 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { - printk(KERN_WARNING "mptsas: lost hotplug event\n"); + printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name); goto out; } @@ -2754,8 +2682,8 @@ mptsas_hotplug_work(struct work_struct *work) printk(MYIOC_s_INFO_FMT "removing %s device, channel %d, id %d, phy %d\n", ioc->name, ds, ev->channel, ev->id, phy_info->phy_id); - dev_printk(KERN_DEBUG, &port->dev, - "delete port (%d)\n", port->port_identifier); + dev_printk(KERN_DEBUG, &port->dev, MYIOC_s_FMT + "delete port (%d)\n", ioc->name, port->port_identifier); sas_port_delete(port); mptsas_port_delete(ioc, phy_info->port_details); break; @@ -2796,8 +2724,8 @@ mptsas_hotplug_work(struct work_struct *work) if (!vtarget) { dfailprintk(ioc, printk(MYIOC_s_ERR_FMT - "%s: exit at line=%d\n", ioc->name, - __FUNCTION__, __LINE__)); + "%s: exit at line=%d\n", ioc->name, + __FUNCTION__, __LINE__)); break; } /* @@ -2930,7 +2858,7 @@ mptsas_send_sas_event(MPT_ADAPTER *ioc, case MPI_EVENT_SAS_DEV_STAT_RC_ADDED: ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { - printk(KERN_WARNING "mptsas: lost hotplug event\n"); + printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name); break; } @@ -2989,7 +2917,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { - printk(KERN_WARNING "mptsas: lost hotplug event\n"); + printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name); return; } @@ -3288,20 +3216,22 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->sg_tablesize = numSGE; } - hd = (MPT_SCSI_HOST *) sh->hostdata; + hd = shost_priv(sh); hd->ioc = ioc; /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); - if (!hd->ScsiLookup) { + ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!ioc->ScsiLookup) { error = -ENOMEM; + spin_unlock_irqrestore(&ioc->FreeQlock, flags); goto out_mptsas_probe; } + spin_lock_init(&ioc->scsi_lookup_lock); dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n", - ioc->name, hd->ScsiLookup)); + ioc->name, ioc->ScsiLookup)); /* Clear the TM flags */ @@ -3340,8 +3270,8 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) error = scsi_add_host(sh, &ioc->pcidev->dev); if (error) { - dprintk(ioc, printk(KERN_ERR MYNAM - "scsi_add_host failed\n")); + dprintk(ioc, printk(MYIOC_s_ERR_FMT + "scsi_add_host failed\n", ioc->name)); goto out_mptsas_probe; } diff --git a/drivers/message/fusion/mptsas.h b/drivers/message/fusion/mptsas.h new file mode 100644 index 000000000000..7c150f50629a --- /dev/null +++ b/drivers/message/fusion/mptsas.h @@ -0,0 +1,158 @@ +/* + * linux/drivers/message/fusion/mptsas.h + * High performance SCSI + LAN / Fibre Channel device drivers. + * For use with PCI chip/adapter(s): + * LSIFC9xx/LSI409xx Fibre Channel + * running LSI MPT (Message Passing Technology) firmware. + * + * Copyright (c) 1999-2007 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; version 2 of the License. + + 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef MPTSAS_H_INCLUDED +#define MPTSAS_H_INCLUDED +/*{-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ + +struct mptsas_target_reset_event { + struct list_head list; + EVENT_DATA_SAS_DEVICE_STATUS_CHANGE sas_event_data; + u8 target_reset_issued; +}; + +enum mptsas_hotplug_action { + MPTSAS_ADD_DEVICE, + MPTSAS_DEL_DEVICE, + MPTSAS_ADD_RAID, + MPTSAS_DEL_RAID, + MPTSAS_ADD_INACTIVE_VOLUME, + MPTSAS_IGNORE_EVENT, +}; + +struct mptsas_hotplug_event { + struct work_struct work; + MPT_ADAPTER *ioc; + enum mptsas_hotplug_action event_type; + u64 sas_address; + u8 channel; + u8 id; + u32 device_info; + u16 handle; + u16 parent_handle; + u8 phy_id; + u8 phys_disk_num_valid; /* hrc (hidden raid component) */ + u8 phys_disk_num; /* hrc - unique index*/ + u8 hidden_raid_component; /* hrc - don't expose*/ +}; + +struct mptsas_discovery_event { + struct work_struct work; + MPT_ADAPTER *ioc; +}; + +/* + * SAS topology structures + * + * The MPT Fusion firmware interface spreads information about the + * SAS topology over many manufacture pages, thus we need some data + * structure to collect it and process it for the SAS transport class. + */ + +struct mptsas_devinfo { + u16 handle; /* unique id to address this device */ + u16 handle_parent; /* unique id to address parent device */ + u16 handle_enclosure; /* enclosure identifier of the enclosure */ + u16 slot; /* physical slot in enclosure */ + u8 phy_id; /* phy number of parent device */ + u8 port_id; /* sas physical port this device + is assoc'd with */ + u8 id; /* logical target id of this device */ + u32 phys_disk_num; /* phys disk id, for csmi-ioctls */ + u8 channel; /* logical bus number of this device */ + u64 sas_address; /* WWN of this device, + SATA is assigned by HBA,expander */ + u32 device_info; /* bitfield detailed info about this device */ +}; + +/* + * Specific details on ports, wide/narrow + */ +struct mptsas_portinfo_details{ + u16 num_phys; /* number of phys belong to this port */ + u64 phy_bitmask; /* TODO, extend support for 255 phys */ + struct sas_rphy *rphy; /* transport layer rphy object */ + struct sas_port *port; /* transport layer port object */ + struct scsi_target *starget; + struct mptsas_portinfo *port_info; +}; + +struct mptsas_phyinfo { + u16 handle; /* unique id to address this */ + u8 phy_id; /* phy index */ + u8 port_id; /* firmware port identifier */ + u8 negotiated_link_rate; /* nego'd link rate for this phy */ + u8 hw_link_rate; /* hardware max/min phys link rate */ + u8 programmed_link_rate; /* programmed max/min phy link rate */ + u8 sas_port_add_phy; /* flag to request sas_port_add_phy*/ + struct mptsas_devinfo identify; /* point to phy device info */ + struct mptsas_devinfo attached; /* point to attached device info */ + struct sas_phy *phy; /* transport layer phy object */ + struct mptsas_portinfo *portinfo; + struct mptsas_portinfo_details * port_details; +}; + +struct mptsas_portinfo { + struct list_head list; + u16 num_phys; /* number of phys */ + struct mptsas_phyinfo *phy_info; +}; + +struct mptsas_enclosure { + u64 enclosure_logical_id; /* The WWN for the enclosure */ + u16 enclosure_handle; /* unique id to address this */ + u16 flags; /* details enclosure management */ + u16 num_slot; /* num slots */ + u16 start_slot; /* first slot */ + u8 start_id; /* starting logical target id */ + u8 start_channel; /* starting logical channel id */ + u8 sep_id; /* SEP device logical target id */ + u8 sep_channel; /* SEP channel logical channel id */ +}; + +/*}-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ +#endif diff --git a/drivers/message/fusion/mptscsih.c b/drivers/message/fusion/mptscsih.c index 5431529741ad..bdff950a54a1 100644 --- a/drivers/message/fusion/mptscsih.c +++ b/drivers/message/fusion/mptscsih.c @@ -1,9 +1,9 @@ /* * linux/drivers/message/fusion/mptscsih.c - * For use with LSI Logic PCI chip/adapter(s) - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * For use with LSI PCI chip/adapter(s) + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -80,6 +80,10 @@ MODULE_VERSION(my_VERSION); /* * Other private/forward protos... */ +static struct scsi_cmnd * mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i); +static struct scsi_cmnd * mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i); +static void mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd); +static int SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *scmd); int mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); static void mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSIIORequest_t *pScsiReq); int mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *r); @@ -90,7 +94,6 @@ static void mptscsih_freeChainBuffers(MPT_ADAPTER *ioc, int req_idx); static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply); static int mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd); static int mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ); -static int SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc); static int mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int ctx2abort, ulong timeout); @@ -192,7 +195,7 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex) int chain_idx; dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer called\n", - ioc->name)); + ioc->name)); spin_lock_irqsave(&ioc->FreeQlock, flags); if (!list_empty(&ioc->FreeChainQ)) { int offset; @@ -203,13 +206,14 @@ mptscsih_getFreeChainBuffer(MPT_ADAPTER *ioc, int *retIndex) offset = (u8 *)chainBuf - (u8 *)ioc->ChainBuffer; chain_idx = offset / ioc->req_sz; rc = SUCCESS; - dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n", - ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx)); + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "getFreeChainBuffer chainBuf=%p ChainBuffer=%p offset=%d chain_idx=%d\n", + ioc->name, chainBuf, ioc->ChainBuffer, offset, chain_idx)); } else { rc = FAILED; chain_idx = MPT_HOST_NO_CHAIN; - dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer failed\n", - ioc->name)); + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "getFreeChainBuffer failed\n", + ioc->name)); } spin_unlock_irqrestore(&ioc->FreeQlock, flags); @@ -419,8 +423,8 @@ nextSGEset: * out the Address and Flags fields. */ chainSge = (char *) psge; - dsgprintk(ioc, printk(KERN_DEBUG " Current buff @ %p (index 0x%x)", - psge, req_idx)); + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Current buff @ %p (index 0x%x)", + ioc->name, psge, req_idx)); /* Start the SGE for the next buffer */ @@ -428,8 +432,8 @@ nextSGEset: sgeOffset = 0; sg_done = 0; - dsgprintk(ioc, printk(KERN_DEBUG " Chain buff @ %p (index 0x%x)\n", - psge, chain_idx)); + dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Chain buff @ %p (index 0x%x)\n", + ioc->name, psge, chain_idx)); /* Start the SGE for the next buffer */ @@ -588,18 +592,17 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc } scsi_print_command(sc); - printk(KERN_DEBUG "\tfw_channel = %d, fw_id = %d\n", - pScsiReply->Bus, pScsiReply->TargetID); - printk(KERN_DEBUG "\trequest_len = %d, underflow = %d, resid = %d\n", - scsi_bufflen(sc), sc->underflow, scsi_get_resid(sc)); - printk(KERN_DEBUG "\ttag = %d, transfer_count = %d, sc->result = %08X\n", - le16_to_cpu(pScsiReply->TaskTag), + printk(MYIOC_s_DEBUG_FMT "\tfw_channel = %d, fw_id = %d\n", + ioc->name, pScsiReply->Bus, pScsiReply->TargetID); + printk(MYIOC_s_DEBUG_FMT "\trequest_len = %d, underflow = %d, " + "resid = %d\n", ioc->name, scsi_bufflen(sc), sc->underflow, + scsi_get_resid(sc)); + printk(MYIOC_s_DEBUG_FMT "\ttag = %d, transfer_count = %d, " + "sc->result = %08X\n", ioc->name, le16_to_cpu(pScsiReply->TaskTag), le32_to_cpu(pScsiReply->TransferCount), sc->result); - - printk(KERN_DEBUG "\tiocstatus = %s (0x%04x), " + printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), " "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n", - desc, ioc_status, - desc1, pScsiReply->SCSIStatus, + ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus, pScsiReply->SCSIState); if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { @@ -607,9 +610,8 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc asc = sc->sense_buffer[12]; ascq = sc->sense_buffer[13]; - printk(KERN_DEBUG "\t[sense_key,asc,ascq]: " - "[0x%02x,0x%02x,0x%02x]\n", - skey, asc, ascq); + printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: " + "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq); } /* @@ -617,8 +619,8 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc */ if (pScsiReply->SCSIState & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) - printk(KERN_DEBUG "response_info = %08xh\n", - le32_to_cpu(pScsiReply->ResponseInfo)); + printk(MYIOC_s_DEBUG_FMT "response_info = %08xh\n", + ioc->name, le32_to_cpu(pScsiReply->ResponseInfo)); } #endif @@ -645,11 +647,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) SCSIIORequest_t *pScsiReq; SCSIIOReply_t *pScsiReply; u16 req_idx, req_idx_MR; - VirtDevice *vdev; + VirtDevice *vdevice; VirtTarget *vtarget; - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; - + hd = shost_priv(ioc->sh); req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); req_idx_MR = (mr != NULL) ? le16_to_cpu(mr->u.frame.hwhdr.msgctxu.fld.req_idx) : req_idx; @@ -660,12 +661,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) printk (MYIOC_s_ERR_FMT "req_idx=%x req_idx_MR=%x mf=%p mr=%p sc=%p\n", ioc->name, req_idx, req_idx_MR, mf, mr, - hd->ScsiLookup[req_idx_MR]); + mptscsih_get_scsi_lookup(ioc, req_idx_MR)); return 0; } - sc = hd->ScsiLookup[req_idx]; - hd->ScsiLookup[req_idx] = NULL; + sc = mptscsih_getclear_scsi_lookup(ioc, req_idx); if (sc == NULL) { MPIHeader_t *hdr = (MPIHeader_t *)mf; @@ -738,8 +738,8 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ if (scsi_state & MPI_SCSI_STATE_RESPONSE_INFO_VALID && pScsiReply->ResponseInfo) { - printk(KERN_NOTICE "[%d:%d:%d:%d] " - "FCP_ResponseInfo=%08xh\n", + printk(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] " + "FCP_ResponseInfo=%08xh\n", ioc->name, sc->device->host->host_no, sc->device->channel, sc->device->id, sc->device->lun, le32_to_cpu(pScsiReply->ResponseInfo)); @@ -771,10 +771,10 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) if (hd->sel_timeout[pScsiReq->TargetID] < 0xFFFF) hd->sel_timeout[pScsiReq->TargetID]++; - vdev = sc->device->hostdata; - if (!vdev) + vdevice = sc->device->hostdata; + if (!vdevice) break; - vtarget = vdev->vtarget; + vtarget = vdevice->vtarget; if (vtarget->tflags & MPT_TARGET_FLAGS_LED_ON) { mptscsih_issue_sep_command(ioc, vtarget, MPI_SEP_REQ_SLOTSTATUS_UNCONFIGURED); @@ -824,9 +824,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) sc->result=DID_SOFT_ERROR << 16; else /* Sufficient data transfer occurred */ sc->result = (DID_OK << 16) | scsi_status; - dreplyprintk(ioc, printk(KERN_DEBUG + dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n", - sc->result, sc->device->channel, sc->device->id)); + ioc->name, sc->result, sc->device->channel, sc->device->id)); break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ @@ -858,9 +858,11 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } - dreplyprintk(ioc, printk(KERN_DEBUG " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", - sc->underflow)); - dreplyprintk(ioc, printk(KERN_DEBUG " ActBytesXferd=%02xh\n", xfer_cnt)); + dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT + " sc->underflow={report ERR if < %02xh bytes xfer'd}\n", + ioc->name, sc->underflow)); + dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT + " ActBytesXferd=%02xh\n", ioc->name, xfer_cnt)); /* Report Queue Full */ @@ -969,48 +971,32 @@ static void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) { MPT_ADAPTER *ioc = hd->ioc; - struct scsi_cmnd *SCpnt; - MPT_FRAME_HDR *mf; + struct scsi_cmnd *sc; + SCSIIORequest_t *mf = NULL; int ii; - int max = ioc->req_depth; - - dprintk(ioc, printk(KERN_DEBUG MYNAM ": flush_ScsiLookup called\n")); - for (ii= 0; ii < max; ii++) { - if ((SCpnt = hd->ScsiLookup[ii]) != NULL) { - - /* Command found. - */ - - /* Null ScsiLookup index - */ - hd->ScsiLookup[ii] = NULL; - - mf = MPT_INDEX_2_MFPTR(ioc, ii); - dmfprintk(ioc, printk(KERN_DEBUG MYNAM ": flush: ScsiDone (mf=%p,sc=%p)\n", - mf, SCpnt)); - - /* Free Chain buffers */ - mptscsih_freeChainBuffers(ioc, ii); - - /* Free Message frames */ - mpt_free_msg_frame(ioc, mf); - - if ((unsigned char *)mf != SCpnt->host_scribble) - continue; - - /* Set status, free OS resources (SG DMA buffers) - * Do OS callback - */ - scsi_dma_unmap(SCpnt); - - SCpnt->result = DID_RESET << 16; - SCpnt->host_scribble = NULL; + int channel, id; - SCpnt->scsi_done(SCpnt); /* Issue the command callback */ - } + for (ii= 0; ii < ioc->req_depth; ii++) { + sc = mptscsih_getclear_scsi_lookup(ioc, ii); + if (!sc) + continue; + mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); + if (!mf) + continue; + channel = mf->Bus; + id = mf->TargetID; + mptscsih_freeChainBuffers(ioc, ii); + mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); + if ((unsigned char *)mf != sc->host_scribble) + continue; + scsi_dma_unmap(sc); + sc->result = DID_RESET << 16; + sc->host_scribble = NULL; + sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT + "completing cmds: fw_channel %d, fw_id %d, sc=%p," + " mf = %p, idx=%x\n", ioc->name, channel, id, sc, mf, ii); + sc->scsi_done(sc); } - - return; } /* @@ -1032,17 +1018,16 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) { SCSIIORequest_t *mf = NULL; int ii; - int max = hd->ioc->req_depth; struct scsi_cmnd *sc; struct scsi_lun lun; + MPT_ADAPTER *ioc = hd->ioc; + unsigned long flags; - dsprintk(hd->ioc, printk(KERN_DEBUG MYNAM ": search_running channel %d id %d lun %d max %d\n", - vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, max)); - - for (ii=0; ii < max; ii++) { - if ((sc = hd->ScsiLookup[ii]) != NULL) { + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + for (ii = 0; ii < ioc->req_depth; ii++) { + if ((sc = ioc->ScsiLookup[ii]) != NULL) { - mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); + mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); if (mf == NULL) continue; /* If the device is a hidden raid component, then its @@ -1059,22 +1044,23 @@ mptscsih_search_running_cmds(MPT_SCSI_HOST *hd, VirtDevice *vdevice) memcmp(lun.scsi_lun, mf->LUN, 8)) continue; - /* Cleanup - */ - hd->ScsiLookup[ii] = NULL; - mptscsih_freeChainBuffers(hd->ioc, ii); - mpt_free_msg_frame(hd->ioc, (MPT_FRAME_HDR *)mf); if ((unsigned char *)mf != sc->host_scribble) continue; + ioc->ScsiLookup[ii] = NULL; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + mptscsih_freeChainBuffers(ioc, ii); + mpt_free_msg_frame(ioc, (MPT_FRAME_HDR *)mf); scsi_dma_unmap(sc); sc->host_scribble = NULL; sc->result = DID_NO_CONNECT << 16; - sdev_printk(KERN_INFO, sc->device, "completing cmds: fw_channel %d," - "fw_id %d, sc=%p, mf = %p, idx=%x\n", vdevice->vtarget->channel, + sdev_printk(KERN_INFO, sc->device, MYIOC_s_FMT "completing cmds: fw_channel %d," + "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel, vdevice->vtarget->id, sc, mf, ii); sc->scsi_done(sc); + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); } } + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); return; } @@ -1097,17 +1083,18 @@ mptscsih_report_queue_full(struct scsi_cmnd *sc, SCSIIOReply_t *pScsiReply, SCSI { long time = jiffies; MPT_SCSI_HOST *hd; + MPT_ADAPTER *ioc; if (sc->device == NULL) return; if (sc->device->host == NULL) return; - if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL) + if ((hd = shost_priv(sc->device->host)) == NULL) return; - + ioc = hd->ioc; if (time - hd->last_queue_full > 10 * HZ) { - dprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", - hd->ioc->name, 0, sc->device->id, sc->device->lun)); + dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", + ioc->name, 0, sc->device->id, sc->device->lun)); hd->last_queue_full = time; } } @@ -1134,28 +1121,28 @@ mptscsih_remove(struct pci_dev *pdev) scsi_remove_host(host); - if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) + if((hd = shost_priv(host)) == NULL) return; mptscsih_shutdown(pdev); sz1=0; - if (hd->ScsiLookup != NULL) { - sz1 = hd->ioc->req_depth * sizeof(void *); - kfree(hd->ScsiLookup); - hd->ScsiLookup = NULL; + if (ioc->ScsiLookup != NULL) { + sz1 = ioc->req_depth * sizeof(void *); + kfree(ioc->ScsiLookup); + ioc->ScsiLookup = NULL; } - dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Free'd ScsiLookup (%d) memory\n", - hd->ioc->name, sz1)); + ioc->name, sz1)); kfree(hd->info_kbuf); /* NULL the Scsi_Host pointer */ - hd->ioc->sh = NULL; + ioc->sh = NULL; scsi_host_put(host); @@ -1171,15 +1158,6 @@ mptscsih_remove(struct pci_dev *pdev) void mptscsih_shutdown(struct pci_dev *pdev) { - MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - struct Scsi_Host *host = ioc->sh; - MPT_SCSI_HOST *hd; - - if(!host) - return; - - hd = (MPT_SCSI_HOST *)host->hostdata; - } #ifdef CONFIG_PM @@ -1225,7 +1203,7 @@ mptscsih_info(struct Scsi_Host *SChost) MPT_SCSI_HOST *h; int size = 0; - h = (MPT_SCSI_HOST *)SChost->hostdata; + h = shost_priv(SChost); if (h) { if (h->info_kbuf == NULL) @@ -1319,7 +1297,7 @@ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; int size = 0; @@ -1358,7 +1336,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; SCSIIORequest_t *pScsiReq; - VirtDevice *vdev = SCpnt->device->hostdata; + VirtDevice *vdevice = SCpnt->device->hostdata; int lun; u32 datalen; u32 scsictl; @@ -1368,7 +1346,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) int ii; MPT_ADAPTER *ioc; - hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; + hd = shost_priv(SCpnt->device->host); ioc = hd->ioc; lun = SCpnt->device->lun; SCpnt->scsi_done = done; @@ -1385,7 +1363,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* * Put together a MPT SCSI request... */ - if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", ioc->name)); return SCSI_MLQUEUE_HOST_BUSY; @@ -1415,8 +1393,8 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Default to untagged. Once a target structure has been allocated, * use the Inquiry data to determine if device supports tagged. */ - if (vdev - && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) + if (vdevice + && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) && (SCpnt->device->tagged_supported)) { scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; } else { @@ -1425,10 +1403,10 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* Use the above information to set up the message frame */ - pScsiReq->TargetID = (u8) vdev->vtarget->id; - pScsiReq->Bus = vdev->vtarget->channel; + pScsiReq->TargetID = (u8) vdevice->vtarget->id; + pScsiReq->Bus = vdevice->vtarget->channel; pScsiReq->ChainOffset = 0; - if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) + if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; else pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; @@ -1453,7 +1431,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) pScsiReq->DataLength = cpu_to_le32(datalen); /* SenseBuffer low address */ - pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma + pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + (my_idx * MPT_SENSE_BUFFER_ALLOC)); /* Now add the SG list @@ -1465,23 +1443,22 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) (dma_addr_t) -1); } else { /* Add a 32 or 64 bit SGE */ - if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) + if (mptscsih_AddSGE(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) goto fail; } SCpnt->host_scribble = (unsigned char *)mf; - hd->ScsiLookup[my_idx] = SCpnt; + mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt); - mpt_put_msg_frame(hd->ioc->DoneCtx, hd->ioc, mf); + mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Issued SCSI cmd (%p) mf=%p idx=%d\n", ioc->name, SCpnt, mf, my_idx)); - DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf) + DBG_DUMP_REQUEST_FRAME(ioc, (u32 *)mf); return 0; fail: - hd->ScsiLookup[my_idx] = NULL; - mptscsih_freeChainBuffers(hd->ioc, my_idx); - mpt_free_msg_frame(hd->ioc, mf); + mptscsih_freeChainBuffers(ioc, my_idx); + mpt_free_msg_frame(ioc, mf); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1590,38 +1567,38 @@ mptscsih_TMHandler(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, int c */ if (mptscsih_tm_pending_wait(hd) == FAILED) { if (type == MPI_SCSITASKMGMT_TASKTYPE_ABORT_TASK) { - dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler abort: " + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler abort: " "Timed out waiting for last TM (%d) to complete! \n", ioc->name, hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET) { - dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler target " + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler target " "reset: Timed out waiting for last TM (%d) " "to complete! \n", ioc->name, hd->tmPending)); return FAILED; } else if (type == MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS) { - dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler bus reset: " + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "TMHandler bus reset: " "Timed out waiting for last TM (%d) to complete! \n", ioc->name, hd->tmPending)); return FAILED; } } else { - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + spin_lock_irqsave(&ioc->FreeQlock, flags); hd->tmPending |= (1 << type); - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); } - ioc_raw_state = mpt_GetIocState(hd->ioc, 0); + ioc_raw_state = mpt_GetIocState(ioc, 0); if ((ioc_raw_state & MPI_IOC_STATE_MASK) != MPI_IOC_STATE_OPERATIONAL) { printk(MYIOC_s_WARN_FMT "TM Handler for type=%x: IOC Not operational (0x%x)!\n", ioc->name, type, ioc_raw_state); - printk(KERN_WARNING " Issuing HardReset!!\n"); + printk(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name); if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) - printk((KERN_WARNING "TMHandler: HardReset " - "FAILED!!\n")); + printk(MYIOC_s_WARN_FMT "TMHandler: HardReset " + "FAILED!!\n", ioc->name); return FAILED; } @@ -1680,16 +1657,17 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i SCSITaskMgmt_t *pScsiTm; int ii; int retval; + MPT_ADAPTER *ioc = hd->ioc; /* Return Fail to calling function if no message frames available. */ - if ((mf = mpt_get_msg_frame(hd->ioc->TaskCtx, hd->ioc)) == NULL) { - dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", - hd->ioc->name)); + if ((mf = mpt_get_msg_frame(ioc->TaskCtx, ioc)) == NULL) { + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", + ioc->name)); return FAILED; } - dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", - hd->ioc->name, mf)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", + ioc->name, mf)); /* Format the Request */ @@ -1712,28 +1690,34 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i pScsiTm->TaskMsgContext = ctx2abort; - dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " - "type=%d\n", hd->ioc->name, ctx2abort, type)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " + "type=%d\n", ioc->name, ctx2abort, type)); DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); - if ((retval = mpt_send_handshake_request(hd->ioc->TaskCtx, hd->ioc, - sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP)) != 0) { - dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!" - " (hd %p, ioc %p, mf %p, rc=%d) \n", hd->ioc->name, hd, - hd->ioc, mf, retval)); - goto fail_out; + if ((ioc->facts.IOCCapabilities & MPI_IOCFACTS_CAPABILITY_HIGH_PRI_Q) && + (ioc->facts.MsgVersion >= MPI_VERSION_01_05)) + mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, mf); + else { + retval = mpt_send_handshake_request(ioc->TaskCtx, ioc, + sizeof(SCSITaskMgmt_t), (u32*)pScsiTm, CAN_SLEEP); + if (retval) { + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "send_handshake FAILED!" + " (hd %p, ioc %p, mf %p, rc=%d) \n", ioc->name, hd, + ioc, mf, retval)); + goto fail_out; + } } if(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { - dfailprintk(hd->ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!" - " (hd %p, ioc %p, mf %p) \n", hd->ioc->name, hd, - hd->ioc, mf)); - dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", - hd->ioc->name)); - retval = mpt_HardResetHandler(hd->ioc, CAN_SLEEP); - dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n", - hd->ioc->name, retval)); + dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "task management request TIMED OUT!" + " (hd %p, ioc %p, mf %p) \n", ioc->name, hd, + ioc, mf)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling HardReset! \n", + ioc->name)); + retval = mpt_HardResetHandler(ioc, CAN_SLEEP); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "rc=%d \n", + ioc->name, retval)); goto fail_out; } @@ -1754,7 +1738,7 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i /* * Free task managment mf, and corresponding tm flags */ - mpt_free_msg_frame(hd->ioc, mf); + mpt_free_msg_frame(ioc, mf); hd->tmPending = 0; hd->tmState = TM_STATE_NONE; return FAILED; @@ -1797,11 +1781,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* If we can't locate our host adapter structure, return FAILED status. */ - if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) { + if ((hd = shost_priv(SCpnt->device->host)) == NULL) { SCpnt->result = DID_RESET << 16; SCpnt->scsi_done(SCpnt); - printk(KERN_DEBUG MYNAM ": mptscsih_abort: Can't locate " - "host! (sc=%p)\n", SCpnt); + printk(KERN_ERR MYNAM ": task abort: " + "can't locate host! (sc=%p)\n", SCpnt); return FAILED; } @@ -1812,8 +1796,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdevice = SCpnt->device->hostdata; if (!vdevice || !vdevice->vtarget) { - dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: device has been " - "deleted (sc=%p)\n", ioc->name, SCpnt)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "task abort: device has been deleted (sc=%p)\n", + ioc->name, SCpnt)); SCpnt->result = DID_NO_CONNECT << 16; SCpnt->scsi_done(SCpnt); retval = 0; @@ -1823,8 +1808,9 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* Task aborts are not supported for hidden raid components. */ if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) { - dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: hidden raid " - "component (sc=%p)\n", ioc->name, SCpnt)); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "task abort: hidden raid component (sc=%p)\n", + ioc->name, SCpnt)); SCpnt->result = DID_RESET << 16; retval = FAILED; goto out; @@ -1832,12 +1818,12 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* Find this command */ - if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { + if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) { /* Cmd not found in ScsiLookup. * Do OS callback. */ SCpnt->result = DID_RESET << 16; - dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: mptscsih_abort: " + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: " "Command not in the active list! (sc=%p)\n", ioc->name, SCpnt)); retval = 0; @@ -1859,7 +1845,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) * swap it here either. It is an opaque cookie to * the controller, so it does not matter. -DaveM */ - mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); + mf = MPT_INDEX_2_MFPTR(ioc, scpnt_idx); ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; hd->abortSCpnt = SCpnt; @@ -1868,7 +1854,7 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) vdevice->vtarget->channel, vdevice->vtarget->id, vdevice->lun, ctx2abort, mptscsih_get_tm_timeout(ioc)); - if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && + if (SCPNT_TO_LOOKUP_IDX(ioc, SCpnt) == scpnt_idx && SCpnt->serial_number == sn) retval = FAILED; @@ -1901,9 +1887,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) /* If we can't locate our host adapter structure, return FAILED status. */ - if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - printk(KERN_DEBUG MYNAM ": mptscsih_dev_reset: Can't " - "locate host! (sc=%p)\n", SCpnt); + if ((hd = shost_priv(SCpnt->device->host)) == NULL){ + printk(KERN_ERR MYNAM ": target reset: " + "Can't locate host! (sc=%p)\n", SCpnt); return FAILED; } @@ -1959,14 +1945,14 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; int retval; - VirtDevice *vdev; + VirtDevice *vdevice; MPT_ADAPTER *ioc; /* If we can't locate our host adapter structure, return FAILED status. */ - if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - printk(KERN_DEBUG MYNAM ": mptscsih_bus_reset: Can't " - "locate host! (sc=%p)\n", SCpnt ); + if ((hd = shost_priv(SCpnt->device->host)) == NULL){ + printk(KERN_ERR MYNAM ": bus reset: " + "Can't locate host! (sc=%p)\n", SCpnt); return FAILED; } @@ -1978,9 +1964,9 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) if (hd->timeouts < -1) hd->timeouts++; - vdev = SCpnt->device->hostdata; + vdevice = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdev->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc)); + vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc)); printk(MYIOC_s_INFO_FMT "bus reset: %s (sc=%p)\n", ioc->name, ((retval == 0) ? "SUCCESS" : "FAILED" ), SCpnt); @@ -2008,9 +1994,9 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) MPT_ADAPTER *ioc; /* If we can't locate the host to reset, then we failed. */ - if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL){ - printk( KERN_DEBUG MYNAM ": mptscsih_host_reset: Can't " - "locate host! (sc=%p)\n", SCpnt); + if ((hd = shost_priv(SCpnt->device->host)) == NULL){ + printk(KERN_ERR MYNAM ": host reset: " + "Can't locate host! (sc=%p)\n", SCpnt); return FAILED; } @@ -2021,7 +2007,7 @@ mptscsih_host_reset(struct scsi_cmnd *SCpnt) /* If our attempts to reset the host failed, then return a failed * status. The host will be taken off line by the SCSI mid-layer. */ - if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) { + if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) { retval = FAILED; } else { /* Make sure TM pending is cleared and TM state is set to @@ -2051,17 +2037,18 @@ mptscsih_tm_pending_wait(MPT_SCSI_HOST * hd) unsigned long flags; int loop_count = 4 * 10; /* Wait 10 seconds */ int status = FAILED; + MPT_ADAPTER *ioc = hd->ioc; do { - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + spin_lock_irqsave(&ioc->FreeQlock, flags); if (hd->tmState == TM_STATE_NONE) { hd->tmState = TM_STATE_IN_PROGRESS; hd->tmPending = 1; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); status = SUCCESS; break; } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); msleep(250); } while (--loop_count); @@ -2082,15 +2069,16 @@ mptscsih_tm_wait_for_completion(MPT_SCSI_HOST * hd, ulong timeout ) unsigned long flags; int loop_count = 4 * timeout; int status = FAILED; + MPT_ADAPTER *ioc = hd->ioc; do { - spin_lock_irqsave(&hd->ioc->FreeQlock, flags); + spin_lock_irqsave(&ioc->FreeQlock, flags); if(hd->tmPending == 0) { status = SUCCESS; - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); break; } - spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); + spin_unlock_irqrestore(&ioc->FreeQlock, flags); msleep(250); } while (--loop_count); @@ -2172,7 +2160,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m return 1; } - hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; + hd = shost_priv(ioc->sh); pScsiTmReply = (SCSITaskMgmtReply_t*)mr; pScsiTmReq = (SCSITaskMgmt_t*)mf; tmType = pScsiTmReq->TaskType; @@ -2223,7 +2211,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m if (iocstatus == MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED || hd->cmdPtr) if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) - printk((KERN_WARNING " Firmware Reload FAILED!!\n")); + printk(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name); break; case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: @@ -2366,7 +2354,7 @@ void mptscsih_slave_destroy(struct scsi_device *sdev) { struct Scsi_Host *host = sdev->host; - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); VirtTarget *vtarget; VirtDevice *vdevice; struct scsi_target *starget; @@ -2393,16 +2381,17 @@ mptscsih_slave_destroy(struct scsi_device *sdev) int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(sdev->host); VirtTarget *vtarget; struct scsi_target *starget; int max_depth; int tagged; + MPT_ADAPTER *ioc = hd->ioc; starget = scsi_target(sdev); vtarget = starget->hostdata; - if (hd->ioc->bus_type == SPI) { + if (ioc->bus_type == SPI) { if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) max_depth = 1; else if (sdev->type == TYPE_DISK && @@ -2437,19 +2426,20 @@ mptscsih_slave_configure(struct scsi_device *sdev) VirtTarget *vtarget; VirtDevice *vdevice; struct scsi_target *starget; - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata; + MPT_SCSI_HOST *hd = shost_priv(sh); + MPT_ADAPTER *ioc = hd->ioc; starget = scsi_target(sdev); vtarget = starget->hostdata; vdevice = sdev->hostdata; - dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT + dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "device @ %p, channel=%d, id=%d, lun=%d\n", - hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); - if (hd->ioc->bus_type == SPI) - dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT + ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); + if (ioc->bus_type == SPI) + dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sdtr %d wdtr %d ppr %d inq length=%d\n", - hd->ioc->name, sdev->sdtr, sdev->wdtr, + ioc->name, sdev->sdtr, sdev->wdtr, sdev->ppr, sdev->inquiry_len)); if (sdev->id > sh->max_id) { @@ -2461,21 +2451,21 @@ mptscsih_slave_configure(struct scsi_device *sdev) vdevice->configured_lun = 1; mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); - dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT + dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Queue depth=%d, tflags=%x\n", - hd->ioc->name, sdev->queue_depth, vtarget->tflags)); + ioc->name, sdev->queue_depth, vtarget->tflags)); - if (hd->ioc->bus_type == SPI) - dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT + if (ioc->bus_type == SPI) + dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n", - hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset, + ioc->name, vtarget->negoFlags, vtarget->maxOffset, vtarget->minSyncFactor)); slave_configure_exit: - dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT + dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "tagged %d, simple %d, ordered %d\n", - hd->ioc->name,sdev->tagged_supported, sdev->simple_tags, + ioc->name,sdev->tagged_supported, sdev->simple_tags, sdev->ordered_tags)); return 0; @@ -2494,14 +2484,15 @@ slave_configure_exit: static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply) { - VirtDevice *vdev; + VirtDevice *vdevice; SCSIIORequest_t *pReq; u32 sense_count = le32_to_cpu(pScsiReply->SenseCount); + MPT_ADAPTER *ioc = hd->ioc; /* Get target structure */ pReq = (SCSIIORequest_t *) mf; - vdev = sc->device->hostdata; + vdevice = sc->device->hostdata; if (sense_count) { u8 *sense_data; @@ -2509,15 +2500,14 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR /* Copy the sense received into the scsi command block. */ req_index = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - sense_data = ((u8 *)hd->ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); + sense_data = ((u8 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); memcpy(sc->sense_buffer, sense_data, SNS_LEN(sc)); /* Log SMART data (asc = 0x5D, non-IM case only) if required. */ - if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { - if ((sense_data[12] == 0x5D) && (vdev->vtarget->raidVolume == 0)) { + if ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { + if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) { int idx; - MPT_ADAPTER *ioc = hd->ioc; idx = ioc->eventContext % MPTCTL_EVENT_LOG_SIZE; ioc->events[idx].event = MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE; @@ -2530,36 +2520,116 @@ mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR ioc->events[idx].data[1] = (sense_data[13] << 8) | sense_data[12]; ioc->eventContext++; - if (hd->ioc->pcidev->vendor == + if (ioc->pcidev->vendor == PCI_VENDOR_ID_IBM) { - mptscsih_issue_sep_command(hd->ioc, - vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); - vdev->vtarget->tflags |= + mptscsih_issue_sep_command(ioc, + vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); + vdevice->vtarget->tflags |= MPT_TARGET_FLAGS_LED_ON; } } } } else { - dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n", - hd->ioc->name)); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n", + ioc->name)); } } -static int -SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) +/** + * mptscsih_get_scsi_lookup + * + * retrieves scmd entry from ScsiLookup[] array list + * + * @ioc: Pointer to MPT_ADAPTER structure + * @i: index into the array + * + * Returns the scsi_cmd pointer + * + **/ +static struct scsi_cmnd * +mptscsih_get_scsi_lookup(MPT_ADAPTER *ioc, int i) { - MPT_SCSI_HOST *hd; - int i; + unsigned long flags; + struct scsi_cmnd *scmd; - hd = (MPT_SCSI_HOST *) sc->device->host->hostdata; + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + scmd = ioc->ScsiLookup[i]; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + + return scmd; +} + +/** + * mptscsih_getclear_scsi_lookup + * + * retrieves and clears scmd entry from ScsiLookup[] array list + * + * @ioc: Pointer to MPT_ADAPTER structure + * @i: index into the array + * + * Returns the scsi_cmd pointer + * + **/ +static struct scsi_cmnd * +mptscsih_getclear_scsi_lookup(MPT_ADAPTER *ioc, int i) +{ + unsigned long flags; + struct scsi_cmnd *scmd; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + scmd = ioc->ScsiLookup[i]; + ioc->ScsiLookup[i] = NULL; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + + return scmd; +} - for (i = 0; i < hd->ioc->req_depth; i++) { - if (hd->ScsiLookup[i] == sc) { - return i; +/** + * mptscsih_set_scsi_lookup + * + * writes a scmd entry into the ScsiLookup[] array list + * + * @ioc: Pointer to MPT_ADAPTER structure + * @i: index into the array + * @scmd: scsi_cmnd pointer + * + **/ +static void +mptscsih_set_scsi_lookup(MPT_ADAPTER *ioc, int i, struct scsi_cmnd *scmd) +{ + unsigned long flags; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + ioc->ScsiLookup[i] = scmd; + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); +} + +/** + * SCPNT_TO_LOOKUP_IDX + * + * search's for a given scmd in the ScsiLookup[] array list + * + * @ioc: Pointer to MPT_ADAPTER structure + * @scmd: scsi_cmnd pointer + * + **/ +static int +SCPNT_TO_LOOKUP_IDX(MPT_ADAPTER *ioc, struct scsi_cmnd *sc) +{ + unsigned long flags; + int i, index=-1; + + spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); + for (i = 0; i < ioc->req_depth; i++) { + if (ioc->ScsiLookup[i] == sc) { + index = i; + goto out; } } - return -1; + out: + spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); + return index; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2568,21 +2638,20 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { MPT_SCSI_HOST *hd; unsigned long flags; - int ii; - dtmprintk(ioc, printk(KERN_DEBUG MYNAM - ": IOC %s_reset routed to SCSI host driver!\n", - reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( - reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); + dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT + ": IOC %s_reset routed to SCSI host driver!\n", + ioc->name, reset_phase==MPT_IOC_SETUP_RESET ? "setup" : ( + reset_phase==MPT_IOC_PRE_RESET ? "pre" : "post"))); /* If a FW reload request arrives after base installed but * before all scsi hosts have been attached, then an alt_ioc * may have a NULL sh pointer. */ - if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL)) + if (ioc->sh == NULL || shost_priv(ioc->sh) == NULL) return 0; else - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + hd = shost_priv(ioc->sh); if (reset_phase == MPT_IOC_SETUP_RESET) { dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name)); @@ -2624,11 +2693,6 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) * Init all control structures. */ - /* ScsiLookup initialization - */ - for (ii=0; ii < hd->ioc->req_depth; ii++) - hd->ScsiLookup[ii] = NULL; - /* 2. Chain Buffer initialization */ @@ -2675,7 +2739,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) ioc->name, event)); if (ioc->sh == NULL || - ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) + ((hd = shost_priv(ioc->sh)) == NULL)) return 1; switch (event) { @@ -2713,7 +2777,8 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) case MPI_EVENT_STATE_CHANGE: /* 02 */ case MPI_EVENT_EVENT_CHANGE: /* 0A */ default: - dprintk(ioc, printk(KERN_DEBUG MYNAM ": Ignoring event (=%02Xh)\n", event)); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n", + ioc->name, event)); break; } @@ -2753,7 +2818,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) int completionCode; u16 req_idx; - hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + hd = shost_priv(ioc->sh); if ((mf == NULL) || (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { @@ -2765,17 +2830,17 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) del_timer(&hd->timer); req_idx = le16_to_cpu(mf->u.frame.hwhdr.msgctxu.fld.req_idx); - hd->ScsiLookup[req_idx] = NULL; + mptscsih_set_scsi_lookup(ioc, req_idx, NULL); pReq = (SCSIIORequest_t *) mf; if (mf != hd->cmdPtr) { printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n", - hd->ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); + ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); } hd->cmdPtr = NULL; ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScanDvComplete (mf=%p,mr=%p,idx=%d)\n", - hd->ioc->name, mf, mr, req_idx)); + ioc->name, mf, mr, req_idx)); hd->pLocal = &hd->localReply; hd->pLocal->scsiStatus = 0; @@ -2839,15 +2904,15 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) */ completionCode = MPT_SCANDV_SENSE; hd->pLocal->scsiStatus = scsi_status; - sense_data = ((u8 *)hd->ioc->sense_buf_pool + + sense_data = ((u8 *)ioc->sense_buf_pool + (req_idx * MPT_SENSE_BUFFER_ALLOC)); sz = min_t(int, pReq->SenseBufferLength, SCSI_STD_SENSE_BYTES); memcpy(hd->pLocal->sense, sense_data, sz); - ddvprintk(ioc, printk(KERN_DEBUG " Check Condition, sense ptr %p\n", - sense_data)); + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Check Condition, sense ptr %p\n", + ioc->name, sense_data)); } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { if (pReq->CDB[0] == INQUIRY) completionCode = MPT_SCANDV_ISSUE_SENSE; @@ -2906,8 +2971,9 @@ void mptscsih_timer_expired(unsigned long data) { MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; + MPT_ADAPTER *ioc = hd->ioc; - ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr)); + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", ioc->name, hd->cmdPtr)); if (hd->cmdPtr) { MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr; @@ -2921,13 +2987,13 @@ mptscsih_timer_expired(unsigned long data) */ } else { /* Perform a FW reload */ - if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { - printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name); + if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { + printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name); } } } else { /* This should NEVER happen */ - printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name); + printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", ioc->name); } /* No more processing. @@ -2935,7 +3001,7 @@ mptscsih_timer_expired(unsigned long data) * The FW will reply to all outstanding commands, callback will finish cleanup. * Hard reset clean-up will free all resources. */ - ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", hd->ioc->name)); + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", ioc->name)); return; } @@ -2973,11 +3039,12 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) char cmdLen; char CDB[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; char cmd = io->cmd; + MPT_ADAPTER *ioc = hd->ioc; in_isr = in_interrupt(); if (in_isr) { - dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n", - hd->ioc->name)); + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n", + ioc->name)); return -EPERM; } @@ -3078,9 +3145,9 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) /* Get and Populate a free Frame */ - if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { - ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "No msg frames!\n", - hd->ioc->name)); + if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { + dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n", + ioc->name)); return -EBUSY; } @@ -3119,19 +3186,19 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) if (cmd == REQUEST_SENSE) { pScsiReq->Control = cpu_to_le32(dir | MPI_SCSIIO_CONTROL_UNTAGGED); - ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n", - hd->ioc->name, cmd)); + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n", + ioc->name, cmd)); } for (ii=0; ii < 16; ii++) pScsiReq->CDB[ii] = CDB[ii]; pScsiReq->DataLength = cpu_to_le32(io->size); - pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma + pScsiReq->SenseBufferLowAddr = cpu_to_le32(ioc->sense_buf_low_dma + (my_idx * MPT_SENSE_BUFFER_ALLOC)); - ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n", - hd->ioc->name, cmd, io->channel, io->id, io->lun)); + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Sending Command 0x%x for (%d:%d:%d)\n", + ioc->name, cmd, io->channel, io->id, io->lun)); if (dir == MPI_SCSIIO_CONTROL_READ) { mpt_add_sge((char *) &pScsiReq->SGL, @@ -3166,7 +3233,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) hd->cmdPtr = mf; add_timer(&hd->timer); - mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); + mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); wait_event(hd->scandv_waitq, hd->scandv_wait_done); if (hd->pLocal) { @@ -3182,8 +3249,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) } else { rc = -EFAULT; /* This should never happen. */ - ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n", - hd->ioc->name)); + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n", + ioc->name)); } return rc; @@ -3235,7 +3302,7 @@ static ssize_t mptscsih_version_fw_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", @@ -3250,7 +3317,7 @@ static ssize_t mptscsih_version_bios_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", @@ -3265,7 +3332,7 @@ static ssize_t mptscsih_version_mpi_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion); @@ -3276,7 +3343,7 @@ static ssize_t mptscsih_version_product_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name); @@ -3288,7 +3355,7 @@ static ssize_t mptscsih_version_nvdata_persistent_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02xh\n", @@ -3301,7 +3368,7 @@ static ssize_t mptscsih_version_nvdata_default_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default); @@ -3313,7 +3380,7 @@ static ssize_t mptscsih_board_name_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name); @@ -3324,7 +3391,7 @@ static ssize_t mptscsih_board_assembly_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly); @@ -3336,7 +3403,7 @@ static ssize_t mptscsih_board_tracer_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer); @@ -3348,7 +3415,7 @@ static ssize_t mptscsih_io_delay_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); @@ -3360,7 +3427,7 @@ static ssize_t mptscsih_device_delay_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); @@ -3372,7 +3439,7 @@ static ssize_t mptscsih_debug_level_show(struct class_device *cdev, char *buf) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level); @@ -3382,7 +3449,7 @@ mptscsih_debug_level_store(struct class_device *cdev, const char *buf, size_t count) { struct Scsi_Host *host = class_to_shost(cdev); - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(host); MPT_ADAPTER *ioc = hd->ioc; int val = 0; diff --git a/drivers/message/fusion/mptscsih.h b/drivers/message/fusion/mptscsih.h index 67b088db2f10..d289e97cfe8b 100644 --- a/drivers/message/fusion/mptscsih.h +++ b/drivers/message/fusion/mptscsih.h @@ -3,9 +3,9 @@ * High performance SCSI / Fibre Channel SCSI Host device driver. * For use with PCI chip/adapter(s): * LSIFC9xx/LSI409xx Fibre Channel - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c index 8c98420640a5..25bcfcf36f2e 100644 --- a/drivers/message/fusion/mptspi.c +++ b/drivers/message/fusion/mptspi.c @@ -1,9 +1,9 @@ /* * linux/drivers/message/fusion/mptspi.c - * For use with LSI Logic PCI chip/adapter(s) - * running LSI Logic Fusion MPT (Message Passing Technology) firmware. + * For use with LSI PCI chip/adapter(s) + * running LSI Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Logic Corporation + * Copyright (c) 1999-2007 LSI Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -90,9 +90,9 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *, static struct scsi_transport_template *mptspi_transport_template = NULL; -static int mptspiDoneCtx = -1; -static int mptspiTaskCtx = -1; -static int mptspiInternalCtx = -1; /* Used only for internal commands */ +static u8 mptspiDoneCtx = MPT_MAX_PROTOCOL_DRIVERS; +static u8 mptspiTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; +static u8 mptspiInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; /* Used only for internal commands */ /** * mptspi_setTargetNegoParms - Update the target negotiation parameters @@ -107,7 +107,8 @@ static void mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, struct scsi_device *sdev) { - SpiCfgData *pspi_data = &hd->ioc->spi_data; + MPT_ADAPTER *ioc = hd->ioc; + SpiCfgData *pspi_data = &ioc->spi_data; int id = (int) target->id; int nvram; u8 width = MPT_NARROW; @@ -138,9 +139,10 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, else { factor = MPT_ULTRA320; if (scsi_device_qas(sdev)) { - ddvprintk(hd->ioc, - printk(KERN_DEBUG "Enabling QAS due to " - "byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id)); + ddvprintk(ioc, + printk(MYIOC_s_DEBUG_FMT "Enabling QAS due to " + "byte56=%02x on id=%d!\n", ioc->name, + scsi_device_qas(sdev), id)); noQas = 0; } if (sdev->type == TYPE_TAPE && @@ -227,8 +229,8 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, /* Disable QAS in a mixed configuration case */ - ddvprintk(hd->ioc, printk(KERN_DEBUG - "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "Disabling QAS due to noQas=%02x on id=%d!\n", ioc->name, noQas, id)); } } @@ -302,7 +304,7 @@ mptspi_writeIOCPage4(MPT_SCSI_HOST *hd, u8 channel , u8 id) ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "writeIOCPage4: MaxSEP=%d ActiveSEP=%d id=%d bus=%d\n", - ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel)); + ioc->name, IOCPage4Ptr->MaxSEP, IOCPage4Ptr->ActiveSEP, id, channel)); mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); @@ -374,14 +376,15 @@ static int mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id) { int i, rc = 0; + MPT_ADAPTER *ioc = hd->ioc; - if (!hd->ioc->raid_data.pIocPg2) + if (!ioc->raid_data.pIocPg2) goto out; - if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes) + if (!ioc->raid_data.pIocPg2->NumActiveVolumes) goto out; - for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { - if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) { + for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { + if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) { rc = 1; goto out; } @@ -394,17 +397,19 @@ mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id) static int mptspi_target_alloc(struct scsi_target *starget) { struct Scsi_Host *shost = dev_to_shost(&starget->dev); - struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(shost); VirtTarget *vtarget; + MPT_ADAPTER *ioc; if (hd == NULL) return -ENODEV; + ioc = hd->ioc; vtarget = kzalloc(sizeof(VirtTarget), GFP_KERNEL); if (!vtarget) return -ENOMEM; - vtarget->ioc_id = hd->ioc->id; + vtarget->ioc_id = ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; vtarget->id = (u8)starget->id; vtarget->channel = (u8)starget->channel; @@ -412,34 +417,34 @@ static int mptspi_target_alloc(struct scsi_target *starget) starget->hostdata = vtarget; if (starget->channel == 1) { - if (mptscsih_is_phys_disk(hd->ioc, 0, starget->id) == 0) + if (mptscsih_is_phys_disk(ioc, 0, starget->id) == 0) return 0; vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; /* The real channel for this device is zero */ vtarget->channel = 0; /* The actual physdisknum (for RAID passthrough) */ - vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0, + vtarget->id = mptscsih_raid_id_to_num(ioc, 0, starget->id); } if (starget->channel == 0 && mptspi_is_raid(hd, starget->id)) { vtarget->raidVolume = 1; - ddvprintk(hd->ioc, printk(KERN_DEBUG - "RAID Volume @ channel=%d id=%d\n", starget->channel, + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT + "RAID Volume @ channel=%d id=%d\n", ioc->name, starget->channel, starget->id)); } - if (hd->ioc->spi_data.nvram && - hd->ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { - u32 nvram = hd->ioc->spi_data.nvram[starget->id]; + if (ioc->spi_data.nvram && + ioc->spi_data.nvram[starget->id] != MPT_HOST_NVRAM_INVALID) { + u32 nvram = ioc->spi_data.nvram[starget->id]; spi_min_period(starget) = (nvram & MPT_NVRAM_SYNC_MASK) >> MPT_NVRAM_SYNC_SHIFT; spi_max_width(starget) = nvram & MPT_NVRAM_WIDE_DISABLE ? 0 : 1; } else { - spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor; - spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth; + spi_min_period(starget) = ioc->spi_data.minSyncFactor; + spi_max_width(starget) = ioc->spi_data.maxBusWidth; } - spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset; + spi_max_offset(starget) = ioc->spi_data.maxSyncOffset; spi_offset(starget) = 0; mptspi_write_width(starget, 0); @@ -509,10 +514,10 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, struct _CONFIG_PAGE_SCSI_DEVICE_0 *pass_pg0) { struct Scsi_Host *shost = dev_to_shost(&starget->dev); - struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(shost); struct _MPT_ADAPTER *ioc = hd->ioc; - struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0; - dma_addr_t pg0_dma; + struct _CONFIG_PAGE_SCSI_DEVICE_0 *spi_dev_pg0; + dma_addr_t spi_dev_pg0_dma; int size; struct _x_config_parms cfg; struct _CONFIG_PAGE_HEADER hdr; @@ -530,9 +535,10 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, size += 2048; */ - pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg0_dma, GFP_KERNEL); - if (pg0 == NULL) { - starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); + spi_dev_pg0 = dma_alloc_coherent(&ioc->pcidev->dev, size, &spi_dev_pg0_dma, GFP_KERNEL); + if (spi_dev_pg0 == NULL) { + starget_printk(KERN_ERR, starget, MYIOC_s_FMT + "dma_alloc_coherent for parameters failed\n", ioc->name); return -EINVAL; } @@ -546,22 +552,22 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, memset(&cfg, 0, sizeof(cfg)); cfg.cfghdr.hdr = &hdr; - cfg.physAddr = pg0_dma; + cfg.physAddr = spi_dev_pg0_dma; cfg.action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; cfg.dir = 0; cfg.pageAddr = starget->id; if (mpt_config(ioc, &cfg)) { - starget_printk(KERN_ERR, starget, "mpt_config failed\n"); + starget_printk(KERN_ERR, starget, MYIOC_s_FMT "mpt_config failed\n", ioc->name); goto out_free; } err = 0; - memcpy(pass_pg0, pg0, size); + memcpy(pass_pg0, spi_dev_pg0, size); - mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters)); + mptspi_print_read_nego(hd, starget, le32_to_cpu(spi_dev_pg0->NegotiatedParameters)); out_free: - dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma); + dma_free_coherent(&ioc->pcidev->dev, size, spi_dev_pg0, spi_dev_pg0_dma); return err; } @@ -588,11 +594,11 @@ static u32 mptspi_getRP(struct scsi_target *starget) static void mptspi_read_parameters(struct scsi_target *starget) { int nego; - struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0; + struct _CONFIG_PAGE_SCSI_DEVICE_0 spi_dev_pg0; - mptspi_read_spi_device_pg0(starget, &pg0); + mptspi_read_spi_device_pg0(starget, &spi_dev_pg0); - nego = le32_to_cpu(pg0.NegotiatedParameters); + nego = le32_to_cpu(spi_dev_pg0.NegotiatedParameters); spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0; spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0; @@ -612,12 +618,13 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) { MpiRaidActionRequest_t *pReq; MPT_FRAME_HDR *mf; + MPT_ADAPTER *ioc = hd->ioc; /* Get and Populate a free Frame */ - if ((mf = mpt_get_msg_frame(hd->ioc->InternalCtx, hd->ioc)) == NULL) { - ddvprintk(hd->ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", - hd->ioc->name)); + if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { + ddvprintk(ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", + ioc->name)); return -EAGAIN; } pReq = (MpiRaidActionRequest_t *)mf; @@ -638,8 +645,8 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) mpt_add_sge((char *)&pReq->ActionDataSGE, MPT_SGE_FLAGS_SSIMPLE_READ | 0, (dma_addr_t) -1); - ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", - hd->ioc->name, pReq->Action, channel, id)); + ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", + ioc->name, pReq->Action, channel, id)); hd->pLocal = NULL; hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ @@ -651,7 +658,7 @@ mptscsih_quiesce_raid(MPT_SCSI_HOST *hd, int quiesce, u8 channel, u8 id) hd->cmdPtr = mf; add_timer(&hd->timer); - mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); + mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); wait_event(hd->scandv_waitq, hd->scandv_wait_done); if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0)) @@ -664,6 +671,7 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, struct scsi_device *sdev) { VirtTarget *vtarget = scsi_target(sdev)->hostdata; + MPT_ADAPTER *ioc = hd->ioc; /* no DV on RAID devices */ if (sdev->channel == 0 && @@ -673,8 +681,8 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, /* If this is a piece of a RAID, then quiesce first */ if (sdev->channel == 1 && mptscsih_quiesce_raid(hd, 1, vtarget->channel, vtarget->id) < 0) { - starget_printk(KERN_ERR, scsi_target(sdev), - "Integrated RAID quiesce failed\n"); + starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT + "Integrated RAID quiesce failed\n", ioc->name); return; } @@ -684,8 +692,8 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, if (sdev->channel == 1 && mptscsih_quiesce_raid(hd, 0, vtarget->channel, vtarget->id) < 0) - starget_printk(KERN_ERR, scsi_target(sdev), - "Integrated RAID resume failed\n"); + starget_printk(KERN_ERR, scsi_target(sdev), MYIOC_s_FMT + "Integrated RAID resume failed\n", ioc->name); mptspi_read_parameters(sdev->sdev_target); spi_display_xfer_agreement(sdev->sdev_target); @@ -694,28 +702,29 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, static int mptspi_slave_alloc(struct scsi_device *sdev) { - MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; + MPT_SCSI_HOST *hd = shost_priv(sdev->host); VirtTarget *vtarget; - VirtDevice *vdev; + VirtDevice *vdevice; struct scsi_target *starget; + MPT_ADAPTER *ioc = hd->ioc; if (sdev->channel == 1 && - mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0) + mptscsih_is_phys_disk(ioc, 0, sdev->id) == 0) return -ENXIO; - vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdev) { + vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdevice) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", - hd->ioc->name, sizeof(VirtDevice)); + ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - vdev->lun = sdev->lun; - sdev->hostdata = vdev; + vdevice->lun = sdev->lun; + sdev->hostdata = vdevice; starget = scsi_target(sdev); vtarget = starget->hostdata; - vdev->vtarget = vtarget; + vdevice->vtarget = vtarget; vtarget->num_luns++; if (sdev->channel == 1) @@ -726,8 +735,7 @@ static int mptspi_slave_alloc(struct scsi_device *sdev) static int mptspi_slave_configure(struct scsi_device *sdev) { - struct _MPT_SCSI_HOST *hd = - (struct _MPT_SCSI_HOST *)sdev->host->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(sdev->host); VirtTarget *vtarget = scsi_target(sdev)->hostdata; int ret; @@ -755,24 +763,25 @@ static int mptspi_slave_configure(struct scsi_device *sdev) static int mptspi_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; - VirtDevice *vdev = SCpnt->device->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(SCpnt->device->host); + VirtDevice *vdevice = SCpnt->device->hostdata; + MPT_ADAPTER *ioc = hd->ioc; - if (!vdev || !vdev->vtarget) { + if (!vdevice || !vdevice->vtarget) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } if (SCpnt->device->channel == 1 && - mptscsih_is_phys_disk(hd->ioc, 0, SCpnt->device->id) == 0) { + mptscsih_is_phys_disk(ioc, 0, SCpnt->device->id) == 0) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } if (spi_dv_pending(scsi_target(SCpnt->device))) - ddvprintk(hd->ioc, scsi_print_command(SCpnt)); + ddvprintk(ioc, scsi_print_command(SCpnt)); return mptscsih_qcmd(SCpnt,done); } @@ -829,7 +838,7 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget, struct _CONFIG_PAGE_SCSI_DEVICE_1 *pass_pg1) { struct Scsi_Host *shost = dev_to_shost(&starget->dev); - struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(shost); struct _MPT_ADAPTER *ioc = hd->ioc; struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1; dma_addr_t pg1_dma; @@ -847,7 +856,8 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget, pg1 = dma_alloc_coherent(&ioc->pcidev->dev, size, &pg1_dma, GFP_KERNEL); if (pg1 == NULL) { - starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); + starget_printk(KERN_ERR, starget, MYIOC_s_FMT + "dma_alloc_coherent for parameters failed\n", ioc->name); return -EINVAL; } @@ -876,7 +886,8 @@ static int mptspi_write_spi_device_pg1(struct scsi_target *starget, mptspi_print_write_nego(hd, starget, le32_to_cpu(pg1->RequestedParameters)); if (mpt_config(ioc, &cfg)) { - starget_printk(KERN_ERR, starget, "mpt_config failed\n"); + starget_printk(KERN_ERR, starget, MYIOC_s_FMT + "mpt_config failed\n", ioc->name); goto out_free; } err = 0; @@ -1015,7 +1026,7 @@ static void mptspi_write_qas(struct scsi_target *starget, int qas) { struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; struct Scsi_Host *shost = dev_to_shost(&starget->dev); - struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(shost); VirtTarget *vtarget = starget->hostdata; u32 nego; @@ -1067,15 +1078,16 @@ static void mpt_work_wrapper(struct work_struct *work) struct work_queue_wrapper *wqw = container_of(work, struct work_queue_wrapper, work); struct _MPT_SCSI_HOST *hd = wqw->hd; - struct Scsi_Host *shost = hd->ioc->sh; + MPT_ADAPTER *ioc = hd->ioc; + struct Scsi_Host *shost = ioc->sh; struct scsi_device *sdev; int disk = wqw->disk; struct _CONFIG_PAGE_IOC_3 *pg3; kfree(wqw); - mpt_findImVolumes(hd->ioc); - pg3 = hd->ioc->raid_data.pIocPg3; + mpt_findImVolumes(ioc); + pg3 = ioc->raid_data.pIocPg3; if (!pg3) return; @@ -1092,24 +1104,25 @@ static void mpt_work_wrapper(struct work_struct *work) if(vtarget->id != disk) continue; - starget_printk(KERN_INFO, vtarget->starget, - "Integrated RAID requests DV of new device\n"); + starget_printk(KERN_INFO, vtarget->starget, MYIOC_s_FMT + "Integrated RAID requests DV of new device\n", ioc->name); mptspi_dv_device(hd, sdev); } - shost_printk(KERN_INFO, shost, - "Integrated RAID detects new device %d\n", disk); - scsi_scan_target(&hd->ioc->sh->shost_gendev, 1, disk, 0, 1); + shost_printk(KERN_INFO, shost, MYIOC_s_FMT + "Integrated RAID detects new device %d\n", ioc->name, disk); + scsi_scan_target(&ioc->sh->shost_gendev, 1, disk, 0, 1); } static void mpt_dv_raid(struct _MPT_SCSI_HOST *hd, int disk) { struct work_queue_wrapper *wqw = kmalloc(sizeof(*wqw), GFP_ATOMIC); + MPT_ADAPTER *ioc = hd->ioc; if (!wqw) { - shost_printk(KERN_ERR, hd->ioc->sh, - "Failed to act on RAID event for physical disk %d\n", - disk); + shost_printk(KERN_ERR, ioc->sh, MYIOC_s_FMT + "Failed to act on RAID event for physical disk %d\n", + ioc->name, disk); return; } INIT_WORK(&wqw->work, mpt_work_wrapper); @@ -1123,7 +1136,7 @@ static int mptspi_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) { u8 event = le32_to_cpu(pEvReply->Event) & 0xFF; - struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); if (hd && event == MPI_EVENT_INTEGRATED_RAID) { int reason @@ -1190,6 +1203,8 @@ static struct spi_function_template mptspi_transport_functions = { static struct pci_device_id mptspi_pci_table[] = { { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030, PCI_ANY_ID, PCI_ANY_ID }, + { PCI_VENDOR_ID_ATTO, MPI_MANUFACTPAGE_DEVID_53C1030, + PCI_ANY_ID, PCI_ANY_ID }, { PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1035, PCI_ANY_ID, PCI_ANY_ID }, {0} /* Terminating entry */ @@ -1210,11 +1225,12 @@ mptspi_dv_renegotiate_work(struct work_struct *work) struct scsi_target *starget; struct _CONFIG_PAGE_SCSI_DEVICE_1 pg1; u32 nego; + MPT_ADAPTER *ioc = hd->ioc; kfree(wqw); if (hd->spi_pending) { - shost_for_each_device(sdev, hd->ioc->sh) { + shost_for_each_device(sdev, ioc->sh) { if (hd->spi_pending & (1 << sdev->id)) continue; starget = scsi_target(sdev); @@ -1225,7 +1241,7 @@ mptspi_dv_renegotiate_work(struct work_struct *work) mptspi_write_spi_device_pg1(starget, &pg1); } } else { - shost_for_each_device(sdev, hd->ioc->sh) + shost_for_each_device(sdev, ioc->sh) mptspi_dv_device(hd, sdev); } } @@ -1250,7 +1266,7 @@ mptspi_dv_renegotiate(struct _MPT_SCSI_HOST *hd) static int mptspi_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { - struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); int rc; rc = mptscsih_ioc_reset(ioc, reset_phase); @@ -1269,7 +1285,7 @@ static int mptspi_resume(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; + struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); int rc; rc = mptscsih_resume(pdev); @@ -1416,7 +1432,7 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (numSGE < sh->sg_tablesize) { /* Reset this value */ - dprintk(ioc, printk(MYIOC_s_INFO_FMT + dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Resetting sg_tablesize to %d from %d\n", ioc->name, numSGE, sh->sg_tablesize)); sh->sg_tablesize = numSGE; @@ -1424,20 +1440,21 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_unlock_irqrestore(&ioc->FreeQlock, flags); - hd = (MPT_SCSI_HOST *) sh->hostdata; + hd = shost_priv(sh); hd->ioc = ioc; /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); - if (!hd->ScsiLookup) { + ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!ioc->ScsiLookup) { error = -ENOMEM; goto out_mptspi_probe; } + spin_lock_init(&ioc->scsi_lookup_lock); dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "ScsiLookup @ %p\n", - ioc->name, hd->ScsiLookup)); + ioc->name, ioc->ScsiLookup)); /* Clear the TM flags */ @@ -1477,13 +1494,13 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) /* Some versions of the firmware don't support page 0; without * that we can't get the parameters */ - if (hd->ioc->spi_data.sdp0length != 0) + if (ioc->spi_data.sdp0length != 0) sh->transportt = mptspi_transport_template; error = scsi_add_host (sh, &ioc->pcidev->dev); if(error) { - dprintk(ioc, printk(KERN_ERR MYNAM - "scsi_add_host failed\n")); + dprintk(ioc, printk(MYIOC_s_ERR_FMT + "scsi_add_host failed\n", ioc->name)); goto out_mptspi_probe; } diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c index f0eba534f805..01c351c176ac 100644 --- a/drivers/pci/hotplug/pci_hotplug_core.c +++ b/drivers/pci/hotplug/pci_hotplug_core.c @@ -689,8 +689,6 @@ int pci_hp_deregister (struct hotplug_slot *slot) int __must_check pci_hp_change_slot_info(struct hotplug_slot *slot, struct hotplug_slot_info *info) { - int retval; - if ((slot == NULL) || (info == NULL)) return -ENODEV; diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c index 90aa53fc4f3e..7507067351bd 100644 --- a/drivers/s390/scsi/zfcp_aux.c +++ b/drivers/s390/scsi/zfcp_aux.c @@ -891,7 +891,7 @@ zfcp_unit_dequeue(struct zfcp_unit *unit) /* * Allocates a combined QTCB/fsf_req buffer for erp actions and fcp/SCSI * commands. - * It also genrates fcp-nameserver request/response buffer and unsolicited + * It also genrates fcp-nameserver request/response buffer and unsolicited * status read fsf_req buffers. * * locks: must only be called with zfcp_data.config_sema taken @@ -982,7 +982,7 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) struct zfcp_adapter *adapter; /* - * Note: It is safe to release the list_lock, as any list changes + * Note: It is safe to release the list_lock, as any list changes * are protected by the config_sema, which must be held to get here */ @@ -1038,6 +1038,10 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) spin_lock_init(&adapter->san_dbf_lock); spin_lock_init(&adapter->scsi_dbf_lock); + retval = zfcp_adapter_debug_register(adapter); + if (retval) + goto debug_register_failed; + /* initialize error recovery stuff */ rwlock_init(&adapter->erp_lock); @@ -1058,7 +1062,6 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) /* mark adapter unusable as long as sysfs registration is not complete */ atomic_set_mask(ZFCP_STATUS_COMMON_REMOVE, &adapter->status); - adapter->ccw_device = ccw_device; dev_set_drvdata(&ccw_device->dev, adapter); if (zfcp_sysfs_adapter_create_files(&ccw_device->dev)) @@ -1085,6 +1088,8 @@ zfcp_adapter_enqueue(struct ccw_device *ccw_device) generic_services_failed: zfcp_sysfs_adapter_remove_files(&adapter->ccw_device->dev); sysfs_failed: + zfcp_adapter_debug_unregister(adapter); + debug_register_failed: dev_set_drvdata(&ccw_device->dev, NULL); zfcp_reqlist_free(adapter); failed_low_mem_buffers: @@ -1130,6 +1135,8 @@ zfcp_adapter_dequeue(struct zfcp_adapter *adapter) goto out; } + zfcp_adapter_debug_unregister(adapter); + /* remove specified adapter data structure from list */ write_lock_irq(&zfcp_data.config_lock); list_del(&adapter->list); diff --git a/drivers/s390/scsi/zfcp_ccw.c b/drivers/s390/scsi/zfcp_ccw.c index c0d1c0eb3209..e01cbf152a81 100644 --- a/drivers/s390/scsi/zfcp_ccw.c +++ b/drivers/s390/scsi/zfcp_ccw.c @@ -148,15 +148,12 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device) down(&zfcp_data.config_sema); adapter = dev_get_drvdata(&ccw_device->dev); - retval = zfcp_adapter_debug_register(adapter); - if (retval) - goto out; retval = zfcp_erp_thread_setup(adapter); if (retval) { ZFCP_LOG_INFO("error: start of error recovery thread for " "adapter %s failed\n", zfcp_get_busid_by_adapter(adapter)); - goto out_erp_thread; + goto out; } retval = zfcp_adapter_scsi_register(adapter); @@ -175,8 +172,6 @@ zfcp_ccw_set_online(struct ccw_device *ccw_device) out_scsi_register: zfcp_erp_thread_kill(adapter); - out_erp_thread: - zfcp_adapter_debug_unregister(adapter); out: up(&zfcp_data.config_sema); return retval; @@ -199,7 +194,6 @@ zfcp_ccw_set_offline(struct ccw_device *ccw_device) zfcp_erp_adapter_shutdown(adapter, 0); zfcp_erp_wait(adapter); zfcp_erp_thread_kill(adapter); - zfcp_adapter_debug_unregister(adapter); up(&zfcp_data.config_sema); return 0; } diff --git a/drivers/s390/scsi/zfcp_def.h b/drivers/s390/scsi/zfcp_def.h index b36dfc40d9fa..16e5563e0c65 100644 --- a/drivers/s390/scsi/zfcp_def.h +++ b/drivers/s390/scsi/zfcp_def.h @@ -1,23 +1,23 @@ -/* +/* * This file is part of the zfcp device driver for * FCP adapters for IBM System z9 and zSeries. * * (C) Copyright IBM Corp. 2002, 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ #ifndef ZFCP_DEF_H #define ZFCP_DEF_H @@ -90,7 +90,7 @@ zfcp_address_to_sg(void *address, struct scatterlist *list) #define ZFCP_DEVICE_TYPE 0x1732 #define ZFCP_DEVICE_MODEL 0x03 #define ZFCP_DEVICE_MODEL_PRIV 0x04 - + /* allow as many chained SBALs as are supported by hardware */ #define ZFCP_MAX_SBALS_PER_REQ FSF_MAX_SBALS_PER_REQ #define ZFCP_MAX_SBALS_PER_CT_REQ FSF_MAX_SBALS_PER_REQ @@ -508,7 +508,7 @@ struct zfcp_rc_entry { /* * this allows removal of logging code by the preprocessor - * (the most detailed log level still to be compiled in is specified, + * (the most detailed log level still to be compiled in is specified, * higher log levels are removed) */ #define ZFCP_LOG_LEVEL_LIMIT ZFCP_LOG_LEVEL_TRACE @@ -546,7 +546,7 @@ do { \ if (ZFCP_LOG_CHECK(level)) \ _ZFCP_LOG(fmt, ##args); \ } while (0) - + #if ZFCP_LOG_LEVEL_LIMIT < ZFCP_LOG_LEVEL_NORMAL # define ZFCP_LOG_NORMAL(fmt, args...) do { } while (0) #else @@ -583,8 +583,8 @@ do { \ /*************** ADAPTER/PORT/UNIT AND FSF_REQ STATUS FLAGS ******************/ -/* - * Note, the leftmost status byte is common among adapter, port +/* + * Note, the leftmost status byte is common among adapter, port * and unit */ #define ZFCP_COMMON_FLAGS 0xfff00000 @@ -1007,8 +1007,8 @@ struct zfcp_fsf_req { u32 fsf_command; /* FSF Command copy */ struct fsf_qtcb *qtcb; /* address of associated QTCB */ u32 seq_no; /* Sequence number of request */ - unsigned long data; /* private data of request */ - struct timer_list timer; /* used for erp or scsi er */ + unsigned long data; /* private data of request */ + struct timer_list timer; /* used for erp or scsi er */ struct zfcp_erp_action *erp_action; /* used if this request is issued on behalf of erp */ mempool_t *pool; /* used if request was alloacted diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c index 16b4418ab257..a6475a2bb8a7 100644 --- a/drivers/s390/scsi/zfcp_erp.c +++ b/drivers/s390/scsi/zfcp_erp.c @@ -1,22 +1,22 @@ -/* +/* * This file is part of the zfcp device driver for * FCP adapters for IBM System z9 and zSeries. * * (C) Copyright IBM Corp. 2002, 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_ERP @@ -191,7 +191,7 @@ void zfcp_fsf_start_timer(struct zfcp_fsf_req *fsf_req, unsigned long timeout) } /* - * function: + * function: * * purpose: called if an adapter failed, * initiates adapter recovery which is done @@ -228,7 +228,7 @@ zfcp_erp_adapter_reopen_internal(struct zfcp_adapter *adapter, int clear_mask) } /* - * function: + * function: * * purpose: Wrappper for zfcp_erp_adapter_reopen_internal * used to ensure the correct locking @@ -476,7 +476,7 @@ zfcp_test_link(struct zfcp_port *port) /* - * function: + * function: * * purpose: called if a port failed to be opened normally * initiates Forced Reopen recovery which is done @@ -517,7 +517,7 @@ zfcp_erp_port_forced_reopen_internal(struct zfcp_port *port, int clear_mask) } /* - * function: + * function: * * purpose: Wrappper for zfcp_erp_port_forced_reopen_internal * used to ensure the correct locking @@ -543,7 +543,7 @@ zfcp_erp_port_forced_reopen(struct zfcp_port *port, int clear_mask) } /* - * function: + * function: * * purpose: called if a port is to be opened * initiates Reopen recovery which is done @@ -612,7 +612,7 @@ zfcp_erp_port_reopen(struct zfcp_port *port, int clear_mask) } /* - * function: + * function: * * purpose: called if a unit is to be opened * initiates Reopen recovery which is done @@ -704,7 +704,7 @@ static void zfcp_erp_adapter_unblock(struct zfcp_adapter *adapter) } /* - * function: + * function: * * purpose: disable I/O, * return any open requests and clean them up, @@ -725,7 +725,7 @@ zfcp_erp_port_block(struct zfcp_port *port, int clear_mask) } /* - * function: + * function: * * purpose: enable I/O * @@ -742,7 +742,7 @@ zfcp_erp_port_unblock(struct zfcp_port *port) } /* - * function: + * function: * * purpose: disable I/O, * return any open requests and clean them up, @@ -763,7 +763,7 @@ zfcp_erp_unit_block(struct zfcp_unit *unit, int clear_mask) } /* - * function: + * function: * * purpose: enable I/O * @@ -792,7 +792,7 @@ zfcp_erp_action_ready(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * * purpose: * @@ -967,7 +967,7 @@ static void zfcp_erp_timeout_handler(unsigned long data) * zfcp_erp_action_dismiss - dismiss an erp_action * * adapter->erp_lock must be held - * + * * Dismissal of an erp_action is usually required if an erp_action of * higher priority is generated. */ @@ -1005,9 +1005,9 @@ zfcp_erp_thread_setup(struct zfcp_adapter *adapter) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: * @@ -1094,7 +1094,7 @@ zfcp_erp_thread(void *data) } /* - * function: + * function: * * purpose: drives single error recovery action and schedules higher and * subordinate actions, if necessary @@ -1206,7 +1206,7 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action) /* * put this target through the erp mill again if someone has - * requested to change the status of a target being online + * requested to change the status of a target being online * to offline or the other way around * (old retval is preserved if nothing has to be done here) */ @@ -1228,7 +1228,7 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action) unlock: write_unlock(&adapter->erp_lock); read_unlock_irqrestore(&zfcp_data.config_lock, flags); - + if (retval != ZFCP_ERP_CONTINUES) zfcp_erp_action_cleanup(action, adapter, port, unit, retval); @@ -1250,9 +1250,9 @@ zfcp_erp_strategy(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_DISMISSED - if action has been dismissed * retval - otherwise @@ -1322,7 +1322,7 @@ zfcp_erp_strategy_do_action(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * * purpose: triggers retry of this action after a certain amount of time * by means of timer provided by erp_action @@ -1346,7 +1346,7 @@ zfcp_erp_strategy_memwait(struct zfcp_erp_action *erp_action) return retval; } -/* +/* * function: zfcp_erp_adapter_failed * * purpose: sets the adapter and all underlying devices to ERP_FAILED @@ -1362,7 +1362,7 @@ zfcp_erp_adapter_failed(struct zfcp_adapter *adapter) debug_text_event(adapter->erp_dbf, 2, "a_afail"); } -/* +/* * function: zfcp_erp_port_failed * * purpose: sets the port and all underlying devices to ERP_FAILED @@ -1386,7 +1386,7 @@ zfcp_erp_port_failed(struct zfcp_port *port) debug_event(port->adapter->erp_dbf, 2, &port->wwpn, sizeof (wwn_t)); } -/* +/* * function: zfcp_erp_unit_failed * * purpose: sets the unit to ERP_FAILED @@ -1417,7 +1417,7 @@ zfcp_erp_unit_failed(struct zfcp_unit *unit) * successfully is reset. * * returns: ZFCP_ERP_CONTINUES - action continues (not considered) - * ZFCP_ERP_SUCCEEDED - action finished successfully + * ZFCP_ERP_SUCCEEDED - action finished successfully * ZFCP_ERP_EXIT - action failed and will not continue */ static int @@ -1646,7 +1646,7 @@ zfcp_erp_schedule_work(struct zfcp_unit *unit) } /* - * function: + * function: * * purpose: remaining things in good cases, * escalation in bad cases @@ -1687,8 +1687,8 @@ zfcp_erp_strategy_followup_actions(int action, break; case ZFCP_ERP_ACTION_REOPEN_UNIT: - if (status == ZFCP_ERP_SUCCEEDED) ; /* no further action */ - else + /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */ + if (status != ZFCP_ERP_SUCCEEDED) zfcp_erp_port_reopen_internal(unit->port, 0); break; } @@ -1815,7 +1815,7 @@ zfcp_erp_modify_unit_status(struct zfcp_unit *unit, u32 mask, int set_or_clear) } /* - * function: + * function: * * purpose: Wrappper for zfcp_erp_port_reopen_all_internal * used to ensure the correct locking @@ -1852,9 +1852,9 @@ zfcp_erp_port_reopen_all_internal(struct zfcp_adapter *adapter, int clear_mask) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: FIXME */ @@ -1871,7 +1871,7 @@ zfcp_erp_unit_reopen_all_internal(struct zfcp_port *port, int clear_mask) } /* - * function: + * function: * * purpose: this routine executes the 'Reopen Adapter' action * (the entire action is processed synchronously, since @@ -1908,9 +1908,9 @@ zfcp_erp_adapter_strategy(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_SUCCEEDED - action finished successfully * ZFCP_ERP_FAILED - action finished unsuccessfully @@ -1930,9 +1930,9 @@ zfcp_erp_adapter_strategy_close(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_SUCCEEDED - action finished successfully * ZFCP_ERP_FAILED - action finished unsuccessfully @@ -1957,7 +1957,7 @@ zfcp_erp_adapter_strategy_open(struct zfcp_erp_action *erp_action) * purpose: allocate the irq associated with this devno and register * the FSF adapter with the SCSI stack * - * returns: + * returns: */ static int zfcp_erp_adapter_strategy_generic(struct zfcp_erp_action *erp_action, int close) @@ -2197,7 +2197,7 @@ zfcp_erp_adapter_strategy_open_fsf_xport(struct zfcp_erp_action *erp_action) zfcp_erp_action_to_running(erp_action); write_unlock_irq(&adapter->erp_lock); - ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); + ret = zfcp_fsf_exchange_port_data(erp_action); if (ret == -EOPNOTSUPP) { debug_text_event(adapter->erp_dbf, 3, "a_xport_notsupp"); return ZFCP_ERP_SUCCEEDED; @@ -2249,7 +2249,7 @@ zfcp_erp_adapter_strategy_open_fsf_statusread(struct zfcp_erp_action } /* - * function: + * function: * * purpose: this routine executes the 'Reopen Physical Port' action * @@ -2308,7 +2308,7 @@ zfcp_erp_port_forced_strategy(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * * purpose: this routine executes the 'Reopen Port' action * @@ -2530,7 +2530,7 @@ zfcp_erp_port_strategy_open_nameserver(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * * purpose: makes the erp thread continue with reopen (physical) port * actions which have been paused until the name server port @@ -2570,9 +2570,9 @@ zfcp_erp_port_strategy_open_nameserver_wakeup(struct zfcp_erp_action } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) * ZFCP_ERP_FAILED - action finished unsuccessfully @@ -2626,9 +2626,9 @@ zfcp_erp_port_strategy_clearstati(struct zfcp_port *port) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) * ZFCP_ERP_FAILED - action finished unsuccessfully @@ -2663,9 +2663,9 @@ zfcp_erp_port_strategy_close(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) * ZFCP_ERP_FAILED - action finished unsuccessfully @@ -2700,9 +2700,9 @@ zfcp_erp_port_strategy_open_port(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) * ZFCP_ERP_FAILED - action finished unsuccessfully @@ -2737,7 +2737,7 @@ zfcp_erp_port_strategy_open_common_lookup(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * * purpose: this routine executes the 'Reopen Unit' action * currently no retries @@ -2825,9 +2825,9 @@ zfcp_erp_unit_strategy_clearstati(struct zfcp_unit *unit) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) * ZFCP_ERP_FAILED - action finished unsuccessfully @@ -2865,9 +2865,9 @@ zfcp_erp_unit_strategy_close(struct zfcp_erp_action *erp_action) } /* - * function: + * function: * - * purpose: + * purpose: * * returns: ZFCP_ERP_CONTINUES - action continues (asynchronously) * ZFCP_ERP_FAILED - action finished unsuccessfully @@ -2913,7 +2913,7 @@ void zfcp_erp_start_timer(struct zfcp_fsf_req *fsf_req) } /* - * function: + * function: * * purpose: enqueue the specified error recovery action, if needed * @@ -2992,7 +2992,7 @@ zfcp_erp_action_enqueue(int action, port->erp_action.action); debug_text_event(adapter->erp_dbf, 4, "pf_actenq_drp"); - } else + } else debug_text_event(adapter->erp_dbf, 4, "pf_actenq_drpcp"); debug_event(adapter->erp_dbf, 4, &port->wwpn, diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h index 991d45667a44..8534cf09546c 100644 --- a/drivers/s390/scsi/zfcp_ext.h +++ b/drivers/s390/scsi/zfcp_ext.h @@ -1,22 +1,22 @@ -/* +/* * This file is part of the zfcp device driver for * FCP adapters for IBM System z9 and zSeries. * * (C) Copyright IBM Corp. 2002, 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef ZFCP_EXT_H @@ -82,9 +82,11 @@ extern int zfcp_fsf_open_unit(struct zfcp_erp_action *); extern int zfcp_fsf_close_unit(struct zfcp_erp_action *); extern int zfcp_fsf_exchange_config_data(struct zfcp_erp_action *); -extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *, - struct zfcp_adapter *, - struct fsf_qtcb_bottom_port *); +extern int zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *, + struct fsf_qtcb_bottom_config *); +extern int zfcp_fsf_exchange_port_data(struct zfcp_erp_action *); +extern int zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *, + struct fsf_qtcb_bottom_port *); extern int zfcp_fsf_control_file(struct zfcp_adapter *, struct zfcp_fsf_req **, u32, u32, struct zfcp_sg_list *); extern void zfcp_fsf_start_timer(struct zfcp_fsf_req *, unsigned long); diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c index 99299976e891..ff866ebd44ac 100644 --- a/drivers/s390/scsi/zfcp_fsf.c +++ b/drivers/s390/scsi/zfcp_fsf.c @@ -80,10 +80,10 @@ static const char zfcp_act_subtable_type[5][8] = { /* * function: zfcp_fsf_req_alloc * - * purpose: Obtains an fsf_req and potentially a qtcb (for all but + * purpose: Obtains an fsf_req and potentially a qtcb (for all but * unsolicited requests) via helper functions * Does some initial fsf request set-up. - * + * * returns: pointer to allocated fsf_req if successfull * NULL otherwise * @@ -192,7 +192,7 @@ void zfcp_fsf_req_dismiss_all(struct zfcp_adapter *adapter) * returns: 0 - success * !0 - failure * - * context: + * context: */ int zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req) @@ -214,8 +214,8 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req) } /* - * fsf_req may be deleted due to waking up functions, so - * cleanup is saved here and used later + * fsf_req may be deleted due to waking up functions, so + * cleanup is saved here and used later */ if (likely(fsf_req->status & ZFCP_STATUS_FSFREQ_CLEANUP)) cleanup = 1; @@ -259,9 +259,9 @@ zfcp_fsf_req_complete(struct zfcp_fsf_req *fsf_req) * and initiates appropriate actions * (usually calling FSF command specific handlers) * - * returns: + * returns: * - * context: + * context: * * locks: */ @@ -638,7 +638,7 @@ zfcp_fsf_link_down_info_eval(struct zfcp_adapter *adapter, * * purpose: calls the appropriate command specific handler * - * returns: + * returns: */ static int zfcp_fsf_req_dispatch(struct zfcp_fsf_req *fsf_req) @@ -854,7 +854,7 @@ zfcp_fsf_status_read_port_closed(struct zfcp_fsf_req *fsf_req) * * purpose: is called for finished Open Port command * - * returns: + * returns: */ static int zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) @@ -1088,7 +1088,7 @@ zfcp_fsf_status_read_handler(struct zfcp_fsf_req *fsf_req) * returns: address of initiated FSF request * NULL - request could not be initiated * - * FIXME(design): should be watched by a timeout !!! + * FIXME(design): should be watched by a timeout !!! * FIXME(design) shouldn't this be modified to return an int * also...don't know how though */ @@ -1157,7 +1157,7 @@ zfcp_fsf_abort_fcp_command(unsigned long old_req_id, * * purpose: is called for finished Abort FCP Command request * - * returns: + * returns: */ static int zfcp_fsf_abort_fcp_command_handler(struct zfcp_fsf_req *new_fsf_req) @@ -1941,25 +1941,28 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) { volatile struct qdio_buffer_element *sbale; struct zfcp_fsf_req *fsf_req; + struct zfcp_adapter *adapter = erp_action->adapter; unsigned long lock_flags; - int retval = 0; + int retval; /* setup new FSF request */ - retval = zfcp_fsf_req_create(erp_action->adapter, + retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, ZFCP_REQ_AUTO_CLEANUP, - erp_action->adapter->pool.fsf_req_erp, + adapter->pool.fsf_req_erp, &lock_flags, &fsf_req); - if (retval < 0) { + if (retval) { ZFCP_LOG_INFO("error: Could not create exchange configuration " "data request for adapter %s.\n", - zfcp_get_busid_by_adapter(erp_action->adapter)); - goto out; + zfcp_get_busid_by_adapter(adapter)); + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); + return retval; } sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); - sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; - sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; fsf_req->qtcb->bottom.config.feature_selection = FSF_FEATURE_CFDC | @@ -1971,23 +1974,71 @@ zfcp_fsf_exchange_config_data(struct zfcp_erp_action *erp_action) zfcp_erp_start_timer(fsf_req); retval = zfcp_fsf_req_send(fsf_req); + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); if (retval) { - ZFCP_LOG_INFO - ("error: Could not send exchange configuration data " - "command on the adapter %s\n", - zfcp_get_busid_by_adapter(erp_action->adapter)); + ZFCP_LOG_INFO("error: Could not send exchange configuration " + "data command on the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); zfcp_fsf_req_free(fsf_req); erp_action->fsf_req = NULL; - goto out; } + else + ZFCP_LOG_DEBUG("exchange configuration data request initiated " + "(adapter %s)\n", + zfcp_get_busid_by_adapter(adapter)); - ZFCP_LOG_DEBUG("exchange configuration data request initiated " - "(adapter %s)\n", - zfcp_get_busid_by_adapter(erp_action->adapter)); + return retval; +} - out: - write_unlock_irqrestore(&erp_action->adapter->request_queue.queue_lock, +int +zfcp_fsf_exchange_config_data_sync(struct zfcp_adapter *adapter, + struct fsf_qtcb_bottom_config *data) +{ + volatile struct qdio_buffer_element *sbale; + struct zfcp_fsf_req *fsf_req; + unsigned long lock_flags; + int retval; + + /* setup new FSF request */ + retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, + 0, NULL, &lock_flags, &fsf_req); + if (retval) { + ZFCP_LOG_INFO("error: Could not create exchange configuration " + "data request for adapter %s.\n", + zfcp_get_busid_by_adapter(adapter)); + write_unlock_irqrestore(&adapter->request_queue.queue_lock, + lock_flags); + return retval; + } + + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + + fsf_req->qtcb->bottom.config.feature_selection = + FSF_FEATURE_CFDC | + FSF_FEATURE_LUN_SHARING | + FSF_FEATURE_NOTIFICATION_LOST | + FSF_FEATURE_UPDATE_ALERT; + + if (data) + fsf_req->data = (unsigned long) data; + + zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); + retval = zfcp_fsf_req_send(fsf_req); + write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); + if (retval) + ZFCP_LOG_INFO("error: Could not send exchange configuration " + "data command on the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + else + wait_event(fsf_req->completion_wq, + fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); + + zfcp_fsf_req_free(fsf_req); + return retval; } @@ -2016,11 +2067,17 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) adapter->peer_d_id = 0; if (xchg_ok) { + + if (fsf_req->data) + memcpy((struct fsf_qtcb_bottom_config *) fsf_req->data, + bottom, sizeof (struct fsf_qtcb_bottom_config)); + fc_host_node_name(shost) = bottom->nport_serv_param.wwnn; fc_host_port_name(shost) = bottom->nport_serv_param.wwpn; fc_host_port_id(shost) = bottom->s_id & ZFCP_DID_MASK; fc_host_speed(shost) = bottom->fc_link_speed; - fc_host_supported_classes(shost) = FC_COS_CLASS2 | FC_COS_CLASS3; + fc_host_supported_classes(shost) = + FC_COS_CLASS2 | FC_COS_CLASS3; adapter->hydra_version = bottom->adapter_type; if (fc_host_permanent_port_name(shost) == -1) fc_host_permanent_port_name(shost) = @@ -2053,7 +2110,8 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) min(FC_SERIAL_NUMBER_SIZE, 17)); } - ZFCP_LOG_NORMAL("The adapter %s reported the following characteristics:\n" + ZFCP_LOG_NORMAL("The adapter %s reported the following " + "characteristics:\n" "WWNN 0x%016Lx, " "WWPN 0x%016Lx, " "S_ID 0x%06x,\n" @@ -2090,7 +2148,7 @@ zfcp_fsf_exchange_config_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) return 0; } -/* +/** * function: zfcp_fsf_exchange_config_data_handler * * purpose: is called for finished Exchange Configuration Data command @@ -2125,7 +2183,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) adapter->peer_wwpn, adapter->peer_d_id); debug_text_event(fsf_req->adapter->erp_dbf, 0, - "top-p-to-p"); + "top-p-to-p"); break; case FC_PORTTYPE_NLPORT: ZFCP_LOG_NORMAL("error: Arbitrated loop fibrechannel " @@ -2138,8 +2196,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) return -EIO; case FC_PORTTYPE_NPORT: ZFCP_LOG_NORMAL("Switched fabric fibrechannel " - "network detected at adapter %s.\n", - zfcp_get_busid_by_adapter(adapter)); + "network detected at adapter %s.\n", + zfcp_get_busid_by_adapter(adapter)); break; default: ZFCP_LOG_NORMAL("bug: The fibrechannel topology " @@ -2179,7 +2237,8 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) if (zfcp_fsf_exchange_config_evaluate(fsf_req, 0)) return -EIO; - atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, &adapter->status); + atomic_set_mask(ZFCP_STATUS_ADAPTER_XCONFIG_OK, + &adapter->status); zfcp_fsf_link_down_info_eval(adapter, &qtcb->header.fsf_status_qual.link_down_info); @@ -2187,7 +2246,7 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) default: debug_text_event(fsf_req->adapter->erp_dbf, 0, "fsf-stat-ng"); debug_event(fsf_req->adapter->erp_dbf, 0, - &fsf_req->qtcb->header.fsf_status, sizeof (u32)); + &fsf_req->qtcb->header.fsf_status, sizeof(u32)); zfcp_erp_adapter_shutdown(adapter, 0); return -EIO; } @@ -2197,74 +2256,118 @@ zfcp_fsf_exchange_config_data_handler(struct zfcp_fsf_req *fsf_req) /** * zfcp_fsf_exchange_port_data - request information about local port * @erp_action: ERP action for the adapter for which port data is requested - * @adapter: for which port data is requested - * @data: response to exchange port data request */ int -zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, - struct zfcp_adapter *adapter, - struct fsf_qtcb_bottom_port *data) +zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action) { volatile struct qdio_buffer_element *sbale; - struct zfcp_fsf_req *fsf_req; + struct zfcp_fsf_req *fsf_req; + struct zfcp_adapter *adapter = erp_action->adapter; unsigned long lock_flags; - int retval = 0; + int retval; if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { ZFCP_LOG_INFO("error: exchange port data " - "command not supported by adapter %s\n", + "command not supported by adapter %s\n", zfcp_get_busid_by_adapter(adapter)); - return -EOPNOTSUPP; - } + return -EOPNOTSUPP; + } /* setup new FSF request */ retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, - erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0, - NULL, &lock_flags, &fsf_req); - if (retval < 0) { + ZFCP_REQ_AUTO_CLEANUP, + adapter->pool.fsf_req_erp, + &lock_flags, &fsf_req); + if (retval) { ZFCP_LOG_INFO("error: Out of resources. Could not create an " - "exchange port data request for" - "the adapter %s.\n", + "exchange port data request for" + "the adapter %s.\n", zfcp_get_busid_by_adapter(adapter)); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); return retval; } - if (data) - fsf_req->data = (unsigned long) data; - sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); - sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; - sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; - if (erp_action) { - erp_action->fsf_req = fsf_req; - fsf_req->erp_action = erp_action; - zfcp_erp_start_timer(fsf_req); - } else - zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); + erp_action->fsf_req = fsf_req; + fsf_req->erp_action = erp_action; + zfcp_erp_start_timer(fsf_req); retval = zfcp_fsf_req_send(fsf_req); + write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); + if (retval) { ZFCP_LOG_INFO("error: Could not send an exchange port data " - "command on the adapter %s\n", + "command on the adapter %s\n", zfcp_get_busid_by_adapter(adapter)); zfcp_fsf_req_free(fsf_req); - if (erp_action) - erp_action->fsf_req = NULL; + erp_action->fsf_req = NULL; + } + else + ZFCP_LOG_DEBUG("exchange port data request initiated " + "(adapter %s)\n", + zfcp_get_busid_by_adapter(adapter)); + return retval; +} + + +/** + * zfcp_fsf_exchange_port_data_sync - request information about local port + * and wait until information is ready + */ +int +zfcp_fsf_exchange_port_data_sync(struct zfcp_adapter *adapter, + struct fsf_qtcb_bottom_port *data) +{ + volatile struct qdio_buffer_element *sbale; + struct zfcp_fsf_req *fsf_req; + unsigned long lock_flags; + int retval; + + if (!(adapter->adapter_features & FSF_FEATURE_HBAAPI_MANAGEMENT)) { + ZFCP_LOG_INFO("error: exchange port data " + "command not supported by adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + return -EOPNOTSUPP; + } + + /* setup new FSF request */ + retval = zfcp_fsf_req_create(adapter, FSF_QTCB_EXCHANGE_PORT_DATA, + 0, NULL, &lock_flags, &fsf_req); + if (retval) { + ZFCP_LOG_INFO("error: Out of resources. Could not create an " + "exchange port data request for" + "the adapter %s.\n", + zfcp_get_busid_by_adapter(adapter)); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); return retval; } + if (data) + fsf_req->data = (unsigned long) data; + + sbale = zfcp_qdio_sbale_req(fsf_req, fsf_req->sbal_curr, 0); + sbale[0].flags |= SBAL_FLAGS0_TYPE_READ; + sbale[1].flags |= SBAL_FLAGS_LAST_ENTRY; + + zfcp_fsf_start_timer(fsf_req, ZFCP_FSF_REQUEST_TIMEOUT); + retval = zfcp_fsf_req_send(fsf_req); write_unlock_irqrestore(&adapter->request_queue.queue_lock, lock_flags); - if (!erp_action) { + if (retval) + ZFCP_LOG_INFO("error: Could not send an exchange port data " + "command on the adapter %s\n", + zfcp_get_busid_by_adapter(adapter)); + else wait_event(fsf_req->completion_wq, fsf_req->status & ZFCP_STATUS_FSFREQ_COMPLETED); - zfcp_fsf_req_free(fsf_req); - } + + zfcp_fsf_req_free(fsf_req); + return retval; } @@ -2277,18 +2380,16 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) { struct zfcp_adapter *adapter; - struct fsf_qtcb *qtcb; - struct fsf_qtcb_bottom_port *bottom, *data; + struct fsf_qtcb_bottom_port *bottom; struct Scsi_Host *shost; adapter = fsf_req->adapter; - qtcb = fsf_req->qtcb; - bottom = &qtcb->bottom.port; + bottom = &fsf_req->qtcb->bottom.port; shost = adapter->scsi_host; - data = (struct fsf_qtcb_bottom_port*) fsf_req->data; - if (data) - memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); + if (fsf_req->data) + memcpy((struct fsf_qtcb_bottom_port*) fsf_req->data, bottom, + sizeof(struct fsf_qtcb_bottom_port)); if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) fc_host_permanent_port_name(shost) = bottom->wwpn; @@ -2336,10 +2437,10 @@ zfcp_fsf_exchange_port_data_handler(struct zfcp_fsf_req *fsf_req) /* * function: zfcp_fsf_open_port * - * purpose: + * purpose: * * returns: address of initiated FSF request - * NULL - request could not be initiated + * NULL - request could not be initiated */ int zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) @@ -2400,7 +2501,7 @@ zfcp_fsf_open_port(struct zfcp_erp_action *erp_action) * * purpose: is called for finished Open Port command * - * returns: + * returns: */ static int zfcp_fsf_open_port_handler(struct zfcp_fsf_req *fsf_req) @@ -3002,7 +3103,7 @@ zfcp_fsf_open_unit(struct zfcp_erp_action *erp_action) * * purpose: is called for finished Open LUN command * - * returns: + * returns: */ static int zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) @@ -3265,7 +3366,7 @@ zfcp_fsf_open_unit_handler(struct zfcp_fsf_req *fsf_req) * purpose: * * returns: address of fsf_req - request successfully initiated - * NULL - + * NULL - * * assumptions: This routine does not check whether the associated * remote port/lun has already been opened. This should be @@ -3586,17 +3687,17 @@ zfcp_fsf_send_fcp_command_task(struct zfcp_adapter *adapter, ZFCP_LOG_DEBUG( "Data did not fit into available buffer(s), " "waiting for more...\n"); - retval = -EIO; - } else { - ZFCP_LOG_NORMAL("error: No truncation implemented but " - "required. Shutting down unit " - "(adapter %s, port 0x%016Lx, " - "unit 0x%016Lx)\n", - zfcp_get_busid_by_unit(unit), - unit->port->wwpn, - unit->fcp_lun); - zfcp_erp_unit_shutdown(unit, 0); - retval = -EINVAL; + retval = -EIO; + } else { + ZFCP_LOG_NORMAL("error: No truncation implemented but " + "required. Shutting down unit " + "(adapter %s, port 0x%016Lx, " + "unit 0x%016Lx)\n", + zfcp_get_busid_by_unit(unit), + unit->port->wwpn, + unit->fcp_lun); + zfcp_erp_unit_shutdown(unit, 0); + retval = -EINVAL; } goto no_fit; } @@ -3727,7 +3828,7 @@ zfcp_fsf_send_fcp_command_task_management(struct zfcp_adapter *adapter, * * purpose: is called for finished Send FCP Command * - * returns: + * returns: */ static int zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) @@ -3964,7 +4065,7 @@ zfcp_fsf_send_fcp_command_handler(struct zfcp_fsf_req *fsf_req) * * purpose: evaluates FCP_RSP IU * - * returns: + * returns: */ static int zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) @@ -4192,7 +4293,7 @@ zfcp_fsf_send_fcp_command_task_handler(struct zfcp_fsf_req *fsf_req) * * purpose: evaluates FCP_RSP IU * - * returns: + * returns: */ static int zfcp_fsf_send_fcp_command_task_management_handler(struct zfcp_fsf_req *fsf_req) @@ -4635,7 +4736,7 @@ zfcp_fsf_req_create(struct zfcp_adapter *adapter, u32 fsf_cmd, int req_flags, INIT_LIST_HEAD(&fsf_req->list); init_timer(&fsf_req->timer); - /* initialize waitqueue which may be used to wait on + /* initialize waitqueue which may be used to wait on this request completion */ init_waitqueue_head(&fsf_req->completion_wq); diff --git a/drivers/s390/scsi/zfcp_fsf.h b/drivers/s390/scsi/zfcp_fsf.h index 71186618947c..8cce5cc11d50 100644 --- a/drivers/s390/scsi/zfcp_fsf.h +++ b/drivers/s390/scsi/zfcp_fsf.h @@ -1,22 +1,22 @@ -/* +/* * This file is part of the zfcp device driver for * FCP adapters for IBM System z9 and zSeries. * * (C) Copyright IBM Corp. 2002, 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #ifndef FSF_H diff --git a/drivers/s390/scsi/zfcp_qdio.c b/drivers/s390/scsi/zfcp_qdio.c index c6899efdc8f6..3f105fdcf239 100644 --- a/drivers/s390/scsi/zfcp_qdio.c +++ b/drivers/s390/scsi/zfcp_qdio.c @@ -174,10 +174,9 @@ zfcp_qdio_handler_error_check(struct zfcp_adapter *adapter, unsigned int status, * That is why we need to clear the link-down flag * which is set again in case we have missed by a mile. */ - zfcp_erp_adapter_reopen( - adapter, - ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | - ZFCP_STATUS_COMMON_ERP_FAILED); + zfcp_erp_adapter_reopen(adapter, + ZFCP_STATUS_ADAPTER_LINK_UNPLUGGED | + ZFCP_STATUS_COMMON_ERP_FAILED); } return retval; } diff --git a/drivers/s390/scsi/zfcp_scsi.c b/drivers/s390/scsi/zfcp_scsi.c index ad7eb4a9261c..abae2027f7e5 100644 --- a/drivers/s390/scsi/zfcp_scsi.c +++ b/drivers/s390/scsi/zfcp_scsi.c @@ -1,22 +1,22 @@ -/* +/* * This file is part of the zfcp device driver for * FCP adapters for IBM System z9 and zSeries. * * (C) Copyright IBM Corp. 2002, 2006 - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #define ZFCP_LOG_AREA ZFCP_LOG_AREA_SCSI @@ -101,7 +101,7 @@ zfcp_get_fcp_dl_ptr(struct fcp_cmnd_iu * fcp_cmd) ((unsigned char *) fcp_cmd + sizeof (struct fcp_cmnd_iu) + additional_length); /* - * fcp_dl_addr = start address of fcp_cmnd structure + + * fcp_dl_addr = start address of fcp_cmnd structure + * size of fixed part + size of dynamically sized add_dcp_cdb field * SEE FCP-2 documentation */ @@ -189,13 +189,12 @@ static void zfcp_scsi_slave_destroy(struct scsi_device *sdpnt) unit->device = NULL; zfcp_erp_unit_failed(unit); zfcp_unit_put(unit); - } else { + } else ZFCP_LOG_NORMAL("bug: no unit associated with SCSI device at " "address %p\n", sdpnt); - } } -/* +/* * called from scsi midlayer to allow finetuning of a device. */ static int @@ -361,12 +360,11 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id, list_for_each_entry(port, &adapter->port_list_head, list) { if (!port->rport || (id != port->rport->scsi_target_id)) continue; - list_for_each_entry(unit, &port->unit_list_head, list) { + list_for_each_entry(unit, &port->unit_list_head, list) if (lun == unit->scsi_lun) { retval = unit; goto out; } - } } out: return retval; @@ -374,7 +372,7 @@ zfcp_unit_lookup(struct zfcp_adapter *adapter, int channel, unsigned int id, /** * zfcp_scsi_eh_abort_handler - abort the specified SCSI command - * @scpnt: pointer to scsi_cmnd to be aborted + * @scpnt: pointer to scsi_cmnd to be aborted * Return: SUCCESS - command has been aborted and cleaned up in internal * bookkeeping, SCSI stack won't be called for aborted command * FAILED - otherwise @@ -733,7 +731,7 @@ zfcp_get_fc_host_stats(struct Scsi_Host *shost) if (!data) return NULL; - ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); + ret = zfcp_fsf_exchange_port_data_sync(adapter, data); if (ret) { kfree(data); return NULL; /* XXX return zeroed fc_stats? */ @@ -763,7 +761,7 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost) if (!data) return; - ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); + ret = zfcp_fsf_exchange_port_data_sync(adapter, data); if (ret) { kfree(data); } else { @@ -802,6 +800,7 @@ struct fc_function_template zfcp_transport_functions = { .show_host_port_type = 1, .show_host_speed = 1, .show_host_port_id = 1, + .disable_target_scan = 1, }; /** diff --git a/drivers/s390/scsi/zfcp_sysfs_unit.c b/drivers/s390/scsi/zfcp_sysfs_unit.c index 81a484175863..63f75ee95c33 100644 --- a/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/drivers/s390/scsi/zfcp_sysfs_unit.c @@ -139,7 +139,7 @@ static struct attribute_group zfcp_unit_attr_group = { .attrs = zfcp_unit_attrs, }; -/** +/** * zfcp_sysfs_create_unit_files - create sysfs unit files * @dev: pointer to belonging device * @@ -151,7 +151,7 @@ zfcp_sysfs_unit_create_files(struct device *dev) return sysfs_create_group(&dev->kobj, &zfcp_unit_attr_group); } -/** +/** * zfcp_sysfs_remove_unit_files - remove sysfs unit files * @dev: pointer to belonging device * diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 6f2c71ef47ee..30905cebefbb 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -272,6 +272,13 @@ config SCSI_FC_ATTRS each attached FiberChannel device to sysfs, say Y. Otherwise, say N. +config SCSI_FC_TGT_ATTRS + bool "SCSI target support for FiberChannel Transport Attributes" + depends on SCSI_FC_ATTRS + depends on SCSI_TGT = y || SCSI_TGT = SCSI_FC_ATTRS + help + If you want to use SCSI target mode drivers enable this option. + config SCSI_ISCSI_ATTRS tristate "iSCSI Transport Attributes" depends on SCSI && NET @@ -289,6 +296,20 @@ config SCSI_SAS_ATTRS source "drivers/scsi/libsas/Kconfig" +config SCSI_SRP_ATTRS + tristate "SRP Transport Attributes" + depends on SCSI + help + If you wish to export transport-specific information about + each attached SRP device to sysfs, say Y. + +config SCSI_SRP_TGT_ATTRS + bool "SCSI target support for SRP Transport Attributes" + depends on SCSI_SRP_ATTRS + depends on SCSI_TGT = y || SCSI_TGT = SCSI_SRP_ATTRS + help + If you want to use SCSI target mode drivers enable this option. + endmenu menuconfig SCSI_LOWLEVEL @@ -502,7 +523,6 @@ config SCSI_ADVANSYS tristate "AdvanSys SCSI support" depends on SCSI depends on ISA || EISA || PCI - depends on BROKEN || X86_32 help This is a driver for all SCSI host adapters manufactured by AdvanSys. It is documented in the kernel source in @@ -524,19 +544,32 @@ config SCSI_IN2000 module will be called in2000. config SCSI_ARCMSR - tristate "ARECA ARC11X0[PCI-X]/ARC12X0[PCI-EXPRESS] SATA-RAID support" + tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter" depends on PCI && SCSI help - This driver supports all of ARECA's SATA RAID controller cards. + This driver supports all of ARECA's SATA/SAS RAID controller cards. This is an ARECA-maintained driver by Erich Chen. - If you have any problems, please mail to: < erich@areca.com.tw > + If you have any problems, please mail to: <erich@areca.com.tw>. Areca supports Linux RAID config tools. - - < http://www.areca.com.tw > + Please link <http://www.areca.com.tw> To compile this driver as a module, choose M here: the module will be called arcmsr (modprobe arcmsr). +config SCSI_ARCMSR_AER + bool "Enable PCI Error Recovery Capability in Areca Driver(ARCMSR)" + depends on SCSI_ARCMSR && PCIEAER + default n + help + The advanced error reporting(AER) capability is "NOT" provided by + ARC1200/1201/1202 SATA RAID controllers cards. + If your card is one of ARC1200/1201/1202, please use the default setting, n. + If your card is other models, you could pick it + on condition that the kernel version is greater than 2.6.19. + This function is maintained driver by Nick Cheng. If you have any + problems or suggestion, you are welcome to contact with <nick.cheng@areca.com.tw>. + To enable this function, choose Y here. + source "drivers/scsi/megaraid/Kconfig.megaraid" config SCSI_HPTIOP @@ -836,6 +869,7 @@ config SCSI_IPS config SCSI_IBMVSCSI tristate "IBM Virtual SCSI support" depends on PPC_PSERIES || PPC_ISERIES + select SCSI_SRP_ATTRS help This is the IBM POWER Virtual SCSI Client @@ -844,7 +878,7 @@ config SCSI_IBMVSCSI config SCSI_IBMVSCSIS tristate "IBM Virtual SCSI Server support" - depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP + depends on PPC_PSERIES && SCSI_SRP && SCSI_SRP_TGT_ATTRS help This is the SRP target driver for IBM pSeries virtual environments. diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile index 86a7ba7bad63..6141389dcdb2 100644 --- a/drivers/scsi/Makefile +++ b/drivers/scsi/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_SCSI_FC_ATTRS) += scsi_transport_fc.o obj-$(CONFIG_SCSI_ISCSI_ATTRS) += scsi_transport_iscsi.o obj-$(CONFIG_SCSI_SAS_ATTRS) += scsi_transport_sas.o obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas/ +obj-$(CONFIG_SCSI_SRP_ATTRS) += scsi_transport_srp.o obj-$(CONFIG_ISCSI_TCP) += libiscsi.o iscsi_tcp.o obj-$(CONFIG_INFINIBAND_ISER) += libiscsi.o diff --git a/drivers/scsi/NCR5380.c b/drivers/scsi/NCR5380.c index f8e449a98d29..988f0bc5eda5 100644 --- a/drivers/scsi/NCR5380.c +++ b/drivers/scsi/NCR5380.c @@ -1542,9 +1542,7 @@ part2: hostdata->connected = cmd; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); - if (cmd->SCp.ptr != (char *)cmd->sense_buffer) { - initialize_SCp(cmd); - } + initialize_SCp(cmd); return 0; @@ -2133,7 +2131,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->done(cmd); + cmd->scsi_done(cmd); return; #endif /* @@ -2196,7 +2194,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->done(cmd); + cmd->scsi_done(cmd); /* XXX - need to source or sink data here, as appropriate */ } else cmd->SCp.this_residual -= transfersize - len; @@ -2280,19 +2278,16 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); #ifdef AUTOSENSE + if ((cmd->cmnd[0] == REQUEST_SENSE) && + hostdata->ses.cmd_len) { + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + hostdata->ses.cmd_len = 0 ; + } + if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { + scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); + dprintk(NDEBUG_AUTOSENSE, ("scsi%d : performing request sense\n", instance->host_no)); - cmd->cmnd[0] = REQUEST_SENSE; - cmd->cmnd[1] &= 0xe0; - cmd->cmnd[2] = 0; - cmd->cmnd[3] = 0; - cmd->cmnd[4] = sizeof(cmd->sense_buffer); - cmd->cmnd[5] = 0; - - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - cmd->SCp.ptr = (char *) cmd->sense_buffer; - cmd->SCp.this_residual = sizeof(cmd->sense_buffer); LIST(cmd, hostdata->issue_queue); cmd->host_scribble = (unsigned char *) @@ -2740,7 +2735,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) { tmp->host_scribble = NULL; tmp->result = DID_ABORT << 16; dprintk(NDEBUG_ABORT, ("scsi%d : abort removed command from issue queue.\n", instance->host_no)); - tmp->done(tmp); + tmp->scsi_done(tmp); return SUCCESS; } #if (NDEBUG & NDEBUG_ABORT) @@ -2805,7 +2800,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) { *prev = (Scsi_Cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; tmp->result = DID_ABORT << 16; - tmp->done(tmp); + tmp->scsi_done(tmp); return SUCCESS; } } diff --git a/drivers/scsi/NCR5380.h b/drivers/scsi/NCR5380.h index bccf13f71532..bdc468c9e1d9 100644 --- a/drivers/scsi/NCR5380.h +++ b/drivers/scsi/NCR5380.h @@ -30,6 +30,10 @@ #include <linux/interrupt.h> +#ifdef AUTOSENSE +#include <scsi/scsi_eh.h> +#endif + #define NCR5380_PUBLIC_RELEASE 7 #define NCR53C400_PUBLIC_RELEASE 2 @@ -281,6 +285,9 @@ struct NCR5380_hostdata { unsigned pendingr; unsigned pendingw; #endif +#ifdef AUTOSENSE + struct scsi_eh_save ses; +#endif }; #ifdef __KERNEL__ diff --git a/drivers/scsi/NCR53C9x.c b/drivers/scsi/NCR53C9x.c index 79b4df158140..96e8e29aa05d 100644 --- a/drivers/scsi/NCR53C9x.c +++ b/drivers/scsi/NCR53C9x.c @@ -1385,7 +1385,7 @@ int esp_abort(Scsi_Cmnd *SCptr) this->host_scribble = NULL; esp_release_dmabufs(esp, this); this->result = DID_ABORT << 16; - this->done(this); + this->scsi_done(this); if(don) esp->dma_ints_on(esp); return SUCCESS; diff --git a/drivers/scsi/NCR_D700.c b/drivers/scsi/NCR_D700.c index 3a8089705feb..9e64b21ef637 100644 --- a/drivers/scsi/NCR_D700.c +++ b/drivers/scsi/NCR_D700.c @@ -97,7 +97,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/mca.h> -#include <linux/interrupt.h> #include <asm/io.h> #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> @@ -314,10 +313,10 @@ NCR_D700_probe(struct device *dev) break; } - p = kmalloc(sizeof(*p), GFP_KERNEL); + p = kzalloc(sizeof(*p), GFP_KERNEL); if (!p) return -ENOMEM; - memset(p, '\0', sizeof(*p)); + p->dev = dev; snprintf(p->name, sizeof(p->name), "D700(%s)", dev->bus_id); if (request_irq(irq, NCR_D700_intr, IRQF_SHARED, p->name, p)) { diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 0c758d1452ba..d4bda2017746 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -37,7 +37,7 @@ static struct platform_device *a4000t_scsi_device; static int __devinit a4000t_probe(struct device *dev) { - struct Scsi_Host * host = NULL; + struct Scsi_Host *host; struct NCR_700_Host_Parameters *hostdata; if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) @@ -47,12 +47,11 @@ static int __devinit a4000t_probe(struct device *dev) "A4000T builtin SCSI")) goto out; - hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); - if (hostdata == NULL) { + hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + if (!hostdata) { printk(KERN_ERR "a4000t-scsi: Failed to allocate host data\n"); goto out_release; } - memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); /* Fill in the required pieces of hostdata */ hostdata->base = (void __iomem *)ZTWO_VADDR(A4000T_SCSI_ADDR); diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c index 6800e578e4b1..80e448d0f3db 100644 --- a/drivers/scsi/aacraid/aachba.c +++ b/drivers/scsi/aacraid/aachba.c @@ -177,9 +177,9 @@ int check_interval = 24 * 60 * 60; module_param(check_interval, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(check_interval, "Interval in seconds between adapter health checks."); -int check_reset = 1; -module_param(check_reset, int, S_IRUGO|S_IWUSR); -MODULE_PARM_DESC(check_reset, "If adapter fails health check, reset the adapter."); +int aac_check_reset = 1; +module_param_named(check_reset, aac_check_reset, int, S_IRUGO|S_IWUSR); +MODULE_PARM_DESC(aac_check_reset, "If adapter fails health check, reset the adapter."); int expose_physicals = -1; module_param(expose_physicals, int, S_IRUGO|S_IWUSR); @@ -1305,7 +1305,7 @@ int aac_get_adapter_info(struct aac_dev* dev) (int)sizeof(dev->supplement_adapter_info.VpdInfo.Tsid), dev->supplement_adapter_info.VpdInfo.Tsid); } - if (!check_reset || + if (!aac_check_reset || (dev->supplement_adapter_info.SupportedOptions2 & le32_to_cpu(AAC_OPTION_IGNORE_RESET))) { printk(KERN_INFO "%s%d: Reset Adapter Ignored\n", diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h index 94727b9375ec..03b51025a8f4 100644 --- a/drivers/scsi/aacraid/aacraid.h +++ b/drivers/scsi/aacraid/aacraid.h @@ -1871,4 +1871,4 @@ extern int aac_reset_devices; extern int aac_commit; extern int update_interval; extern int check_interval; -extern int check_reset; +extern int aac_check_reset; diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index bb870906b4cf..240a0bb8986f 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -1372,8 +1372,9 @@ int aac_check_health(struct aac_dev * aac) printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED); - if (!check_reset || (aac->supplement_adapter_info.SupportedOptions2 & - le32_to_cpu(AAC_OPTION_IGNORE_RESET))) + if (!aac_check_reset || + (aac->supplement_adapter_info.SupportedOptions2 & + le32_to_cpu(AAC_OPTION_IGNORE_RESET))) goto out; host = aac->scsi_host_ptr; if (aac->thread->pid != current->pid) diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 79c0b6e37a3b..9dd3952516c5 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c @@ -1,765 +1,27 @@ -#define ASC_VERSION "3.3K" /* AdvanSys Driver Version */ +#define DRV_NAME "advansys" +#define ASC_VERSION "3.4" /* AdvanSys Driver Version */ /* * advansys.c - Linux Host Driver for AdvanSys SCSI Adapters * * Copyright (c) 1995-2000 Advanced System Products, Inc. * Copyright (c) 2000-2001 ConnectCom Solutions, Inc. + * Copyright (c) 2007 Matthew Wilcox <matthew@wil.cx> * All Rights Reserved. * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that redistributions of source - * code retain the above copyright notice and this comment without - * modification. - * - * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys) - * changed its name to ConnectCom Solutions, Inc. - * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. */ /* - - Documentation for the AdvanSys Driver - - A. Linux Kernels Supported by this Driver - B. Adapters Supported by this Driver - C. Linux source files modified by AdvanSys Driver - D. Source Comments - E. Driver Compile Time Options and Debugging - F. Driver LILO Option - G. Tests to run before releasing new driver - H. Release History - I. Known Problems/Fix List - J. Credits (Chronological Order) - - A. Linux Kernels Supported by this Driver - - This driver has been tested in the following Linux kernels: v2.2.18 - v2.4.0. The driver is supported on v2.2 and v2.4 kernels and on x86, - alpha, and PowerPC platforms. - - B. Adapters Supported by this Driver - - AdvanSys (Advanced System Products, Inc.) manufactures the following - RISC-based, Bus-Mastering, Fast (10 Mhz) and Ultra (20 Mhz) Narrow - (8-bit transfer) SCSI Host Adapters for the ISA, EISA, VL, and PCI - buses and RISC-based, Bus-Mastering, Ultra (20 Mhz) Wide (16-bit - transfer) SCSI Host Adapters for the PCI bus. - - The CDB counts below indicate the number of SCSI CDB (Command - Descriptor Block) requests that can be stored in the RISC chip - cache and board LRAM. A CDB is a single SCSI command. The driver - detect routine will display the number of CDBs available for each - adapter detected. The number of CDBs used by the driver can be - lowered in the BIOS by changing the 'Host Queue Size' adapter setting. - - Laptop Products: - ABP-480 - Bus-Master CardBus (16 CDB) (2.4 kernel and greater) - - Connectivity Products: - ABP510/5150 - Bus-Master ISA (240 CDB) - ABP5140 - Bus-Master ISA PnP (16 CDB) - ABP5142 - Bus-Master ISA PnP with floppy (16 CDB) - ABP902/3902 - Bus-Master PCI (16 CDB) - ABP3905 - Bus-Master PCI (16 CDB) - ABP915 - Bus-Master PCI (16 CDB) - ABP920 - Bus-Master PCI (16 CDB) - ABP3922 - Bus-Master PCI (16 CDB) - ABP3925 - Bus-Master PCI (16 CDB) - ABP930 - Bus-Master PCI (16 CDB) - ABP930U - Bus-Master PCI Ultra (16 CDB) - ABP930UA - Bus-Master PCI Ultra (16 CDB) - ABP960 - Bus-Master PCI MAC/PC (16 CDB) - ABP960U - Bus-Master PCI MAC/PC Ultra (16 CDB) - - Single Channel Products: - ABP542 - Bus-Master ISA with floppy (240 CDB) - ABP742 - Bus-Master EISA (240 CDB) - ABP842 - Bus-Master VL (240 CDB) - ABP940 - Bus-Master PCI (240 CDB) - ABP940U - Bus-Master PCI Ultra (240 CDB) - ABP940UA/3940UA - Bus-Master PCI Ultra (240 CDB) - ABP970 - Bus-Master PCI MAC/PC (240 CDB) - ABP970U - Bus-Master PCI MAC/PC Ultra (240 CDB) - ABP3960UA - Bus-Master PCI MAC/PC Ultra (240 CDB) - ABP940UW/3940UW - Bus-Master PCI Ultra-Wide (253 CDB) - ABP970UW - Bus-Master PCI MAC/PC Ultra-Wide (253 CDB) - ABP3940U2W - Bus-Master PCI LVD/Ultra2-Wide (253 CDB) - - Multi-Channel Products: - ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) - ABP852 - Dual Channel Bus-Master VL (240 CDB Per Channel) - ABP950 - Dual Channel Bus-Master PCI (240 CDB Per Channel) - ABP950UW - Dual Channel Bus-Master PCI Ultra-Wide (253 CDB Per Channel) - ABP980 - Four Channel Bus-Master PCI (240 CDB Per Channel) - ABP980U - Four Channel Bus-Master PCI Ultra (240 CDB Per Channel) - ABP980UA/3980UA - Four Channel Bus-Master PCI Ultra (16 CDB Per Chan.) - ABP3950U2W - Bus-Master PCI LVD/Ultra2-Wide and Ultra-Wide (253 CDB) - ABP3950U3W - Bus-Master PCI Dual LVD2/Ultra3-Wide (253 CDB) - - C. Linux source files modified by AdvanSys Driver - - This section for historical purposes documents the changes - originally made to the Linux kernel source to add the advansys - driver. As Linux has changed some of these files have also - been modified. - - 1. linux/arch/i386/config.in: - - bool 'AdvanSys SCSI support' CONFIG_SCSI_ADVANSYS y - - 2. linux/drivers/scsi/hosts.c: - - #ifdef CONFIG_SCSI_ADVANSYS - #include "advansys.h" - #endif - - and after "static struct scsi_host_template builtin_scsi_hosts[] =": - - #ifdef CONFIG_SCSI_ADVANSYS - ADVANSYS, - #endif - - 3. linux/drivers/scsi/Makefile: - - ifdef CONFIG_SCSI_ADVANSYS - SCSI_SRCS := $(SCSI_SRCS) advansys.c - SCSI_OBJS := $(SCSI_OBJS) advansys.o - else - SCSI_MODULE_OBJS := $(SCSI_MODULE_OBJS) advansys.o - endif - - 4. linux/init/main.c: - - extern void advansys_setup(char *str, int *ints); - - and add the following lines to the bootsetups[] array. - - #ifdef CONFIG_SCSI_ADVANSYS - { "advansys=", advansys_setup }, - #endif - - D. Source Comments - - 1. Use tab stops set to 4 for the source files. For vi use 'se tabstops=4'. - - 2. This driver should be maintained in multiple files. But to make - it easier to include with Linux and to follow Linux conventions, - the whole driver is maintained in the source files advansys.h and - advansys.c. In this file logical sections of the driver begin with - a comment that contains '---'. The following are the logical sections - of the driver below. - - --- Linux Version - --- Linux Include File - --- Driver Options - --- Debugging Header - --- Asc Library Constants and Macros - --- Adv Library Constants and Macros - --- Driver Constants and Macros - --- Driver Structures - --- Driver Data - --- Driver Function Prototypes - --- Linux 'struct scsi_host_template' and advansys_setup() Functions - --- Loadable Driver Support - --- Miscellaneous Driver Functions - --- Functions Required by the Asc Library - --- Functions Required by the Adv Library - --- Tracing and Debugging Functions - --- Asc Library Functions - --- Adv Library Functions - - 3. The string 'XXX' is used to flag code that needs to be re-written - or that contains a problem that needs to be addressed. - - 4. I have stripped comments from and reformatted the source for the - Asc Library and Adv Library to reduce the size of this file. This - source can be found under the following headings. The Asc Library - is used to support Narrow Boards. The Adv Library is used to - support Wide Boards. - - --- Asc Library Constants and Macros - --- Adv Library Constants and Macros - --- Asc Library Functions - --- Adv Library Functions - - E. Driver Compile Time Options and Debugging - - In this source file the following constants can be defined. They are - defined in the source below. Both of these options are enabled by - default. - - 1. ADVANSYS_ASSERT - Enable driver assertions (Def: Enabled) - - Enabling this option adds assertion logic statements to the - driver. If an assertion fails a message will be displayed to - the console, but the system will continue to operate. Any - assertions encountered should be reported to the person - responsible for the driver. Assertion statements may proactively - detect problems with the driver and facilitate fixing these - problems. Enabling assertions will add a small overhead to the - execution of the driver. - - 2. ADVANSYS_DEBUG - Enable driver debugging (Def: Disabled) - - Enabling this option adds tracing functions to the driver and - the ability to set a driver tracing level at boot time. This - option will also export symbols not required outside the driver to - the kernel name space. This option is very useful for debugging - the driver, but it will add to the size of the driver execution - image and add overhead to the execution of the driver. - - The amount of debugging output can be controlled with the global - variable 'asc_dbglvl'. The higher the number the more output. By - default the debug level is 0. - - If the driver is loaded at boot time and the LILO Driver Option - is included in the system, the debug level can be changed by - specifying a 5th (ASC_NUM_IOPORT_PROBE + 1) I/O Port. The - first three hex digits of the pseudo I/O Port must be set to - 'deb' and the fourth hex digit specifies the debug level: 0 - F. - The following command line will look for an adapter at 0x330 - and set the debug level to 2. - - linux advansys=0x330,0,0,0,0xdeb2 - - If the driver is built as a loadable module this variable can be - defined when the driver is loaded. The following insmod command - will set the debug level to one. - - insmod advansys.o asc_dbglvl=1 - - Debugging Message Levels: - 0: Errors Only - 1: High-Level Tracing - 2-N: Verbose Tracing - - To enable debug output to console, please make sure that: - - a. System and kernel logging is enabled (syslogd, klogd running). - b. Kernel messages are routed to console output. Check - /etc/syslog.conf for an entry similar to this: - - kern.* /dev/console - - c. klogd is started with the appropriate -c parameter - (e.g. klogd -c 8) - - This will cause printk() messages to be be displayed on the - current console. Refer to the klogd(8) and syslogd(8) man pages - for details. - - Alternatively you can enable printk() to console with this - program. However, this is not the 'official' way to do this. - Debug output is logged in /var/log/messages. - - main() - { - syscall(103, 7, 0, 0); - } - - Increasing LOG_BUF_LEN in kernel/printk.c to something like - 40960 allows more debug messages to be buffered in the kernel - and written to the console or log file. - - 3. ADVANSYS_STATS - Enable statistics (Def: Enabled >= v1.3.0) - - Enabling this option adds statistics collection and display - through /proc to the driver. The information is useful for - monitoring driver and device performance. It will add to the - size of the driver execution image and add minor overhead to - the execution of the driver. - - Statistics are maintained on a per adapter basis. Driver entry - point call counts and transfer size counts are maintained. - Statistics are only available for kernels greater than or equal - to v1.3.0 with the CONFIG_PROC_FS (/proc) file system configured. - - AdvanSys SCSI adapter files have the following path name format: - - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] - - This information can be displayed with cat. For example: - - cat /proc/scsi/advansys/0 - - When ADVANSYS_STATS is not defined the AdvanSys /proc files only - contain adapter and device configuration information. - - F. Driver LILO Option - - If init/main.c is modified as described in the 'Directions for Adding - the AdvanSys Driver to Linux' section (B.4.) above, the driver will - recognize the 'advansys' LILO command line and /etc/lilo.conf option. - This option can be used to either disable I/O port scanning or to limit - scanning to 1 - 4 I/O ports. Regardless of the option setting EISA and - PCI boards will still be searched for and detected. This option only - affects searching for ISA and VL boards. - - Examples: - 1. Eliminate I/O port scanning: - boot: linux advansys= - or - boot: linux advansys=0x0 - 2. Limit I/O port scanning to one I/O port: - boot: linux advansys=0x110 - 3. Limit I/O port scanning to four I/O ports: - boot: linux advansys=0x110,0x210,0x230,0x330 - - For a loadable module the same effect can be achieved by setting - the 'asc_iopflag' variable and 'asc_ioport' array when loading - the driver, e.g. - - insmod advansys.o asc_iopflag=1 asc_ioport=0x110,0x330 - - If ADVANSYS_DEBUG is defined a 5th (ASC_NUM_IOPORT_PROBE + 1) - I/O Port may be added to specify the driver debug level. Refer to - the 'Driver Compile Time Options and Debugging' section above for - more information. - - G. Tests to run before releasing new driver - - 1. In the supported kernels verify there are no warning or compile - errors when the kernel is built as both a driver and as a module - and with the following options: - - ADVANSYS_DEBUG - enabled and disabled - CONFIG_SMP - enabled and disabled - CONFIG_PROC_FS - enabled and disabled - - 2. Run tests on an x86, alpha, and PowerPC with at least one narrow - card and one wide card attached to a hard disk and CD-ROM drive: - fdisk, mkfs, fsck, bonnie, copy/compare test from the - CD-ROM to the hard drive. - - H. Release History - - BETA-1.0 (12/23/95): - First Release - - BETA-1.1 (12/28/95): - 1. Prevent advansys_detect() from being called twice. - 2. Add LILO 0xdeb[0-f] option to set 'asc_dbglvl'. - - 1.2 (1/12/96): - 1. Prevent re-entrancy in the interrupt handler which - resulted in the driver hanging Linux. - 2. Fix problem that prevented ABP-940 cards from being - recognized on some PCI motherboards. - 3. Add support for the ABP-5140 PnP ISA card. - 4. Fix check condition return status. - 5. Add conditionally compiled code for Linux v1.3.X. - - 1.3 (2/23/96): - 1. Fix problem in advansys_biosparam() that resulted in the - wrong drive geometry being returned for drives > 1GB with - extended translation enabled. - 2. Add additional tracing during device initialization. - 3. Change code that only applies to ISA PnP adapter. - 4. Eliminate 'make dep' warning. - 5. Try to fix problem with handling resets by increasing their - timeout value. - - 1.4 (5/8/96): - 1. Change definitions to eliminate conflicts with other subsystems. - 2. Add versioning code for the shared interrupt changes. - 3. Eliminate problem in asc_rmqueue() with iterating after removing - a request. - 4. Remove reset request loop problem from the "Known Problems or - Issues" section. This problem was isolated and fixed in the - mid-level SCSI driver. - - 1.5 (8/8/96): - 1. Add support for ABP-940U (PCI Ultra) adapter. - 2. Add support for IRQ sharing by setting the IRQF_SHARED flag for - request_irq and supplying a dev_id pointer to both request_irq() - and free_irq(). - 3. In AscSearchIOPortAddr11() restore a call to check_region() which - should be used before I/O port probing. - 4. Fix bug in asc_prt_hex() which resulted in the displaying - the wrong data. - 5. Incorporate miscellaneous Asc Library bug fixes and new microcode. - 6. Change driver versioning to be specific to each Linux sub-level. - 7. Change statistics gathering to be per adapter instead of global - to the driver. - 8. Add more information and statistics to the adapter /proc file: - /proc/scsi/advansys[0...]. - 9. Remove 'cmd_per_lun' from the "Known Problems or Issues" list. - This problem has been addressed with the SCSI mid-level changes - made in v1.3.89. The advansys_select_queue_depths() function - was added for the v1.3.89 changes. - - 1.6 (9/10/96): - 1. Incorporate miscellaneous Asc Library bug fixes and new microcode. - - 1.7 (9/25/96): - 1. Enable clustering and optimize the setting of the maximum number - of scatter gather elements for any particular board. Clustering - increases CPU utilization, but results in a relatively larger - increase in I/O throughput. - 2. Improve the performance of the request queuing functions by - adding a last pointer to the queue structure. - 3. Correct problems with reset and abort request handling that - could have hung or crashed Linux. - 4. Add more information to the adapter /proc file: - /proc/scsi/advansys[0...]. - 5. Remove the request timeout issue form the driver issues list. - 6. Miscellaneous documentation additions and changes. - - 1.8 (10/4/96): - 1. Make changes to handle the new v2.1.0 kernel memory mapping - in which a kernel virtual address may not be equivalent to its - bus or DMA memory address. - 2. Change abort and reset request handling to make it yet even - more robust. - 3. Try to mitigate request starvation by sending ordered requests - to heavily loaded, tag queuing enabled devices. - 4. Maintain statistics on request response time. - 5. Add request response time statistics and other information to - the adapter /proc file: /proc/scsi/advansys[0...]. - - 1.9 (10/21/96): - 1. Add conditionally compiled code (ASC_QUEUE_FLOW_CONTROL) to - make use of mid-level SCSI driver device queue depth flow - control mechanism. This will eliminate aborts caused by a - device being unable to keep up with requests and eliminate - repeat busy or QUEUE FULL status returned by a device. - 2. Incorporate miscellaneous Asc Library bug fixes. - 3. To allow the driver to work in kernels with broken module - support set 'cmd_per_lun' if the driver is compiled as a - module. This change affects kernels v1.3.89 to present. - 4. Remove PCI BIOS address from the driver banner. The PCI BIOS - is relocated by the motherboard BIOS and its new address can - not be determined by the driver. - 5. Add mid-level SCSI queue depth information to the adapter - /proc file: /proc/scsi/advansys[0...]. - - 2.0 (11/14/96): - 1. Change allocation of global structures used for device - initialization to guarantee they are in DMA-able memory. - Previously when the driver was loaded as a module these - structures might not have been in DMA-able memory, causing - device initialization to fail. - - 2.1 (12/30/96): - 1. In advansys_reset(), if the request is a synchronous reset - request, even if the request serial number has changed, then - complete the request. - 2. Add Asc Library bug fixes including new microcode. - 3. Clear inquiry buffer before using it. - 4. Correct ifdef typo. - - 2.2 (1/15/97): - 1. Add Asc Library bug fixes including new microcode. - 2. Add synchronous data transfer rate information to the - adapter /proc file: /proc/scsi/advansys[0...]. - 3. Change ADVANSYS_DEBUG to be disabled by default. This - will reduce the size of the driver image, eliminate execution - overhead, and remove unneeded symbols from the kernel symbol - space that were previously added by the driver. - 4. Add new compile-time option ADVANSYS_ASSERT for assertion - code that used to be defined within ADVANSYS_DEBUG. This - option is enabled by default. - - 2.8 (5/26/97): - 1. Change version number to 2.8 to synchronize the Linux driver - version numbering with other AdvanSys drivers. - 2. Reformat source files without tabs to present the same view - of the file to everyone regardless of the editor tab setting - being used. - 3. Add Asc Library bug fixes. - - 3.1A (1/8/98): - 1. Change version number to 3.1 to indicate that support for - Ultra-Wide adapters (ABP-940UW) is included in this release. - 2. Add Asc Library (Narrow Board) bug fixes. - 3. Report an underrun condition with the host status byte set - to DID_UNDERRUN. Currently DID_UNDERRUN is defined to 0 which - causes the underrun condition to be ignored. When Linux defines - its own DID_UNDERRUN the constant defined in this file can be - removed. - 4. Add patch to AscWaitTixISRDone(). - 5. Add support for up to 16 different AdvanSys host adapter SCSI - channels in one system. This allows four cards with four channels - to be used in one system. - - 3.1B (1/9/98): - 1. Handle that PCI register base addresses are not always page - aligned even though ioremap() requires that the address argument - be page aligned. - - 3.1C (1/10/98): - 1. Update latest BIOS version checked for from the /proc file. - 2. Don't set microcode SDTR variable at initialization. Instead - wait until device capabilities have been detected from an Inquiry - command. - - 3.1D (1/21/98): - 1. Improve performance when the driver is compiled as module by - allowing up to 64 scatter-gather elements instead of 8. - - 3.1E (5/1/98): - 1. Set time delay in AscWaitTixISRDone() to 1000 ms. - 2. Include SMP locking changes. - 3. For v2.1.93 and newer kernels use CONFIG_PCI and new PCI BIOS - access functions. - 4. Update board serial number printing. - 5. Try allocating an IRQ both with and without the IRQF_DISABLED - flag set to allow IRQ sharing with drivers that do not set - the IRQF_DISABLED flag. Also display a more descriptive error - message if request_irq() fails. - 6. Update to latest Asc and Adv Libraries. - - 3.2A (7/22/99): - 1. Update Adv Library to 4.16 which includes support for - the ASC38C0800 (Ultra2/LVD) IC. - - 3.2B (8/23/99): - 1. Correct PCI compile time option for v2.1.93 and greater - kernels, advansys_info() string, and debug compile time - option. - 2. Correct DvcSleepMilliSecond() for v2.1.0 and greater - kernels. This caused an LVD detection/BIST problem problem - among other things. - 3. Sort PCI cards by PCI Bus, Slot, Function ascending order - to be consistent with the BIOS. - 4. Update to Asc Library S121 and Adv Library 5.2. - - 3.2C (8/24/99): - 1. Correct PCI card detection bug introduced in 3.2B that - prevented PCI cards from being detected in kernels older - than v2.1.93. - - 3.2D (8/26/99): - 1. Correct /proc device synchronous speed information display. - Also when re-negotiation is pending for a target device - note this condition with an * and footnote. - 2. Correct initialization problem with Ultra-Wide cards that - have a pre-3.2 BIOS. A microcode variable changed locations - in 3.2 and greater BIOSes which caused WDTR to be attempted - erroneously with drives that don't support WDTR. - - 3.2E (8/30/99): - 1. Fix compile error caused by v2.3.13 PCI structure change. - 2. Remove field from ASCEEP_CONFIG that resulted in an EEPROM - checksum error for ISA cards. - 3. Remove ASC_QUEUE_FLOW_CONTROL conditional code. The mid-level - SCSI changes that it depended on were never included in Linux. - - 3.2F (9/3/99): - 1. Handle new initial function code added in v2.3.16 for all - driver versions. - - 3.2G (9/8/99): - 1. Fix PCI board detection in v2.3.13 and greater kernels. - 2. Fix comiple errors in v2.3.X with debugging enabled. - - 3.2H (9/13/99): - 1. Add 64-bit address, long support for Alpha and UltraSPARC. - The driver has been verified to work on an Alpha system. - 2. Add partial byte order handling support for Power PC and - other big-endian platforms. This support has not yet been - completed or verified. - 3. For wide boards replace block zeroing of request and - scatter-gather structures with individual field initialization - to improve performance. - 4. Correct and clarify ROM BIOS version detection. - - 3.2I (10/8/99): - 1. Update to Adv Library 5.4. - 2. Add v2.3.19 underrun reporting to asc_isr_callback() and - adv_isr_callback(). Remove DID_UNDERRUN constant and other - no longer needed code that previously documented the lack - of underrun handling. - - 3.2J (10/14/99): - 1. Eliminate compile errors for v2.0 and earlier kernels. - - 3.2K (11/15/99): - 1. Correct debug compile error in asc_prt_adv_scsi_req_q(). - 2. Update Adv Library to 5.5. - 3. Add ifdef handling for /proc changes added in v2.3.28. - 4. Increase Wide board scatter-gather list maximum length to - 255 when the driver is compiled into the kernel. - - 3.2L (11/18/99): - 1. Fix bug in adv_get_sglist() that caused an assertion failure - at line 7475. The reqp->sgblkp pointer must be initialized - to NULL in adv_get_sglist(). - - 3.2M (11/29/99): - 1. Really fix bug in adv_get_sglist(). - 2. Incorporate v2.3.29 changes into driver. - - 3.2N (4/1/00): - 1. Add CONFIG_ISA ifdef code. - 2. Include advansys_interrupts_enabled name change patch. - 3. For >= v2.3.28 use new SCSI error handling with new function - advansys_eh_bus_reset(). Don't include an abort function - because of base library limitations. - 4. For >= v2.3.28 use per board lock instead of io_request_lock. - 5. For >= v2.3.28 eliminate advansys_command() and - advansys_command_done(). - 6. Add some changes for PowerPC (Big Endian) support, but it isn't - working yet. - 7. Fix "nonexistent resource free" problem that occurred on a module - unload for boards with an I/O space >= 255. The 'n_io_port' field - is only one byte and can not be used to hold an ioport length more - than 255. - - 3.3A (4/4/00): - 1. Update to Adv Library 5.8. - 2. For wide cards add support for CDBs up to 16 bytes. - 3. Eliminate warnings when CONFIG_PROC_FS is not defined. - - 3.3B (5/1/00): - 1. Support for PowerPC (Big Endian) wide cards. Narrow cards - still need work. - 2. Change bitfields to shift and mask access for endian - portability. - - 3.3C (10/13/00): - 1. Update for latest 2.4 kernel. - 2. Test ABP-480 CardBus support in 2.4 kernel - works! - 3. Update to Asc Library S123. - 4. Update to Adv Library 5.12. - - 3.3D (11/22/00): - 1. Update for latest 2.4 kernel. - 2. Create patches for 2.2 and 2.4 kernels. - - 3.3E (1/9/01): - 1. Now that 2.4 is released remove ifdef code for kernel versions - less than 2.2. The driver is now only supported in kernels 2.2, - 2.4, and greater. - 2. Add code to release and acquire the io_request_lock in - the driver entrypoint functions: advansys_detect and - advansys_queuecommand. In kernel 2.4 the SCSI mid-level driver - still holds the io_request_lock on entry to SCSI low-level drivers. - This was supposed to be removed before 2.4 was released but never - happened. When the mid-level SCSI driver is changed all references - to the io_request_lock should be removed from the driver. - 3. Simplify error handling by removing advansys_abort(), - AscAbortSRB(), AscResetDevice(). SCSI bus reset requests are - now handled by resetting the SCSI bus and fully re-initializing - the chip. This simple method of error recovery has proven to work - most reliably after attempts at different methods. Also now only - support the "new" error handling method and remove the obsolete - error handling interface. - 4. Fix debug build errors. - - 3.3F (1/24/01): - 1. Merge with ConnectCom version from Andy Kellner which - updates Adv Library to 5.14. - 2. Make PowerPC (Big Endian) work for narrow cards and - fix problems writing EEPROM for wide cards. - 3. Remove interrupts_enabled assertion function. - - 3.3G (2/16/01): - 1. Return an error from narrow boards if passed a 16 byte - CDB. The wide board can already handle 16 byte CDBs. - - 3.3GJ (4/15/02): - 1. hacks for lk 2.5 series (D. Gilbert) - - 3.3GJD (10/14/02): - 1. change select_queue_depths to slave_configure - 2. make cmd_per_lun be sane again - - 3.3K [2004/06/24]: - 1. continuing cleanup for lk 2.6 series - 2. Fix problem in lk 2.6.7-bk2 that broke PCI wide cards - 3. Fix problem that oopsed ISA cards - - I. Known Problems/Fix List (XXX) - - 1. Need to add memory mapping workaround. Test the memory mapping. - If it doesn't work revert to I/O port access. Can a test be done - safely? - 2. Handle an interrupt not working. Keep an interrupt counter in - the interrupt handler. In the timeout function if the interrupt - has not occurred then print a message and run in polled mode. - 3. Allow bus type scanning order to be changed. - 4. Need to add support for target mode commands, cf. CAM XPT. - - J. Credits (Chronological Order) - - Bob Frey <bfrey@turbolinux.com.cn> wrote the AdvanSys SCSI driver - and maintained it up to 3.3F. He continues to answer questions - and help maintain the driver. - - Nathan Hartwell <mage@cdc3.cdc.net> provided the directions and - basis for the Linux v1.3.X changes which were included in the - 1.2 release. - - Thomas E Zerucha <zerucha@shell.portal.com> pointed out a bug - in advansys_biosparam() which was fixed in the 1.3 release. - - Erik Ratcliffe <erik@caldera.com> has done testing of the - AdvanSys driver in the Caldera releases. - - Rik van Riel <H.H.vanRiel@fys.ruu.nl> provided a patch to - AscWaitTixISRDone() which he found necessary to make the - driver work with a SCSI-1 disk. - - Mark Moran <mmoran@mmoran.com> has helped test Ultra-Wide - support in the 3.1A driver. - - Doug Gilbert <dgilbert@interlog.com> has made changes and - suggestions to improve the driver and done a lot of testing. - - Ken Mort <ken@mort.net> reported a DEBUG compile bug fixed - in 3.2K. - - Tom Rini <trini@kernel.crashing.org> provided the CONFIG_ISA - patch and helped with PowerPC wide and narrow board support. - - Philip Blundell <philb@gnu.org> provided an - advansys_interrupts_enabled patch. - - Dave Jones <dave@denial.force9.co.uk> reported the compiler - warnings generated when CONFIG_PROC_FS was not defined in - the 3.2M driver. - - Jerry Quinn <jlquinn@us.ibm.com> fixed PowerPC support (endian - problems) for wide cards. - - Bryan Henderson <bryanh@giraffe-data.com> helped debug narrow - card error handling. - - Manuel Veloso <veloso@pobox.com> worked hard on PowerPC narrow - board support and fixed a bug in AscGetEEPConfig(). - - Arnaldo Carvalho de Melo <acme@conectiva.com.br> made - save_flags/restore_flags changes. - - Andy Kellner <AKellner@connectcom.net> continues the Advansys SCSI - driver development for ConnectCom (Version > 3.3F). - - K. ConnectCom (AdvanSys) Contact Information - - Mail: ConnectCom Solutions, Inc. - 1150 Ringwood Court - San Jose, CA 95131 - Operator/Sales: 1-408-383-9400 - FAX: 1-408-383-9612 - Tech Support: 1-408-467-2930 - Tech Support E-Mail: linux@connectcom.net - FTP Site: ftp.connectcom.net (login: anonymous) - Web Site: http://www.connectcom.net - -*/ - -/* - * --- Linux Include Files + * As of March 8, 2000 Advanced System Products, Inc. (AdvanSys) + * changed its name to ConnectCom Solutions, Inc. + * On June 18, 2001 Initio Corp. acquired ConnectCom's SCSI assets */ #include <linux/module.h> - -#if defined(CONFIG_X86) && !defined(CONFIG_ISA) -#define CONFIG_ISA -#endif /* CONFIG_X86 && !CONFIG_ISA */ - #include <linux/string.h> #include <linux/kernel.h> #include <linux/types.h> @@ -771,7 +33,9 @@ #include <linux/proc_fs.h> #include <linux/init.h> #include <linux/blkdev.h> -#include <linux/stat.h> +#include <linux/isa.h> +#include <linux/eisa.h> +#include <linux/pci.h> #include <linux/spinlock.h> #include <linux/dma-mapping.h> @@ -779,49 +43,38 @@ #include <asm/system.h> #include <asm/dma.h> -/* FIXME: (by jejb@steeleye.com) This warning is present for two - * reasons: - * - * 1) This driver badly needs converting to the correct driver model - * probing API - * - * 2) Although all of the necessary command mapping places have the - * appropriate dma_map.. APIs, the driver still processes its internal - * queue using bus_to_virt() and virt_to_bus() which are illegal under - * the API. The entire queue processing structure will need to be - * altered to fix this. - */ -#warning this driver is still not properly converted to the DMA API - #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_tcq.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> -#ifdef CONFIG_PCI -#include <linux/pci.h> -#endif /* CONFIG_PCI */ -/* - * --- Driver Options +/* FIXME: + * + * 1. Although all of the necessary command mapping places have the + * appropriate dma_map.. APIs, the driver still processes its internal + * queue using bus_to_virt() and virt_to_bus() which are illegal under + * the API. The entire queue processing structure will need to be + * altered to fix this. + * 2. Need to add memory mapping workaround. Test the memory mapping. + * If it doesn't work revert to I/O port access. Can a test be done + * safely? + * 3. Handle an interrupt not working. Keep an interrupt counter in + * the interrupt handler. In the timeout function if the interrupt + * has not occurred then print a message and run in polled mode. + * 4. Need to add support for target mode commands, cf. CAM XPT. + * 5. check DMA mapping functions for failure + * 6. Use scsi_transport_spi + * 7. advansys_info is not safe against multiple simultaneous callers + * 8. Add module_param to override ISA/VLB ioport array */ - -/* Enable driver assertions. */ -#define ADVANSYS_ASSERT +#warning this driver is still not properly converted to the DMA API /* Enable driver /proc statistics. */ #define ADVANSYS_STATS /* Enable driver tracing. */ -/* #define ADVANSYS_DEBUG */ - -/* - * --- Asc Library Constants and Macros - */ - -#define ASC_LIB_VERSION_MAJOR 1 -#define ASC_LIB_VERSION_MINOR 24 -#define ASC_LIB_SERIAL_NUMBER 123 +#undef ADVANSYS_DEBUG /* * Portable Data Types @@ -837,17 +90,6 @@ #define ASC_DCNT __u32 /* Unsigned Data count type. */ #define ASC_SDCNT __s32 /* Signed Data count type. */ -/* - * These macros are used to convert a virtual address to a - * 32-bit value. This currently can be used on Linux Alpha - * which uses 64-bit virtual address but a 32-bit bus address. - * This is likely to break in the future, but doing this now - * will give us time to change the HW and FW to handle 64-bit - * addresses. - */ -#define ASC_VADDR_TO_U32 virt_to_bus -#define ASC_U32_TO_VADDR bus_to_virt - typedef unsigned char uchar; #ifndef TRUE @@ -857,29 +99,9 @@ typedef unsigned char uchar; #define FALSE (0) #endif -#define EOF (-1) #define ERR (-1) #define UW_ERR (uint)(0xFFFF) #define isodd_word(val) ((((uint)val) & (uint)0x0001) != 0) -#define AscPCIConfigVendorIDRegister 0x0000 -#define AscPCIConfigDeviceIDRegister 0x0002 -#define AscPCIConfigCommandRegister 0x0004 -#define AscPCIConfigStatusRegister 0x0006 -#define AscPCIConfigRevisionIDRegister 0x0008 -#define AscPCIConfigCacheSize 0x000C -#define AscPCIConfigLatencyTimer 0x000D -#define AscPCIIOBaseRegister 0x0010 -#define AscPCICmdRegBits_IOMemBusMaster 0x0007 -#define ASC_PCI_ID2BUS(id) ((id) & 0xFF) -#define ASC_PCI_ID2DEV(id) (((id) >> 11) & 0x1F) -#define ASC_PCI_ID2FUNC(id) (((id) >> 8) & 0x7) -#define ASC_PCI_MKID(bus, dev, func) ((((dev) & 0x1F) << 11) | (((func) & 0x7) << 8) | ((bus) & 0xFF)) -#define ASC_PCI_REVISION_3150 0x02 -#define ASC_PCI_REVISION_3050 0x03 - -#define ASC_DVCLIB_CALL_DONE (1) -#define ASC_DVCLIB_CALL_FAILED (0) -#define ASC_DVCLIB_CALL_ERROR (-1) #define PCI_VENDOR_ID_ASP 0x10cd #define PCI_DEVICE_ID_ASP_1200A 0x1100 @@ -898,7 +120,7 @@ typedef unsigned char uchar; #define CC_VERY_LONG_SG_LIST 0 #define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr) -#define PortAddr unsigned short /* port address size */ +#define PortAddr unsigned int /* port address size */ #define inp(port) inb(port) #define outp(port, byte) outb((byte), (port)) @@ -918,11 +140,10 @@ typedef unsigned char uchar; #define ASC_IS_PCMCIA (0x0008) #define ASC_IS_MCA (0x0020) #define ASC_IS_VL (0x0040) -#define ASC_ISA_PNP_PORT_ADDR (0x279) -#define ASC_ISA_PNP_PORT_WRITE (ASC_ISA_PNP_PORT_ADDR+0x800) #define ASC_IS_WIDESCSI_16 (0x0100) #define ASC_IS_WIDESCSI_32 (0x0200) #define ASC_IS_BIG_ENDIAN (0x8000) + #define ASC_CHIP_MIN_VER_VL (0x01) #define ASC_CHIP_MAX_VER_VL (0x07) #define ASC_CHIP_MIN_VER_PCI (0x09) @@ -941,16 +162,9 @@ typedef unsigned char uchar; #define ASC_CHIP_MAX_VER_EISA (0x47) #define ASC_CHIP_VER_EISA_BIT (0x40) #define ASC_CHIP_LATEST_VER_EISA ((ASC_CHIP_MIN_VER_EISA - 1) + 3) -#define ASC_MAX_LIB_SUPPORTED_ISA_CHIP_VER 0x21 -#define ASC_MAX_LIB_SUPPORTED_PCI_CHIP_VER 0x0A -#define ASC_MAX_VL_DMA_ADDR (0x07FFFFFFL) #define ASC_MAX_VL_DMA_COUNT (0x07FFFFFFL) -#define ASC_MAX_PCI_DMA_ADDR (0xFFFFFFFFL) #define ASC_MAX_PCI_DMA_COUNT (0xFFFFFFFFL) -#define ASC_MAX_ISA_DMA_ADDR (0x00FFFFFFL) #define ASC_MAX_ISA_DMA_COUNT (0x00FFFFFFL) -#define ASC_MAX_EISA_DMA_ADDR (0x07FFFFFFL) -#define ASC_MAX_EISA_DMA_COUNT (0x07FFFFFFL) #define ASC_SCSI_ID_BITS 3 #define ASC_SCSI_TIX_TYPE uchar @@ -961,82 +175,17 @@ typedef unsigned char uchar; #define ASC_SCSI_WIDTH_BIT_SET 0xFF #define ASC_MAX_SENSE_LEN 32 #define ASC_MIN_SENSE_LEN 14 -#define ASC_MAX_CDB_LEN 12 #define ASC_SCSI_RESET_HOLD_TIME_US 60 -#define ADV_INQ_CLOCKING_ST_ONLY 0x0 -#define ADV_INQ_CLOCKING_DT_ONLY 0x1 -#define ADV_INQ_CLOCKING_ST_AND_DT 0x3 - /* - * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data) - * and CmdDt (Command Support Data) field bit definitions. + * Narrow boards only support 12-byte commands, while wide boards + * extend to 16-byte commands. */ -#define ADV_INQ_RTN_VPD_AND_CMDDT 0x3 -#define ADV_INQ_RTN_CMDDT_FOR_OP_CODE 0x2 -#define ADV_INQ_RTN_VPD_FOR_PG_CODE 0x1 -#define ADV_INQ_RTN_STD_INQUIRY_DATA 0x0 - -#define ASC_SCSIDIR_NOCHK 0x00 -#define ASC_SCSIDIR_T2H 0x08 -#define ASC_SCSIDIR_H2T 0x10 -#define ASC_SCSIDIR_NODATA 0x18 -#define SCSI_ASC_NOMEDIA 0x3A -#define ASC_SRB_HOST(x) ((uchar)((uchar)(x) >> 4)) -#define ASC_SRB_TID(x) ((uchar)((uchar)(x) & (uchar)0x0F)) -#define ASC_SRB_LUN(x) ((uchar)((uint)(x) >> 13)) -#define PUT_CDB1(x) ((uchar)((uint)(x) >> 8)) -#define MS_CMD_DONE 0x00 -#define MS_EXTEND 0x01 +#define ASC_MAX_CDB_LEN 12 +#define ADV_MAX_CDB_LEN 16 + #define MS_SDTR_LEN 0x03 -#define MS_SDTR_CODE 0x01 #define MS_WDTR_LEN 0x02 -#define MS_WDTR_CODE 0x03 -#define MS_MDP_LEN 0x05 -#define MS_MDP_CODE 0x00 - -/* - * Inquiry data structure and bitfield macros - * - * Only quantities of more than 1 bit are shifted, since the others are - * just tested for true or false. C bitfields aren't portable between big - * and little-endian platforms so they are not used. - */ - -#define ASC_INQ_DVC_TYPE(inq) ((inq)->periph & 0x1f) -#define ASC_INQ_QUALIFIER(inq) (((inq)->periph & 0xe0) >> 5) -#define ASC_INQ_DVC_TYPE_MOD(inq) ((inq)->devtype & 0x7f) -#define ASC_INQ_REMOVABLE(inq) ((inq)->devtype & 0x80) -#define ASC_INQ_ANSI_VER(inq) ((inq)->ver & 0x07) -#define ASC_INQ_ECMA_VER(inq) (((inq)->ver & 0x38) >> 3) -#define ASC_INQ_ISO_VER(inq) (((inq)->ver & 0xc0) >> 6) -#define ASC_INQ_RESPONSE_FMT(inq) ((inq)->byte3 & 0x0f) -#define ASC_INQ_TERM_IO(inq) ((inq)->byte3 & 0x40) -#define ASC_INQ_ASYNC_NOTIF(inq) ((inq)->byte3 & 0x80) -#define ASC_INQ_SOFT_RESET(inq) ((inq)->flags & 0x01) -#define ASC_INQ_CMD_QUEUE(inq) ((inq)->flags & 0x02) -#define ASC_INQ_LINK_CMD(inq) ((inq)->flags & 0x08) -#define ASC_INQ_SYNC(inq) ((inq)->flags & 0x10) -#define ASC_INQ_WIDE16(inq) ((inq)->flags & 0x20) -#define ASC_INQ_WIDE32(inq) ((inq)->flags & 0x40) -#define ASC_INQ_REL_ADDR(inq) ((inq)->flags & 0x80) -#define ASC_INQ_INFO_UNIT(inq) ((inq)->info & 0x01) -#define ASC_INQ_QUICK_ARB(inq) ((inq)->info & 0x02) -#define ASC_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2) - -typedef struct { - uchar periph; - uchar devtype; - uchar ver; - uchar byte3; - uchar add_len; - uchar res1; - uchar res2; - uchar flags; - uchar vendor_id[8]; - uchar product_id[16]; - uchar product_rev_level[4]; -} ASC_SCSI_INQUIRY; #define ASC_SG_LIST_PER_Q 7 #define QS_FREE 0x00 @@ -1215,22 +364,9 @@ typedef struct asc_sg_head { ushort queue_cnt; ushort entry_to_copy; ushort res; - ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; + ASC_SG_LIST sg_list[0]; } ASC_SG_HEAD; -#define ASC_MIN_SG_LIST 2 - -typedef struct asc_min_sg_head { - ushort entry_cnt; - ushort queue_cnt; - ushort entry_to_copy; - ushort res; - ASC_SG_LIST sg_list[ASC_MIN_SG_LIST]; -} ASC_MIN_SG_HEAD; - -#define QCX_SORT (0x0001) -#define QCX_COALEASE (0x0002) - typedef struct asc_scsi_q { ASC_SCSIQ_1 q1; ASC_SCSIQ_2 q2; @@ -1287,45 +423,12 @@ typedef struct asc_risc_sg_list_q { ASC_SG_LIST sg_list[7]; } ASC_RISC_SG_LIST_Q; -#define ASC_EXE_SCSI_IO_MAX_IDLE_LOOP 0x1000000UL -#define ASC_EXE_SCSI_IO_MAX_WAIT_LOOP 1024 -#define ASCQ_ERR_NO_ERROR 0 -#define ASCQ_ERR_IO_NOT_FOUND 1 -#define ASCQ_ERR_LOCAL_MEM 2 -#define ASCQ_ERR_CHKSUM 3 -#define ASCQ_ERR_START_CHIP 4 -#define ASCQ_ERR_INT_TARGET_ID 5 -#define ASCQ_ERR_INT_LOCAL_MEM 6 -#define ASCQ_ERR_HALT_RISC 7 -#define ASCQ_ERR_GET_ASPI_ENTRY 8 -#define ASCQ_ERR_CLOSE_ASPI 9 -#define ASCQ_ERR_HOST_INQUIRY 0x0A -#define ASCQ_ERR_SAVED_SRB_BAD 0x0B -#define ASCQ_ERR_QCNTL_SG_LIST 0x0C #define ASCQ_ERR_Q_STATUS 0x0D -#define ASCQ_ERR_WR_SCSIQ 0x0E -#define ASCQ_ERR_PC_ADDR 0x0F -#define ASCQ_ERR_SYN_OFFSET 0x10 -#define ASCQ_ERR_SYN_XFER_TIME 0x11 -#define ASCQ_ERR_LOCK_DMA 0x12 -#define ASCQ_ERR_UNLOCK_DMA 0x13 -#define ASCQ_ERR_VDS_CHK_INSTALL 0x14 -#define ASCQ_ERR_MICRO_CODE_HALT 0x15 -#define ASCQ_ERR_SET_LRAM_ADDR 0x16 #define ASCQ_ERR_CUR_QNG 0x17 #define ASCQ_ERR_SG_Q_LINKS 0x18 -#define ASCQ_ERR_SCSIQ_PTR 0x19 #define ASCQ_ERR_ISR_RE_ENTRY 0x1A #define ASCQ_ERR_CRITICAL_RE_ENTRY 0x1B #define ASCQ_ERR_ISR_ON_CRITICAL 0x1C -#define ASCQ_ERR_SG_LIST_ODD_ADDRESS 0x1D -#define ASCQ_ERR_XFER_ADDRESS_TOO_BIG 0x1E -#define ASCQ_ERR_SCSIQ_NULL_PTR 0x1F -#define ASCQ_ERR_SCSIQ_BAD_NEXT_PTR 0x20 -#define ASCQ_ERR_GET_NUM_OF_FREE_Q 0x21 -#define ASCQ_ERR_SEND_SCSI_Q 0x22 -#define ASCQ_ERR_HOST_REQ_RISC_HALT 0x23 -#define ASCQ_ERR_RESET_SDTR 0x24 /* * Warning code values are set in ASC_DVC_VAR 'warn_code'. @@ -1338,84 +441,51 @@ typedef struct asc_risc_sg_list_q { #define ASC_WARN_CMD_QNG_CONFLICT 0x0010 #define ASC_WARN_EEPROM_RECOVER 0x0020 #define ASC_WARN_CFG_MSW_RECOVER 0x0040 -#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* - * Error code values are set in ASC_DVC_VAR 'err_code'. + * Error code values are set in {ASC/ADV}_DVC_VAR 'err_code'. */ -#define ASC_IERR_WRITE_EEPROM 0x0001 -#define ASC_IERR_MCODE_CHKSUM 0x0002 -#define ASC_IERR_SET_PC_ADDR 0x0004 -#define ASC_IERR_START_STOP_CHIP 0x0008 -#define ASC_IERR_IRQ_NO 0x0010 -#define ASC_IERR_SET_IRQ_NO 0x0020 -#define ASC_IERR_CHIP_VERSION 0x0040 -#define ASC_IERR_SET_SCSI_ID 0x0080 -#define ASC_IERR_GET_PHY_ADDR 0x0100 -#define ASC_IERR_BAD_SIGNATURE 0x0200 -#define ASC_IERR_NO_BUS_TYPE 0x0400 -#define ASC_IERR_SCAM 0x0800 -#define ASC_IERR_SET_SDTR 0x1000 -#define ASC_IERR_RW_LRAM 0x8000 - -#define ASC_DEF_IRQ_NO 10 -#define ASC_MAX_IRQ_NO 15 -#define ASC_MIN_IRQ_NO 10 -#define ASC_MIN_REMAIN_Q (0x02) +#define ASC_IERR_NO_CARRIER 0x0001 /* No more carrier memory */ +#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */ +#define ASC_IERR_SET_PC_ADDR 0x0004 +#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */ +#define ASC_IERR_ILLEGAL_CONNECTION 0x0010 /* Illegal cable connection */ +#define ASC_IERR_SINGLE_END_DEVICE 0x0020 /* SE device on DIFF bus */ +#define ASC_IERR_REVERSED_CABLE 0x0040 /* Narrow flat cable reversed */ +#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */ +#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD device on LVD port */ +#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */ +#define ASC_IERR_NO_BUS_TYPE 0x0400 +#define ASC_IERR_BIST_PRE_TEST 0x0800 /* BIST pre-test error */ +#define ASC_IERR_BIST_RAM_TEST 0x1000 /* BIST RAM test error */ +#define ASC_IERR_BAD_CHIPTYPE 0x2000 /* Invalid chip_type setting */ + #define ASC_DEF_MAX_TOTAL_QNG (0xF0) #define ASC_MIN_TAG_Q_PER_DVC (0x04) -#define ASC_DEF_TAG_Q_PER_DVC (0x04) -#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q +#define ASC_MIN_FREE_Q (0x02) #define ASC_MIN_TOTAL_QNG ((ASC_MAX_SG_QUEUE)+(ASC_MIN_FREE_Q)) #define ASC_MAX_TOTAL_QNG 240 #define ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG 16 #define ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG 8 #define ASC_MAX_PCI_INRAM_TOTAL_QNG 20 #define ASC_MAX_INRAM_TAG_QNG 16 -#define ASC_IOADR_TABLE_MAX_IX 11 #define ASC_IOADR_GAP 0x10 -#define ASC_SEARCH_IOP_GAP 0x10 -#define ASC_MIN_IOP_ADDR (PortAddr)0x0100 -#define ASC_MAX_IOP_ADDR (PortAddr)0x3F0 -#define ASC_IOADR_1 (PortAddr)0x0110 -#define ASC_IOADR_2 (PortAddr)0x0130 -#define ASC_IOADR_3 (PortAddr)0x0150 -#define ASC_IOADR_4 (PortAddr)0x0190 -#define ASC_IOADR_5 (PortAddr)0x0210 -#define ASC_IOADR_6 (PortAddr)0x0230 -#define ASC_IOADR_7 (PortAddr)0x0250 -#define ASC_IOADR_8 (PortAddr)0x0330 -#define ASC_IOADR_DEF ASC_IOADR_8 -#define ASC_LIB_SCSIQ_WK_SP 256 -#define ASC_MAX_SYN_XFER_NO 16 #define ASC_SYN_MAX_OFFSET 0x0F #define ASC_DEF_SDTR_OFFSET 0x0F -#define ASC_DEF_SDTR_INDEX 0x00 #define ASC_SDTR_ULTRA_PCI_10MB_INDEX 0x02 -#define SYN_XFER_NS_0 25 -#define SYN_XFER_NS_1 30 -#define SYN_XFER_NS_2 35 -#define SYN_XFER_NS_3 40 -#define SYN_XFER_NS_4 50 -#define SYN_XFER_NS_5 60 -#define SYN_XFER_NS_6 70 -#define SYN_XFER_NS_7 85 -#define SYN_ULTRA_XFER_NS_0 12 -#define SYN_ULTRA_XFER_NS_1 19 -#define SYN_ULTRA_XFER_NS_2 25 -#define SYN_ULTRA_XFER_NS_3 32 -#define SYN_ULTRA_XFER_NS_4 38 -#define SYN_ULTRA_XFER_NS_5 44 -#define SYN_ULTRA_XFER_NS_6 50 -#define SYN_ULTRA_XFER_NS_7 57 -#define SYN_ULTRA_XFER_NS_8 63 -#define SYN_ULTRA_XFER_NS_9 69 -#define SYN_ULTRA_XFER_NS_10 75 -#define SYN_ULTRA_XFER_NS_11 82 -#define SYN_ULTRA_XFER_NS_12 88 -#define SYN_ULTRA_XFER_NS_13 94 -#define SYN_ULTRA_XFER_NS_14 100 -#define SYN_ULTRA_XFER_NS_15 107 +#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41 + +/* The narrow chip only supports a limited selection of transfer rates. + * These are encoded in the range 0..7 or 0..15 depending whether the chip + * is Ultra-capable or not. These tables let us convert from one to the other. + */ +static const unsigned char asc_syn_xfer_period[8] = { + 25, 30, 35, 40, 50, 60, 70, 85 +}; + +static const unsigned char asc_syn_ultra_xfer_period[16] = { + 12, 19, 25, 32, 38, 44, 50, 57, 63, 69, 75, 82, 88, 94, 100, 107 +}; typedef struct ext_msg { uchar msg_type; @@ -1456,22 +526,16 @@ typedef struct asc_dvc_cfg { uchar isa_dma_speed; uchar isa_dma_channel; uchar chip_version; - ushort lib_serial_no; - ushort lib_version; ushort mcode_date; ushort mcode_version; uchar max_tag_qng[ASC_MAX_TID + 1]; - uchar *overrun_buf; uchar sdtr_period_offset[ASC_MAX_TID + 1]; - ushort pci_slot_info; uchar adapter_info[6]; - struct device *dev; } ASC_DVC_CFG; #define ASC_DEF_DVC_CNTL 0xFFFF #define ASC_DEF_CHIP_SCSI_ID 7 #define ASC_DEF_ISA_DMA_SPEED 4 -#define ASC_INIT_STATE_NULL 0x0000 #define ASC_INIT_STATE_BEG_GET_CFG 0x0001 #define ASC_INIT_STATE_END_GET_CFG 0x0002 #define ASC_INIT_STATE_BEG_SET_CFG 0x0004 @@ -1484,43 +548,39 @@ typedef struct asc_dvc_cfg { #define ASC_INIT_STATE_WITHOUT_EEP 0x8000 #define ASC_BUG_FIX_IF_NOT_DWB 0x0001 #define ASC_BUG_FIX_ASYN_USE_SYN 0x0002 -#define ASYN_SDTR_DATA_FIX_PCI_REV_AB 0x41 #define ASC_MIN_TAGGED_CMD 7 #define ASC_MAX_SCSI_RESET_WAIT 30 +#define ASC_OVERRUN_BSIZE 64 struct asc_dvc_var; /* Forward Declaration. */ -typedef void (*ASC_ISR_CALLBACK) (struct asc_dvc_var *, ASC_QDONE_INFO *); -typedef int (*ASC_EXE_CALLBACK) (struct asc_dvc_var *, ASC_SCSI_Q *); - typedef struct asc_dvc_var { PortAddr iop_base; ushort err_code; ushort dvc_cntl; ushort bug_fix_cntl; ushort bus_type; - ASC_ISR_CALLBACK isr_callback; - ASC_EXE_CALLBACK exe_callback; ASC_SCSI_BIT_ID_TYPE init_sdtr; ASC_SCSI_BIT_ID_TYPE sdtr_done; ASC_SCSI_BIT_ID_TYPE use_tagged_qng; ASC_SCSI_BIT_ID_TYPE unit_not_ready; ASC_SCSI_BIT_ID_TYPE queue_full_or_busy; ASC_SCSI_BIT_ID_TYPE start_motor; + uchar overrun_buf[ASC_OVERRUN_BSIZE] __aligned(8); + dma_addr_t overrun_dma; uchar scsi_reset_wait; uchar chip_no; char is_in_int; uchar max_total_qng; uchar cur_total_qng; uchar in_critical_cnt; - uchar irq_no; uchar last_q_shortage; ushort init_state; uchar cur_dvc_qng[ASC_MAX_TID + 1]; uchar max_dvc_qng[ASC_MAX_TID + 1]; ASC_SCSI_Q *scsiq_busy_head[ASC_MAX_TID + 1]; ASC_SCSI_Q *scsiq_busy_tail[ASC_MAX_TID + 1]; - uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO]; + const uchar *sdtr_period_tbl; ASC_DVC_CFG *cfg; ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always; char redo_scam; @@ -1529,9 +589,11 @@ typedef struct asc_dvc_var { ASC_DCNT max_dma_count; ASC_SCSI_BIT_ID_TYPE no_scam; ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer; + uchar min_sdtr_index; uchar max_sdtr_index; - uchar host_init_sdtr_index; struct asc_board *drv_ptr; + int ptr_map_count; + void **ptr_map; ASC_DCNT uc_break; } ASC_DVC_VAR; @@ -1568,12 +630,7 @@ typedef struct asc_cap_info_array { #define ASC_EEP_MAX_DVC_ADDR_VL 15 #define ASC_EEP_DVC_CFG_BEG 32 #define ASC_EEP_MAX_DVC_ADDR 45 -#define ASC_EEP_DEFINED_WORDS 10 -#define ASC_EEP_MAX_ADDR 63 -#define ASC_EEP_RES_WORDS 0 #define ASC_EEP_MAX_RETRY 20 -#define ASC_MAX_INIT_BUSY_RETRY 8 -#define ASC_EEP_ISA_PNP_WSIZE 16 /* * These macros keep the chip SCSI id and ISA DMA speed @@ -1609,17 +666,10 @@ typedef struct asceep_config { ushort chksum; } ASCEEP_CONFIG; -#define ASC_PCI_CFG_LSW_SCSI_PARITY 0x0800 -#define ASC_PCI_CFG_LSW_BURST_MODE 0x0080 -#define ASC_PCI_CFG_LSW_INTR_ABLE 0x0020 - #define ASC_EEP_CMD_READ 0x80 #define ASC_EEP_CMD_WRITE 0x40 #define ASC_EEP_CMD_WRITE_ABLE 0x30 #define ASC_EEP_CMD_WRITE_DISABLE 0x00 -#define ASC_OVERRUN_BSIZE 0x00000048UL -#define ASC_CTRL_BREAK_ONCE 0x0001 -#define ASC_CTRL_BREAK_STAY_IDLE 0x0002 #define ASCV_MSGOUT_BEG 0x0000 #define ASCV_MSGOUT_SDTR_PERIOD (ASCV_MSGOUT_BEG+3) #define ASCV_MSGOUT_SDTR_OFFSET (ASCV_MSGOUT_BEG+4) @@ -1796,16 +846,9 @@ typedef struct asceep_config { #define ASC_1000_ID0W 0x04C1 #define ASC_1000_ID0W_FIX 0x00C1 #define ASC_1000_ID1B 0x25 -#define ASC_EISA_BIG_IOP_GAP (0x1C30-0x0C50) -#define ASC_EISA_SMALL_IOP_GAP (0x0020) -#define ASC_EISA_MIN_IOP_ADDR (0x0C30) -#define ASC_EISA_MAX_IOP_ADDR (0xFC50) #define ASC_EISA_REV_IOP_MASK (0x0C83) -#define ASC_EISA_PID_IOP_MASK (0x0C80) #define ASC_EISA_CFG_IOP_MASK (0x0C86) #define ASC_GET_EISA_SLOT(iop) (PortAddr)((iop) & 0xF000) -#define ASC_EISA_ID_740 0x01745004UL -#define ASC_EISA_ID_750 0x01755004UL #define INS_HALTINT (ushort)0x6281 #define INS_HALT (ushort)0x6280 #define INS_SINT (ushort)0x6200 @@ -1828,11 +871,10 @@ typedef struct asc_mc_saved { #define AscGetRiscVarDoneQTail(port) AscReadLramByte((port), ASCV_DONENEXT_B) #define AscPutRiscVarFreeQHead(port, val) AscWriteLramByte((port), ASCV_NEXTRDY_B, val) #define AscPutRiscVarDoneQTail(port, val) AscWriteLramByte((port), ASCV_DONENEXT_B, val) -#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data)); -#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id)); -#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data); -#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id)); -#define AscSynIndexToPeriod(index) (uchar)(asc_dvc->sdtr_period_tbl[ (index) ]) +#define AscPutMCodeSDTRDoneAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id), (data)) +#define AscGetMCodeSDTRDoneAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DONE_BEG+(ushort)id)) +#define AscPutMCodeInitSDTRAtID(port, id, data) AscWriteLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id), data) +#define AscGetMCodeInitSDTRAtID(port, id) AscReadLramByte((port), (ushort)((ushort)ASCV_SDTR_DATA_BEG+(ushort)id)) #define AscGetChipSignatureByte(port) (uchar)inp((port)+IOP_SIG_BYTE) #define AscGetChipSignatureWord(port) (ushort)inpw((port)+IOP_SIG_WORD) #define AscGetChipVerNo(port) (uchar)inp((port)+IOP_VERSION) @@ -1887,125 +929,6 @@ typedef struct asc_mc_saved { #define AscReadChipDvcID(port) (uchar)inp((port)+IOP_REG_ID) #define AscWriteChipDvcID(port, data) outp((port)+IOP_REG_ID, data) -static int AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg); -static int AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg); -static void AscWaitEEPRead(void); -static void AscWaitEEPWrite(void); -static ushort AscReadEEPWord(PortAddr, uchar); -static ushort AscWriteEEPWord(PortAddr, uchar, ushort); -static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); -static int AscSetEEPConfigOnce(PortAddr, ASCEEP_CONFIG *, ushort); -static int AscSetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); -static int AscStartChip(PortAddr); -static int AscStopChip(PortAddr); -static void AscSetChipIH(PortAddr, ushort); -static int AscIsChipHalted(PortAddr); -static void AscAckInterrupt(PortAddr); -static void AscDisableInterrupt(PortAddr); -static void AscEnableInterrupt(PortAddr); -static void AscSetBank(PortAddr, uchar); -static int AscResetChipAndScsiBus(ASC_DVC_VAR *); -#ifdef CONFIG_ISA -static ushort AscGetIsaDmaChannel(PortAddr); -static ushort AscSetIsaDmaChannel(PortAddr, ushort); -static uchar AscSetIsaDmaSpeed(PortAddr, uchar); -static uchar AscGetIsaDmaSpeed(PortAddr); -#endif /* CONFIG_ISA */ -static uchar AscReadLramByte(PortAddr, ushort); -static ushort AscReadLramWord(PortAddr, ushort); -#if CC_VERY_LONG_SG_LIST -static ASC_DCNT AscReadLramDWord(PortAddr, ushort); -#endif /* CC_VERY_LONG_SG_LIST */ -static void AscWriteLramWord(PortAddr, ushort, ushort); -static void AscWriteLramByte(PortAddr, ushort, uchar); -static ASC_DCNT AscMemSumLramWord(PortAddr, ushort, int); -static void AscMemWordSetLram(PortAddr, ushort, ushort, int); -static void AscMemWordCopyPtrToLram(PortAddr, ushort, uchar *, int); -static void AscMemDWordCopyPtrToLram(PortAddr, ushort, uchar *, int); -static void AscMemWordCopyPtrFromLram(PortAddr, ushort, uchar *, int); -static ushort AscInitAscDvcVar(ASC_DVC_VAR *); -static ushort AscInitFromEEP(ASC_DVC_VAR *); -static ushort AscInitFromAscDvcVar(ASC_DVC_VAR *); -static ushort AscInitMicroCodeVar(ASC_DVC_VAR *); -static int AscTestExternalLram(ASC_DVC_VAR *); -static uchar AscMsgOutSDTR(ASC_DVC_VAR *, uchar, uchar); -static uchar AscCalSDTRData(ASC_DVC_VAR *, uchar, uchar); -static void AscSetChipSDTR(PortAddr, uchar, uchar); -static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *, uchar); -static uchar AscAllocFreeQueue(PortAddr, uchar); -static uchar AscAllocMultipleFreeQueue(PortAddr, uchar, uchar); -static int AscHostReqRiscHalt(PortAddr); -static int AscStopQueueExe(PortAddr); -static int AscSendScsiQueue(ASC_DVC_VAR *, - ASC_SCSI_Q *scsiq, uchar n_q_required); -static int AscPutReadyQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar); -static int AscPutReadySgListQueue(ASC_DVC_VAR *, ASC_SCSI_Q *, uchar); -static int AscSetChipSynRegAtID(PortAddr, uchar, uchar); -static int AscSetRunChipSynRegAtID(PortAddr, uchar, uchar); -static ushort AscInitLram(ASC_DVC_VAR *); -static ushort AscInitQLinkVar(ASC_DVC_VAR *); -static int AscSetLibErrorCode(ASC_DVC_VAR *, ushort); -static int AscIsrChipHalted(ASC_DVC_VAR *); -static uchar _AscCopyLramScsiDoneQ(PortAddr, ushort, - ASC_QDONE_INFO *, ASC_DCNT); -static int AscIsrQDone(ASC_DVC_VAR *); -static int AscCompareString(uchar *, uchar *, int); -#ifdef CONFIG_ISA -static ushort AscGetEisaChipCfg(PortAddr); -static ASC_DCNT AscGetEisaProductID(PortAddr); -static PortAddr AscSearchIOPortAddrEISA(PortAddr); -static PortAddr AscSearchIOPortAddr11(PortAddr); -static PortAddr AscSearchIOPortAddr(PortAddr, ushort); -static void AscSetISAPNPWaitForKey(void); -#endif /* CONFIG_ISA */ -static uchar AscGetChipScsiCtrl(PortAddr); -static uchar AscSetChipScsiID(PortAddr, uchar); -static uchar AscGetChipVersion(PortAddr, ushort); -static ushort AscGetChipBusType(PortAddr); -static ASC_DCNT AscLoadMicroCode(PortAddr, ushort, uchar *, ushort); -static int AscFindSignature(PortAddr); -static void AscToggleIRQAct(PortAddr); -static uchar AscGetChipIRQ(PortAddr, ushort); -static uchar AscSetChipIRQ(PortAddr, uchar, ushort); -static ushort AscGetChipBiosAddress(PortAddr, ushort); -static inline ulong DvcEnterCritical(void); -static inline void DvcLeaveCritical(ulong); -#ifdef CONFIG_PCI -static uchar DvcReadPCIConfigByte(ASC_DVC_VAR *, ushort); -static void DvcWritePCIConfigByte(ASC_DVC_VAR *, ushort, uchar); -#endif /* CONFIG_PCI */ -static ushort AscGetChipBiosAddress(PortAddr, ushort); -static void DvcSleepMilliSecond(ASC_DCNT); -static void DvcDelayNanoSecond(ASC_DVC_VAR *, ASC_DCNT); -static void DvcPutScsiQ(PortAddr, ushort, uchar *, int); -static void DvcGetQinfo(PortAddr, ushort, uchar *, int); -static ushort AscInitGetConfig(ASC_DVC_VAR *); -static ushort AscInitSetConfig(ASC_DVC_VAR *); -static ushort AscInitAsc1000Driver(ASC_DVC_VAR *); -static void AscAsyncFix(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *); -static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *); -static void AscInquiryHandling(ASC_DVC_VAR *, uchar, ASC_SCSI_INQUIRY *); -static int AscExeScsiQueue(ASC_DVC_VAR *, ASC_SCSI_Q *); -static int AscISR(ASC_DVC_VAR *); -static uint AscGetNumOfFreeQueue(ASC_DVC_VAR *, uchar, uchar); -static int AscSgListToQueue(int); -#ifdef CONFIG_ISA -static void AscEnableIsaDma(uchar); -#endif /* CONFIG_ISA */ -static ASC_DCNT AscGetMaxDmaCount(ushort); -static const char *advansys_info(struct Scsi_Host *shost); - -/* - * --- Adv Library Constants and Macros - */ - -#define ADV_LIB_VERSION_MAJOR 5 -#define ADV_LIB_VERSION_MINOR 14 - -/* - * Define Adv Library required special types. - */ - /* * Portable Data Types * @@ -2045,12 +968,6 @@ static const char *advansys_info(struct Scsi_Host *shost); #define ADV_CARRIER_COUNT (ASC_DEF_MAX_HOST_QNG + 15) /* - * For wide boards a CDB length maximum of 16 bytes - * is supported. - */ -#define ADV_MAX_CDB_LEN 16 - -/* * Define total number of simultaneous maximum element scatter-gather * request blocks per wide adapter. ASC_DEF_MAX_HOST_QNG (253) is the * maximum number of outstanding commands per wide host adapter. Each @@ -2058,28 +975,14 @@ static const char *advansys_info(struct Scsi_Host *shost); * elements. Allow each command to have at least one ADV_SG_BLOCK structure. * This allows about 15 commands to have the maximum 17 ADV_SG_BLOCK * structures or 255 scatter-gather elements. - * */ #define ADV_TOT_SG_BLOCK ASC_DEF_MAX_HOST_QNG /* - * Define Adv Library required maximum number of scatter-gather - * elements per request. + * Define maximum number of scatter-gather elements per request. */ #define ADV_MAX_SG_LIST 255 - -/* Number of SG blocks needed. */ -#define ADV_NUM_SG_BLOCK \ - ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK) - -/* Total contiguous memory needed for SG blocks. */ -#define ADV_SG_TOTAL_MEM_SIZE \ - (sizeof(ADV_SG_BLOCK) * ADV_NUM_SG_BLOCK) - -#define ADV_PAGE_SIZE PAGE_SIZE - -#define ADV_NUM_PAGE_CROSSING \ - ((ADV_SG_TOTAL_MEM_SIZE + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE) +#define NO_OF_SG_PER_BLOCK 15 #define ADV_EEP_DVC_CFG_BEGIN (0x00) #define ADV_EEP_DVC_CFG_END (0x15) @@ -2385,10 +1288,6 @@ typedef struct adveep_38C1600_config { * EEPROM Commands */ #define ASC_EEP_CMD_DONE 0x0200 -#define ASC_EEP_CMD_DONE_ERR 0x0001 - -/* cfg_word */ -#define EEP_CFG_WORD_BIG_ENDIAN 0x8000 /* bios_ctrl */ #define BIOS_CTRL_BIOS 0x0001 @@ -2405,10 +1304,8 @@ typedef struct adveep_38C1600_config { #define BIOS_CTRL_AIPP_DIS 0x2000 #define ADV_3550_MEMSIZE 0x2000 /* 8 KB Internal Memory */ -#define ADV_3550_IOLEN 0x40 /* I/O Port Range in bytes */ #define ADV_38C0800_MEMSIZE 0x4000 /* 16 KB Internal Memory */ -#define ADV_38C0800_IOLEN 0x100 /* I/O Port Range in bytes */ /* * XXX - Since ASC38C1600 Rev.3 has a local RAM failure issue, there is @@ -2418,8 +1315,6 @@ typedef struct adveep_38C1600_config { * #define ADV_38C1600_MEMSIZE 0x8000L * 32 KB Internal Memory * */ #define ADV_38C1600_MEMSIZE 0x4000 /* 16 KB Internal Memory */ -#define ADV_38C1600_IOLEN 0x100 /* I/O Port Range 256 bytes */ -#define ADV_38C1600_MEMLEN 0x1000 /* Memory Range 4KB bytes */ /* * Byte I/O register address from base of 'iop_base'. @@ -2549,8 +1444,6 @@ typedef struct adveep_38C1600_config { #define ADV_CHIP_ID_BYTE 0x25 #define ADV_CHIP_ID_WORD 0x04C1 -#define ADV_SC_SCSI_BUS_RESET 0x2000 - #define ADV_INTR_ENABLE_HOST_INTR 0x01 #define ADV_INTR_ENABLE_SEL_INTR 0x02 #define ADV_INTR_ENABLE_DPR_INTR 0x04 @@ -2590,8 +1483,6 @@ typedef struct adveep_38C1600_config { #define ADV_TICKLE_B 0x02 #define ADV_TICKLE_C 0x03 -#define ADV_SCSI_CTRL_RSTOUT 0x2000 - #define AdvIsIntPending(port) \ (AdvReadWordRegister(port, IOPW_CTRL_REG) & ADV_CTRL_REG_HOST_INTR) @@ -2744,14 +1635,11 @@ typedef struct adveep_38C1600_config { */ #define INTAB 0x01 -/* a_advlib.h */ - /* * Adv Library Status Definitions */ #define ADV_TRUE 1 #define ADV_FALSE 0 -#define ADV_NOERROR 1 #define ADV_SUCCESS 1 #define ADV_BUSY 0 #define ADV_ERROR (-1) @@ -2762,31 +1650,12 @@ typedef struct adveep_38C1600_config { #define ASC_WARN_BUSRESET_ERROR 0x0001 /* SCSI Bus Reset error */ #define ASC_WARN_EEPROM_CHKSUM 0x0002 /* EEP check sum error */ #define ASC_WARN_EEPROM_TERMINATION 0x0004 /* EEP termination bad field */ -#define ASC_WARN_SET_PCI_CONFIG_SPACE 0x0080 /* PCI config space set error */ #define ASC_WARN_ERROR 0xFFFF /* ADV_ERROR return */ #define ADV_MAX_TID 15 /* max. target identifier */ #define ADV_MAX_LUN 7 /* max. logical unit number */ /* - * Error code values are set in ADV_DVC_VAR 'err_code'. - */ -#define ASC_IERR_WRITE_EEPROM 0x0001 /* write EEPROM error */ -#define ASC_IERR_MCODE_CHKSUM 0x0002 /* micro code check sum error */ -#define ASC_IERR_NO_CARRIER 0x0004 /* No more carrier memory. */ -#define ASC_IERR_START_STOP_CHIP 0x0008 /* start/stop chip failed */ -#define ASC_IERR_CHIP_VERSION 0x0040 /* wrong chip version */ -#define ASC_IERR_SET_SCSI_ID 0x0080 /* set SCSI ID failed */ -#define ASC_IERR_HVD_DEVICE 0x0100 /* HVD attached to LVD connector. */ -#define ASC_IERR_BAD_SIGNATURE 0x0200 /* signature not found */ -#define ASC_IERR_ILLEGAL_CONNECTION 0x0400 /* Illegal cable connection */ -#define ASC_IERR_SINGLE_END_DEVICE 0x0800 /* Single-end used w/differential */ -#define ASC_IERR_REVERSED_CABLE 0x1000 /* Narrow flat cable reversed */ -#define ASC_IERR_BIST_PRE_TEST 0x2000 /* BIST pre-test error */ -#define ASC_IERR_BIST_RAM_TEST 0x4000 /* BIST RAM test error */ -#define ASC_IERR_BAD_CHIPTYPE 0x8000 /* Invalid 'chip_type' setting. */ - -/* * Fixed locations of microcode operating variables. */ #define ASC_MC_CODE_BEGIN_ADDR 0x0028 /* microcode start address */ @@ -2902,8 +1771,7 @@ typedef struct adv_carr_t { #define ASC_GET_CARRP(carrp) ((carrp) & ASC_NEXT_VPA_MASK) #define ADV_CARRIER_NUM_PAGE_CROSSING \ - (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \ - (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE) + (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + (PAGE_SIZE - 1))/PAGE_SIZE) #define ADV_CARRIER_BUFSIZE \ ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T)) @@ -2937,80 +1805,17 @@ typedef struct adv_dvc_cfg { ushort disc_enable; /* enable disconnection */ uchar chip_version; /* chip version */ uchar termination; /* Term. Ctrl. bits 6-5 of SCSI_CFG1 register */ - ushort lib_version; /* Adv Library version number */ ushort control_flag; /* Microcode Control Flag */ ushort mcode_date; /* Microcode date */ ushort mcode_version; /* Microcode version */ - ushort pci_slot_info; /* high byte device/function number */ - /* bits 7-3 device num., bits 2-0 function num. */ - /* low byte bus num. */ ushort serial1; /* EEPROM serial number word 1 */ ushort serial2; /* EEPROM serial number word 2 */ ushort serial3; /* EEPROM serial number word 3 */ - struct device *dev; /* pointer to the pci dev structure for this board */ } ADV_DVC_CFG; struct adv_dvc_var; struct adv_scsi_req_q; -typedef void (*ADV_ISR_CALLBACK) - (struct adv_dvc_var *, struct adv_scsi_req_q *); - -typedef void (*ADV_ASYNC_CALLBACK) - (struct adv_dvc_var *, uchar); - -/* - * Adapter operation variable structure. - * - * One structure is required per host adapter. - * - * Field naming convention: - * - * *_able indicates both whether a feature should be enabled or disabled - * and whether a device isi capable of the feature. At initialization - * this field may be set, but later if a device is found to be incapable - * of the feature, the field is cleared. - */ -typedef struct adv_dvc_var { - AdvPortAddr iop_base; /* I/O port address */ - ushort err_code; /* fatal error code */ - ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */ - ADV_ISR_CALLBACK isr_callback; - ADV_ASYNC_CALLBACK async_callback; - ushort wdtr_able; /* try WDTR for a device */ - ushort sdtr_able; /* try SDTR for a device */ - ushort ultra_able; /* try SDTR Ultra speed for a device */ - ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */ - ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */ - ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */ - ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */ - ushort tagqng_able; /* try tagged queuing with a device */ - ushort ppr_able; /* PPR message capable per TID bitmask. */ - uchar max_dvc_qng; /* maximum number of tagged commands per device */ - ushort start_motor; /* start motor command allowed */ - uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */ - uchar chip_no; /* should be assigned by caller */ - uchar max_host_qng; /* maximum number of Q'ed command allowed */ - uchar irq_no; /* IRQ number */ - ushort no_scam; /* scam_tolerant of EEPROM */ - struct asc_board *drv_ptr; /* driver pointer to private structure */ - uchar chip_scsi_id; /* chip SCSI target ID */ - uchar chip_type; - uchar bist_err_code; - ADV_CARR_T *carrier_buf; - ADV_CARR_T *carr_freelist; /* Carrier free list. */ - ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */ - ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */ - ushort carr_pending_cnt; /* Count of pending carriers. */ - /* - * Note: The following fields will not be used after initialization. The - * driver may discard the buffer after initialization is done. - */ - ADV_DVC_CFG *cfg; /* temporary configuration structure */ -} ADV_DVC_VAR; - -#define NO_OF_SG_PER_BLOCK 15 - typedef struct asc_sg_block { uchar reserved1; uchar reserved2; @@ -3069,6 +1874,83 @@ typedef struct adv_scsi_req_q { } ADV_SCSI_REQ_Q; /* + * The following two structures are used to process Wide Board requests. + * + * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library + * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the + * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the + * Mid-Level SCSI request structure. + * + * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each + * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux + * up to 255 scatter-gather elements may be used per request or + * ADV_SCSI_REQ_Q. + * + * Both structures must be 32 byte aligned. + */ +typedef struct adv_sgblk { + ADV_SG_BLOCK sg_block; /* Sgblock structure. */ + uchar align[32]; /* Sgblock structure padding. */ + struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */ +} adv_sgblk_t; + +typedef struct adv_req { + ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */ + uchar align[32]; /* Request structure padding. */ + struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */ + adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */ + struct adv_req *next_reqp; /* Next Request Structure. */ +} adv_req_t; + +/* + * Adapter operation variable structure. + * + * One structure is required per host adapter. + * + * Field naming convention: + * + * *_able indicates both whether a feature should be enabled or disabled + * and whether a device isi capable of the feature. At initialization + * this field may be set, but later if a device is found to be incapable + * of the feature, the field is cleared. + */ +typedef struct adv_dvc_var { + AdvPortAddr iop_base; /* I/O port address */ + ushort err_code; /* fatal error code */ + ushort bios_ctrl; /* BIOS control word, EEPROM word 12 */ + ushort wdtr_able; /* try WDTR for a device */ + ushort sdtr_able; /* try SDTR for a device */ + ushort ultra_able; /* try SDTR Ultra speed for a device */ + ushort sdtr_speed1; /* EEPROM SDTR Speed for TID 0-3 */ + ushort sdtr_speed2; /* EEPROM SDTR Speed for TID 4-7 */ + ushort sdtr_speed3; /* EEPROM SDTR Speed for TID 8-11 */ + ushort sdtr_speed4; /* EEPROM SDTR Speed for TID 12-15 */ + ushort tagqng_able; /* try tagged queuing with a device */ + ushort ppr_able; /* PPR message capable per TID bitmask. */ + uchar max_dvc_qng; /* maximum number of tagged commands per device */ + ushort start_motor; /* start motor command allowed */ + uchar scsi_reset_wait; /* delay in seconds after scsi bus reset */ + uchar chip_no; /* should be assigned by caller */ + uchar max_host_qng; /* maximum number of Q'ed command allowed */ + ushort no_scam; /* scam_tolerant of EEPROM */ + struct asc_board *drv_ptr; /* driver pointer to private structure */ + uchar chip_scsi_id; /* chip SCSI target ID */ + uchar chip_type; + uchar bist_err_code; + ADV_CARR_T *carrier_buf; + ADV_CARR_T *carr_freelist; /* Carrier free list. */ + ADV_CARR_T *icq_sp; /* Initiator command queue stopper pointer. */ + ADV_CARR_T *irq_sp; /* Initiator response queue stopper pointer. */ + ushort carr_pending_cnt; /* Count of pending carriers. */ + struct adv_req *orig_reqp; /* adv_req_t memory block. */ + /* + * Note: The following fields will not be used after initialization. The + * driver may discard the buffer after initialization is done. + */ + ADV_DVC_CFG *cfg; /* temporary configuration structure */ +} ADV_DVC_VAR; + +/* * Microcode idle loop commands */ #define IDLE_CMD_COMPLETED 0 @@ -3092,10 +1974,8 @@ typedef struct adv_scsi_req_q { /* * Wait loop time out values. */ -#define SCSI_WAIT_10_SEC 10UL /* 10 seconds */ #define SCSI_WAIT_100_MSEC 100UL /* 100 milliseconds */ #define SCSI_US_PER_MSEC 1000 /* microseconds per millisecond */ -#define SCSI_MS_PER_SEC 1000UL /* milliseconds per second */ #define SCSI_MAX_RETRY 10 /* retry count */ #define ADV_ASYNC_RDMA_FAILURE 0x01 /* Fatal RDMA failure. */ @@ -3105,53 +1985,6 @@ typedef struct adv_scsi_req_q { #define ADV_HOST_SCSI_BUS_RESET 0x80 /* Host Initiated SCSI Bus Reset. */ -/* - * Device drivers must define the following functions. - */ -static inline ulong DvcEnterCritical(void); -static inline void DvcLeaveCritical(ulong); -static void DvcSleepMilliSecond(ADV_DCNT); -static uchar DvcAdvReadPCIConfigByte(ADV_DVC_VAR *, ushort); -static void DvcAdvWritePCIConfigByte(ADV_DVC_VAR *, ushort, uchar); -static ADV_PADDR DvcGetPhyAddr(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *, - uchar *, ASC_SDCNT *, int); -static void DvcDelayMicroSecond(ADV_DVC_VAR *, ushort); - -/* - * Adv Library functions available to drivers. - */ -static int AdvExeScsiQueue(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -static int AdvISR(ADV_DVC_VAR *); -static int AdvInitGetConfig(ADV_DVC_VAR *); -static int AdvInitAsc3550Driver(ADV_DVC_VAR *); -static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *); -static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *); -static int AdvResetChipAndSB(ADV_DVC_VAR *); -static int AdvResetSB(ADV_DVC_VAR *asc_dvc); - -/* - * Internal Adv Library functions. - */ -static int AdvSendIdleCmd(ADV_DVC_VAR *, ushort, ADV_DCNT); -static void AdvInquiryHandling(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -static int AdvInitFrom3550EEP(ADV_DVC_VAR *); -static int AdvInitFrom38C0800EEP(ADV_DVC_VAR *); -static int AdvInitFrom38C1600EEP(ADV_DVC_VAR *); -static ushort AdvGet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); -static void AdvSet3550EEPConfig(AdvPortAddr, ADVEEP_3550_CONFIG *); -static ushort AdvGet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); -static void AdvSet38C0800EEPConfig(AdvPortAddr, ADVEEP_38C0800_CONFIG *); -static ushort AdvGet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); -static void AdvSet38C1600EEPConfig(AdvPortAddr, ADVEEP_38C1600_CONFIG *); -static void AdvWaitEEPCmd(AdvPortAddr); -static ushort AdvReadEEPWord(AdvPortAddr, int); - -/* - * PCI Bus Definitions - */ -#define AscPCICmdRegBits_BusMastering 0x0007 -#define AscPCICmdRegBits_ParErrRespCtrl 0x0040 - /* Read byte from a register. */ #define AdvReadByteRegister(iop_base, reg_off) \ (ADV_MEM_READB((iop_base) + (reg_off))) @@ -3319,23 +2152,6 @@ do { \ #define QHSTA_M_FROZEN_TIDQ 0x46 /* TID Queue frozen. */ #define QHSTA_M_SGBACKUP_ERROR 0x47 /* Scatter-Gather backup error */ -/* - * Default EEPROM Configuration structure defined in a_init.c. - */ -static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config; -static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config; -static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config; - -/* - * DvcGetPhyAddr() flag arguments - */ -#define ADV_IS_SCSIQ_FLAG 0x01 /* 'addr' is ASC_SCSI_REQ_Q pointer */ -#define ADV_ASCGETSGLIST_VADDR 0x02 /* 'addr' is AscGetSGList() virtual addr */ -#define ADV_IS_SENSE_FLAG 0x04 /* 'addr' is sense virtual pointer */ -#define ADV_IS_DATA_FLAG 0x08 /* 'addr' is data virtual pointer */ -#define ADV_IS_SGLIST_FLAG 0x10 /* 'addr' is sglist virtual pointer */ -#define ADV_IS_CARRIER_FLAG 0x20 /* 'addr' is ADV_CARR_T pointer */ - /* Return the address that is aligned at the next doubleword >= to 'addr'. */ #define ADV_8BALIGN(addr) (((ulong) (addr) + 0x7) & ~0x7) #define ADV_16BALIGN(addr) (((ulong) (addr) + 0xF) & ~0xF) @@ -3353,92 +2169,10 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config; (sizeof(ADV_SG_BLOCK) * \ ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)) -/* - * Inquiry data structure and bitfield macros - * - * Using bitfields to access the subchar data isn't portable across - * endianness, so instead mask and shift. Only quantities of more - * than 1 bit are shifted, since the others are just tested for true - * or false. - */ - -#define ADV_INQ_DVC_TYPE(inq) ((inq)->periph & 0x1f) -#define ADV_INQ_QUALIFIER(inq) (((inq)->periph & 0xe0) >> 5) -#define ADV_INQ_DVC_TYPE_MOD(inq) ((inq)->devtype & 0x7f) -#define ADV_INQ_REMOVABLE(inq) ((inq)->devtype & 0x80) -#define ADV_INQ_ANSI_VER(inq) ((inq)->ver & 0x07) -#define ADV_INQ_ECMA_VER(inq) (((inq)->ver & 0x38) >> 3) -#define ADV_INQ_ISO_VER(inq) (((inq)->ver & 0xc0) >> 6) -#define ADV_INQ_RESPONSE_FMT(inq) ((inq)->byte3 & 0x0f) -#define ADV_INQ_TERM_IO(inq) ((inq)->byte3 & 0x40) -#define ADV_INQ_ASYNC_NOTIF(inq) ((inq)->byte3 & 0x80) -#define ADV_INQ_SOFT_RESET(inq) ((inq)->flags & 0x01) -#define ADV_INQ_CMD_QUEUE(inq) ((inq)->flags & 0x02) -#define ADV_INQ_LINK_CMD(inq) ((inq)->flags & 0x08) -#define ADV_INQ_SYNC(inq) ((inq)->flags & 0x10) -#define ADV_INQ_WIDE16(inq) ((inq)->flags & 0x20) -#define ADV_INQ_WIDE32(inq) ((inq)->flags & 0x40) -#define ADV_INQ_REL_ADDR(inq) ((inq)->flags & 0x80) -#define ADV_INQ_INFO_UNIT(inq) ((inq)->info & 0x01) -#define ADV_INQ_QUICK_ARB(inq) ((inq)->info & 0x02) -#define ADV_INQ_CLOCKING(inq) (((inq)->info & 0x0c) >> 2) - -typedef struct { - uchar periph; /* peripheral device type [0:4] */ - /* peripheral qualifier [5:7] */ - uchar devtype; /* device type modifier (for SCSI I) [0:6] */ - /* RMB - removable medium bit [7] */ - uchar ver; /* ANSI approved version [0:2] */ - /* ECMA version [3:5] */ - /* ISO version [6:7] */ - uchar byte3; /* response data format [0:3] */ - /* 0 SCSI 1 */ - /* 1 CCS */ - /* 2 SCSI-2 */ - /* 3-F reserved */ - /* reserved [4:5] */ - /* terminate I/O process bit (see 5.6.22) [6] */ - /* asynch. event notification (processor) [7] */ - uchar add_len; /* additional length */ - uchar res1; /* reserved */ - uchar res2; /* reserved */ - uchar flags; /* soft reset implemented [0] */ - /* command queuing [1] */ - /* reserved [2] */ - /* linked command for this logical unit [3] */ - /* synchronous data transfer [4] */ - /* wide bus 16 bit data transfer [5] */ - /* wide bus 32 bit data transfer [6] */ - /* relative addressing mode [7] */ - uchar vendor_id[8]; /* vendor identification */ - uchar product_id[16]; /* product identification */ - uchar product_rev_level[4]; /* product revision level */ - uchar vendor_specific[20]; /* vendor specific */ - uchar info; /* information unit supported [0] */ - /* quick arbitrate supported [1] */ - /* clocking field [2:3] */ - /* reserved [4:7] */ - uchar res3; /* reserved */ -} ADV_SCSI_INQUIRY; /* 58 bytes */ - -/* - * --- Driver Constants and Macros - */ - -#define ASC_NUM_BOARD_SUPPORTED 16 -#define ASC_NUM_IOPORT_PROBE 4 -#define ASC_NUM_BUS 4 - -/* Reference Scsi_Host hostdata */ -#define ASC_BOARDP(host) ((asc_board_t *) &((host)->hostdata)) - -/* asc_board_t flags */ -#define ASC_HOST_IN_RESET 0x01 +/* struct asc_board flags */ #define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */ -#define ASC_SELECT_QUEUE_DEPTHS 0x08 #define ASC_NARROW_BOARD(boardp) (((boardp)->flags & ASC_IS_WIDE_BOARD) == 0) -#define ASC_WIDE_BOARD(boardp) ((boardp)->flags & ASC_IS_WIDE_BOARD) #define NO_ISA_DMA 0xff /* No ISA DMA Channel Used */ @@ -3473,82 +2207,14 @@ typedef struct { #define HOST_BYTE(byte) ((byte) << 16) #define DRIVER_BYTE(byte) ((byte) << 24) -/* - * The following definitions and macros are OS independent interfaces to - * the queue functions: - * REQ - SCSI request structure - * REQP - pointer to SCSI request structure - * REQPTID(reqp) - reqp's target id - * REQPNEXT(reqp) - reqp's next pointer - * REQPNEXTP(reqp) - pointer to reqp's next pointer - * REQPTIME(reqp) - reqp's time stamp value - * REQTIMESTAMP() - system time stamp value - */ -typedef struct scsi_cmnd REQ, *REQP; -#define REQPNEXT(reqp) ((REQP) ((reqp)->host_scribble)) -#define REQPNEXTP(reqp) ((REQP *) &((reqp)->host_scribble)) -#define REQPTID(reqp) ((reqp)->device->id) -#define REQPTIME(reqp) ((reqp)->SCp.this_residual) -#define REQTIMESTAMP() (jiffies) - -#define REQTIMESTAT(function, ascq, reqp, tid) \ -{ \ - /* - * If the request time stamp is less than the system time stamp, then \ - * maybe the system time stamp wrapped. Set the request time to zero.\ - */ \ - if (REQPTIME(reqp) <= REQTIMESTAMP()) { \ - REQPTIME(reqp) = REQTIMESTAMP() - REQPTIME(reqp); \ - } else { \ - /* Indicate an error occurred with the assertion. */ \ - ASC_ASSERT(REQPTIME(reqp) <= REQTIMESTAMP()); \ - REQPTIME(reqp) = 0; \ - } \ - /* Handle first minimum time case without external initialization. */ \ - if (((ascq)->q_tot_cnt[tid] == 1) || \ - (REQPTIME(reqp) < (ascq)->q_min_tim[tid])) { \ - (ascq)->q_min_tim[tid] = REQPTIME(reqp); \ - ASC_DBG3(1, "%s: new q_min_tim[%d] %u\n", \ - (function), (tid), (ascq)->q_min_tim[tid]); \ - } \ - if (REQPTIME(reqp) > (ascq)->q_max_tim[tid]) { \ - (ascq)->q_max_tim[tid] = REQPTIME(reqp); \ - ASC_DBG3(1, "%s: new q_max_tim[%d] %u\n", \ - (function), tid, (ascq)->q_max_tim[tid]); \ - } \ - (ascq)->q_tot_tim[tid] += REQPTIME(reqp); \ - /* Reset the time stamp field. */ \ - REQPTIME(reqp) = 0; \ -} - -/* asc_enqueue() flags */ -#define ASC_FRONT 1 -#define ASC_BACK 2 - -/* asc_dequeue_list() argument */ -#define ASC_TID_ALL (-1) - -/* Return non-zero, if the queue is empty. */ -#define ASC_QUEUE_EMPTY(ascq) ((ascq)->q_tidmask == 0) - -#define PCI_MAX_SLOT 0x1F -#define PCI_MAX_BUS 0xFF -#define PCI_IOADDRESS_MASK 0xFFFE -#define ASC_PCI_DEVICE_ID_CNT 6 /* PCI Device ID count. */ - +#define ASC_STATS(shost, counter) ASC_STATS_ADD(shost, counter, 1) #ifndef ADVANSYS_STATS -#define ASC_STATS(shost, counter) #define ASC_STATS_ADD(shost, counter, count) #else /* ADVANSYS_STATS */ -#define ASC_STATS(shost, counter) \ - (ASC_BOARDP(shost)->asc_stats.counter++) - #define ASC_STATS_ADD(shost, counter, count) \ - (ASC_BOARDP(shost)->asc_stats.counter += (count)) + (((struct asc_board *) shost_priv(shost))->asc_stats.counter += (count)) #endif /* ADVANSYS_STATS */ -#define ASC_CEILING(val, unit) (((val) + ((unit) - 1))/(unit)) - /* If the result wraps when calculating tenths, return 0. */ #define ASC_TENTHS(num, den) \ (((10 * ((num)/(den))) > (((num) * 10)/(den))) ? \ @@ -3589,13 +2255,8 @@ typedef struct scsi_cmnd REQ, *REQP; #ifndef ADVANSYS_DEBUG -#define ASC_DBG(lvl, s) -#define ASC_DBG1(lvl, s, a1) -#define ASC_DBG2(lvl, s, a1, a2) -#define ASC_DBG3(lvl, s, a1, a2, a3) -#define ASC_DBG4(lvl, s, a1, a2, a3, a4) +#define ASC_DBG(lvl, s...) #define ASC_DBG_PRT_SCSI_HOST(lvl, s) -#define ASC_DBG_PRT_SCSI_CMND(lvl, s) #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) #define ASC_DBG_PRT_ADV_SCSI_REQ_Q(lvl, scsiqp) #define ASC_DBG_PRT_ASC_QDONE_INFO(lvl, qdone) @@ -3614,40 +2275,11 @@ typedef struct scsi_cmnd REQ, *REQP; * 2-N: Verbose Tracing */ -#define ASC_DBG(lvl, s) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk(s); \ - } \ - } - -#define ASC_DBG1(lvl, s, a1) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk((s), (a1)); \ - } \ - } - -#define ASC_DBG2(lvl, s, a1, a2) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk((s), (a1), (a2)); \ - } \ - } - -#define ASC_DBG3(lvl, s, a1, a2, a3) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk((s), (a1), (a2), (a3)); \ - } \ - } - -#define ASC_DBG4(lvl, s, a1, a2, a3, a4) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - printk((s), (a1), (a2), (a3), (a4)); \ - } \ - } +#define ASC_DBG(lvl, format, arg...) { \ + if (asc_dbglvl >= (lvl)) \ + printk(KERN_DEBUG "%s: %s: " format, DRV_NAME, \ + __FUNCTION__ , ## arg); \ +} #define ASC_DBG_PRT_SCSI_HOST(lvl, s) \ { \ @@ -3656,13 +2288,6 @@ typedef struct scsi_cmnd REQ, *REQP; } \ } -#define ASC_DBG_PRT_SCSI_CMND(lvl, s) \ - { \ - if (asc_dbglvl >= (lvl)) { \ - asc_prt_scsi_cmnd(s); \ - } \ - } - #define ASC_DBG_PRT_ASC_SCSI_Q(lvl, scsiqp) \ { \ if (asc_dbglvl >= (lvl)) { \ @@ -3701,24 +2326,6 @@ typedef struct scsi_cmnd REQ, *REQP; ASC_DBG_PRT_HEX((lvl), "INQUIRY", (uchar *) (inq), (len)); #endif /* ADVANSYS_DEBUG */ -#ifndef ADVANSYS_ASSERT -#define ASC_ASSERT(a) -#else /* ADVANSYS_ASSERT */ - -#define ASC_ASSERT(a) \ - { \ - if (!(a)) { \ - printk("ASC_ASSERT() Failure: file %s, line %d\n", \ - __FILE__, __LINE__); \ - } \ - } - -#endif /* ADVANSYS_ASSERT */ - -/* - * --- Driver Structures - */ - #ifdef ADVANSYS_STATS /* Per board statistics structure */ @@ -3739,72 +2346,23 @@ struct asc_stats { ADV_DCNT exe_error; /* # ASC_ERROR returns. */ ADV_DCNT exe_unknown; /* # unknown returns. */ /* Data Transfer Statistics */ - ADV_DCNT cont_cnt; /* # non-scatter-gather I/O requests received */ - ADV_DCNT cont_xfer; /* # contiguous transfer 512-bytes */ - ADV_DCNT sg_cnt; /* # scatter-gather I/O requests received */ - ADV_DCNT sg_elem; /* # scatter-gather elements */ - ADV_DCNT sg_xfer; /* # scatter-gather transfer 512-bytes */ + ADV_DCNT xfer_cnt; /* # I/O requests received */ + ADV_DCNT xfer_elem; /* # scatter-gather elements */ + ADV_DCNT xfer_sect; /* # 512-byte blocks */ }; #endif /* ADVANSYS_STATS */ /* - * Request queuing structure - */ -typedef struct asc_queue { - ADV_SCSI_BIT_ID_TYPE q_tidmask; /* queue mask */ - REQP q_first[ADV_MAX_TID + 1]; /* first queued request */ - REQP q_last[ADV_MAX_TID + 1]; /* last queued request */ -#ifdef ADVANSYS_STATS - short q_cur_cnt[ADV_MAX_TID + 1]; /* current queue count */ - short q_max_cnt[ADV_MAX_TID + 1]; /* maximum queue count */ - ADV_DCNT q_tot_cnt[ADV_MAX_TID + 1]; /* total enqueue count */ - ADV_DCNT q_tot_tim[ADV_MAX_TID + 1]; /* total time queued */ - ushort q_max_tim[ADV_MAX_TID + 1]; /* maximum time queued */ - ushort q_min_tim[ADV_MAX_TID + 1]; /* minimum time queued */ -#endif /* ADVANSYS_STATS */ -} asc_queue_t; - -/* - * Adv Library Request Structures - * - * The following two structures are used to process Wide Board requests. - * - * The ADV_SCSI_REQ_Q structure in adv_req_t is passed to the Adv Library - * and microcode with the ADV_SCSI_REQ_Q field 'srb_ptr' pointing to the - * adv_req_t. The adv_req_t structure 'cmndp' field in turn points to the - * Mid-Level SCSI request structure. - * - * Zero or more ADV_SG_BLOCK are used with each ADV_SCSI_REQ_Q. Each - * ADV_SG_BLOCK structure holds 15 scatter-gather elements. Under Linux - * up to 255 scatter-gather elements may be used per request or - * ADV_SCSI_REQ_Q. - * - * Both structures must be 32 byte aligned. - */ -typedef struct adv_sgblk { - ADV_SG_BLOCK sg_block; /* Sgblock structure. */ - uchar align[32]; /* Sgblock structure padding. */ - struct adv_sgblk *next_sgblkp; /* Next scatter-gather structure. */ -} adv_sgblk_t; - -typedef struct adv_req { - ADV_SCSI_REQ_Q scsi_req_q; /* Adv Library request structure. */ - uchar align[32]; /* Request structure padding. */ - struct scsi_cmnd *cmndp; /* Mid-Level SCSI command pointer. */ - adv_sgblk_t *sgblkp; /* Adv Library scatter-gather pointer. */ - struct adv_req *next_reqp; /* Next Request Structure. */ -} adv_req_t; - -/* * Structure allocated for each board. * - * This structure is allocated by scsi_register() at the end + * This structure is allocated by scsi_host_alloc() at the end * of the 'Scsi_Host' structure starting at the 'hostdata' * field. It is guaranteed to be allocated from DMA-able memory. */ -typedef struct asc_board { - int id; /* Board Id */ +struct asc_board { + struct device *dev; uint flags; /* Board flags */ + unsigned int irq; union { ASC_DVC_VAR asc_dvc_var; /* Narrow board */ ADV_DVC_VAR adv_dvc_var; /* Wide board */ @@ -3814,11 +2372,7 @@ typedef struct asc_board { ADV_DVC_CFG adv_dvc_cfg; /* Wide board */ } dvc_cfg; ushort asc_n_io_port; /* Number I/O ports. */ - asc_queue_t active; /* Active command queue */ - asc_queue_t waiting; /* Waiting command queue */ - asc_queue_t done; /* Done command queue */ ADV_SCSI_BIT_ID_TYPE init_tidmask; /* Target init./valid mask */ - struct scsi_device *device[ADV_MAX_TID + 1]; /* Mid-Level Scsi Device */ ushort reqcnt[ADV_MAX_TID + 1]; /* Starvation request count */ ADV_SCSI_BIT_ID_TYPE queue_full; /* Queue full mask */ ushort queue_full_cnt[ADV_MAX_TID + 1]; /* Queue full count */ @@ -3829,2409 +2383,529 @@ typedef struct asc_board { ADVEEP_38C1600_CONFIG adv_38C1600_eep; /* 38C1600 EEPROM config. */ } eep_config; ulong last_reset; /* Saved last reset time */ - spinlock_t lock; /* Board spinlock */ -#ifdef CONFIG_PROC_FS /* /proc/scsi/advansys/[0...] */ char *prtbuf; /* /proc print buffer */ -#endif /* CONFIG_PROC_FS */ #ifdef ADVANSYS_STATS struct asc_stats asc_stats; /* Board statistics */ #endif /* ADVANSYS_STATS */ /* * The following fields are used only for Narrow Boards. */ - /* The following three structures must be in DMA-able memory. */ - ASC_SCSI_REQ_Q scsireqq; - ASC_CAP_INFO cap_info; - ASC_SCSI_INQUIRY inquiry; uchar sdtr_data[ASC_MAX_TID + 1]; /* SDTR information */ /* * The following fields are used only for Wide Boards. */ void __iomem *ioremap_addr; /* I/O Memory remap address. */ ushort ioport; /* I/O Port address. */ - ADV_CARR_T *orig_carrp; /* ADV_CARR_T memory block. */ - adv_req_t *orig_reqp; /* adv_req_t memory block. */ adv_req_t *adv_reqp; /* Request structures. */ adv_sgblk_t *adv_sgblkp; /* Scatter-gather structures. */ ushort bios_signature; /* BIOS Signature. */ ushort bios_version; /* BIOS Version. */ ushort bios_codeseg; /* BIOS Code Segment. */ ushort bios_codelen; /* BIOS Code Segment Length. */ -} asc_board_t; - -/* - * PCI configuration structures - */ -typedef struct _PCI_DATA_ { - uchar type; - uchar bus; - uchar slot; - uchar func; - uchar offset; -} PCI_DATA; - -typedef struct _PCI_DEVICE_ { - ushort vendorID; - ushort deviceID; - ushort slotNumber; - ushort slotFound; - uchar busNumber; - uchar maxBusNumber; - uchar devFunc; - ushort startSlot; - ushort endSlot; - uchar bridge; - uchar type; -} PCI_DEVICE; - -typedef struct _PCI_CONFIG_SPACE_ { - ushort vendorID; - ushort deviceID; - ushort command; - ushort status; - uchar revision; - uchar classCode[3]; - uchar cacheSize; - uchar latencyTimer; - uchar headerType; - uchar bist; - ADV_PADDR baseAddress[6]; - ushort reserved[4]; - ADV_PADDR optionRomAddr; - ushort reserved2[4]; - uchar irqLine; - uchar irqPin; - uchar minGnt; - uchar maxLatency; -} PCI_CONFIG_SPACE; - -/* - * --- Driver Data - */ - -/* Note: All driver global data should be initialized. */ - -/* Number of boards detected in system. */ -static int asc_board_count = 0; -static struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL }; - -/* Overrun buffer used by all narrow boards. */ -static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; - -/* - * Global structures required to issue a command. - */ -static ASC_SCSI_Q asc_scsi_q = { {0} }; -static ASC_SG_HEAD asc_sg_head = { 0 }; - -/* List of supported bus types. */ -static ushort asc_bus[ASC_NUM_BUS] __initdata = { - ASC_IS_ISA, - ASC_IS_VL, - ASC_IS_EISA, - ASC_IS_PCI, }; -static int asc_iopflag = ASC_FALSE; -static int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; +#define asc_dvc_to_board(asc_dvc) container_of(asc_dvc, struct asc_board, \ + dvc_var.asc_dvc_var) +#define adv_dvc_to_board(adv_dvc) container_of(adv_dvc, struct asc_board, \ + dvc_var.adv_dvc_var) +#define adv_dvc_to_pdev(adv_dvc) to_pci_dev(adv_dvc_to_board(adv_dvc)->dev) #ifdef ADVANSYS_DEBUG -static char *asc_bus_name[ASC_NUM_BUS] = { - "ASC_IS_ISA", - "ASC_IS_VL", - "ASC_IS_EISA", - "ASC_IS_PCI", -}; - static int asc_dbglvl = 3; -#endif /* ADVANSYS_DEBUG */ - -/* Declaration for Asc Library internal data referenced by driver. */ -static PortAddr _asc_def_iop_base[]; - -/* - * --- Driver Function Prototypes - * - * advansys.h contains function prototypes for functions global to Linux. - */ - -static irqreturn_t advansys_interrupt(int, void *); -static int advansys_slave_configure(struct scsi_device *); -static void asc_scsi_done_list(struct scsi_cmnd *); -static int asc_execute_scsi_cmnd(struct scsi_cmnd *); -static int asc_build_req(asc_board_t *, struct scsi_cmnd *); -static int adv_build_req(asc_board_t *, struct scsi_cmnd *, ADV_SCSI_REQ_Q **); -static int adv_get_sglist(asc_board_t *, adv_req_t *, struct scsi_cmnd *, int); -static void asc_isr_callback(ASC_DVC_VAR *, ASC_QDONE_INFO *); -static void adv_isr_callback(ADV_DVC_VAR *, ADV_SCSI_REQ_Q *); -static void adv_async_callback(ADV_DVC_VAR *, uchar); -static void asc_enqueue(asc_queue_t *, REQP, int); -static REQP asc_dequeue(asc_queue_t *, int); -static REQP asc_dequeue_list(asc_queue_t *, REQP *, int); -static int asc_rmqueue(asc_queue_t *, REQP); -static void asc_execute_queue(asc_queue_t *); -#ifdef CONFIG_PROC_FS -static int asc_proc_copy(off_t, off_t, char *, int, char *, int); -static int asc_prt_board_devices(struct Scsi_Host *, char *, int); -static int asc_prt_adv_bios(struct Scsi_Host *, char *, int); -static int asc_get_eeprom_string(ushort *serialnum, uchar *cp); -static int asc_prt_asc_board_eeprom(struct Scsi_Host *, char *, int); -static int asc_prt_adv_board_eeprom(struct Scsi_Host *, char *, int); -static int asc_prt_driver_conf(struct Scsi_Host *, char *, int); -static int asc_prt_asc_board_info(struct Scsi_Host *, char *, int); -static int asc_prt_adv_board_info(struct Scsi_Host *, char *, int); -static int asc_prt_line(char *, int, char *fmt, ...); -#endif /* CONFIG_PROC_FS */ - -/* Declaration for Asc Library internal functions referenced by driver. */ -static int AscFindSignature(PortAddr); -static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); - -/* Statistics function prototypes. */ -#ifdef ADVANSYS_STATS -#ifdef CONFIG_PROC_FS -static int asc_prt_board_stats(struct Scsi_Host *, char *, int); -static int asc_prt_target_stats(struct Scsi_Host *, int, char *, int); -#endif /* CONFIG_PROC_FS */ -#endif /* ADVANSYS_STATS */ - -/* Debug function prototypes. */ -#ifdef ADVANSYS_DEBUG -static void asc_prt_scsi_host(struct Scsi_Host *); -static void asc_prt_scsi_cmnd(struct scsi_cmnd *); -static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *); -static void asc_prt_asc_dvc_var(ASC_DVC_VAR *); -static void asc_prt_asc_scsi_q(ASC_SCSI_Q *); -static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *); -static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *); -static void asc_prt_adv_dvc_var(ADV_DVC_VAR *); -static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *); -static void asc_prt_adv_sgblock(int, ADV_SG_BLOCK *); -static void asc_prt_hex(char *f, uchar *, int); -#endif /* ADVANSYS_DEBUG */ -#ifdef CONFIG_PROC_FS /* - * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] - * - * *buffer: I/O buffer - * **start: if inout == FALSE pointer into buffer where user read should start - * offset: current offset into a /proc/scsi/advansys/[0...] file - * length: length of buffer - * hostno: Scsi_Host host_no - * inout: TRUE - user is writing; FALSE - user is reading - * - * Return the number of bytes read from or written to a - * /proc/scsi/advansys/[0...] file. - * - * Note: This function uses the per board buffer 'prtbuf' which is - * allocated when the board is initialized in advansys_detect(). The - * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is - * used to write to the buffer. The way asc_proc_copy() is written - * if 'prtbuf' is too small it will not be overwritten. Instead the - * user just won't get all the available statistics. + * asc_prt_asc_dvc_var() */ -static int -advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, - off_t offset, int length, int inout) +static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h) { - struct Scsi_Host *shp; - asc_board_t *boardp; - int i; - char *cp; - int cplen; - int cnt; - int totcnt; - int leftlen; - char *curbuf; - off_t advoffset; -#ifdef ADVANSYS_STATS - int tgt_id; -#endif /* ADVANSYS_STATS */ - - ASC_DBG(1, "advansys_proc_info: begin\n"); - - /* - * User write not supported. - */ - if (inout == TRUE) { - return (-ENOSYS); - } - - /* - * User read of /proc/scsi/advansys/[0...] file. - */ - - /* Find the specified board. */ - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i]->host_no == shost->host_no) { - break; - } - } - if (i == asc_board_count) { - return (-ENOENT); - } - - shp = asc_host[i]; - boardp = ASC_BOARDP(shp); - - /* Copy read data starting at the beginning of the buffer. */ - *start = buffer; - curbuf = buffer; - advoffset = 0; - totcnt = 0; - leftlen = length; - - /* - * Get board configuration information. - * - * advansys_info() returns the board string from its own static buffer. - */ - cp = (char *)advansys_info(shp); - strcat(cp, "\n"); - cplen = strlen(cp); - /* Copy board information. */ - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - /* - * Display Wide Board BIOS Information. - */ - if (ASC_WIDE_BOARD(boardp)) { - cp = boardp->prtbuf; - cplen = asc_prt_adv_bios(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = - asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, - cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - } - - /* - * Display driver information for each device attached to the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_board_devices(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - /* - * Display EEPROM configuration for the board. - */ - cp = boardp->prtbuf; - if (ASC_NARROW_BOARD(boardp)) { - cplen = asc_prt_asc_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); - } else { - cplen = asc_prt_adv_board_eeprom(shp, cp, ASC_PRTBUF_SIZE); - } - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - - /* - * Display driver configuration and information for the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_driver_conf(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h); -#ifdef ADVANSYS_STATS - /* - * Display driver statistics for the board. - */ - cp = boardp->prtbuf; - cplen = asc_prt_board_stats(shp, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + printk(" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl " + "%d,\n", h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); - /* - * Display driver statistics for each target. - */ - for (tgt_id = 0; tgt_id <= ADV_MAX_TID; tgt_id++) { - cp = boardp->prtbuf; - cplen = asc_prt_target_stats(shp, tgt_id, cp, ASC_PRTBUF_SIZE); - ASC_ASSERT(cplen <= ASC_PRTBUF_SIZE); - cnt = - asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, - cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; - } -#endif /* ADVANSYS_STATS */ + printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type, + (unsigned)h->init_sdtr); - /* - * Display Asc Library dynamic configuration information - * for the board. - */ - cp = boardp->prtbuf; - if (ASC_NARROW_BOARD(boardp)) { - cplen = asc_prt_asc_board_info(shp, cp, ASC_PRTBUF_SIZE); - } else { - cplen = asc_prt_adv_board_info(shp, cp, ASC_PRTBUF_SIZE); - } - ASC_ASSERT(cplen < ASC_PRTBUF_SIZE); - cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); - totcnt += cnt; - leftlen -= cnt; - if (leftlen == 0) { - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - return totcnt; - } - advoffset += cplen; - curbuf += cnt; + printk(" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, " + "chip_no 0x%x,\n", (unsigned)h->sdtr_done, + (unsigned)h->use_tagged_qng, (unsigned)h->unit_not_ready, + (unsigned)h->chip_no); - ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); + printk(" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait " + "%u,\n", (unsigned)h->queue_full_or_busy, + (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait); - return totcnt; -} -#endif /* CONFIG_PROC_FS */ + printk(" is_in_int %u, max_total_qng %u, cur_total_qng %u, " + "in_critical_cnt %u,\n", (unsigned)h->is_in_int, + (unsigned)h->max_total_qng, (unsigned)h->cur_total_qng, + (unsigned)h->in_critical_cnt); -/* - * advansys_info() - * - * Return suitable for printing on the console with the argument - * adapter's configuration information. - * - * Note: The information line should not exceed ASC_INFO_SIZE bytes, - * otherwise the static 'info' array will be overrun. - */ -static const char *advansys_info(struct Scsi_Host *shost) -{ - static char info[ASC_INFO_SIZE]; - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - char *busname; - int iolen; - char *widename = NULL; + printk(" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, " + "pci_fix_asyn_xfer 0x%x,\n", (unsigned)h->last_q_shortage, + (unsigned)h->init_state, (unsigned)h->no_scam, + (unsigned)h->pci_fix_asyn_xfer); - boardp = ASC_BOARDP(shost); - if (ASC_NARROW_BOARD(boardp)) { - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - ASC_DBG(1, "advansys_info: begin\n"); - if (asc_dvc_varp->bus_type & ASC_IS_ISA) { - if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == - ASC_IS_ISAPNP) { - busname = "ISA PnP"; - } else { - busname = "ISA"; - } - /* Don't reference 'shost->n_io_port'; It may be truncated. */ - sprintf(info, - "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X", - ASC_VERSION, busname, - (ulong)shost->io_port, - (ulong)shost->io_port + boardp->asc_n_io_port - - 1, shost->irq, shost->dma_channel); - } else { - if (asc_dvc_varp->bus_type & ASC_IS_VL) { - busname = "VL"; - } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { - busname = "EISA"; - } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { - if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) - == ASC_IS_PCI_ULTRA) { - busname = "PCI Ultra"; - } else { - busname = "PCI"; - } - } else { - busname = "?"; - ASC_PRINT2 - ("advansys_info: board %d: unknown bus type %d\n", - boardp->id, asc_dvc_varp->bus_type); - } - /* Don't reference 'shost->n_io_port'; It may be truncated. */ - sprintf(info, - "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X", - ASC_VERSION, busname, - (ulong)shost->io_port, - (ulong)shost->io_port + boardp->asc_n_io_port - - 1, shost->irq); - } - } else { - /* - * Wide Adapter Information - * - * Memory-mapped I/O is used instead of I/O space to access - * the adapter, but display the I/O Port range. The Memory - * I/O address is displayed through the driver /proc file. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - iolen = ADV_3550_IOLEN; - widename = "Ultra-Wide"; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - iolen = ADV_38C0800_IOLEN; - widename = "Ultra2-Wide"; - } else { - iolen = ADV_38C1600_IOLEN; - widename = "Ultra3-Wide"; - } - sprintf(info, - "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X", - ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base, - (ulong)adv_dvc_varp->iop_base + iolen - 1, shost->irq); - } - ASC_ASSERT(strlen(info) < ASC_INFO_SIZE); - ASC_DBG(1, "advansys_info: end\n"); - return info; + printk(" cfg 0x%lx\n", (ulong)h->cfg); } /* - * advansys_queuecommand() - interrupt-driven I/O entrypoint. - * - * This function always returns 0. Command return status is saved - * in the 'scp' result field. + * asc_prt_asc_dvc_cfg() */ -static int -advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) +static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) { - struct Scsi_Host *shost; - asc_board_t *boardp; - ulong flags; - struct scsi_cmnd *done_scp; - - shost = scp->device->host; - boardp = ASC_BOARDP(shost); - ASC_STATS(shost, queuecommand); - - /* host_lock taken by mid-level prior to call but need to protect */ - /* against own ISR */ - spin_lock_irqsave(&boardp->lock, flags); - - /* - * Block new commands while handling a reset or abort request. - */ - if (boardp->flags & ASC_HOST_IN_RESET) { - ASC_DBG1(1, - "advansys_queuecommand: scp 0x%lx blocked for reset request\n", - (ulong)scp); - scp->result = HOST_BYTE(DID_RESET); - - /* - * Add blocked requests to the board's 'done' queue. The queued - * requests will be completed at the end of the abort or reset - * handling. - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); - spin_unlock_irqrestore(&boardp->lock, flags); - return 0; - } + printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h); - /* - * Attempt to execute any waiting commands for the board. - */ - if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { - ASC_DBG(1, - "advansys_queuecommand: before asc_execute_queue() waiting\n"); - asc_execute_queue(&boardp->waiting); - } + printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n", + h->can_tagged_qng, h->cmd_qng_enabled); + printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n", + h->disc_enable, h->sdtr_enable); - /* - * Save the function pointer to Linux mid-level 'done' function - * and attempt to execute the command. - * - * If ASC_NOERROR is returned the request has been added to the - * board's 'active' queue and will be completed by the interrupt - * handler. - * - * If ASC_BUSY is returned add the request to the board's per - * target waiting list. This is the first time the request has - * been tried. Add it to the back of the waiting list. It will be - * retried later. - * - * If an error occurred, the request will have been placed on the - * board's 'done' queue and must be completed before returning. - */ - scp->scsi_done = done; - switch (asc_execute_scsi_cmnd(scp)) { - case ASC_NOERROR: - break; - case ASC_BUSY: - asc_enqueue(&boardp->waiting, scp, ASC_BACK); - break; - case ASC_ERROR: - default: - done_scp = asc_dequeue_list(&boardp->done, NULL, ASC_TID_ALL); - /* Interrupts could be enabled here. */ - asc_scsi_done_list(done_scp); - break; - } - spin_unlock_irqrestore(&boardp->lock, flags); + printk(" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, " + "chip_version %d,\n", h->chip_scsi_id, h->isa_dma_speed, + h->isa_dma_channel, h->chip_version); - return 0; + printk(" mcode_date 0x%x, mcode_version %d\n", + h->mcode_date, h->mcode_version); } /* - * advansys_reset() - * - * Reset the bus associated with the command 'scp'. + * asc_prt_adv_dvc_var() * - * This function runs its own thread. Interrupts must be blocked but - * sleeping is allowed and no locking other than for host structures is - * required. Returns SUCCESS or FAILED. + * Display an ADV_DVC_VAR structure. */ -static int advansys_reset(struct scsi_cmnd *scp) +static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h) { - struct Scsi_Host *shost; - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - ulong flags; - struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; - struct scsi_cmnd *tscp, *new_last_scp; - int status; - int ret = SUCCESS; - - ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp); - -#ifdef ADVANSYS_STATS - if (scp->device->host != NULL) { - ASC_STATS(scp->device->host, reset); - } -#endif /* ADVANSYS_STATS */ - - if ((shost = scp->device->host) == NULL) { - scp->result = HOST_BYTE(DID_ERROR); - return FAILED; - } - - boardp = ASC_BOARDP(shost); - - ASC_PRINT1("advansys_reset: board %d: SCSI bus reset started...\n", - boardp->id); - /* - * Check for re-entrancy. - */ - spin_lock_irqsave(&boardp->lock, flags); - if (boardp->flags & ASC_HOST_IN_RESET) { - spin_unlock_irqrestore(&boardp->lock, flags); - return FAILED; - } - boardp->flags |= ASC_HOST_IN_RESET; - spin_unlock_irqrestore(&boardp->lock, flags); - - if (ASC_NARROW_BOARD(boardp)) { - /* - * Narrow Board - */ - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - - /* - * Reset the chip and SCSI bus. - */ - ASC_DBG(1, "advansys_reset: before AscInitAsc1000Driver()\n"); - status = AscInitAsc1000Driver(asc_dvc_varp); - - /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */ - if (asc_dvc_varp->err_code) { - ASC_PRINT2 - ("advansys_reset: board %d: SCSI bus reset error: 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ret = FAILED; - } else if (status) { - ASC_PRINT2 - ("advansys_reset: board %d: SCSI bus reset warning: 0x%x\n", - boardp->id, status); - } else { - ASC_PRINT1 - ("advansys_reset: board %d: SCSI bus reset successful.\n", - boardp->id); - } - - ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n"); - spin_lock_irqsave(&boardp->lock, flags); - - } else { - /* - * Wide Board - * - * If the suggest reset bus flags are set, then reset the bus. - * Otherwise only reset the device. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - - /* - * Reset the target's SCSI bus. - */ - ASC_DBG(1, "advansys_reset: before AdvResetChipAndSB()\n"); - switch (AdvResetChipAndSB(adv_dvc_varp)) { - case ASC_TRUE: - ASC_PRINT1 - ("advansys_reset: board %d: SCSI bus reset successful.\n", - boardp->id); - break; - case ASC_FALSE: - default: - ASC_PRINT1 - ("advansys_reset: board %d: SCSI bus reset error.\n", - boardp->id); - ret = FAILED; - break; - } - spin_lock_irqsave(&boardp->lock, flags); - (void)AdvISR(adv_dvc_varp); - } - /* Board lock is held. */ - - /* - * Dequeue all board 'done' requests. A pointer to the last request - * is returned in 'last_scp'. - */ - done_scp = asc_dequeue_list(&boardp->done, &last_scp, ASC_TID_ALL); - - /* - * Dequeue all board 'active' requests for all devices and set - * the request status to DID_RESET. A pointer to the last request - * is returned in 'last_scp'. - */ - if (done_scp == NULL) { - done_scp = - asc_dequeue_list(&boardp->active, &last_scp, ASC_TID_ALL); - for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - } else { - /* Append to 'done_scp' at the end with 'last_scp'. */ - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = - (unsigned char *)asc_dequeue_list(&boardp->active, - &new_last_scp, - ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - for (tscp = REQPNEXT(last_scp); tscp; - tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - last_scp = new_last_scp; - } - } - - /* - * Dequeue all 'waiting' requests and set the request status - * to DID_RESET. - */ - if (done_scp == NULL) { - done_scp = - asc_dequeue_list(&boardp->waiting, &last_scp, ASC_TID_ALL); - for (tscp = done_scp; tscp; tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - } else { - /* Append to 'done_scp' at the end with 'last_scp'. */ - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = - (unsigned char *)asc_dequeue_list(&boardp->waiting, - &new_last_scp, - ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - for (tscp = REQPNEXT(last_scp); tscp; - tscp = REQPNEXT(tscp)) { - tscp->result = HOST_BYTE(DID_RESET); - } - last_scp = new_last_scp; - } - } + printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h); - /* Save the time of the most recently completed reset. */ - boardp->last_reset = jiffies; + printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", + (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able); - /* Clear reset flag. */ - boardp->flags &= ~ASC_HOST_IN_RESET; - spin_unlock_irqrestore(&boardp->lock, flags); + printk(" sdtr_able 0x%x, wdtr_able 0x%x\n", + (unsigned)h->sdtr_able, (unsigned)h->wdtr_able); - /* - * Complete all the 'done_scp' requests. - */ - if (done_scp != NULL) { - asc_scsi_done_list(done_scp); - } + printk(" start_motor 0x%x, scsi_reset_wait 0x%x\n", + (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait); - ASC_DBG1(1, "advansys_reset: ret %d\n", ret); + printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n", + (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng, + (ulong)h->carr_freelist); - return ret; -} + printk(" icq_sp 0x%lx, irq_sp 0x%lx\n", + (ulong)h->icq_sp, (ulong)h->irq_sp); -/* - * advansys_biosparam() - * - * Translate disk drive geometry if the "BIOS greater than 1 GB" - * support is enabled for a drive. - * - * ip (information pointer) is an int array with the following definition: - * ip[0]: heads - * ip[1]: sectors - * ip[2]: cylinders - */ -static int -advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int ip[]) -{ - asc_board_t *boardp; + printk(" no_scam 0x%x, tagqng_able 0x%x\n", + (unsigned)h->no_scam, (unsigned)h->tagqng_able); - ASC_DBG(1, "advansys_biosparam: begin\n"); - ASC_STATS(sdev->host, biosparam); - boardp = ASC_BOARDP(sdev->host); - if (ASC_NARROW_BOARD(boardp)) { - if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & - ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) { - ip[0] = 255; - ip[1] = 63; - } else { - ip[0] = 64; - ip[1] = 32; - } - } else { - if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & - BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) { - ip[0] = 255; - ip[1] = 63; - } else { - ip[0] = 64; - ip[1] = 32; - } - } - ip[2] = (unsigned long)capacity / (ip[0] * ip[1]); - ASC_DBG(1, "advansys_biosparam: end\n"); - return 0; + printk(" chip_scsi_id 0x%x, cfg 0x%lx\n", + (unsigned)h->chip_scsi_id, (ulong)h->cfg); } -static int __init advansys_detect(struct scsi_host_template *tpnt); -static int advansys_release(struct Scsi_Host *shp); - -static struct scsi_host_template driver_template = { - .proc_name = "advansys", -#ifdef CONFIG_PROC_FS - .proc_info = advansys_proc_info, -#endif - .name = "advansys", - .detect = advansys_detect, - .release = advansys_release, - .info = advansys_info, - .queuecommand = advansys_queuecommand, - .eh_bus_reset_handler = advansys_reset, - .bios_param = advansys_biosparam, - .slave_configure = advansys_slave_configure, - /* - * Because the driver may control an ISA adapter 'unchecked_isa_dma' - * must be set. The flag will be cleared in advansys_detect for non-ISA - * adapters. Refer to the comment in scsi_module.c for more information. - */ - .unchecked_isa_dma = 1, - /* - * All adapters controlled by this driver are capable of large - * scatter-gather lists. According to the mid-level SCSI documentation - * this obviates any performance gain provided by setting - * 'use_clustering'. But empirically while CPU utilization is increased - * by enabling clustering, I/O throughput increases as well. - */ - .use_clustering = ENABLE_CLUSTERING, -}; - -#include "scsi_module.c" - -/* - * --- Miscellaneous Driver Functions - */ - /* - * First-level interrupt handler. + * asc_prt_adv_dvc_cfg() * - * 'dev_id' is a pointer to the interrupting adapter's asc_board_t. Because - * all boards are currently checked for interrupts on each interrupt, 'dev_id' - * is not referenced. 'dev_id' could be used to identify an interrupt passed - * to the AdvanSys driver which is for a device sharing an interrupt with - * an AdvanSys adapter. + * Display an ADV_DVC_CFG structure. */ -static irqreturn_t advansys_interrupt(int irq, void *dev_id) +static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) { - ulong flags; - int i; - asc_board_t *boardp; - struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; - struct scsi_cmnd *new_last_scp; - struct Scsi_Host *shost; - - ASC_DBG(1, "advansys_interrupt: begin\n"); - - /* - * Check for interrupts on all boards. - * AscISR() will call asc_isr_callback(). - */ - for (i = 0; i < asc_board_count; i++) { - shost = asc_host[i]; - boardp = ASC_BOARDP(shost); - ASC_DBG2(2, "advansys_interrupt: i %d, boardp 0x%lx\n", - i, (ulong)boardp); - spin_lock_irqsave(&boardp->lock, flags); - if (ASC_NARROW_BOARD(boardp)) { - /* - * Narrow Board - */ - if (AscIsIntPending(shost->io_port)) { - ASC_STATS(shost, interrupt); - ASC_DBG(1, - "advansys_interrupt: before AscISR()\n"); - AscISR(&boardp->dvc_var.asc_dvc_var); - } - } else { - /* - * Wide Board - */ - ASC_DBG(1, "advansys_interrupt: before AdvISR()\n"); - if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { - ASC_STATS(shost, interrupt); - } - } - - /* - * Start waiting requests and create a list of completed requests. - * - * If a reset request is being performed for the board, the reset - * handler will complete pending requests after it has completed. - */ - if ((boardp->flags & ASC_HOST_IN_RESET) == 0) { - ASC_DBG2(1, - "advansys_interrupt: done_scp 0x%lx, last_scp 0x%lx\n", - (ulong)done_scp, (ulong)last_scp); - - /* Start any waiting commands for the board. */ - if (!ASC_QUEUE_EMPTY(&boardp->waiting)) { - ASC_DBG(1, - "advansys_interrupt: before asc_execute_queue()\n"); - asc_execute_queue(&boardp->waiting); - } - - /* - * Add to the list of requests that must be completed. - * - * 'done_scp' will always be NULL on the first iteration - * of this loop. 'last_scp' is set at the same time as - * 'done_scp'. - */ - if (done_scp == NULL) { - done_scp = - asc_dequeue_list(&boardp->done, &last_scp, - ASC_TID_ALL); - } else { - ASC_ASSERT(last_scp != NULL); - last_scp->host_scribble = - (unsigned char *)asc_dequeue_list(&boardp-> - done, - &new_last_scp, - ASC_TID_ALL); - if (new_last_scp != NULL) { - ASC_ASSERT(REQPNEXT(last_scp) != NULL); - last_scp = new_last_scp; - } - } - } - spin_unlock_irqrestore(&boardp->lock, flags); - } - - /* - * If interrupts were enabled on entry, then they - * are now enabled here. - * - * Complete all requests on the done list. - */ - - asc_scsi_done_list(done_scp); + printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h); - ASC_DBG(1, "advansys_interrupt: end\n"); - return IRQ_HANDLED; -} + printk(" disc_enable 0x%x, termination 0x%x\n", + h->disc_enable, h->termination); -/* - * Set the number of commands to queue per device for the - * specified host adapter. - */ -static int advansys_slave_configure(struct scsi_device *device) -{ - asc_board_t *boardp; + printk(" chip_version 0x%x, mcode_date 0x%x\n", + h->chip_version, h->mcode_date); - boardp = ASC_BOARDP(device->host); - boardp->flags |= ASC_SELECT_QUEUE_DEPTHS; - /* - * Save a pointer to the device and set its initial/maximum - * queue depth. Only save the pointer for a lun0 dev though. - */ - if (device->lun == 0) - boardp->device[device->id] = device; - if (device->tagged_supported) { - if (ASC_NARROW_BOARD(boardp)) { - scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, - boardp->dvc_var.asc_dvc_var. - max_dvc_qng[device->id]); - } else { - scsi_adjust_queue_depth(device, MSG_ORDERED_TAG, - boardp->dvc_var.adv_dvc_var. - max_dvc_qng); - } - } else { - scsi_adjust_queue_depth(device, 0, device->host->cmd_per_lun); - } - ASC_DBG4(1, - "advansys_slave_configure: device 0x%lx, boardp 0x%lx, id %d, depth %d\n", - (ulong)device, (ulong)boardp, device->id, device->queue_depth); - return 0; + printk(" mcode_version 0x%x, control_flag 0x%x\n", + h->mcode_version, h->control_flag); } /* - * Complete all requests on the singly linked list pointed - * to by 'scp'. - * - * Interrupts can be enabled on entry. + * asc_prt_scsi_host() */ -static void asc_scsi_done_list(struct scsi_cmnd *scp) +static void asc_prt_scsi_host(struct Scsi_Host *s) { - struct scsi_cmnd *tscp; - - ASC_DBG(2, "asc_scsi_done_list: begin\n"); - while (scp != NULL) { - asc_board_t *boardp; - struct device *dev; + struct asc_board *boardp = shost_priv(s); - ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp); - tscp = REQPNEXT(scp); - scp->host_scribble = NULL; - - boardp = ASC_BOARDP(scp->device->host); - - if (ASC_NARROW_BOARD(boardp)) - dev = boardp->dvc_cfg.asc_dvc_cfg.dev; - else - dev = boardp->dvc_cfg.adv_dvc_cfg.dev; + printk("Scsi_Host at addr 0x%p, device %s\n", s, boardp->dev->bus_id); + printk(" host_busy %u, host_no %d, last_reset %d,\n", + s->host_busy, s->host_no, (unsigned)s->last_reset); - if (scp->use_sg) - dma_unmap_sg(dev, - (struct scatterlist *)scp->request_buffer, - scp->use_sg, scp->sc_data_direction); - else if (scp->request_bufflen) - dma_unmap_single(dev, scp->SCp.dma_handle, - scp->request_bufflen, - scp->sc_data_direction); + printk(" base 0x%lx, io_port 0x%lx, irq %d,\n", + (ulong)s->base, (ulong)s->io_port, boardp->irq); - ASC_STATS(scp->device->host, done); - ASC_ASSERT(scp->scsi_done != NULL); + printk(" dma_channel %d, this_id %d, can_queue %d,\n", + s->dma_channel, s->this_id, s->can_queue); - scp->scsi_done(scp); + printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", + s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); - scp = tscp; + if (ASC_NARROW_BOARD(boardp)) { + asc_prt_asc_dvc_var(&boardp->dvc_var.asc_dvc_var); + asc_prt_asc_dvc_cfg(&boardp->dvc_cfg.asc_dvc_cfg); + } else { + asc_prt_adv_dvc_var(&boardp->dvc_var.adv_dvc_var); + asc_prt_adv_dvc_cfg(&boardp->dvc_cfg.adv_dvc_cfg); } - ASC_DBG(2, "asc_scsi_done_list: done\n"); - return; } /* - * Execute a single 'Scsi_Cmnd'. - * - * The function 'done' is called when the request has been completed. - * - * Scsi_Cmnd: - * - * host - board controlling device - * device - device to send command - * target - target of device - * lun - lun of device - * cmd_len - length of SCSI CDB - * cmnd - buffer for SCSI 8, 10, or 12 byte CDB - * use_sg - if non-zero indicates scatter-gather request with use_sg elements - * - * if (use_sg == 0) { - * request_buffer - buffer address for request - * request_bufflen - length of request buffer - * } else { - * request_buffer - pointer to scatterlist structure - * } - * - * sense_buffer - sense command buffer - * - * result (4 bytes of an int): - * Byte Meaning - * 0 SCSI Status Byte Code - * 1 SCSI One Byte Message Code - * 2 Host Error Code - * 3 Mid-Level Error Code - * - * host driver fields: - * SCp - Scsi_Pointer used for command processing status - * scsi_done - used to save caller's done function - * host_scribble - used for pointer to another struct scsi_cmnd - * - * If this function returns ASC_NOERROR the request has been enqueued - * on the board's 'active' queue and will be completed from the - * interrupt handler. - * - * If this function returns ASC_NOERROR the request has been enqueued - * on the board's 'done' queue and must be completed by the caller. + * asc_prt_hex() * - * If ASC_BUSY is returned the request will be enqueued by the - * caller on the target's waiting queue and re-tried later. + * Print hexadecimal output in 4 byte groupings 32 bytes + * or 8 double-words per line. */ -static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) +static void asc_prt_hex(char *f, uchar *s, int l) { - asc_board_t *boardp; - ASC_DVC_VAR *asc_dvc_varp; - ADV_DVC_VAR *adv_dvc_varp; - ADV_SCSI_REQ_Q *adv_scsiqp; - struct scsi_device *device; - int ret; - - ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n", - (ulong)scp, (ulong)scp->scsi_done); - - boardp = ASC_BOARDP(scp->device->host); - device = boardp->device[scp->device->id]; + int i; + int j; + int k; + int m; - if (ASC_NARROW_BOARD(boardp)) { - /* - * Build and execute Narrow Board request. - */ + printk("%s: (%d bytes)\n", f, l); - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + for (i = 0; i < l; i += 32) { - /* - * Build Asc Library request structure using the - * global structures 'asc_scsi_req' and 'asc_sg_head'. - * - * If an error is returned, then the request has been - * queued on the board done queue. It will be completed - * by the caller. - * - * asc_build_req() can not return ASC_BUSY. - */ - if (asc_build_req(boardp, scp) == ASC_ERROR) { - ASC_STATS(scp->device->host, build_error); - return ASC_ERROR; + /* Display a maximum of 8 double-words per line. */ + if ((k = (l - i) / 4) >= 8) { + k = 8; + m = 0; + } else { + m = (l - i) % 4; } - /* - * Execute the command. If there is no error, add the command - * to the active queue. - */ - switch (ret = AscExeScsiQueue(asc_dvc_varp, &asc_scsi_q)) { - case ASC_NOERROR: - ASC_STATS(scp->device->host, exe_noerror); - /* - * Increment monotonically increasing per device successful - * request counter. Wrapping doesn't matter. - */ - boardp->reqcnt[scp->device->id]++; - asc_enqueue(&boardp->active, scp, ASC_BACK); - ASC_DBG(1, - "asc_execute_scsi_cmnd: AscExeScsiQueue(), ASC_NOERROR\n"); - break; - case ASC_BUSY: - /* - * Caller will enqueue request on the target's waiting queue - * and retry later. - */ - ASC_STATS(scp->device->host, exe_busy); - break; - case ASC_ERROR: - ASC_PRINT2 - ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() ASC_ERROR, err_code 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_error); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; - default: - ASC_PRINT2 - ("asc_execute_scsi_cmnd: board %d: AscExeScsiQueue() unknown, err_code 0x%x\n", - boardp->id, asc_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_unknown); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - break; + for (j = 0; j < k; j++) { + printk(" %2.2X%2.2X%2.2X%2.2X", + (unsigned)s[i + (j * 4)], + (unsigned)s[i + (j * 4) + 1], + (unsigned)s[i + (j * 4) + 2], + (unsigned)s[i + (j * 4) + 3]); } - } else { - /* - * Build and execute Wide Board request. - */ - adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - /* - * Build and get a pointer to an Adv Library request structure. - * - * If the request is successfully built then send it below, - * otherwise return with an error. - */ - switch (adv_build_req(boardp, scp, &adv_scsiqp)) { - case ASC_NOERROR: - ASC_DBG(3, - "asc_execute_scsi_cmnd: adv_build_req ASC_NOERROR\n"); - break; - case ASC_BUSY: - ASC_DBG(1, - "asc_execute_scsi_cmnd: adv_build_req ASC_BUSY\n"); - /* - * If busy is returned the request has not been enqueued. - * It will be enqueued by the caller on the target's waiting - * queue and retried later. - * - * The asc_stats fields 'adv_build_noreq' and 'adv_build_nosg' - * count wide board busy conditions. They are updated in - * adv_build_req and adv_get_sglist, respectively. - */ - return ASC_BUSY; - case ASC_ERROR: - /* - * If an error is returned, then the request has been - * queued on the board done queue. It will be completed - * by the caller. - */ + switch (m) { + case 0: default: - ASC_DBG(1, - "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n"); - ASC_STATS(scp->device->host, build_error); - return ASC_ERROR; - } - - /* - * Execute the command. If there is no error, add the command - * to the active queue. - */ - switch (ret = AdvExeScsiQueue(adv_dvc_varp, adv_scsiqp)) { - case ASC_NOERROR: - ASC_STATS(scp->device->host, exe_noerror); - /* - * Increment monotonically increasing per device successful - * request counter. Wrapping doesn't matter. - */ - boardp->reqcnt[scp->device->id]++; - asc_enqueue(&boardp->active, scp, ASC_BACK); - ASC_DBG(1, - "asc_execute_scsi_cmnd: AdvExeScsiQueue(), ASC_NOERROR\n"); break; - case ASC_BUSY: - /* - * Caller will enqueue request on the target's waiting queue - * and retry later. - */ - ASC_STATS(scp->device->host, exe_busy); + case 1: + printk(" %2.2X", (unsigned)s[i + (j * 4)]); break; - case ASC_ERROR: - ASC_PRINT2 - ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() ASC_ERROR, err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_error); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); + case 2: + printk(" %2.2X%2.2X", + (unsigned)s[i + (j * 4)], + (unsigned)s[i + (j * 4) + 1]); break; - default: - ASC_PRINT2 - ("asc_execute_scsi_cmnd: board %d: AdvExeScsiQueue() unknown, err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - ASC_STATS(scp->device->host, exe_unknown); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); + case 3: + printk(" %2.2X%2.2X%2.2X", + (unsigned)s[i + (j * 4) + 1], + (unsigned)s[i + (j * 4) + 2], + (unsigned)s[i + (j * 4) + 3]); break; } - } - - ASC_DBG(1, "asc_execute_scsi_cmnd: end\n"); - return ret; -} -/* - * Build a request structure for the Asc Library (Narrow Board). - * - * The global structures 'asc_scsi_q' and 'asc_sg_head' are - * used to build the request. - * - * If an error occurs, then queue the request on the board done - * queue and return ASC_ERROR. - */ -static int asc_build_req(asc_board_t *boardp, struct scsi_cmnd *scp) -{ - struct device *dev = boardp->dvc_cfg.asc_dvc_cfg.dev; - - /* - * Mutually exclusive access is required to 'asc_scsi_q' and - * 'asc_sg_head' until after the request is started. - */ - memset(&asc_scsi_q, 0, sizeof(ASC_SCSI_Q)); - - /* - * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. - */ - asc_scsi_q.q2.srb_ptr = ASC_VADDR_TO_U32(scp); - - /* - * Build the ASC_SCSI_Q request. - * - * For narrow boards a CDB length maximum of 12 bytes - * is supported. - */ - if (scp->cmd_len > ASC_MAX_CDB_LEN) { - ASC_PRINT3 - ("asc_build_req: board %d: cmd_len %d > ASC_MAX_CDB_LEN %d\n", - boardp->id, scp->cmd_len, ASC_MAX_CDB_LEN); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - asc_scsi_q.cdbptr = &scp->cmnd[0]; - asc_scsi_q.q2.cdb_len = scp->cmd_len; - asc_scsi_q.q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); - asc_scsi_q.q1.target_lun = scp->device->lun; - asc_scsi_q.q2.target_ix = - ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); - asc_scsi_q.q1.sense_addr = - cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); - asc_scsi_q.q1.sense_len = sizeof(scp->sense_buffer); - - /* - * If there are any outstanding requests for the current target, - * then every 255th request send an ORDERED request. This heuristic - * tries to retain the benefit of request sorting while preventing - * request starvation. 255 is the max number of tags or pending commands - * a device may have outstanding. - * - * The request count is incremented below for every successfully - * started request. - * - */ - if ((boardp->dvc_var.asc_dvc_var.cur_dvc_qng[scp->device->id] > 0) && - (boardp->reqcnt[scp->device->id] % 255) == 0) { - asc_scsi_q.q2.tag_code = MSG_ORDERED_TAG; - } else { - asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; - } - - /* - * Build ASC_SCSI_Q for a contiguous buffer or a scatter-gather - * buffer command. - */ - if (scp->use_sg == 0) { - /* - * CDB request of single contiguous buffer. - */ - ASC_STATS(scp->device->host, cont_cnt); - scp->SCp.dma_handle = scp->request_bufflen ? - dma_map_single(dev, scp->request_buffer, - scp->request_bufflen, - scp->sc_data_direction) : 0; - asc_scsi_q.q1.data_addr = cpu_to_le32(scp->SCp.dma_handle); - asc_scsi_q.q1.data_cnt = cpu_to_le32(scp->request_bufflen); - ASC_STATS_ADD(scp->device->host, cont_xfer, - ASC_CEILING(scp->request_bufflen, 512)); - asc_scsi_q.q1.sg_queue_cnt = 0; - asc_scsi_q.sg_head = NULL; - } else { - /* - * CDB scatter-gather request list. - */ - int sgcnt; - int use_sg; - struct scatterlist *slp; - - slp = (struct scatterlist *)scp->request_buffer; - use_sg = - dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - - if (use_sg > scp->device->host->sg_tablesize) { - ASC_PRINT3 - ("asc_build_req: board %d: use_sg %d > sg_tablesize %d\n", - boardp->id, use_sg, - scp->device->host->sg_tablesize); - dma_unmap_sg(dev, slp, scp->use_sg, - scp->sc_data_direction); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - - ASC_STATS(scp->device->host, sg_cnt); - - /* - * Use global ASC_SG_HEAD structure and set the ASC_SCSI_Q - * structure to point to it. - */ - memset(&asc_sg_head, 0, sizeof(ASC_SG_HEAD)); - - asc_scsi_q.q1.cntl |= QC_SG_HEAD; - asc_scsi_q.sg_head = &asc_sg_head; - asc_scsi_q.q1.data_cnt = 0; - asc_scsi_q.q1.data_addr = 0; - /* This is a byte value, otherwise it would need to be swapped. */ - asc_sg_head.entry_cnt = asc_scsi_q.q1.sg_queue_cnt = use_sg; - ASC_STATS_ADD(scp->device->host, sg_elem, - asc_sg_head.entry_cnt); - - /* - * Convert scatter-gather list into ASC_SG_HEAD list. - */ - for (sgcnt = 0; sgcnt < use_sg; sgcnt++, slp++) { - asc_sg_head.sg_list[sgcnt].addr = - cpu_to_le32(sg_dma_address(slp)); - asc_sg_head.sg_list[sgcnt].bytes = - cpu_to_le32(sg_dma_len(slp)); - ASC_STATS_ADD(scp->device->host, sg_xfer, - ASC_CEILING(sg_dma_len(slp), 512)); - } + printk("\n"); } - - ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); - ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); - - return ASC_NOERROR; } /* - * Build a request structure for the Adv Library (Wide Board). - * - * If an adv_req_t can not be allocated to issue the request, - * then return ASC_BUSY. If an error occurs, then return ASC_ERROR. - * - * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the - * microcode for DMA addresses or math operations are byte swapped - * to little-endian order. + * asc_prt_asc_scsi_q() */ -static int -adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, - ADV_SCSI_REQ_Q **adv_scsiqpp) +static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q) { - adv_req_t *reqp; - ADV_SCSI_REQ_Q *scsiqp; + ASC_SG_HEAD *sgp; int i; - int ret; - struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev; - /* - * Allocate an adv_req_t structure from the board to execute - * the command. - */ - if (boardp->adv_reqp == NULL) { - ASC_DBG(1, "adv_build_req: no free adv_req_t\n"); - ASC_STATS(scp->device->host, adv_build_noreq); - return ASC_BUSY; - } else { - reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp->next_reqp; - reqp->next_reqp = NULL; - } - - /* - * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. - */ - scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); - - /* - * Initialize the structure. - */ - scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; - - /* - * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. - */ - scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); - - /* - * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. - */ - reqp->cmndp = scp; - - /* - * Build the ADV_SCSI_REQ_Q request. - */ - - /* - * Set CDB length and copy it to the request structure. - * For wide boards a CDB length maximum of 16 bytes - * is supported. - */ - if (scp->cmd_len > ADV_MAX_CDB_LEN) { - ASC_PRINT3 - ("adv_build_req: board %d: cmd_len %d > ADV_MAX_CDB_LEN %d\n", - boardp->id, scp->cmd_len, ADV_MAX_CDB_LEN); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); - return ASC_ERROR; - } - scsiqp->cdb_len = scp->cmd_len; - /* Copy first 12 CDB bytes to cdb[]. */ - for (i = 0; i < scp->cmd_len && i < 12; i++) { - scsiqp->cdb[i] = scp->cmnd[i]; - } - /* Copy last 4 CDB bytes, if present, to cdb16[]. */ - for (; i < scp->cmd_len; i++) { - scsiqp->cdb16[i - 12] = scp->cmnd[i]; - } - - scsiqp->target_id = scp->device->id; - scsiqp->target_lun = scp->device->lun; - - scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); - scsiqp->sense_len = sizeof(scp->sense_buffer); - - /* - * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather - * buffer command. - */ - - scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); - scsiqp->vdata_addr = scp->request_buffer; - scsiqp->data_addr = cpu_to_le32(virt_to_bus(scp->request_buffer)); - - if (scp->use_sg == 0) { - /* - * CDB request of single contiguous buffer. - */ - reqp->sgblkp = NULL; - scsiqp->data_cnt = cpu_to_le32(scp->request_bufflen); - if (scp->request_bufflen) { - scsiqp->vdata_addr = scp->request_buffer; - scp->SCp.dma_handle = - dma_map_single(dev, scp->request_buffer, - scp->request_bufflen, - scp->sc_data_direction); - } else { - scsiqp->vdata_addr = NULL; - scp->SCp.dma_handle = 0; - } - scsiqp->data_addr = cpu_to_le32(scp->SCp.dma_handle); - scsiqp->sg_list_ptr = NULL; - scsiqp->sg_real_addr = 0; - ASC_STATS(scp->device->host, cont_cnt); - ASC_STATS_ADD(scp->device->host, cont_xfer, - ASC_CEILING(scp->request_bufflen, 512)); - } else { - /* - * CDB scatter-gather request list. - */ - struct scatterlist *slp; - int use_sg; - - slp = (struct scatterlist *)scp->request_buffer; - use_sg = - dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - - if (use_sg > ADV_MAX_SG_LIST) { - ASC_PRINT3 - ("adv_build_req: board %d: use_sg %d > ADV_MAX_SG_LIST %d\n", - boardp->id, use_sg, - scp->device->host->sg_tablesize); - dma_unmap_sg(dev, slp, scp->use_sg, - scp->sc_data_direction); - scp->result = HOST_BYTE(DID_ERROR); - asc_enqueue(&boardp->done, scp, ASC_BACK); + printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q); - /* - * Free the 'adv_req_t' structure by adding it back to the - * board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; + printk + (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n", + q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr, + q->q2.tag_code); - return ASC_ERROR; - } + printk + (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", + (ulong)le32_to_cpu(q->q1.data_addr), + (ulong)le32_to_cpu(q->q1.data_cnt), + (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len); - if ((ret = - adv_get_sglist(boardp, reqp, scp, - use_sg)) != ADV_SUCCESS) { - /* - * Free the adv_req_t structure by adding it back to the - * board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; + printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n", + (ulong)q->cdbptr, q->q2.cdb_len, + (ulong)q->sg_head, q->q1.sg_queue_cnt); - return ret; + if (q->sg_head) { + sgp = q->sg_head; + printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp); + printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, + sgp->queue_cnt); + for (i = 0; i < sgp->entry_cnt; i++) { + printk(" [%u]: addr 0x%lx, bytes %lu\n", + i, (ulong)le32_to_cpu(sgp->sg_list[i].addr), + (ulong)le32_to_cpu(sgp->sg_list[i].bytes)); } - ASC_STATS(scp->device->host, sg_cnt); - ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); } - - ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); - ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); - - *adv_scsiqpp = scsiqp; - - return ASC_NOERROR; } /* - * Build scatter-gather list for Adv Library (Wide Board). - * - * Additional ADV_SG_BLOCK structures will need to be allocated - * if the total number of scatter-gather elements exceeds - * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are - * assumed to be physically contiguous. - * - * Return: - * ADV_SUCCESS(1) - SG List successfully created - * ADV_ERROR(-1) - SG List creation failed + * asc_prt_asc_qdone_info() */ -static int -adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, - int use_sg) +static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) { - adv_sgblk_t *sgblkp; - ADV_SCSI_REQ_Q *scsiqp; - struct scatterlist *slp; - int sg_elem_cnt; - ADV_SG_BLOCK *sg_block, *prev_sg_block; - ADV_PADDR sg_block_paddr; - int i; - - scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); - slp = (struct scatterlist *)scp->request_buffer; - sg_elem_cnt = use_sg; - prev_sg_block = NULL; - reqp->sgblkp = NULL; - - do { - /* - * Allocate a 'adv_sgblk_t' structure from the board free - * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK - * (15) scatter-gather elements. - */ - if ((sgblkp = boardp->adv_sgblkp) == NULL) { - ASC_DBG(1, "adv_get_sglist: no free adv_sgblk_t\n"); - ASC_STATS(scp->device->host, adv_build_nosg); - - /* - * Allocation failed. Free 'adv_sgblk_t' structures already - * allocated for the request. - */ - while ((sgblkp = reqp->sgblkp) != NULL) { - /* Remove 'sgblkp' from the request list. */ - reqp->sgblkp = sgblkp->next_sgblkp; - - /* Add 'sgblkp' to the board free list. */ - sgblkp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgblkp; - } - return ASC_BUSY; - } else { - /* Complete 'adv_sgblk_t' board allocation. */ - boardp->adv_sgblkp = sgblkp->next_sgblkp; - sgblkp->next_sgblkp = NULL; - - /* - * Get 8 byte aligned virtual and physical addresses for - * the allocated ADV_SG_BLOCK structure. - */ - sg_block = - (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block); - sg_block_paddr = virt_to_bus(sg_block); - - /* - * Check if this is the first 'adv_sgblk_t' for the request. - */ - if (reqp->sgblkp == NULL) { - /* Request's first scatter-gather block. */ - reqp->sgblkp = sgblkp; - - /* - * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical - * address pointers. - */ - scsiqp->sg_list_ptr = sg_block; - scsiqp->sg_real_addr = - cpu_to_le32(sg_block_paddr); - } else { - /* Request's second or later scatter-gather block. */ - sgblkp->next_sgblkp = reqp->sgblkp; - reqp->sgblkp = sgblkp; - - /* - * Point the previous ADV_SG_BLOCK structure to - * the newly allocated ADV_SG_BLOCK structure. - */ - ASC_ASSERT(prev_sg_block != NULL); - prev_sg_block->sg_ptr = - cpu_to_le32(sg_block_paddr); - } - } - - for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { - sg_block->sg_list[i].sg_addr = - cpu_to_le32(sg_dma_address(slp)); - sg_block->sg_list[i].sg_count = - cpu_to_le32(sg_dma_len(slp)); - ASC_STATS_ADD(scp->device->host, sg_xfer, - ASC_CEILING(sg_dma_len(slp), 512)); - - if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */ - sg_block->sg_cnt = i + 1; - sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */ - return ADV_SUCCESS; - } - slp++; - } - sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; - prev_sg_block = sg_block; - } - while (1); - /* NOTREACHED */ + printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q); + printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n", + (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, + q->d2.tag_code); + printk + (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n", + q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); } /* - * asc_isr_callback() - Second Level Interrupt Handler called by AscISR(). + * asc_prt_adv_sgblock() * - * Interrupt callback function for the Narrow SCSI Asc Library. + * Display an ADV_SG_BLOCK structure. */ -static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) +static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) { - asc_board_t *boardp; - struct scsi_cmnd *scp; - struct Scsi_Host *shost; int i; - ASC_DBG2(1, "asc_isr_callback: asc_dvc_varp 0x%lx, qdonep 0x%lx\n", - (ulong)asc_dvc_varp, (ulong)qdonep); - ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); - - /* - * Get the struct scsi_cmnd structure and Scsi_Host structure for the - * command that has been completed. - */ - scp = (struct scsi_cmnd *)ASC_U32_TO_VADDR(qdonep->d2.srb_ptr); - ASC_DBG1(1, "asc_isr_callback: scp 0x%lx\n", (ulong)scp); - - if (scp == NULL) { - ASC_PRINT("asc_isr_callback: scp is NULL\n"); - return; - } - ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); - - /* - * If the request's host pointer is not valid, display a - * message and return. - */ - shost = scp->device->host; - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i] == shost) { - break; - } - } - if (i == asc_board_count) { - ASC_PRINT2 - ("asc_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", - (ulong)scp, (ulong)shost); - return; - } - - ASC_STATS(shost, callback); - ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost); - - /* - * If the request isn't found on the active queue, it may - * have been removed to handle a reset request. - * Display a message and return. - */ - boardp = ASC_BOARDP(shost); - ASC_ASSERT(asc_dvc_varp == &boardp->dvc_var.asc_dvc_var); - if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { - ASC_PRINT2 - ("asc_isr_callback: board %d: scp 0x%lx not on active queue\n", - boardp->id, (ulong)scp); - return; - } - - /* - * 'qdonep' contains the command's ending status. - */ - switch (qdonep->d3.done_stat) { - case QD_NO_ERROR: - ASC_DBG(2, "asc_isr_callback: QD_NO_ERROR\n"); - scp->result = 0; - - /* - * If an INQUIRY command completed successfully, then call - * the AscInquiryHandling() function to set-up the device. - */ - if (scp->cmnd[0] == INQUIRY && scp->device->lun == 0 && - (scp->request_bufflen - qdonep->remain_bytes) >= 8) { - AscInquiryHandling(asc_dvc_varp, scp->device->id & 0x7, - (ASC_SCSI_INQUIRY *)scp-> - request_buffer); - } - - /* - * Check for an underrun condition. - * - * If there was no error and an underrun condition, then - * then return the number of underrun bytes. - */ - if (scp->request_bufflen != 0 && qdonep->remain_bytes != 0 && - qdonep->remain_bytes <= scp->request_bufflen) { - ASC_DBG1(1, - "asc_isr_callback: underrun condition %u bytes\n", - (unsigned)qdonep->remain_bytes); - scp->resid = qdonep->remain_bytes; - } - break; - - case QD_WITH_ERROR: - ASC_DBG(2, "asc_isr_callback: QD_WITH_ERROR\n"); - switch (qdonep->d3.host_stat) { - case QHSTA_NO_ERROR: - if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { - ASC_DBG(2, - "asc_isr_callback: SAM_STAT_CHECK_CONDITION\n"); - ASC_DBG_PRT_SENSE(2, scp->sense_buffer, - sizeof(scp->sense_buffer)); - /* - * Note: The 'status_byte()' macro used by target drivers - * defined in scsi.h shifts the status byte returned by - * host drivers right by 1 bit. This is why target drivers - * also use right shifted status byte definitions. For - * instance target drivers use CHECK_CONDITION, defined to - * 0x1, instead of the SCSI defined check condition value - * of 0x2. Host drivers are supposed to return the status - * byte as it is defined by SCSI. - */ - scp->result = DRIVER_BYTE(DRIVER_SENSE) | - STATUS_BYTE(qdonep->d3.scsi_stat); - } else { - scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); - } - break; - - default: - /* QHSTA error occurred */ - ASC_DBG1(1, "asc_isr_callback: host_stat 0x%x\n", - qdonep->d3.host_stat); - scp->result = HOST_BYTE(DID_BAD_TARGET); - break; - } - break; - - case QD_ABORTED_BY_HOST: - ASC_DBG(1, "asc_isr_callback: QD_ABORTED_BY_HOST\n"); - scp->result = - HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3. - scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - - default: - ASC_DBG1(1, "asc_isr_callback: done_stat 0x%x\n", - qdonep->d3.done_stat); - scp->result = - HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3. - scsi_msg) | - STATUS_BYTE(qdonep->d3.scsi_stat); - break; - } - - /* - * If the 'init_tidmask' bit isn't already set for the target and the - * current request finished normally, then set the bit for the target - * to indicate that a device is present. - */ - if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && - qdonep->d3.done_stat == QD_NO_ERROR && - qdonep->d3.host_stat == QHSTA_NO_ERROR) { - boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); + printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n", + (ulong)b, sgblockno); + printk(" sg_cnt %u, sg_ptr 0x%lx\n", + b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr)); + BUG_ON(b->sg_cnt > NO_OF_SG_PER_BLOCK); + if (b->sg_ptr != 0) + BUG_ON(b->sg_cnt != NO_OF_SG_PER_BLOCK); + for (i = 0; i < b->sg_cnt; i++) { + printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n", + i, (ulong)b->sg_list[i].sg_addr, + (ulong)b->sg_list[i].sg_count); } - - /* - * Because interrupts may be enabled by the 'struct scsi_cmnd' done - * function, add the command to the end of the board's done queue. - * The done function for the command will be called from - * advansys_interrupt(). - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); - - return; } /* - * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR(). + * asc_prt_adv_scsi_req_q() * - * Callback function for the Wide SCSI Adv Library. + * Display an ADV_SCSI_REQ_Q structure. */ -static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) +static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) { - asc_board_t *boardp; - adv_req_t *reqp; - adv_sgblk_t *sgblkp; - struct scsi_cmnd *scp; - struct Scsi_Host *shost; - int i; - ADV_DCNT resid_cnt; - - ASC_DBG2(1, "adv_isr_callback: adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", - (ulong)adv_dvc_varp, (ulong)scsiqp); - ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); + int sg_blk_cnt; + struct asc_sg_block *sg_ptr; - /* - * Get the adv_req_t structure for the command that has been - * completed. The adv_req_t structure actually contains the - * completed ADV_SCSI_REQ_Q structure. - */ - reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr); - ASC_DBG1(1, "adv_isr_callback: reqp 0x%lx\n", (ulong)reqp); - if (reqp == NULL) { - ASC_PRINT("adv_isr_callback: reqp is NULL\n"); - return; - } + printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q); - /* - * Get the struct scsi_cmnd structure and Scsi_Host structure for the - * command that has been completed. - * - * Note: The adv_req_t request structure and adv_sgblk_t structure, - * if any, are dropped, because a board structure pointer can not be - * determined. - */ - scp = reqp->cmndp; - ASC_DBG1(1, "adv_isr_callback: scp 0x%lx\n", (ulong)scp); - if (scp == NULL) { - ASC_PRINT - ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); - return; - } - ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", + q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag); - /* - * If the request's host pointer is not valid, display a message - * and return. - */ - shost = scp->device->host; - for (i = 0; i < asc_board_count; i++) { - if (asc_host[i] == shost) { - break; - } - } - /* - * Note: If the host structure is not found, the adv_req_t request - * structure and adv_sgblk_t structure, if any, is dropped. - */ - if (i == asc_board_count) { - ASC_PRINT2 - ("adv_isr_callback: scp 0x%lx has bad host pointer, host 0x%lx\n", - (ulong)scp, (ulong)shost); - return; - } + printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", + q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr); - ASC_STATS(shost, callback); - ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost); + printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", + (ulong)le32_to_cpu(q->data_cnt), + (ulong)le32_to_cpu(q->sense_addr), q->sense_len); - /* - * If the request isn't found on the active queue, it may have been - * removed to handle a reset request. Display a message and return. - * - * Note: Because the structure may still be in use don't attempt - * to free the adv_req_t and adv_sgblk_t, if any, structures. - */ - boardp = ASC_BOARDP(shost); - ASC_ASSERT(adv_dvc_varp == &boardp->dvc_var.adv_dvc_var); - if (asc_rmqueue(&boardp->active, scp) == ASC_FALSE) { - ASC_PRINT2 - ("adv_isr_callback: board %d: scp 0x%lx not on active queue\n", - boardp->id, (ulong)scp); - return; - } + printk + (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", + q->cdb_len, q->done_status, q->host_status, q->scsi_status); - /* - * 'done_status' contains the command's ending status. - */ - switch (scsiqp->done_status) { - case QD_NO_ERROR: - ASC_DBG(2, "adv_isr_callback: QD_NO_ERROR\n"); - scp->result = 0; + printk(" sg_working_ix 0x%x, target_cmd %u\n", + q->sg_working_ix, q->target_cmd); - /* - * Check for an underrun condition. - * - * If there was no error and an underrun condition, then - * then return the number of underrun bytes. - */ - resid_cnt = le32_to_cpu(scsiqp->data_cnt); - if (scp->request_bufflen != 0 && resid_cnt != 0 && - resid_cnt <= scp->request_bufflen) { - ASC_DBG1(1, - "adv_isr_callback: underrun condition %lu bytes\n", - (ulong)resid_cnt); - scp->resid = resid_cnt; - } - break; + printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n", + (ulong)le32_to_cpu(q->scsiq_rptr), + (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr); - case QD_WITH_ERROR: - ASC_DBG(2, "adv_isr_callback: QD_WITH_ERROR\n"); - switch (scsiqp->host_status) { - case QHSTA_NO_ERROR: - if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { - ASC_DBG(2, - "adv_isr_callback: SAM_STAT_CHECK_CONDITION\n"); - ASC_DBG_PRT_SENSE(2, scp->sense_buffer, - sizeof(scp->sense_buffer)); - /* - * Note: The 'status_byte()' macro used by target drivers - * defined in scsi.h shifts the status byte returned by - * host drivers right by 1 bit. This is why target drivers - * also use right shifted status byte definitions. For - * instance target drivers use CHECK_CONDITION, defined to - * 0x1, instead of the SCSI defined check condition value - * of 0x2. Host drivers are supposed to return the status - * byte as it is defined by SCSI. - */ - scp->result = DRIVER_BYTE(DRIVER_SENSE) | - STATUS_BYTE(scsiqp->scsi_status); - } else { - scp->result = STATUS_BYTE(scsiqp->scsi_status); + /* Display the request's ADV_SG_BLOCK structures. */ + if (q->sg_list_ptr != NULL) { + sg_blk_cnt = 0; + while (1) { + /* + * 'sg_ptr' is a physical address. Convert it to a virtual + * address by indexing 'sg_blk_cnt' into the virtual address + * array 'sg_list_ptr'. + * + * XXX - Assumes all SG physical blocks are virtually contiguous. + */ + sg_ptr = + &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]); + asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr); + if (sg_ptr->sg_ptr == 0) { + break; } - break; - - default: - /* Some other QHSTA error occurred. */ - ASC_DBG1(1, "adv_isr_callback: host_status 0x%x\n", - scsiqp->host_status); - scp->result = HOST_BYTE(DID_BAD_TARGET); - break; + sg_blk_cnt++; } - break; - - case QD_ABORTED_BY_HOST: - ASC_DBG(1, "adv_isr_callback: QD_ABORTED_BY_HOST\n"); - scp->result = - HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); - break; - - default: - ASC_DBG1(1, "adv_isr_callback: done_status 0x%x\n", - scsiqp->done_status); - scp->result = - HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); - break; - } - - /* - * If the 'init_tidmask' bit isn't already set for the target and the - * current request finished normally, then set the bit for the target - * to indicate that a device is present. - */ - if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && - scsiqp->done_status == QD_NO_ERROR && - scsiqp->host_status == QHSTA_NO_ERROR) { - boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); - } - - /* - * Because interrupts may be enabled by the 'struct scsi_cmnd' done - * function, add the command to the end of the board's done queue. - * The done function for the command will be called from - * advansys_interrupt(). - */ - asc_enqueue(&boardp->done, scp, ASC_BACK); - - /* - * Free all 'adv_sgblk_t' structures allocated for the request. - */ - while ((sgblkp = reqp->sgblkp) != NULL) { - /* Remove 'sgblkp' from the request list. */ - reqp->sgblkp = sgblkp->next_sgblkp; - - /* Add 'sgblkp' to the board free list. */ - sgblkp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgblkp; } - - /* - * Free the adv_req_t structure used with the command by adding - * it back to the board free list. - */ - reqp->next_reqp = boardp->adv_reqp; - boardp->adv_reqp = reqp; - - ASC_DBG(1, "adv_isr_callback: done\n"); - - return; } +#endif /* ADVANSYS_DEBUG */ /* - * adv_async_callback() - Adv Library asynchronous event callback function. + * The advansys chip/microcode contains a 32-bit identifier for each command + * known as the 'srb'. I don't know what it stands for. The driver used + * to encode the scsi_cmnd pointer by calling virt_to_bus and retrieve it + * with bus_to_virt. Now the driver keeps a per-host map of integers to + * pointers. It auto-expands when full, unless it can't allocate memory. + * Note that an srb of 0 is treated specially by the chip/firmware, hence + * the return of i+1 in this routine, and the corresponding subtraction in + * the inverse routine. */ -static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) +#define BAD_SRB 0 +static u32 advansys_ptr_to_srb(struct asc_dvc_var *asc_dvc, void *ptr) { - switch (code) { - case ADV_ASYNC_SCSI_BUS_RESET_DET: - /* - * The firmware detected a SCSI Bus reset. - */ - ASC_DBG(0, - "adv_async_callback: ADV_ASYNC_SCSI_BUS_RESET_DET\n"); - break; + int i; + void **new_ptr; - case ADV_ASYNC_RDMA_FAILURE: - /* - * Handle RDMA failure by resetting the SCSI Bus and - * possibly the chip if it is unresponsive. Log the error - * with a unique code. - */ - ASC_DBG(0, "adv_async_callback: ADV_ASYNC_RDMA_FAILURE\n"); - AdvResetChipAndSB(adv_dvc_varp); - break; + for (i = 0; i < asc_dvc->ptr_map_count; i++) { + if (!asc_dvc->ptr_map[i]) + goto out; + } - case ADV_HOST_SCSI_BUS_RESET: - /* - * Host generated SCSI bus reset occurred. - */ - ASC_DBG(0, "adv_async_callback: ADV_HOST_SCSI_BUS_RESET\n"); - break; + if (asc_dvc->ptr_map_count == 0) + asc_dvc->ptr_map_count = 1; + else + asc_dvc->ptr_map_count *= 2; - default: - ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code); - break; - } + new_ptr = krealloc(asc_dvc->ptr_map, + asc_dvc->ptr_map_count * sizeof(void *), GFP_ATOMIC); + if (!new_ptr) + return BAD_SRB; + asc_dvc->ptr_map = new_ptr; + out: + ASC_DBG(3, "Putting ptr %p into array offset %d\n", ptr, i); + asc_dvc->ptr_map[i] = ptr; + return i + 1; } -/* - * Add a 'REQP' to the end of specified queue. Set 'tidmask' - * to indicate a command is queued for the device. - * - * 'flag' may be either ASC_FRONT or ASC_BACK. - * - * 'REQPNEXT(reqp)' returns reqp's next pointer. - */ -static void asc_enqueue(asc_queue_t *ascq, REQP reqp, int flag) +static void * advansys_srb_to_ptr(struct asc_dvc_var *asc_dvc, u32 srb) { - int tid; - - ASC_DBG3(3, "asc_enqueue: ascq 0x%lx, reqp 0x%lx, flag %d\n", - (ulong)ascq, (ulong)reqp, flag); - ASC_ASSERT(reqp != NULL); - ASC_ASSERT(flag == ASC_FRONT || flag == ASC_BACK); - tid = REQPTID(reqp); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - if (flag == ASC_FRONT) { - reqp->host_scribble = (unsigned char *)ascq->q_first[tid]; - ascq->q_first[tid] = reqp; - /* If the queue was empty, set the last pointer. */ - if (ascq->q_last[tid] == NULL) { - ascq->q_last[tid] = reqp; - } - } else { /* ASC_BACK */ - if (ascq->q_last[tid] != NULL) { - ascq->q_last[tid]->host_scribble = - (unsigned char *)reqp; - } - ascq->q_last[tid] = reqp; - reqp->host_scribble = NULL; - /* If the queue was empty, set the first pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_first[tid] = reqp; - } - } - /* The queue has at least one entry, set its bit. */ - ascq->q_tidmask |= ADV_TID_TO_TIDMASK(tid); -#ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - ascq->q_tot_cnt[tid]++; - ascq->q_cur_cnt[tid]++; - if (ascq->q_cur_cnt[tid] > ascq->q_max_cnt[tid]) { - ascq->q_max_cnt[tid] = ascq->q_cur_cnt[tid]; - ASC_DBG2(2, "asc_enqueue: new q_max_cnt[%d] %d\n", - tid, ascq->q_max_cnt[tid]); - } - REQPTIME(reqp) = REQTIMESTAMP(); -#endif /* ADVANSYS_STATS */ - ASC_DBG1(3, "asc_enqueue: reqp 0x%lx\n", (ulong)reqp); - return; -} + void *ptr; -/* - * Return first queued 'REQP' on the specified queue for - * the specified target device. Clear the 'tidmask' bit for - * the device if no more commands are left queued for it. - * - * 'REQPNEXT(reqp)' returns reqp's next pointer. - */ -static REQP asc_dequeue(asc_queue_t *ascq, int tid) -{ - REQP reqp; - - ASC_DBG2(3, "asc_dequeue: ascq 0x%lx, tid %d\n", (ulong)ascq, tid); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - if ((reqp = ascq->q_first[tid]) != NULL) { - ASC_ASSERT(ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)); - ascq->q_first[tid] = REQPNEXT(reqp); - /* If the queue is empty, clear its bit and the last pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); - ASC_ASSERT(ascq->q_last[tid] == reqp); - ascq->q_last[tid] = NULL; - } -#ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - ascq->q_cur_cnt[tid]--; - ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); - REQTIMESTAT("asc_dequeue", ascq, reqp, tid); -#endif /* ADVANSYS_STATS */ + srb--; + if (srb >= asc_dvc->ptr_map_count) { + printk("advansys: bad SRB %u, max %u\n", srb, + asc_dvc->ptr_map_count); + return NULL; } - ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp); - return reqp; + ptr = asc_dvc->ptr_map[srb]; + asc_dvc->ptr_map[srb] = NULL; + ASC_DBG(3, "Returning ptr %p from array offset %d\n", ptr, srb); + return ptr; } /* - * Return a pointer to a singly linked list of all the requests queued - * for 'tid' on the 'asc_queue_t' pointed to by 'ascq'. - * - * If 'lastpp' is not NULL, '*lastpp' will be set to point to the - * the last request returned in the singly linked list. - * - * 'tid' should either be a valid target id or if it is ASC_TID_ALL, - * then all queued requests are concatenated into one list and - * returned. + * advansys_info() * - * Note: If 'lastpp' is used to append a new list to the end of - * an old list, only change the old list last pointer if '*lastpp' - * (or the function return value) is not NULL, i.e. use a temporary - * variable for 'lastpp' and check its value after the function return - * before assigning it to the list last pointer. + * Return suitable for printing on the console with the argument + * adapter's configuration information. * - * Unfortunately collecting queuing time statistics adds overhead to - * the function that isn't inherent to the function's algorithm. + * Note: The information line should not exceed ASC_INFO_SIZE bytes, + * otherwise the static 'info' array will be overrun. */ -static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) +static const char *advansys_info(struct Scsi_Host *shost) { - REQP firstp, lastp; - int i; - - ASC_DBG2(3, "asc_dequeue_list: ascq 0x%lx, tid %d\n", (ulong)ascq, tid); - ASC_ASSERT((tid == ASC_TID_ALL) || (tid >= 0 && tid <= ADV_MAX_TID)); + static char info[ASC_INFO_SIZE]; + struct asc_board *boardp = shost_priv(shost); + ASC_DVC_VAR *asc_dvc_varp; + ADV_DVC_VAR *adv_dvc_varp; + char *busname; + char *widename = NULL; - /* - * If 'tid' is not ASC_TID_ALL, return requests only for - * the specified 'tid'. If 'tid' is ASC_TID_ALL, return all - * requests for all tids. - */ - if (tid != ASC_TID_ALL) { - /* Return all requests for the specified 'tid'. */ - if ((ascq->q_tidmask & ADV_TID_TO_TIDMASK(tid)) == 0) { - /* List is empty; Set first and last return pointers to NULL. */ - firstp = lastp = NULL; - } else { - firstp = ascq->q_first[tid]; - lastp = ascq->q_last[tid]; - ascq->q_first[tid] = ascq->q_last[tid] = NULL; - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); -#ifdef ADVANSYS_STATS - { - REQP reqp; - ascq->q_cur_cnt[tid] = 0; - for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { - REQTIMESTAT("asc_dequeue_list", ascq, - reqp, tid); - } + if (ASC_NARROW_BOARD(boardp)) { + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; + ASC_DBG(1, "begin\n"); + if (asc_dvc_varp->bus_type & ASC_IS_ISA) { + if ((asc_dvc_varp->bus_type & ASC_IS_ISAPNP) == + ASC_IS_ISAPNP) { + busname = "ISA PnP"; + } else { + busname = "ISA"; } -#endif /* ADVANSYS_STATS */ - } - } else { - /* Return all requests for all tids. */ - firstp = lastp = NULL; - for (i = 0; i <= ADV_MAX_TID; i++) { - if (ascq->q_tidmask & ADV_TID_TO_TIDMASK(i)) { - if (firstp == NULL) { - firstp = ascq->q_first[i]; - lastp = ascq->q_last[i]; + sprintf(info, + "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X, DMA 0x%X", + ASC_VERSION, busname, + (ulong)shost->io_port, + (ulong)shost->io_port + ASC_IOADR_GAP - 1, + boardp->irq, shost->dma_channel); + } else { + if (asc_dvc_varp->bus_type & ASC_IS_VL) { + busname = "VL"; + } else if (asc_dvc_varp->bus_type & ASC_IS_EISA) { + busname = "EISA"; + } else if (asc_dvc_varp->bus_type & ASC_IS_PCI) { + if ((asc_dvc_varp->bus_type & ASC_IS_PCI_ULTRA) + == ASC_IS_PCI_ULTRA) { + busname = "PCI Ultra"; } else { - ASC_ASSERT(lastp != NULL); - lastp->host_scribble = - (unsigned char *)ascq->q_first[i]; - lastp = ascq->q_last[i]; + busname = "PCI"; } - ascq->q_first[i] = ascq->q_last[i] = NULL; - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(i); -#ifdef ADVANSYS_STATS - ascq->q_cur_cnt[i] = 0; -#endif /* ADVANSYS_STATS */ - } - } -#ifdef ADVANSYS_STATS - { - REQP reqp; - for (reqp = firstp; reqp; reqp = REQPNEXT(reqp)) { - REQTIMESTAT("asc_dequeue_list", ascq, reqp, - reqp->device->id); + } else { + busname = "?"; + shost_printk(KERN_ERR, shost, "unknown bus " + "type %d\n", asc_dvc_varp->bus_type); } + sprintf(info, + "AdvanSys SCSI %s: %s: IO 0x%lX-0x%lX, IRQ 0x%X", + ASC_VERSION, busname, (ulong)shost->io_port, + (ulong)shost->io_port + ASC_IOADR_GAP - 1, + boardp->irq); } -#endif /* ADVANSYS_STATS */ - } - if (lastpp) { - *lastpp = lastp; - } - ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp); - return firstp; -} - -/* - * Remove the specified 'REQP' from the specified queue for - * the specified target device. Clear the 'tidmask' bit for the - * device if no more commands are left queued for it. - * - * 'REQPNEXT(reqp)' returns reqp's the next pointer. - * - * Return ASC_TRUE if the command was found and removed, - * otherwise return ASC_FALSE. - */ -static int asc_rmqueue(asc_queue_t *ascq, REQP reqp) -{ - REQP currp, prevp; - int tid; - int ret = ASC_FALSE; - - ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n", - (ulong)ascq, (ulong)reqp); - ASC_ASSERT(reqp != NULL); - - tid = REQPTID(reqp); - ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - - /* - * Handle the common case of 'reqp' being the first - * entry on the queue. - */ - if (reqp == ascq->q_first[tid]) { - ret = ASC_TRUE; - ascq->q_first[tid] = REQPNEXT(reqp); - /* If the queue is now empty, clear its bit and the last pointer. */ - if (ascq->q_first[tid] == NULL) { - ascq->q_tidmask &= ~ADV_TID_TO_TIDMASK(tid); - ASC_ASSERT(ascq->q_last[tid] == reqp); - ascq->q_last[tid] = NULL; - } - } else if (ascq->q_first[tid] != NULL) { - ASC_ASSERT(ascq->q_last[tid] != NULL); + } else { /* - * Because the case of 'reqp' being the first entry has been - * handled above and it is known the queue is not empty, if - * 'reqp' is found on the queue it is guaranteed the queue will - * not become empty and that 'q_first[tid]' will not be changed. + * Wide Adapter Information * - * Set 'prevp' to the first entry, 'currp' to the second entry, - * and search for 'reqp'. + * Memory-mapped I/O is used instead of I/O space to access + * the adapter, but display the I/O Port range. The Memory + * I/O address is displayed through the driver /proc file. */ - for (prevp = ascq->q_first[tid], currp = REQPNEXT(prevp); - currp; prevp = currp, currp = REQPNEXT(currp)) { - if (currp == reqp) { - ret = ASC_TRUE; - prevp->host_scribble = - (unsigned char *)REQPNEXT(currp); - reqp->host_scribble = NULL; - if (ascq->q_last[tid] == reqp) { - ascq->q_last[tid] = prevp; - } - break; - } + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + widename = "Ultra-Wide"; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + widename = "Ultra2-Wide"; + } else { + widename = "Ultra3-Wide"; } + sprintf(info, + "AdvanSys SCSI %s: PCI %s: PCIMEM 0x%lX-0x%lX, IRQ 0x%X", + ASC_VERSION, widename, (ulong)adv_dvc_varp->iop_base, + (ulong)adv_dvc_varp->iop_base + boardp->asc_n_io_port - 1, boardp->irq); } -#ifdef ADVANSYS_STATS - /* Maintain request queue statistics. */ - if (ret == ASC_TRUE) { - ascq->q_cur_cnt[tid]--; - REQTIMESTAT("asc_rmqueue", ascq, reqp, tid); - } - ASC_ASSERT(ascq->q_cur_cnt[tid] >= 0); -#endif /* ADVANSYS_STATS */ - ASC_DBG2(3, "asc_rmqueue: reqp 0x%lx, ret %d\n", (ulong)reqp, ret); - return ret; + BUG_ON(strlen(info) >= ASC_INFO_SIZE); + ASC_DBG(1, "end\n"); + return info; } +#ifdef CONFIG_PROC_FS /* - * Execute as many queued requests as possible for the specified queue. + * asc_prt_line() + * + * If 'cp' is NULL print to the console, otherwise print to a buffer. * - * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd. + * Return 0 if printing to the console, otherwise return the number of + * bytes written to the buffer. + * + * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack + * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes. */ -static void asc_execute_queue(asc_queue_t *ascq) +static int asc_prt_line(char *buf, int buflen, char *fmt, ...) { - ADV_SCSI_BIT_ID_TYPE scan_tidmask; - REQP reqp; - int i; + va_list args; + int ret; + char s[ASC_PRTLINE_SIZE]; - ASC_DBG1(1, "asc_execute_queue: ascq 0x%lx\n", (ulong)ascq); - /* - * Execute queued commands for devices attached to - * the current board in round-robin fashion. - */ - scan_tidmask = ascq->q_tidmask; - do { - for (i = 0; i <= ADV_MAX_TID; i++) { - if (scan_tidmask & ADV_TID_TO_TIDMASK(i)) { - if ((reqp = asc_dequeue(ascq, i)) == NULL) { - scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); - } else - if (asc_execute_scsi_cmnd - ((struct scsi_cmnd *)reqp) - == ASC_BUSY) { - scan_tidmask &= ~ADV_TID_TO_TIDMASK(i); - /* - * The request returned ASC_BUSY. Enqueue at the front of - * target's waiting list to maintain correct ordering. - */ - asc_enqueue(ascq, reqp, ASC_FRONT); - } - } - } - } while (scan_tidmask); - return; + va_start(args, fmt); + ret = vsprintf(s, fmt, args); + BUG_ON(ret >= ASC_PRTLINE_SIZE); + if (buf == NULL) { + (void)printk(s); + ret = 0; + } else { + ret = min(buflen, ret); + memcpy(buf, s, ret); + } + va_end(args); + return ret; } -#ifdef CONFIG_PROC_FS /* * asc_prt_board_devices() * @@ -6245,14 +2919,13 @@ static void asc_execute_queue(asc_queue_t *ascq) */ static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; + struct asc_board *boardp = shost_priv(shost); int leftlen; int totlen; int len; int chip_scsi_id; int i; - boardp = ASC_BOARDP(shost); leftlen = cplen; totlen = len = 0; @@ -6286,13 +2959,12 @@ static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen) */ static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; + struct asc_board *boardp = shost_priv(shost); int leftlen; int totlen; int len; ushort major, minor, letter; - boardp = ASC_BOARDP(shost); leftlen = cplen; totlen = len = 0; @@ -6452,7 +3124,7 @@ static int asc_get_eeprom_string(ushort *serialnum, uchar *cp) */ static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; + struct asc_board *boardp = shost_priv(shost); ASC_DVC_VAR *asc_dvc_varp; int leftlen; int totlen; @@ -6464,7 +3136,6 @@ static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen #endif /* CONFIG_ISA */ uchar serialstr[13]; - boardp = ASC_BOARDP(shost); asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; ep = &boardp->eep_config.asc_eep; @@ -6586,7 +3257,7 @@ static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen */ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; + struct asc_board *boardp = shost_priv(shost); ADV_DVC_VAR *adv_dvc_varp; int leftlen; int totlen; @@ -6601,7 +3272,6 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen ushort *wordp; ushort sdtr_speed = 0; - boardp = ASC_BOARDP(shost); adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { ep_3550 = &boardp->eep_config.adv_3550_eep; @@ -6873,14 +3543,12 @@ static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen */ static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; + struct asc_board *boardp = shost_priv(shost); int leftlen; int totlen; int len; int chip_scsi_id; - boardp = ASC_BOARDP(shost); - leftlen = cplen; totlen = len = 0; @@ -6912,10 +3580,7 @@ static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen) boardp->asc_n_io_port); ASC_PRT_NEXT(); - /* 'shost->n_io_port' may be truncated because it is only one byte. */ - len = asc_prt_line(cp, leftlen, - " io_port 0x%x, n_io_port 0x%x\n", - shost->io_port, shost->n_io_port); + len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port); ASC_PRT_NEXT(); if (ASC_NARROW_BOARD(boardp)) { @@ -6940,7 +3605,7 @@ static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen) */ static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; + struct asc_board *boardp = shost_priv(shost); int chip_scsi_id; int leftlen; int totlen; @@ -6950,7 +3615,6 @@ static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen) int i; int renegotiate = 0; - boardp = ASC_BOARDP(shost); v = &boardp->dvc_var.asc_dvc_var; c = &boardp->dvc_cfg.asc_dvc_cfg; chip_scsi_id = c->chip_scsi_id; @@ -6963,15 +3627,10 @@ static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen) shost->host_no); ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, - " chip_version %u, lib_version 0x%x, lib_serial_no %u, mcode_date 0x%x\n", - c->chip_version, c->lib_version, c->lib_serial_no, - c->mcode_date); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, - " mcode_version 0x%x, err_code %u\n", - c->mcode_version, v->err_code); + len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, " + "mcode_version 0x%x, err_code %u\n", + c->chip_version, c->mcode_date, c->mcode_version, + v->err_code); ASC_PRT_NEXT(); /* Current number of commands waiting for the host. */ @@ -7128,7 +3787,7 @@ static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen) */ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen) { - asc_board_t *boardp; + struct asc_board *boardp = shost_priv(shost); int leftlen; int totlen; int len; @@ -7145,7 +3804,6 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen) ushort period = 0; int renegotiate = 0; - boardp = ASC_BOARDP(shost); v = &boardp->dvc_var.adv_dvc_var; c = &boardp->dvc_cfg.adv_dvc_cfg; iop_base = v->iop_base; @@ -7167,10 +3825,9 @@ static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen) v->err_code); ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, - " chip_version %u, lib_version 0x%x, mcode_date 0x%x, mcode_version 0x%x\n", - c->chip_version, c->lib_version, c->mcode_date, - c->mcode_version); + len = asc_prt_line(cp, leftlen, " chip_version %u, mcode_date 0x%x, " + "mcode_version 0x%x\n", c->chip_version, + c->mcode_date, c->mcode_version); ASC_PRT_NEXT(); AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); @@ -7376,12 +4033,12 @@ asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, { int cnt = 0; - ASC_DBG3(2, "asc_proc_copy: offset %d, advoffset %d, cplen %d\n", + ASC_DBG(2, "offset %d, advoffset %d, cplen %d\n", (unsigned)offset, (unsigned)advoffset, cplen); if (offset <= advoffset) { /* Read offset below current offset, copy everything. */ cnt = min(cplen, leftlen); - ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", + ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n", (ulong)curbuf, (ulong)cp, cnt); memcpy(curbuf, cp, cnt); } else if (offset < advoffset + cplen) { @@ -7389,1125 +4046,4537 @@ asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, cnt = (advoffset + cplen) - offset; cp = (cp + cplen) - cnt; cnt = min(cnt, leftlen); - ASC_DBG3(2, "asc_proc_copy: curbuf 0x%lx, cp 0x%lx, cnt %d\n", + ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n", (ulong)curbuf, (ulong)cp, cnt); memcpy(curbuf, cp, cnt); } return cnt; } +#ifdef ADVANSYS_STATS /* - * asc_prt_line() + * asc_prt_board_stats() * - * If 'cp' is NULL print to the console, otherwise print to a buffer. + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). * - * Return 0 if printing to the console, otherwise return the number of - * bytes written to the buffer. + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. + */ +static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen) +{ + struct asc_board *boardp = shost_priv(shost); + struct asc_stats *s = &boardp->asc_stats; + + int leftlen = cplen; + int len, totlen = 0; + + len = asc_prt_line(cp, leftlen, + "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n", + s->queuecommand, s->reset, s->biosparam, + s->interrupt); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n", + s->callback, s->done, s->build_error, + s->adv_build_noreq, s->adv_build_nosg); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, + " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n", + s->exe_noerror, s->exe_busy, s->exe_error, + s->exe_unknown); + ASC_PRT_NEXT(); + + /* + * Display data transfer statistics. + */ + if (s->xfer_cnt > 0) { + len = asc_prt_line(cp, leftlen, " xfer_cnt %lu, xfer_elem %lu, ", + s->xfer_cnt, s->xfer_elem); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, "xfer_bytes %lu.%01lu kb\n", + s->xfer_sect / 2, ASC_TENTHS(s->xfer_sect, 2)); + ASC_PRT_NEXT(); + + /* Scatter gather transfer statistics */ + len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ", + s->xfer_elem / s->xfer_cnt, + ASC_TENTHS(s->xfer_elem, s->xfer_cnt)); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ", + (s->xfer_sect / 2) / s->xfer_elem, + ASC_TENTHS((s->xfer_sect / 2), s->xfer_elem)); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n", + (s->xfer_sect / 2) / s->xfer_cnt, + ASC_TENTHS((s->xfer_sect / 2), s->xfer_cnt)); + ASC_PRT_NEXT(); + } + + return totlen; +} +#endif /* ADVANSYS_STATS */ + +/* + * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...} * - * Note: If any single line is greater than ASC_PRTLINE_SIZE bytes the stack - * will be corrupted. 's[]' is defined to be ASC_PRTLINE_SIZE bytes. + * *buffer: I/O buffer + * **start: if inout == FALSE pointer into buffer where user read should start + * offset: current offset into a /proc/scsi/advansys/[0...] file + * length: length of buffer + * hostno: Scsi_Host host_no + * inout: TRUE - user is writing; FALSE - user is reading + * + * Return the number of bytes read from or written to a + * /proc/scsi/advansys/[0...] file. + * + * Note: This function uses the per board buffer 'prtbuf' which is + * allocated when the board is initialized in advansys_detect(). The + * buffer is ASC_PRTBUF_SIZE bytes. The function asc_proc_copy() is + * used to write to the buffer. The way asc_proc_copy() is written + * if 'prtbuf' is too small it will not be overwritten. Instead the + * user just won't get all the available statistics. */ -static int asc_prt_line(char *buf, int buflen, char *fmt, ...) +static int +advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, + off_t offset, int length, int inout) { - va_list args; - int ret; - char s[ASC_PRTLINE_SIZE]; + struct asc_board *boardp = shost_priv(shost); + char *cp; + int cplen; + int cnt; + int totcnt; + int leftlen; + char *curbuf; + off_t advoffset; - va_start(args, fmt); - ret = vsprintf(s, fmt, args); - ASC_ASSERT(ret < ASC_PRTLINE_SIZE); - if (buf == NULL) { - (void)printk(s); - ret = 0; + ASC_DBG(1, "begin\n"); + + /* + * User write not supported. + */ + if (inout == TRUE) + return -ENOSYS; + + /* + * User read of /proc/scsi/advansys/[0...] file. + */ + + /* Copy read data starting at the beginning of the buffer. */ + *start = buffer; + curbuf = buffer; + advoffset = 0; + totcnt = 0; + leftlen = length; + + /* + * Get board configuration information. + * + * advansys_info() returns the board string from its own static buffer. + */ + cp = (char *)advansys_info(shost); + strcat(cp, "\n"); + cplen = strlen(cp); + /* Copy board information. */ + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG(1, "totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display Wide Board BIOS Information. + */ + if (!ASC_NARROW_BOARD(boardp)) { + cp = boardp->prtbuf; + cplen = asc_prt_adv_bios(shost, cp, ASC_PRTBUF_SIZE); + BUG_ON(cplen >= ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, + cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG(1, "totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + } + + /* + * Display driver information for each device attached to the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_board_devices(shost, cp, ASC_PRTBUF_SIZE); + BUG_ON(cplen >= ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG(1, "totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display EEPROM configuration for the board. + */ + cp = boardp->prtbuf; + if (ASC_NARROW_BOARD(boardp)) { + cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE); } else { - ret = min(buflen, ret); - memcpy(buf, s, ret); + cplen = asc_prt_adv_board_eeprom(shost, cp, ASC_PRTBUF_SIZE); } - va_end(args); - return ret; + BUG_ON(cplen >= ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG(1, "totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + /* + * Display driver configuration and information for the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_driver_conf(shost, cp, ASC_PRTBUF_SIZE); + BUG_ON(cplen >= ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG(1, "totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + +#ifdef ADVANSYS_STATS + /* + * Display driver statistics for the board. + */ + cp = boardp->prtbuf; + cplen = asc_prt_board_stats(shost, cp, ASC_PRTBUF_SIZE); + BUG_ON(cplen >= ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG(1, "totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; +#endif /* ADVANSYS_STATS */ + + /* + * Display Asc Library dynamic configuration information + * for the board. + */ + cp = boardp->prtbuf; + if (ASC_NARROW_BOARD(boardp)) { + cplen = asc_prt_asc_board_info(shost, cp, ASC_PRTBUF_SIZE); + } else { + cplen = asc_prt_adv_board_info(shost, cp, ASC_PRTBUF_SIZE); + } + BUG_ON(cplen >= ASC_PRTBUF_SIZE); + cnt = asc_proc_copy(advoffset, offset, curbuf, leftlen, cp, cplen); + totcnt += cnt; + leftlen -= cnt; + if (leftlen == 0) { + ASC_DBG(1, "totcnt %d\n", totcnt); + return totcnt; + } + advoffset += cplen; + curbuf += cnt; + + ASC_DBG(1, "totcnt %d\n", totcnt); + + return totcnt; } #endif /* CONFIG_PROC_FS */ -/* - * --- Functions Required by the Asc Library - */ +static void asc_scsi_done(struct scsi_cmnd *scp) +{ + scsi_dma_unmap(scp); + ASC_STATS(scp->device->host, done); + scp->scsi_done(scp); +} -/* - * Delay for 'n' milliseconds. Don't use the 'jiffies' - * global variable which is incremented once every 5 ms - * from a timer interrupt, because this function may be - * called when interrupts are disabled. - */ -static void DvcSleepMilliSecond(ADV_DCNT n) +static void AscSetBank(PortAddr iop_base, uchar bank) { - ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n); - mdelay(n); + uchar val; + + val = AscGetChipControl(iop_base) & + (~ + (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | + CC_CHIP_RESET)); + if (bank == 1) { + val |= CC_BANK_ONE; + } else if (bank == 2) { + val |= CC_DIAG | CC_BANK_ONE; + } else { + val &= ~CC_BANK_ONE; + } + AscSetChipControl(iop_base, val); } -/* - * Currently and inline noop but leave as a placeholder. - * Leave DvcEnterCritical() as a noop placeholder. - */ -static inline ulong DvcEnterCritical(void) +static void AscSetChipIH(PortAddr iop_base, ushort ins_code) { - return 0; + AscSetBank(iop_base, 1); + AscWriteChipIH(iop_base, ins_code); + AscSetBank(iop_base, 0); } -/* - * Critical sections are all protected by the board spinlock. - * Leave DvcLeaveCritical() as a noop placeholder. - */ -static inline void DvcLeaveCritical(ulong flags) +static int AscStartChip(PortAddr iop_base) +{ + AscSetChipControl(iop_base, 0); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + return (0); + } + return (1); +} + +static int AscStopChip(PortAddr iop_base) +{ + uchar cc_val; + + cc_val = + AscGetChipControl(iop_base) & + (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); + AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT)); + AscSetChipIH(iop_base, INS_HALT); + AscSetChipIH(iop_base, INS_RFLAG_WTM); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { + return (0); + } + return (1); +} + +static int AscIsChipHalted(PortAddr iop_base) +{ + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { + return (1); + } + } + return (0); +} + +static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc) +{ + PortAddr iop_base; + int i = 10; + + iop_base = asc_dvc->iop_base; + while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) + && (i-- > 0)) { + mdelay(100); + } + AscStopChip(iop_base); + AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); + udelay(60); + AscSetChipIH(iop_base, INS_RFLAG_WTM); + AscSetChipIH(iop_base, INS_HALT); + AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); + AscSetChipControl(iop_base, CC_HALT); + mdelay(200); + AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); + AscSetChipStatus(iop_base, 0); + return (AscIsChipHalted(iop_base)); +} + +static int AscFindSignature(PortAddr iop_base) +{ + ushort sig_word; + + ASC_DBG(1, "AscGetChipSignatureByte(0x%x) 0x%x\n", + iop_base, AscGetChipSignatureByte(iop_base)); + if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) { + ASC_DBG(1, "AscGetChipSignatureWord(0x%x) 0x%x\n", + iop_base, AscGetChipSignatureWord(iop_base)); + sig_word = AscGetChipSignatureWord(iop_base); + if ((sig_word == (ushort)ASC_1000_ID0W) || + (sig_word == (ushort)ASC_1000_ID0W_FIX)) { + return (1); + } + } + return (0); +} + +static void AscEnableInterrupt(PortAddr iop_base) +{ + ushort cfg; + + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); +} + +static void AscDisableInterrupt(PortAddr iop_base) +{ + ushort cfg; + + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); +} + +static uchar AscReadLramByte(PortAddr iop_base, ushort addr) +{ + unsigned char byte_data; + unsigned short word_data; + + if (isodd_word(addr)) { + AscSetChipLramAddr(iop_base, addr - 1); + word_data = AscGetChipLramData(iop_base); + byte_data = (word_data >> 8) & 0xFF; + } else { + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + byte_data = word_data & 0xFF; + } + return byte_data; +} + +static ushort AscReadLramWord(PortAddr iop_base, ushort addr) +{ + ushort word_data; + + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + return (word_data); +} + +#if CC_VERY_LONG_SG_LIST +static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr) +{ + ushort val_low, val_high; + ASC_DCNT dword_data; + + AscSetChipLramAddr(iop_base, addr); + val_low = AscGetChipLramData(iop_base); + val_high = AscGetChipLramData(iop_base); + dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low; + return (dword_data); +} +#endif /* CC_VERY_LONG_SG_LIST */ + +static void +AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words) +{ + int i; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < words; i++) { + AscSetChipLramData(iop_base, set_wval); + } +} + +static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val) +{ + AscSetChipLramAddr(iop_base, addr); + AscSetChipLramData(iop_base, word_val); +} + +static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val) { - return; + ushort word_data; + + if (isodd_word(addr)) { + addr--; + word_data = AscReadLramWord(iop_base, addr); + word_data &= 0x00FF; + word_data |= (((ushort)byte_val << 8) & 0xFF00); + } else { + word_data = AscReadLramWord(iop_base, addr); + word_data &= 0xFF00; + word_data |= ((ushort)byte_val & 0x00FF); + } + AscWriteLramWord(iop_base, addr, word_data); } /* - * void - * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) - * - * Calling/Exit State: - * none + * Copy 2 bytes to LRAM. * - * Description: - * Output an ASC_SCSI_Q structure to the chip + * The source data is assumed to be in little-endian order in memory + * and is maintained in little-endian order when written to LRAM. */ static void -DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) +AscMemWordCopyPtrToLram(PortAddr iop_base, + ushort s_addr, uchar *s_buffer, int words) { int i; - ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words); AscSetChipLramAddr(iop_base, s_addr); for (i = 0; i < 2 * words; i += 2) { - if (i == 4 || i == 20) { - continue; - } + /* + * On a little-endian system the second argument below + * produces a little-endian ushort which is written to + * LRAM in little-endian order. On a big-endian system + * the second argument produces a big-endian ushort which + * is "transparently" byte-swapped by outpw() and written + * in little-endian order to LRAM. + */ outpw(iop_base + IOP_RAM_DATA, - ((ushort)outbuf[i + 1] << 8) | outbuf[i]); + ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); } } /* - * void - * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) + * Copy 4 bytes to LRAM. * - * Calling/Exit State: - * none + * The source data is assumed to be in little-endian order in memory + * and is maintained in little-endian order when writen to LRAM. + */ +static void +AscMemDWordCopyPtrToLram(PortAddr iop_base, + ushort s_addr, uchar *s_buffer, int dwords) +{ + int i; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 4 * dwords; i += 4) { + outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */ + outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */ + } +} + +/* + * Copy 2 bytes from LRAM. * - * Description: - * Input an ASC_QDONE_INFO structure from the chip + * The source data is assumed to be in little-endian order in LRAM + * and is maintained in little-endian order when written to memory. */ static void -DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) +AscMemWordCopyPtrFromLram(PortAddr iop_base, + ushort s_addr, uchar *d_buffer, int words) { int i; ushort word; AscSetChipLramAddr(iop_base, s_addr); for (i = 0; i < 2 * words; i += 2) { - if (i == 10) { - continue; - } word = inpw(iop_base + IOP_RAM_DATA); - inbuf[i] = word & 0xff; - inbuf[i + 1] = (word >> 8) & 0xff; + d_buffer[i] = word & 0xff; + d_buffer[i + 1] = (word >> 8) & 0xff; } - ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words); } -/* - * Read a PCI configuration byte. - */ -static uchar __init DvcReadPCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset) +static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words) { -#ifdef CONFIG_PCI - uchar byte_data; - pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); - return byte_data; -#else /* !defined(CONFIG_PCI) */ - return 0; -#endif /* !defined(CONFIG_PCI) */ + ASC_DCNT sum; + int i; + + sum = 0L; + for (i = 0; i < words; i++, s_addr += 2) { + sum += AscReadLramWord(iop_base, s_addr); + } + return (sum); } -/* - * Write a PCI configuration byte. - */ -static void __init -DvcWritePCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) +static ushort AscInitLram(ASC_DVC_VAR *asc_dvc) { -#ifdef CONFIG_PCI - pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); -#endif /* CONFIG_PCI */ + uchar i; + ushort s_addr; + PortAddr iop_base; + ushort warn_code; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, + (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) * + 64) >> 1)); + i = ASC_MIN_ACTIVE_QNO; + s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)(i + 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(asc_dvc->max_total_qng)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)i); + i++; + s_addr += ASC_QBLK_SIZE; + for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)(i + 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(i - 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)i); + } + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), + (uchar)ASC_QLINK_END); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), + (uchar)(asc_dvc->max_total_qng - 1)); + AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), + (uchar)asc_dvc->max_total_qng); + i++; + s_addr += ASC_QBLK_SIZE; + for (; i <= (uchar)(asc_dvc->max_total_qng + 3); + i++, s_addr += ASC_QBLK_SIZE) { + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i); + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i); + AscWriteLramByte(iop_base, + (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i); + } + return warn_code; } -/* - * Return the BIOS address of the adapter at the specified - * I/O port and with the specified bus type. - */ -static ushort __init AscGetChipBiosAddress(PortAddr iop_base, ushort bus_type) +static ASC_DCNT +AscLoadMicroCode(PortAddr iop_base, + ushort s_addr, uchar *mcode_buf, ushort mcode_size) { - ushort cfg_lsw; - ushort bios_addr; + ASC_DCNT chksum; + ushort mcode_word_size; + ushort mcode_chksum; - /* - * The PCI BIOS is re-located by the motherboard BIOS. Because - * of this the driver can not determine where a PCI BIOS is - * loaded and executes. - */ - if (bus_type & ASC_IS_PCI) { - return (0); + /* Write the microcode buffer starting at LRAM address 0. */ + mcode_word_size = (ushort)(mcode_size >> 1); + AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); + AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size); + + chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); + ASC_DBG(1, "chksum 0x%lx\n", (ulong)chksum); + mcode_chksum = (ushort)AscMemSumLramWord(iop_base, + (ushort)ASC_CODE_SEC_BEG, + (ushort)((mcode_size - + s_addr - (ushort) + ASC_CODE_SEC_BEG) / + 2)); + ASC_DBG(1, "mcode_chksum 0x%lx\n", (ulong)mcode_chksum); + AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); + AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); + 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; + int i; + ushort lram_addr; + + iop_base = asc_dvc->iop_base; + AscPutRiscVarFreeQHead(iop_base, 1); + AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); + AscPutVarFreeQHead(iop_base, 1); + AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); + AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, + (uchar)((int)asc_dvc->max_total_qng + 1)); + AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, + (uchar)((int)asc_dvc->max_total_qng + 2)); + AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B, + asc_dvc->max_total_qng); + AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); + AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); + AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); + AscPutQDoneInProgress(iop_base, 0); + lram_addr = ASC_QADR_BEG; + for (i = 0; i < 32; i++, lram_addr += 2) { + AscWriteLramWord(iop_base, lram_addr, 0); } -#ifdef CONFIG_ISA - if ((bus_type & ASC_IS_EISA) != 0) { - cfg_lsw = AscGetEisaChipCfg(iop_base); - cfg_lsw &= 0x000F; - bios_addr = (ushort)(ASC_BIOS_MIN_ADDR + - (cfg_lsw * ASC_BIOS_BANK_SIZE)); - return (bios_addr); - } /* if */ -#endif /* CONFIG_ISA */ +} - cfg_lsw = AscGetChipCfgLsw(iop_base); +static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) +{ + int i; + ushort warn_code; + PortAddr iop_base; + ASC_PADDR phy_addr; + ASC_DCNT phy_size; + struct asc_board *board = asc_dvc_to_board(asc_dvc); - /* - * ISA PnP uses the top bit as the 32K BIOS flag - */ - if (bus_type == ASC_IS_ISAPNP) { - cfg_lsw &= 0x7FFF; + iop_base = asc_dvc->iop_base; + warn_code = 0; + for (i = 0; i <= ASC_MAX_TID; i++) { + AscPutMCodeInitSDTRAtID(iop_base, i, + asc_dvc->cfg->sdtr_period_offset[i]); } - /* if */ - bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + - ASC_BIOS_MIN_ADDR); - return (bios_addr); + + AscInitQLinkVar(asc_dvc); + AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, + ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); + + /* Ensure overrun buffer is aligned on an 8 byte boundary. */ + BUG_ON((unsigned long)asc_dvc->overrun_buf & 7); + asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf, + ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); + phy_addr = cpu_to_le32(asc_dvc->overrun_dma); + AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, + (uchar *)&phy_addr, 1); + phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE); + AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D, + (uchar *)&phy_size, 1); + + asc_dvc->cfg->mcode_date = + AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W); + asc_dvc->cfg->mcode_version = + AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W); + + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; + return warn_code; + } + if (AscStartChip(iop_base) != 1) { + asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; + return warn_code; + } + + return warn_code; } -/* - * --- Functions Required by the Adv Library - */ +static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) +{ + ushort warn_code; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + warn_code = 0; + if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && + !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { + AscResetChipAndScsiBus(asc_dvc); + mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ + } + asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; + if (asc_dvc->err_code != 0) + return UW_ERR; + if (!AscFindSignature(asc_dvc->iop_base)) { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + return warn_code; + } + AscDisableInterrupt(iop_base); + 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) { + asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; + return warn_code; + } + warn_code |= AscInitMicroCodeVar(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; + AscEnableInterrupt(iop_base); + return warn_code; +} /* - * DvcGetPhyAddr() + * Load the Microcode + * + * Write the microcode image to RISC memory starting at address 0. + * + * The microcode is stored compressed in the following format: * - * Return the physical address of 'vaddr' and set '*lenp' to the - * number of physically contiguous bytes that follow 'vaddr'. - * 'flag' indicates the type of structure whose physical address - * is being translated. + * 254 word (508 byte) table indexed by byte code followed + * by the following byte codes: * - * Note: Because Linux currently doesn't page the kernel and all - * kernel buffers are physically contiguous, leave '*lenp' unchanged. + * 1-Byte Code: + * 00: Emit word 0 in table. + * 01: Emit word 1 in table. + * . + * FD: Emit word 253 in table. + * + * Multi-Byte Code: + * FE WW WW: (3 byte code) Word to emit is the next word WW WW. + * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. + * + * Returns 0 or an error if the checksum doesn't match */ -ADV_PADDR -DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq, - uchar *vaddr, ADV_SDCNT *lenp, int flag) +static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size, + int memsize, int chksum) { - ADV_PADDR paddr; + int i, j, end, len = 0; + ADV_DCNT sum; + + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - paddr = virt_to_bus(vaddr); + for (i = 253 * 2; i < size; i++) { + if (buf[i] == 0xff) { + unsigned short word = (buf[i + 3] << 8) | buf[i + 2]; + for (j = 0; j < buf[i + 1]; j++) { + AdvWriteWordAutoIncLram(iop_base, word); + len += 2; + } + i += 3; + } else if (buf[i] == 0xfe) { + unsigned short word = (buf[i + 2] << 8) | buf[i + 1]; + AdvWriteWordAutoIncLram(iop_base, word); + i += 2; + len += 2; + } else { + unsigned char off = buf[i] * 2; + unsigned short word = (buf[off + 1] << 8) | buf[off]; + AdvWriteWordAutoIncLram(iop_base, word); + len += 2; + } + } - ASC_DBG4(4, - "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", - (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp), - (ulong)paddr); + end = len; - return paddr; + while (len < memsize) { + AdvWriteWordAutoIncLram(iop_base, 0); + len += 2; + } + + /* Verify the microcode checksum. */ + sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + + for (len = 0; len < end; len += 2) { + sum += AdvReadWordAutoIncLram(iop_base); + } + + if (sum != chksum) + return ASC_IERR_MCODE_CHKSUM; + + return 0; } -/* - * Read a PCI configuration byte. - */ -static uchar __init DvcAdvReadPCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset) +static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc) { -#ifdef CONFIG_PCI - uchar byte_data; - pci_read_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, &byte_data); - return byte_data; -#else /* CONFIG_PCI */ - return 0; -#endif /* CONFIG_PCI */ + ADV_CARR_T *carrp; + ADV_SDCNT buf_size; + ADV_PADDR carr_paddr; + + carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); + asc_dvc->carr_freelist = NULL; + if (carrp == asc_dvc->carrier_buf) { + buf_size = ADV_CARRIER_BUFSIZE; + } else { + buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); + } + + do { + /* Get physical address of the carrier 'carrp'. */ + carr_paddr = cpu_to_le32(virt_to_bus(carrp)); + + buf_size -= sizeof(ADV_CARR_T); + + carrp->carr_pa = carr_paddr; + carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); + + /* + * Insert the carrier at the beginning of the freelist. + */ + carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = carrp; + + carrp++; + } while (buf_size > 0); } /* - * Write a PCI configuration byte. + * Send an idle command to the chip and wait for completion. + * + * Command completion is polled for once per microsecond. + * + * The function can be called from anywhere including an interrupt handler. + * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical() + * functions to prevent reentrancy. + * + * Return Values: + * ADV_TRUE - command completed successfully + * ADV_FALSE - command failed + * ADV_ERROR - command timed out */ -static void __init -DvcAdvWritePCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) +static int +AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, + ushort idle_cmd, ADV_DCNT idle_cmd_parameter) { -#ifdef CONFIG_PCI - pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); -#else /* CONFIG_PCI */ - return; -#endif /* CONFIG_PCI */ + int result; + ADV_DCNT i, j; + AdvPortAddr iop_base; + + iop_base = asc_dvc->iop_base; + + /* + * Clear the idle command status which is set by the microcode + * to a non-zero value to indicate when the command is completed. + * The non-zero result is one of the IDLE_CMD_STATUS_* values + */ + AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0); + + /* + * Write the idle command value after the idle command parameter + * has been written to avoid a race condition. If the order is not + * followed, the microcode may process the idle command before the + * parameters have been written to LRAM. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, + cpu_to_le32(idle_cmd_parameter)); + AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); + + /* + * Tickle the RISC to tell it to process the idle command. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + /* + * Clear the tickle value. In the ASC-3550 the RISC flag + * command 'clr_tickle_b' does not work unless the host + * value is cleared. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); + } + + /* Wait for up to 100 millisecond for the idle command to timeout. */ + for (i = 0; i < SCSI_WAIT_100_MSEC; i++) { + /* Poll once each microsecond for command completion. */ + for (j = 0; j < SCSI_US_PER_MSEC; j++) { + AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, + result); + if (result != 0) + return result; + udelay(1); + } + } + + BUG(); /* The idle command should never timeout. */ + return ADV_ERROR; } /* - * --- Tracing and Debugging Functions + * Reset SCSI Bus and purge all outstanding requests. + * + * Return Value: + * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset. + * ADV_FALSE(0) - Microcode command failed. + * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC + * may be hung which requires driver recovery. */ +static int AdvResetSB(ADV_DVC_VAR *asc_dvc) +{ + int status; + + /* + * Send the SCSI Bus Reset idle start idle command which asserts + * the SCSI Bus Reset signal. + */ + status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L); + if (status != ADV_TRUE) { + return status; + } + + /* + * Delay for the specified SCSI Bus Reset hold time. + * + * The hold time delay is done on the host because the RISC has no + * microsecond accurate timer. + */ + udelay(ASC_SCSI_RESET_HOLD_TIME_US); + + /* + * Send the SCSI Bus Reset end idle command which de-asserts + * the SCSI Bus Reset signal and purges any pending requests. + */ + status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L); + if (status != ADV_TRUE) { + return status; + } + + mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ + + return status; +} -#ifdef ADVANSYS_STATS -#ifdef CONFIG_PROC_FS /* - * asc_prt_board_stats() + * Initialize the ASC-3550. * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). + * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. + * For a non-fatal error return a warning code. If there are no warnings + * then 0 is returned. + * + * Needed after initialization for error recovery. */ -static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen) +static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) { - int leftlen; - int totlen; - int len; - struct asc_stats *s; - asc_board_t *boardp; + AdvPortAddr iop_base; + ushort warn_code; + int begin_addr; + int end_addr; + ushort code_sum; + int word; + int i; + ushort scsi_cfg1; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able = 0, sdtr_able, tagqng_able; + uchar max_cmd[ADV_MAX_TID + 1]; - leftlen = cplen; - totlen = len = 0; + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) + return ADV_ERROR; - boardp = ASC_BOARDP(shost); - s = &boardp->asc_stats; + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC3550. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC3550) { + asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - len = asc_prt_line(cp, leftlen, - "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", - shost->host_no); - ASC_PRT_NEXT(); + warn_code = 0; + iop_base = asc_dvc->iop_base; - len = asc_prt_line(cp, leftlen, - " queuecommand %lu, reset %lu, biosparam %lu, interrupt %lu\n", - s->queuecommand, s->reset, s->biosparam, - s->interrupt); - ASC_PRT_NEXT(); + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - len = asc_prt_line(cp, leftlen, - " callback %lu, done %lu, build_error %lu, build_noreq %lu, build_nosg %lu\n", - s->callback, s->done, s->build_error, - s->adv_build_noreq, s->adv_build_nosg); - ASC_PRT_NEXT(); + /* + * Save current per TID negotiated values. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) { + ushort bios_version, major, minor; - len = asc_prt_line(cp, leftlen, - " exe_noerror %lu, exe_busy %lu, exe_error %lu, exe_unknown %lu\n", - s->exe_noerror, s->exe_busy, s->exe_error, - s->exe_unknown); - ASC_PRT_NEXT(); + bios_version = + bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2]; + major = (bios_version >> 12) & 0xF; + minor = (bios_version >> 8) & 0xF; + if (major < 3 || (major == 3 && minor == 1)) { + /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */ + AdvReadWordLram(iop_base, 0x120, wdtr_able); + } else { + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + } + } + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + + asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc3550_buf, + _adv_asc3550_size, ADV_3550_MEMSIZE, + _adv_asc3550_chksum); + if (asc_dvc->err_code) + return ADV_ERROR; /* - * Display data transfer statistics. + * Restore the RISC memory BIOS region. */ - if (s->cont_cnt > 0) { - len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt); - ASC_PRT_NEXT(); + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ", - s->cont_xfer / 2, - ASC_TENTHS(s->cont_xfer, 2)); - ASC_PRT_NEXT(); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - /* Contiguous transfer average size */ - len = asc_prt_line(cp, leftlen, "avg_xfer %lu.%01lu kb\n", - (s->cont_xfer / 2) / s->cont_cnt, - ASC_TENTHS((s->cont_xfer / 2), s->cont_cnt)); - ASC_PRT_NEXT(); + /* + * Read and save microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); + + /* + * Set the chip type to indicate the ASC3550. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550); + + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); } - if (s->sg_cnt > 0) { + /* + * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO + * threshold of 128 bytes. This register is only accessible to the host. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + START_CTL_EMFU | READ_CMD_MRM); - len = asc_prt_line(cp, leftlen, " sg_cnt %lu, sg_elem %lu, ", - s->sg_cnt, s->sg_elem); - ASC_PRT_NEXT(); + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in slave_configure() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - len = asc_prt_line(cp, leftlen, "sg_xfer %lu.%01lu kb\n", - s->sg_xfer / 2, ASC_TENTHS(s->sg_xfer, 2)); - ASC_PRT_NEXT(); + /* + * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID + * bitmask. These values determine the maximum SDTR speed negotiated + * with a device. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + * + * 4-bit speed SDTR speed name + * =========== =============== + * 0000b (0x0) SDTR disabled + * 0001b (0x1) 5 Mhz + * 0010b (0x2) 10 Mhz + * 0011b (0x3) 20 Mhz (Ultra) + * 0100b (0x4) 40 Mhz (LVD/Ultra2) + * 0101b (0x5) 80 Mhz (LVD2/Ultra3) + * 0110b (0x6) Undefined + * . + * 1111b (0xF) Undefined + */ + word = 0; + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) { + /* Set Ultra speed for TID 'tid'. */ + word |= (0x3 << (4 * (tid % 4))); + } else { + /* Set Fast speed for TID 'tid'. */ + word |= (0x2 << (4 * (tid % 4))); + } + if (tid == 3) { /* Check if done with sdtr_speed1. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word); + word = 0; + } else if (tid == 7) { /* Check if done with sdtr_speed2. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word); + word = 0; + } else if (tid == 11) { /* Check if done with sdtr_speed3. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word); + word = 0; + } else if (tid == 15) { /* Check if done with sdtr_speed4. */ + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word); + /* End of loop. */ + } + } - /* Scatter gather transfer statistics */ - len = asc_prt_line(cp, leftlen, " avg_num_elem %lu.%01lu, ", - s->sg_elem / s->sg_cnt, - ASC_TENTHS(s->sg_elem, s->sg_cnt)); - ASC_PRT_NEXT(); + /* + * Set microcode operating variable for the disconnect per TID bitmask. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); - len = asc_prt_line(cp, leftlen, "avg_elem_size %lu.%01lu kb, ", - (s->sg_xfer / 2) / s->sg_elem, - ASC_TENTHS((s->sg_xfer / 2), s->sg_elem)); - ASC_PRT_NEXT(); + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); - len = asc_prt_line(cp, leftlen, "avg_xfer_size %lu.%01lu kb\n", - (s->sg_xfer / 2) / s->sg_cnt, - ASC_TENTHS((s->sg_xfer / 2), s->sg_cnt)); - ASC_PRT_NEXT(); + /* + * Determine SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + + /* Read current SCSI_CFG1 Register value. */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + + /* + * If all three connectors are in use, return an error. + */ + if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 || + (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) { + asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION; + return ADV_ERROR; } /* - * Display request queuing statistics. + * If the internal narrow cable is reversed all of the SCSI_CTRL + * register signals will be set. Check for and return an error if + * this condition is found. */ - len = asc_prt_line(cp, leftlen, - " Active and Waiting Request Queues (Time Unit: %d HZ):\n", - HZ); - ASC_PRT_NEXT(); + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - return totlen; + /* + * If this is a differential board and a single-ended device + * is attached to one of the connectors, return an error. + */ + if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) { + asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE; + return ADV_ERROR; + } + + /* + * If automatic termination control is enabled, then set the + * termination value based on a table listed in a_condor.h. + * + * If manual termination was specified with an EEPROM setting + * then 'termination' was set-up in AdvInitFrom3550EEPROM() and + * is ready to be 'ored' into SCSI_CFG1. + */ + if (asc_dvc->cfg->termination == 0) { + /* + * The software always controls termination by setting TERM_CTL_SEL. + * If TERM_CTL_SEL were set to 0, the hardware would set termination. + */ + asc_dvc->cfg->termination |= TERM_CTL_SEL; + + switch (scsi_cfg1 & CABLE_DETECT) { + /* TERM_CTL_H: on, TERM_CTL_L: on */ + case 0x3: + case 0x7: + case 0xB: + case 0xD: + case 0xE: + case 0xF: + asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L); + break; + + /* TERM_CTL_H: on, TERM_CTL_L: off */ + case 0x1: + case 0x5: + case 0x9: + case 0xA: + case 0xC: + asc_dvc->cfg->termination |= TERM_CTL_H; + break; + + /* TERM_CTL_H: off, TERM_CTL_L: off */ + case 0x2: + case 0x6: + break; + } + } + + /* + * Clear any set TERM_CTL_H and TERM_CTL_L bits. + */ + scsi_cfg1 &= ~TERM_CTL; + + /* + * Invert the TERM_CTL_H and TERM_CTL_L bits and then + * set 'scsi_cfg1'. The TERM_POL bit does not need to be + * referenced, because the hardware internally inverts + * the Termination High and Low bits if TERM_POL is set. + */ + scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL)); + + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set filter value and possibly modified termination control + * bits in the Microcode SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, + FLTR_DISABLE | scsi_cfg1); + + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-3550 has 8KB internal memory. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_8KB); + + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + + AdvBuildCarrierFreelist(asc_dvc); + + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ + + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * BIOS Handshake Configuration Table and do not perform + * a SCSI Bus Reset. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; + } + } + } + + return warn_code; } /* - * asc_prt_target_stats() + * Initialize the ASC-38C0800. * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). + * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. * - * This is separated from asc_prt_board_stats because a full set - * of targets will overflow ASC_PRTBUF_SIZE. + * For a non-fatal error return a warning code. If there are no warnings + * then 0 is returned. * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. + * Needed after initialization for error recovery. */ -static int -asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen) +static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) { - int leftlen; - int totlen; - int len; - struct asc_stats *s; - ushort chip_scsi_id; - asc_board_t *boardp; - asc_queue_t *active; - asc_queue_t *waiting; + AdvPortAddr iop_base; + ushort warn_code; + int begin_addr; + int end_addr; + ushort code_sum; + int word; + int i; + ushort scsi_cfg1; + uchar byte; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able, sdtr_able, tagqng_able; + uchar max_cmd[ADV_MAX_TID + 1]; - leftlen = cplen; - totlen = len = 0; + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) + return ADV_ERROR; - boardp = ASC_BOARDP(shost); - s = &boardp->asc_stats; + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) { + asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - active = &ASC_BOARDP(shost)->active; - waiting = &ASC_BOARDP(shost)->waiting; + warn_code = 0; + iop_base = asc_dvc->iop_base; - if (ASC_NARROW_BOARD(boardp)) { - chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; - } else { - chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); } - if ((chip_scsi_id == tgt_id) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) { - return 0; + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); } - do { - if (active->q_tot_cnt[tgt_id] > 0 - || waiting->q_tot_cnt[tgt_id] > 0) { - len = asc_prt_line(cp, leftlen, " target %d\n", tgt_id); - ASC_PRT_NEXT(); + /* + * RAM BIST (RAM Built-In Self Test) + * + * Address : I/O base + offset 0x38h register (byte). + * Function: Bit 7-6(RW) : RAM mode + * Normal Mode : 0x00 + * Pre-test Mode : 0x40 + * RAM Test Mode : 0x80 + * Bit 5 : unused + * Bit 4(RO) : Done bit + * Bit 3-0(RO) : Status + * Host Error : 0x08 + * Int_RAM Error : 0x04 + * RISC Error : 0x02 + * SCSI Error : 0x01 + * No Error : 0x00 + * + * Note: RAM BIST code should be put right here, before loading the + * microcode and after saving the RISC memory BIOS region. + */ - len = asc_prt_line(cp, leftlen, - " active: cnt [cur %d, max %d, tot %u], time [min %d, max %d, avg %lu.%01lu]\n", - active->q_cur_cnt[tgt_id], - active->q_max_cnt[tgt_id], - active->q_tot_cnt[tgt_id], - active->q_min_tim[tgt_id], - active->q_max_tim[tgt_id], - (active->q_tot_cnt[tgt_id] == - 0) ? 0 : (active-> - q_tot_tim[tgt_id] / - active-> - q_tot_cnt[tgt_id]), - (active->q_tot_cnt[tgt_id] == - 0) ? 0 : ASC_TENTHS(active-> - q_tot_tim - [tgt_id], - active-> - q_tot_cnt - [tgt_id])); - ASC_PRT_NEXT(); + /* + * LRAM Pre-test + * + * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. + * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return + * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset + * to NORMAL_MODE, return an error too. + */ + for (i = 0; i < 2; i++) { + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); + mdelay(10); /* Wait for 10ms before reading back. */ + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 + || (byte & 0x0F) != PRE_TEST_VALUE) { + asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } - len = asc_prt_line(cp, leftlen, - " waiting: cnt [cur %d, max %d, tot %u], time [min %u, max %u, avg %lu.%01lu]\n", - waiting->q_cur_cnt[tgt_id], - waiting->q_max_cnt[tgt_id], - waiting->q_tot_cnt[tgt_id], - waiting->q_min_tim[tgt_id], - waiting->q_max_tim[tgt_id], - (waiting->q_tot_cnt[tgt_id] == - 0) ? 0 : (waiting-> - q_tot_tim[tgt_id] / - waiting-> - q_tot_cnt[tgt_id]), - (waiting->q_tot_cnt[tgt_id] == - 0) ? 0 : ASC_TENTHS(waiting-> - q_tot_tim - [tgt_id], - waiting-> - q_tot_cnt - [tgt_id])); - ASC_PRT_NEXT(); + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + mdelay(10); /* Wait for 10ms before reading back. */ + if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) + != NORMAL_VALUE) { + asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; } - } while (0); + } - return totlen; -} -#endif /* CONFIG_PROC_FS */ -#endif /* ADVANSYS_STATS */ + /* + * LRAM Test - It takes about 1.5 ms to run through the test. + * + * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. + * If Done bit not set or Status not 0, save register byte, set the + * err_code, and return an error. + */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); + mdelay(10); /* Wait for 10ms before checking status. */ -#ifdef ADVANSYS_DEBUG -/* - * asc_prt_scsi_host() - */ -static void asc_prt_scsi_host(struct Scsi_Host *s) -{ - asc_board_t *boardp; + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { + /* Get here if Done bit not set or Status not 0. */ + asc_dvc->bist_err_code = byte; /* for BIOS display message */ + asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST; + return ADV_ERROR; + } - boardp = ASC_BOARDP(s); + /* We need to reset back to normal mode after LRAM test passes. */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - printk("Scsi_Host at addr 0x%lx\n", (ulong)s); - printk(" host_busy %u, host_no %d, last_reset %d,\n", - s->host_busy, s->host_no, (unsigned)s->last_reset); + asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C0800_buf, + _adv_asc38C0800_size, ADV_38C0800_MEMSIZE, + _adv_asc38C0800_chksum); + if (asc_dvc->err_code) + return ADV_ERROR; - printk(" base 0x%lx, io_port 0x%lx, n_io_port %u, irq 0x%x,\n", - (ulong)s->base, (ulong)s->io_port, s->n_io_port, s->irq); + /* + * Restore the RISC memory BIOS region. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - printk(" dma_channel %d, this_id %d, can_queue %d,\n", - s->dma_channel, s->this_id, s->can_queue); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", - s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); + /* + * Read microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); - if (ASC_NARROW_BOARD(boardp)) { - asc_prt_asc_dvc_var(&ASC_BOARDP(s)->dvc_var.asc_dvc_var); - asc_prt_asc_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.asc_dvc_cfg); - } else { - asc_prt_adv_dvc_var(&ASC_BOARDP(s)->dvc_var.adv_dvc_var); - asc_prt_adv_dvc_cfg(&ASC_BOARDP(s)->dvc_cfg.adv_dvc_cfg); + /* + * Set the chip type to indicate the ASC38C0800. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800); + + /* + * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. + * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current + * cable detection and then we are able to read C_DET[3:0]. + * + * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 + * Microcode Default Value' section below. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, + scsi_cfg1 | DIS_TERM_DRV); + + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); } -} -/* - * asc_prt_scsi_cmnd() - */ -static void asc_prt_scsi_cmnd(struct scsi_cmnd *s) -{ - printk("struct scsi_cmnd at addr 0x%lx\n", (ulong)s); + /* + * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2] + * bits for the default FIFO threshold. + * + * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes. + * + * For DMA Errata #4 set the BC_THRESH_ENB bit. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH | + READ_CMD_MRM); - printk(" host 0x%lx, device 0x%lx, target %u, lun %u, channel %u,\n", - (ulong)s->device->host, (ulong)s->device, s->device->id, - s->device->lun, s->device->channel); + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in slave_configure() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - asc_prt_hex(" CDB", s->cmnd, s->cmd_len); + /* + * Set microcode operating variables for DISC and SDTR_SPEED1, + * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM + * configuration values. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); - printk("sc_data_direction %u, resid %d\n", - s->sc_data_direction, s->resid); + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); - printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len); + /* + * Determine SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ - printk(" serial_number 0x%x, retries %d, allowed %d\n", - (unsigned)s->serial_number, s->retries, s->allowed); + /* Read current SCSI_CFG1 Register value. */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - printk(" timeout_per_command %d\n", s->timeout_per_command); + /* + * If the internal narrow cable is reversed all of the SCSI_CTRL + * register signals will be set. Check for and return an error if + * this condition is found. + */ + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - printk - (" scsi_done 0x%lx, done 0x%lx, host_scribble 0x%lx, result 0x%x\n", - (ulong)s->scsi_done, (ulong)s->done, (ulong)s->host_scribble, - s->result); + /* + * All kind of combinations of devices attached to one of four + * connectors are acceptable except HVD device attached. For example, + * LVD device can be attached to SE connector while SE device attached + * to LVD connector. If LVD device attached to SE connector, it only + * runs up to Ultra speed. + * + * If an HVD device is attached to one of LVD connectors, return an + * error. However, there is no way to detect HVD device attached to + * SE connectors. + */ + if (scsi_cfg1 & HVD) { + asc_dvc->err_code = ASC_IERR_HVD_DEVICE; + return ADV_ERROR; + } - printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid); -} + /* + * If either SE or LVD automatic termination control is enabled, then + * set the termination value based on a table listed in a_condor.h. + * + * If manual termination was specified with an EEPROM setting then + * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready + * to be 'ored' into SCSI_CFG1. + */ + if ((asc_dvc->cfg->termination & TERM_SE) == 0) { + /* SE automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_SE) { + /* TERM_SE_HI: on, TERM_SE_LO: on */ + case 0x1: + case 0x2: + case 0x3: + asc_dvc->cfg->termination |= TERM_SE; + break; -/* - * asc_prt_asc_dvc_var() - */ -static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h) -{ - printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h); + /* TERM_SE_HI: on, TERM_SE_LO: off */ + case 0x0: + asc_dvc->cfg->termination |= TERM_SE_HI; + break; + } + } - printk - (" iop_base 0x%x, err_code 0x%x, dvc_cntl 0x%x, bug_fix_cntl %d,\n", - h->iop_base, h->err_code, h->dvc_cntl, h->bug_fix_cntl); + if ((asc_dvc->cfg->termination & TERM_LVD) == 0) { + /* LVD automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_LVD) { + /* TERM_LVD_HI: on, TERM_LVD_LO: on */ + case 0x4: + case 0x8: + case 0xC: + asc_dvc->cfg->termination |= TERM_LVD; + break; - printk - (" bus_type %d, isr_callback 0x%lx, exe_callback 0x%lx, init_sdtr 0x%x,\n", - h->bus_type, (ulong)h->isr_callback, (ulong)h->exe_callback, - (unsigned)h->init_sdtr); + /* TERM_LVD_HI: off, TERM_LVD_LO: off */ + case 0x0: + break; + } + } - printk - (" sdtr_done 0x%x, use_tagged_qng 0x%x, unit_not_ready 0x%x, chip_no 0x%x,\n", - (unsigned)h->sdtr_done, (unsigned)h->use_tagged_qng, - (unsigned)h->unit_not_ready, (unsigned)h->chip_no); + /* + * Clear any set TERM_SE and TERM_LVD bits. + */ + scsi_cfg1 &= (~TERM_SE & ~TERM_LVD); - printk - (" queue_full_or_busy 0x%x, start_motor 0x%x, scsi_reset_wait %u,\n", - (unsigned)h->queue_full_or_busy, (unsigned)h->start_motor, - (unsigned)h->scsi_reset_wait); + /* + * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'. + */ + scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0); - printk - (" is_in_int %u, max_total_qng %u, cur_total_qng %u, in_critical_cnt %u,\n", - (unsigned)h->is_in_int, (unsigned)h->max_total_qng, - (unsigned)h->cur_total_qng, (unsigned)h->in_critical_cnt); + /* + * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE + * bits and set possibly modified termination control bits in the + * Microcode SCSI_CFG1 Register Value. + */ + scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE); - printk - (" last_q_shortage %u, init_state 0x%x, no_scam 0x%x, pci_fix_asyn_xfer 0x%x,\n", - (unsigned)h->last_q_shortage, (unsigned)h->init_state, - (unsigned)h->no_scam, (unsigned)h->pci_fix_asyn_xfer); + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set possibly modified termination control and reset DIS_TERM_DRV + * bits in the Microcode SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); - printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no); -} + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-38C0800 has 16KB internal memory. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_16KB); -/* - * asc_prt_asc_dvc_cfg() - */ -static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) -{ - printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h); + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); - printk(" can_tagged_qng 0x%x, cmd_qng_enabled 0x%x,\n", - h->can_tagged_qng, h->cmd_qng_enabled); - printk(" disc_enable 0x%x, sdtr_enable 0x%x,\n", - h->disc_enable, h->sdtr_enable); + AdvBuildCarrierFreelist(asc_dvc); - printk - (" chip_scsi_id %d, isa_dma_speed %d, isa_dma_channel %d, chip_version %d,\n", - h->chip_scsi_id, h->isa_dma_speed, h->isa_dma_channel, - h->chip_version); + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ - printk - (" pci_device_id %d, lib_serial_no %u, lib_version %u, mcode_date 0x%x,\n", - to_pci_dev(h->dev)->device, h->lib_serial_no, h->lib_version, - h->mcode_date); + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); - printk(" mcode_version %d, overrun_buf 0x%lx\n", - h->mcode_version, (ulong)h->overrun_buf); + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. + * carr_pa is LE, must be native before write + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + * + * carr_pa is LE, must be native before write * + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * BIOS Handshake Configuration Table and do not perform + * a SCSI Bus Reset. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; + } + } + } + + return warn_code; } /* - * asc_prt_asc_scsi_q() + * Initialize the ASC-38C1600. + * + * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR. + * + * For a non-fatal error return a warning code. If there are no warnings + * then 0 is returned. + * + * Needed after initialization for error recovery. */ -static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q) +static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) { - ASC_SG_HEAD *sgp; + AdvPortAddr iop_base; + ushort warn_code; + int begin_addr; + int end_addr; + ushort code_sum; + long word; int i; + ushort scsi_cfg1; + uchar byte; + uchar tid; + ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ + ushort wdtr_able, sdtr_able, ppr_able, tagqng_able; + uchar max_cmd[ASC_MAX_TID + 1]; - printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q); + /* If there is already an error, don't continue. */ + if (asc_dvc->err_code != 0) { + return ADV_ERROR; + } - printk - (" target_ix 0x%x, target_lun %u, srb_ptr 0x%lx, tag_code 0x%x,\n", - q->q2.target_ix, q->q1.target_lun, (ulong)q->q2.srb_ptr, - q->q2.tag_code); + /* + * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { + asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; + } - printk - (" data_addr 0x%lx, data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", - (ulong)le32_to_cpu(q->q1.data_addr), - (ulong)le32_to_cpu(q->q1.data_cnt), - (ulong)le32_to_cpu(q->q1.sense_addr), q->q1.sense_len); + warn_code = 0; + iop_base = asc_dvc->iop_base; - printk(" cdbptr 0x%lx, cdb_len %u, sg_head 0x%lx, sg_queue_cnt %u\n", - (ulong)q->cdbptr, q->q2.cdb_len, - (ulong)q->sg_head, q->q1.sg_queue_cnt); + /* + * Save the RISC memory BIOS region before writing the microcode. + * The BIOS may already be loaded and using its RISC LRAM region + * so its region must be saved and restored. + * + * Note: This code makes the assumption, which is currently true, + * that a chip reset does not clear RISC LRAM. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - if (q->sg_head) { - sgp = q->sg_head; - printk("ASC_SG_HEAD at addr 0x%lx\n", (ulong)sgp); - printk(" entry_cnt %u, queue_cnt %u\n", sgp->entry_cnt, - sgp->queue_cnt); - for (i = 0; i < sgp->entry_cnt; i++) { - printk(" [%u]: addr 0x%lx, bytes %lu\n", - i, (ulong)le32_to_cpu(sgp->sg_list[i].addr), - (ulong)le32_to_cpu(sgp->sg_list[i].bytes)); + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + + /* + * RAM BIST (Built-In Self Test) + * + * Address : I/O base + offset 0x38h register (byte). + * Function: Bit 7-6(RW) : RAM mode + * Normal Mode : 0x00 + * Pre-test Mode : 0x40 + * RAM Test Mode : 0x80 + * Bit 5 : unused + * Bit 4(RO) : Done bit + * Bit 3-0(RO) : Status + * Host Error : 0x08 + * Int_RAM Error : 0x04 + * RISC Error : 0x02 + * SCSI Error : 0x01 + * No Error : 0x00 + * + * Note: RAM BIST code should be put right here, before loading the + * microcode and after saving the RISC memory BIOS region. + */ + + /* + * LRAM Pre-test + * + * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. + * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return + * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset + * to NORMAL_MODE, return an error too. + */ + for (i = 0; i < 2; i++) { + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); + mdelay(10); /* Wait for 10ms before reading back. */ + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 + || (byte & 0x0F) != PRE_TEST_VALUE) { + asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; } + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + mdelay(10); /* Wait for 10ms before reading back. */ + if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) + != NORMAL_VALUE) { + asc_dvc->err_code = ASC_IERR_BIST_PRE_TEST; + return ADV_ERROR; + } } -} -/* - * asc_prt_asc_qdone_info() - */ -static void asc_prt_asc_qdone_info(ASC_QDONE_INFO *q) -{ - printk("ASC_QDONE_INFO at addr 0x%lx\n", (ulong)q); - printk(" srb_ptr 0x%lx, target_ix %u, cdb_len %u, tag_code %u,\n", - (ulong)q->d2.srb_ptr, q->d2.target_ix, q->d2.cdb_len, - q->d2.tag_code); - printk - (" done_stat 0x%x, host_stat 0x%x, scsi_stat 0x%x, scsi_msg 0x%x\n", - q->d3.done_stat, q->d3.host_stat, q->d3.scsi_stat, q->d3.scsi_msg); -} + /* + * LRAM Test - It takes about 1.5 ms to run through the test. + * + * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. + * If Done bit not set or Status not 0, save register byte, set the + * err_code, and return an error. + */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); + mdelay(10); /* Wait for 10ms before checking status. */ -/* - * asc_prt_adv_dvc_var() - * - * Display an ADV_DVC_VAR structure. - */ -static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h) -{ - printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h); + byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); + if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { + /* Get here if Done bit not set or Status not 0. */ + asc_dvc->bist_err_code = byte; /* for BIOS display message */ + asc_dvc->err_code = ASC_IERR_BIST_RAM_TEST; + return ADV_ERROR; + } - printk(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", - (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able); + /* We need to reset back to normal mode after LRAM test passes. */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - printk(" isr_callback 0x%lx, sdtr_able 0x%x, wdtr_able 0x%x\n", - (ulong)h->isr_callback, (unsigned)h->sdtr_able, - (unsigned)h->wdtr_able); + asc_dvc->err_code = AdvLoadMicrocode(iop_base, _adv_asc38C1600_buf, + _adv_asc38C1600_size, ADV_38C1600_MEMSIZE, + _adv_asc38C1600_chksum); + if (asc_dvc->err_code) + return ADV_ERROR; - printk(" start_motor 0x%x, scsi_reset_wait 0x%x, irq_no 0x%x,\n", - (unsigned)h->start_motor, - (unsigned)h->scsi_reset_wait, (unsigned)h->irq_no); + /* + * Restore the RISC memory BIOS region. + */ + for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { + AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), + bios_mem[i]); + } - printk(" max_host_qng %u, max_dvc_qng %u, carr_freelist 0x%lxn\n", - (unsigned)h->max_host_qng, (unsigned)h->max_dvc_qng, - (ulong)h->carr_freelist); + /* + * Calculate and write the microcode code checksum to the microcode + * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). + */ + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); + AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); + code_sum = 0; + AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); + for (word = begin_addr; word < end_addr; word += 2) { + code_sum += AdvReadWordAutoIncLram(iop_base); + } + AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - printk(" icq_sp 0x%lx, irq_sp 0x%lx\n", - (ulong)h->icq_sp, (ulong)h->irq_sp); + /* + * Read microcode version and date. + */ + AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, + asc_dvc->cfg->mcode_date); + AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, + asc_dvc->cfg->mcode_version); - printk(" no_scam 0x%x, tagqng_able 0x%x\n", - (unsigned)h->no_scam, (unsigned)h->tagqng_able); + /* + * Set the chip type to indicate the ASC38C1600. + */ + AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600); - printk(" chip_scsi_id 0x%x, cfg 0x%lx\n", - (unsigned)h->chip_scsi_id, (ulong)h->cfg); -} + /* + * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. + * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current + * cable detection and then we are able to read C_DET[3:0]. + * + * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 + * Microcode Default Value' section below. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, + scsi_cfg1 | DIS_TERM_DRV); -/* - * asc_prt_adv_dvc_cfg() - * - * Display an ADV_DVC_CFG structure. - */ -static void asc_prt_adv_dvc_cfg(ADV_DVC_CFG *h) -{ - printk(" ADV_DVC_CFG at addr 0x%lx\n", (ulong)h); + /* + * If the PCI Configuration Command Register "Parity Error Response + * Control" Bit was clear (0), then set the microcode variable + * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode + * to ignore DMA parity errors. + */ + if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_IGNORE_PERR; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - printk(" disc_enable 0x%x, termination 0x%x\n", - h->disc_enable, h->termination); + /* + * If the BIOS control flag AIPP (Asynchronous Information + * Phase Protection) disable bit is not set, then set the firmware + * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable + * AIPP checking and encoding. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) { + AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + word |= CONTROL_FLAG_ENABLE_AIPP; + AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); + } - printk(" chip_version 0x%x, mcode_date 0x%x\n", - h->chip_version, h->mcode_date); + /* + * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4], + * and START_CTL_TH [3:2]. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM); - printk(" mcode_version 0x%x, pci_device_id 0x%x, lib_version %u\n", - h->mcode_version, to_pci_dev(h->dev)->device, h->lib_version); + /* + * Microcode operating variables for WDTR, SDTR, and command tag + * queuing will be set in slave_configure() based on what a + * device reports it is capable of in Inquiry byte 7. + * + * If SCSI Bus Resets have been disabled, then directly set + * SDTR and WDTR from the EEPROM configuration. This will allow + * the BIOS and warm boot to work without a SCSI bus hang on + * the Inquiry caused by host and target mismatched DTR values. + * Without the SCSI Bus Reset, before an Inquiry a device can't + * be assumed to be in Asynchronous, Narrow mode. + */ + if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, + asc_dvc->wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, + asc_dvc->sdtr_able); + } - printk(" control_flag 0x%x, pci_slot_info 0x%x\n", - h->control_flag, h->pci_slot_info); -} + /* + * Set microcode operating variables for DISC and SDTR_SPEED1, + * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM + * configuration values. + * + * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, + * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them + * without determining here whether the device supports SDTR. + */ + AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, + asc_dvc->cfg->disc_enable); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); -/* - * asc_prt_adv_scsi_req_q() - * - * Display an ADV_SCSI_REQ_Q structure. - */ -static void asc_prt_adv_scsi_req_q(ADV_SCSI_REQ_Q *q) -{ - int sg_blk_cnt; - struct asc_sg_block *sg_ptr; + /* + * Set SCSI_CFG0 Microcode Default Value. + * + * The microcode will set the SCSI_CFG0 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, + PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | + asc_dvc->chip_scsi_id); - printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q); + /* + * Calculate SCSI_CFG1 Microcode Default Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + * + * Each ASC-38C1600 function has only two cable detect bits. + * The bus mode override bits are in IOPB_SOFT_OVER_WR. + */ + scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - printk(" target_id %u, target_lun %u, srb_ptr 0x%lx, a_flag 0x%x\n", - q->target_id, q->target_lun, (ulong)q->srb_ptr, q->a_flag); + /* + * If the cable is reversed all of the SCSI_CTRL register signals + * will be set. Check for and return an error if this condition is + * found. + */ + if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { + asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; + return ADV_ERROR; + } - printk(" cntl 0x%x, data_addr 0x%lx, vdata_addr 0x%lx\n", - q->cntl, (ulong)le32_to_cpu(q->data_addr), (ulong)q->vdata_addr); + /* + * Each ASC-38C1600 function has two connectors. Only an HVD device + * can not be connected to either connector. An LVD device or SE device + * may be connected to either connecor. If an SE device is connected, + * then at most Ultra speed (20 Mhz) can be used on both connectors. + * + * If an HVD device is attached, return an error. + */ + if (scsi_cfg1 & HVD) { + asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; + return ADV_ERROR; + } - printk(" data_cnt %lu, sense_addr 0x%lx, sense_len %u,\n", - (ulong)le32_to_cpu(q->data_cnt), - (ulong)le32_to_cpu(q->sense_addr), q->sense_len); + /* + * Each function in the ASC-38C1600 uses only the SE cable detect and + * termination because there are two connectors for each function. Each + * function may use either LVD or SE mode. Corresponding the SE automatic + * termination control EEPROM bits are used for each function. Each + * function has its own EEPROM. If SE automatic control is enabled for + * the function, then set the termination value based on a table listed + * in a_condor.h. + * + * If manual termination is specified in the EEPROM for the function, + * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is + * ready to be 'ored' into SCSI_CFG1. + */ + if ((asc_dvc->cfg->termination & TERM_SE) == 0) { + struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc); + /* SE automatic termination control is enabled. */ + switch (scsi_cfg1 & C_DET_SE) { + /* TERM_SE_HI: on, TERM_SE_LO: on */ + case 0x1: + case 0x2: + case 0x3: + asc_dvc->cfg->termination |= TERM_SE; + break; - printk - (" cdb_len %u, done_status 0x%x, host_status 0x%x, scsi_status 0x%x\n", - q->cdb_len, q->done_status, q->host_status, q->scsi_status); + case 0x0: + if (PCI_FUNC(pdev->devfn) == 0) { + /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */ + } else { + /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */ + asc_dvc->cfg->termination |= TERM_SE_HI; + } + break; + } + } - printk(" sg_working_ix 0x%x, target_cmd %u\n", - q->sg_working_ix, q->target_cmd); + /* + * Clear any set TERM_SE bits. + */ + scsi_cfg1 &= ~TERM_SE; - printk(" scsiq_rptr 0x%lx, sg_real_addr 0x%lx, sg_list_ptr 0x%lx\n", - (ulong)le32_to_cpu(q->scsiq_rptr), - (ulong)le32_to_cpu(q->sg_real_addr), (ulong)q->sg_list_ptr); + /* + * Invert the TERM_SE bits and then set 'scsi_cfg1'. + */ + scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE); - /* Display the request's ADV_SG_BLOCK structures. */ - if (q->sg_list_ptr != NULL) { - sg_blk_cnt = 0; - while (1) { + /* + * Clear Big Endian and Terminator Polarity bits and set possibly + * modified termination control bits in the Microcode SCSI_CFG1 + * Register Value. + * + * Big Endian bit is not used even on big endian machines. + */ + scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL); + + /* + * Set SCSI_CFG1 Microcode Default Value + * + * Set possibly modified termination control bits in the Microcode + * SCSI_CFG1 Register Value. + * + * The microcode will set the SCSI_CFG1 register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); + + /* + * Set MEM_CFG Microcode Default Value + * + * The microcode will set the MEM_CFG register using this value + * after it is started below. + * + * MEM_CFG may be accessed as a word or byte, but only bits 0-7 + * are defined. + * + * ASC-38C1600 has 32KB internal memory. + * + * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come + * out a special 16K Adv Library and Microcode version. After the issue + * resolved, we should turn back to the 32K support. Both a_condor.h and + * mcode.sas files also need to be updated. + * + * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + * BIOS_EN | RAM_SZ_32KB); + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, + BIOS_EN | RAM_SZ_16KB); + + /* + * Set SEL_MASK Microcode Default Value + * + * The microcode will set the SEL_MASK register using this value + * after it is started below. + */ + AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, + ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + + AdvBuildCarrierFreelist(asc_dvc); + + /* + * Set-up the Host->RISC Initiator Command Queue (ICQ). + */ + if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); + + /* + * The first command issued will be placed in the stopper carrier. + */ + asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC ICQ physical address start value. Initialize the + * COMMA register to the same value otherwise the RISC will + * prematurely detect a command is available. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); + AdvWriteDWordRegister(iop_base, IOPDW_COMMA, + le32_to_cpu(asc_dvc->icq_sp->carr_pa)); + + /* + * Set-up the RISC->Host Initiator Response Queue (IRQ). + */ + if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { + asc_dvc->err_code |= ASC_IERR_NO_CARRIER; + return ADV_ERROR; + } + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); + + /* + * The first command completed by the RISC will be placed in + * the stopper. + * + * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is + * completed the RISC will set the ASC_RQ_STOPPER bit. + */ + asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + + /* + * Set RISC IRQ physical address start value. + */ + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); + asc_dvc->carr_pending_cnt = 0; + + AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, + (ADV_INTR_ENABLE_HOST_INTR | + ADV_INTR_ENABLE_GLOBAL_INTR)); + AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); + AdvWriteWordRegister(iop_base, IOPW_PC, word); + + /* finally, finally, gentlemen, start your engine */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + + /* + * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus + * Resets should be performed. The RISC has to be running + * to issue a SCSI Bus Reset. + */ + if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { + /* + * If the BIOS Signature is present in memory, restore the + * per TID microcode operating variables. + */ + if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == + 0x55AA) { /* - * 'sg_ptr' is a physical address. Convert it to a virtual - * address by indexing 'sg_blk_cnt' into the virtual address - * array 'sg_list_ptr'. - * - * XXX - Assumes all SG physical blocks are virtually contiguous. + * Restore per TID negotiated values. */ - sg_ptr = - &(((ADV_SG_BLOCK *)(q->sg_list_ptr))[sg_blk_cnt]); - asc_prt_adv_sgblock(sg_blk_cnt, sg_ptr); - if (sg_ptr->sg_ptr == 0) { - break; + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + tagqng_able); + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); + } + } else { + if (AdvResetSB(asc_dvc) != ADV_TRUE) { + warn_code = ASC_WARN_BUSRESET_ERROR; } - sg_blk_cnt++; } } + + return warn_code; } /* - * asc_prt_adv_sgblock() + * Reset chip and SCSI Bus. * - * Display an ADV_SG_BLOCK structure. + * Return Value: + * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful. + * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure. */ -static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) +static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) { - int i; + int status; + ushort wdtr_able, sdtr_able, tagqng_able; + ushort ppr_able = 0; + uchar tid, max_cmd[ADV_MAX_TID + 1]; + AdvPortAddr iop_base; + ushort bios_sig; - printk(" ASC_SG_BLOCK at addr 0x%lx (sgblockno %d)\n", - (ulong)b, sgblockno); - printk(" sg_cnt %u, sg_ptr 0x%lx\n", - b->sg_cnt, (ulong)le32_to_cpu(b->sg_ptr)); - ASC_ASSERT(b->sg_cnt <= NO_OF_SG_PER_BLOCK); - if (b->sg_ptr != 0) { - ASC_ASSERT(b->sg_cnt == NO_OF_SG_PER_BLOCK); + iop_base = asc_dvc->iop_base; + + /* + * Save current per TID negotiated values. + */ + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); } - for (i = 0; i < b->sg_cnt; i++) { - printk(" [%u]: sg_addr 0x%lx, sg_count 0x%lx\n", - i, (ulong)b->sg_list[i].sg_addr, - (ulong)b->sg_list[i].sg_count); + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); } -} -/* - * asc_prt_hex() - * - * Print hexadecimal output in 4 byte groupings 32 bytes - * or 8 double-words per line. - */ -static void asc_prt_hex(char *f, uchar *s, int l) -{ - int i; - int j; - int k; - int m; - - printk("%s: (%d bytes)\n", f, l); + /* + * Force the AdvInitAsc3550/38C0800Driver() function to + * perform a SCSI Bus Reset by clearing the BIOS signature word. + * The initialization functions assumes a SCSI Bus Reset is not + * needed if the BIOS signature word is present. + */ + AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); - for (i = 0; i < l; i += 32) { + /* + * Stop chip and reset it. + */ + AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); + mdelay(100); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_WR_IO_REG); - /* Display a maximum of 8 double-words per line. */ - if ((k = (l - i) / 4) >= 8) { - k = 8; - m = 0; - } else { - m = (l - i) % 4; - } + /* + * Reset Adv Library error code, if any, and try + * re-initializing the chip. + */ + asc_dvc->err_code = 0; + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + status = AdvInitAsc38C1600Driver(asc_dvc); + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + status = AdvInitAsc38C0800Driver(asc_dvc); + } else { + status = AdvInitAsc3550Driver(asc_dvc); + } - for (j = 0; j < k; j++) { - printk(" %2.2X%2.2X%2.2X%2.2X", - (unsigned)s[i + (j * 4)], - (unsigned)s[i + (j * 4) + 1], - (unsigned)s[i + (j * 4) + 2], - (unsigned)s[i + (j * 4) + 3]); - } + /* Translate initialization return value to status value. */ + if (status == 0) { + status = ADV_TRUE; + } else { + status = ADV_FALSE; + } - switch (m) { - case 0: - default: - break; - case 1: - printk(" %2.2X", (unsigned)s[i + (j * 4)]); - break; - case 2: - printk(" %2.2X%2.2X", - (unsigned)s[i + (j * 4)], - (unsigned)s[i + (j * 4) + 1]); - break; - case 3: - printk(" %2.2X%2.2X%2.2X", - (unsigned)s[i + (j * 4) + 1], - (unsigned)s[i + (j * 4) + 2], - (unsigned)s[i + (j * 4) + 3]); - break; - } + /* + * Restore the BIOS signature word. + */ + AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); - printk("\n"); + /* + * Restore per TID negotiated values. + */ + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + } + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, + max_cmd[tid]); } + + return status; } -#endif /* ADVANSYS_DEBUG */ /* - * --- Asc Library Functions + * adv_async_callback() - Adv Library asynchronous event callback function. */ - -static ushort __init AscGetEisaChipCfg(PortAddr iop_base) +static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) { - PortAddr eisa_cfg_iop; + switch (code) { + case ADV_ASYNC_SCSI_BUS_RESET_DET: + /* + * The firmware detected a SCSI Bus reset. + */ + ASC_DBG(0, "ADV_ASYNC_SCSI_BUS_RESET_DET\n"); + break; - eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) (ASC_EISA_CFG_IOP_MASK); - return (inpw(eisa_cfg_iop)); -} + case ADV_ASYNC_RDMA_FAILURE: + /* + * Handle RDMA failure by resetting the SCSI Bus and + * possibly the chip if it is unresponsive. Log the error + * with a unique code. + */ + ASC_DBG(0, "ADV_ASYNC_RDMA_FAILURE\n"); + AdvResetChipAndSB(adv_dvc_varp); + break; -static uchar __init AscSetChipScsiID(PortAddr iop_base, uchar new_host_id) -{ - ushort cfg_lsw; + case ADV_HOST_SCSI_BUS_RESET: + /* + * Host generated SCSI bus reset occurred. + */ + ASC_DBG(0, "ADV_HOST_SCSI_BUS_RESET\n"); + break; - if (AscGetChipScsiID(iop_base) == new_host_id) { - return (new_host_id); + default: + ASC_DBG(0, "unknown code 0x%x\n", code); + break; } - cfg_lsw = AscGetChipCfgLsw(iop_base); - cfg_lsw &= 0xF8FF; - cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8); - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetChipScsiID(iop_base)); } -static uchar __init AscGetChipScsiCtrl(PortAddr iop_base) +/* + * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR(). + * + * Callback function for the Wide SCSI Adv Library. + */ +static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) { - uchar sc; + struct asc_board *boardp; + adv_req_t *reqp; + adv_sgblk_t *sgblkp; + struct scsi_cmnd *scp; + struct Scsi_Host *shost; + ADV_DCNT resid_cnt; - AscSetBank(iop_base, 1); - sc = inp(iop_base + IOP_REG_SC); - AscSetBank(iop_base, 0); - return (sc); -} + ASC_DBG(1, "adv_dvc_varp 0x%lx, scsiqp 0x%lx\n", + (ulong)adv_dvc_varp, (ulong)scsiqp); + ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); -static uchar __init AscGetChipVersion(PortAddr iop_base, ushort bus_type) -{ - if ((bus_type & ASC_IS_EISA) != 0) { - PortAddr eisa_iop; - uchar revision; - eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) ASC_EISA_REV_IOP_MASK; - revision = inp(eisa_iop); - return ((uchar)((ASC_CHIP_MIN_VER_EISA - 1) + revision)); + /* + * Get the adv_req_t structure for the command that has been + * completed. The adv_req_t structure actually contains the + * completed ADV_SCSI_REQ_Q structure. + */ + reqp = (adv_req_t *)ADV_U32_TO_VADDR(scsiqp->srb_ptr); + ASC_DBG(1, "reqp 0x%lx\n", (ulong)reqp); + if (reqp == NULL) { + ASC_PRINT("adv_isr_callback: reqp is NULL\n"); + return; } - return (AscGetChipVerNo(iop_base)); -} -static ushort __init AscGetChipBusType(PortAddr iop_base) -{ - ushort chip_ver; - - chip_ver = AscGetChipVerNo(iop_base); - if ((chip_ver >= ASC_CHIP_MIN_VER_VL) - && (chip_ver <= ASC_CHIP_MAX_VER_VL) - ) { - if (((iop_base & 0x0C30) == 0x0C30) - || ((iop_base & 0x0C50) == 0x0C50) - ) { - return (ASC_IS_EISA); - } - return (ASC_IS_VL); + /* + * Get the struct scsi_cmnd structure and Scsi_Host structure for the + * command that has been completed. + * + * Note: The adv_req_t request structure and adv_sgblk_t structure, + * if any, are dropped, because a board structure pointer can not be + * determined. + */ + scp = reqp->cmndp; + ASC_DBG(1, "scp 0x%p\n", scp); + if (scp == NULL) { + ASC_PRINT + ("adv_isr_callback: scp is NULL; adv_req_t dropped.\n"); + return; } - if ((chip_ver >= ASC_CHIP_MIN_VER_ISA) && - (chip_ver <= ASC_CHIP_MAX_VER_ISA)) { - if (chip_ver >= ASC_CHIP_MIN_VER_ISA_PNP) { - return (ASC_IS_ISAPNP); + ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + + shost = scp->device->host; + ASC_STATS(shost, callback); + ASC_DBG(1, "shost 0x%p\n", shost); + + boardp = shost_priv(shost); + BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var); + + /* + * 'done_status' contains the command's ending status. + */ + switch (scsiqp->done_status) { + case QD_NO_ERROR: + ASC_DBG(2, "QD_NO_ERROR\n"); + scp->result = 0; + + /* + * Check for an underrun condition. + * + * If there was no error and an underrun condition, then + * then return the number of underrun bytes. + */ + resid_cnt = le32_to_cpu(scsiqp->data_cnt); + if (scsi_bufflen(scp) != 0 && resid_cnt != 0 && + resid_cnt <= scsi_bufflen(scp)) { + ASC_DBG(1, "underrun condition %lu bytes\n", + (ulong)resid_cnt); + scsi_set_resid(scp, resid_cnt); } - return (ASC_IS_ISA); - } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && - (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { - return (ASC_IS_PCI); + break; + + case QD_WITH_ERROR: + ASC_DBG(2, "QD_WITH_ERROR\n"); + switch (scsiqp->host_status) { + case QHSTA_NO_ERROR: + if (scsiqp->scsi_status == SAM_STAT_CHECK_CONDITION) { + ASC_DBG(2, "SAM_STAT_CHECK_CONDITION\n"); + ASC_DBG_PRT_SENSE(2, scp->sense_buffer, + sizeof(scp->sense_buffer)); + /* + * Note: The 'status_byte()' macro used by + * target drivers defined in scsi.h shifts the + * status byte returned by host drivers right + * by 1 bit. This is why target drivers also + * use right shifted status byte definitions. + * For instance target drivers use + * CHECK_CONDITION, defined to 0x1, instead of + * the SCSI defined check condition value of + * 0x2. Host drivers are supposed to return + * the status byte as it is defined by SCSI. + */ + scp->result = DRIVER_BYTE(DRIVER_SENSE) | + STATUS_BYTE(scsiqp->scsi_status); + } else { + scp->result = STATUS_BYTE(scsiqp->scsi_status); + } + break; + + default: + /* Some other QHSTA error occurred. */ + ASC_DBG(1, "host_status 0x%x\n", scsiqp->host_status); + scp->result = HOST_BYTE(DID_BAD_TARGET); + break; + } + break; + + case QD_ABORTED_BY_HOST: + ASC_DBG(1, "QD_ABORTED_BY_HOST\n"); + scp->result = + HOST_BYTE(DID_ABORT) | STATUS_BYTE(scsiqp->scsi_status); + break; + + default: + ASC_DBG(1, "done_status 0x%x\n", scsiqp->done_status); + scp->result = + HOST_BYTE(DID_ERROR) | STATUS_BYTE(scsiqp->scsi_status); + break; } - return (0); -} -static ASC_DCNT -AscLoadMicroCode(PortAddr iop_base, - ushort s_addr, uchar *mcode_buf, ushort mcode_size) -{ - ASC_DCNT chksum; - ushort mcode_word_size; - ushort mcode_chksum; + /* + * If the 'init_tidmask' bit isn't already set for the target and the + * current request finished normally, then set the bit for the target + * to indicate that a device is present. + */ + if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && + scsiqp->done_status == QD_NO_ERROR && + scsiqp->host_status == QHSTA_NO_ERROR) { + boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); + } - /* Write the microcode buffer starting at LRAM address 0. */ - mcode_word_size = (ushort)(mcode_size >> 1); - AscMemWordSetLram(iop_base, s_addr, 0, mcode_word_size); - AscMemWordCopyPtrToLram(iop_base, s_addr, mcode_buf, mcode_word_size); + asc_scsi_done(scp); - chksum = AscMemSumLramWord(iop_base, s_addr, mcode_word_size); - ASC_DBG1(1, "AscLoadMicroCode: chksum 0x%lx\n", (ulong)chksum); - mcode_chksum = (ushort)AscMemSumLramWord(iop_base, - (ushort)ASC_CODE_SEC_BEG, - (ushort)((mcode_size - - s_addr - (ushort) - ASC_CODE_SEC_BEG) / - 2)); - ASC_DBG1(1, "AscLoadMicroCode: mcode_chksum 0x%lx\n", - (ulong)mcode_chksum); - AscWriteLramWord(iop_base, ASCV_MCODE_CHKSUM_W, mcode_chksum); - AscWriteLramWord(iop_base, ASCV_MCODE_SIZE_W, mcode_size); - return (chksum); + /* + * Free all 'adv_sgblk_t' structures allocated for the request. + */ + while ((sgblkp = reqp->sgblkp) != NULL) { + /* Remove 'sgblkp' from the request list. */ + reqp->sgblkp = sgblkp->next_sgblkp; + + /* Add 'sgblkp' to the board free list. */ + sgblkp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgblkp; + } + + /* + * Free the adv_req_t structure used with the command by adding + * it back to the board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; + + ASC_DBG(1, "done\n"); } -static int AscFindSignature(PortAddr iop_base) +/* + * Adv Library Interrupt Service Routine + * + * This function is called by a driver's interrupt service routine. + * The function disables and re-enables interrupts. + * + * When a microcode idle command is completed, the ADV_DVC_VAR + * 'idle_cmd_done' field is set to ADV_TRUE. + * + * Note: AdvISR() can be called when interrupts are disabled or even + * when there is no hardware interrupt condition present. It will + * always check for completed idle commands and microcode requests. + * This is an important feature that shouldn't be changed because it + * allows commands to be completed from polling mode loops. + * + * Return: + * ADV_TRUE(1) - interrupt was pending + * ADV_FALSE(0) - no interrupt was pending + */ +static int AdvISR(ADV_DVC_VAR *asc_dvc) { - ushort sig_word; + AdvPortAddr iop_base; + uchar int_stat; + ushort target_bit; + ADV_CARR_T *free_carrp; + ADV_VADDR irq_next_vpa; + ADV_SCSI_REQ_Q *scsiq; - ASC_DBG2(1, "AscFindSignature: AscGetChipSignatureByte(0x%x) 0x%x\n", - iop_base, AscGetChipSignatureByte(iop_base)); - if (AscGetChipSignatureByte(iop_base) == (uchar)ASC_1000_ID1B) { - ASC_DBG2(1, - "AscFindSignature: AscGetChipSignatureWord(0x%x) 0x%x\n", - iop_base, AscGetChipSignatureWord(iop_base)); - sig_word = AscGetChipSignatureWord(iop_base); - if ((sig_word == (ushort)ASC_1000_ID0W) || - (sig_word == (ushort)ASC_1000_ID0W_FIX)) { - return (1); - } + iop_base = asc_dvc->iop_base; + + /* Reading the register clears the interrupt. */ + int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); + + if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | + ADV_INTR_STATUS_INTRC)) == 0) { + return ADV_FALSE; } - return (0); -} -static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __initdata = { - 0x100, ASC_IOADR_1, 0x120, ASC_IOADR_2, 0x140, ASC_IOADR_3, ASC_IOADR_4, - ASC_IOADR_5, ASC_IOADR_6, ASC_IOADR_7, ASC_IOADR_8 -}; + /* + * Notify the driver of an asynchronous microcode condition by + * calling the adv_async_callback function. The function + * is passed the microcode ASC_MC_INTRB_CODE byte value. + */ + if (int_stat & ADV_INTR_STATUS_INTRB) { + uchar intrb_code; -#ifdef CONFIG_ISA -static uchar _isa_pnp_inited __initdata = 0; + AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); -static PortAddr __init AscSearchIOPortAddr(PortAddr iop_beg, ushort bus_type) -{ - if (bus_type & ASC_IS_VL) { - while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { - if (AscGetChipVersion(iop_beg, bus_type) <= - ASC_CHIP_MAX_VER_VL) { - return (iop_beg); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || + asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE && + asc_dvc->carr_pending_cnt != 0) { + AdvWriteByteRegister(iop_base, IOPB_TICKLE, + ADV_TICKLE_A); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + AdvWriteByteRegister(iop_base, + IOPB_TICKLE, + ADV_TICKLE_NOP); + } } } - return (0); + + adv_async_callback(asc_dvc, intrb_code); } - if (bus_type & ASC_IS_ISA) { - if (_isa_pnp_inited == 0) { - AscSetISAPNPWaitForKey(); - _isa_pnp_inited++; - } - while ((iop_beg = AscSearchIOPortAddr11(iop_beg)) != 0) { - if ((AscGetChipVersion(iop_beg, bus_type) & - ASC_CHIP_VER_ISA_BIT) != 0) { - return (iop_beg); - } + + /* + * Check if the IRQ stopper carrier contains a completed request. + */ + while (((irq_next_vpa = + le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) { + /* + * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure. + * The RISC will have set 'areq_vpa' to a virtual address. + * + * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr + * field to the carrier ADV_CARR_T.areq_vpa field. The conversion + * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr' + * in AdvExeScsiQueue(). + */ + scsiq = (ADV_SCSI_REQ_Q *) + ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa)); + + /* + * Request finished with good status and the queue was not + * DMAed to host memory by the firmware. Set all status fields + * to indicate good status. + */ + if ((irq_next_vpa & ASC_RQ_GOOD) != 0) { + scsiq->done_status = QD_NO_ERROR; + scsiq->host_status = scsiq->scsi_status = 0; + scsiq->data_cnt = 0L; } - return (0); + + /* + * Advance the stopper pointer to the next carrier + * ignoring the lower four bits. Free the previous + * stopper carrier. + */ + free_carrp = asc_dvc->irq_sp; + asc_dvc->irq_sp = (ADV_CARR_T *) + ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa)); + + free_carrp->next_vpa = + cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); + asc_dvc->carr_freelist = free_carrp; + asc_dvc->carr_pending_cnt--; + + target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); + + /* + * Clear request microcode control flag. + */ + scsiq->cntl = 0; + + /* + * Notify the driver of the completed request by passing + * the ADV_SCSI_REQ_Q pointer to its callback function. + */ + scsiq->a_flag |= ADV_SCSIQ_DONE; + adv_isr_callback(asc_dvc, scsiq); + /* + * Note: After the driver callback function is called, 'scsiq' + * can no longer be referenced. + * + * Fall through and continue processing other completed + * requests... + */ } - if (bus_type & ASC_IS_EISA) { - if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { - return (iop_beg); - } - return (0); + return ADV_TRUE; +} + +static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code) +{ + if (asc_dvc->err_code == 0) { + asc_dvc->err_code = err_code; + AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, + err_code); } - return (0); + return err_code; } -static PortAddr __init AscSearchIOPortAddr11(PortAddr s_addr) +static void AscAckInterrupt(PortAddr iop_base) { - int i; - PortAddr iop_base; + uchar host_flag; + uchar risc_flag; + ushort loop; - for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { - if (_asc_def_iop_base[i] > s_addr) { + loop = 0; + do { + risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); + if (loop++ > 0x7FFF) { break; } - } - for (; i < ASC_IOADR_TABLE_MAX_IX; i++) { - iop_base = _asc_def_iop_base[i]; - if (!request_region(iop_base, ASC_IOADR_GAP, "advansys")) { - ASC_DBG1(1, - "AscSearchIOPortAddr11: check_region() failed I/O port 0x%x\n", - iop_base); - continue; - } - ASC_DBG1(1, "AscSearchIOPortAddr11: probing I/O port 0x%x\n", - iop_base); - release_region(iop_base, ASC_IOADR_GAP); - if (AscFindSignature(iop_base)) { - return (iop_base); + } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); + host_flag = + AscReadLramByte(iop_base, + ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, + (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT)); + AscSetChipStatus(iop_base, CIW_INT_ACK); + loop = 0; + while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { + AscSetChipStatus(iop_base, CIW_INT_ACK); + if (loop++ > 3) { + break; } } - return (0); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); } -static void __init AscSetISAPNPWaitForKey(void) +static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) { - outp(ASC_ISA_PNP_PORT_ADDR, 0x02); - outp(ASC_ISA_PNP_PORT_WRITE, 0x02); - return; + const uchar *period_table; + int max_index; + int min_index; + int i; + + period_table = asc_dvc->sdtr_period_tbl; + max_index = (int)asc_dvc->max_sdtr_index; + min_index = (int)asc_dvc->min_sdtr_index; + if ((syn_time <= period_table[max_index])) { + for (i = min_index; i < (max_index - 1); i++) { + if (syn_time <= period_table[i]) { + return (uchar)i; + } + } + return (uchar)max_index; + } else { + return (uchar)(max_index + 1); + } } -#endif /* CONFIG_ISA */ -static void __init AscToggleIRQAct(PortAddr iop_base) +static uchar +AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset) { - AscSetChipStatus(iop_base, CIW_IRQ_ACT); - AscSetChipStatus(iop_base, 0); - return; + EXT_MSG sdtr_buf; + uchar sdtr_period_index; + PortAddr iop_base; + + iop_base = asc_dvc->iop_base; + sdtr_buf.msg_type = EXTENDED_MESSAGE; + sdtr_buf.msg_len = MS_SDTR_LEN; + sdtr_buf.msg_req = EXTENDED_SDTR; + sdtr_buf.xfer_period = sdtr_period; + sdtr_offset &= ASC_SYN_MAX_OFFSET; + sdtr_buf.req_ack_offset = sdtr_offset; + sdtr_period_index = AscGetSynPeriodIndex(asc_dvc, sdtr_period); + if (sdtr_period_index <= asc_dvc->max_sdtr_index) { + AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG, + (uchar *)&sdtr_buf, + sizeof(EXT_MSG) >> 1); + return ((sdtr_period_index << 4) | sdtr_offset); + } else { + sdtr_buf.req_ack_offset = 0; + AscMemWordCopyPtrToLram(iop_base, ASCV_MSGOUT_BEG, + (uchar *)&sdtr_buf, + sizeof(EXT_MSG) >> 1); + return 0; + } } -static uchar __init AscGetChipIRQ(PortAddr iop_base, ushort bus_type) +static uchar +AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset) { - ushort cfg_lsw; - uchar chip_irq; + uchar byte; + uchar sdtr_period_ix; - if ((bus_type & ASC_IS_EISA) != 0) { - cfg_lsw = AscGetEisaChipCfg(iop_base); - chip_irq = (uchar)(((cfg_lsw >> 8) & 0x07) + 10); - if ((chip_irq == 13) || (chip_irq > 15)) { - return (0); - } - return (chip_irq); - } - if ((bus_type & ASC_IS_VL) != 0) { - cfg_lsw = AscGetChipCfgLsw(iop_base); - chip_irq = (uchar)(((cfg_lsw >> 2) & 0x07)); - if ((chip_irq == 0) || (chip_irq == 4) || (chip_irq == 7)) { - return (0); - } - return ((uchar)(chip_irq + (ASC_MIN_IRQ_NO - 1))); - } - cfg_lsw = AscGetChipCfgLsw(iop_base); - chip_irq = (uchar)(((cfg_lsw >> 2) & 0x03)); - if (chip_irq == 3) - chip_irq += (uchar)2; - return ((uchar)(chip_irq + ASC_MIN_IRQ_NO)); + sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); + if (sdtr_period_ix > asc_dvc->max_sdtr_index) + return 0xFF; + byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); + return byte; } -static uchar __init -AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type) +static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data) { - ushort cfg_lsw; + ASC_SCSI_BIT_ID_TYPE org_id; + int i; + int sta = TRUE; - if ((bus_type & ASC_IS_VL) != 0) { - if (irq_no != 0) { - if ((irq_no < ASC_MIN_IRQ_NO) - || (irq_no > ASC_MAX_IRQ_NO)) { - irq_no = 0; - } else { - irq_no -= (uchar)((ASC_MIN_IRQ_NO - 1)); - } + AscSetBank(iop_base, 1); + org_id = AscReadChipDvcID(iop_base); + for (i = 0; i <= ASC_MAX_TID; i++) { + if (org_id == (0x01 << i)) + break; + } + org_id = (ASC_SCSI_BIT_ID_TYPE) i; + AscWriteChipDvcID(iop_base, id); + if (AscReadChipDvcID(iop_base) == (0x01 << id)) { + AscSetBank(iop_base, 0); + AscSetChipSyn(iop_base, sdtr_data); + if (AscGetChipSyn(iop_base) != sdtr_data) { + sta = FALSE; } - cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE3); - cfg_lsw |= (ushort)0x0010; - AscSetChipCfgLsw(iop_base, cfg_lsw); - AscToggleIRQAct(iop_base); - cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFE0); - cfg_lsw |= (ushort)((irq_no & 0x07) << 2); - AscSetChipCfgLsw(iop_base, cfg_lsw); - AscToggleIRQAct(iop_base); - return (AscGetChipIRQ(iop_base, bus_type)); - } - if ((bus_type & (ASC_IS_ISA)) != 0) { - if (irq_no == 15) - irq_no -= (uchar)2; - irq_no -= (uchar)ASC_MIN_IRQ_NO; - cfg_lsw = (ushort)(AscGetChipCfgLsw(iop_base) & 0xFFF3); - cfg_lsw |= (ushort)((irq_no & 0x03) << 2); - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetChipIRQ(iop_base, bus_type)); + } else { + sta = FALSE; } - return (0); + AscSetBank(iop_base, 1); + AscWriteChipDvcID(iop_base, org_id); + AscSetBank(iop_base, 0); + return (sta); } -#ifdef CONFIG_ISA -static void __init AscEnableIsaDma(uchar dma_channel) +static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no) { - if (dma_channel < 4) { - outp(0x000B, (ushort)(0xC0 | dma_channel)); - outp(0x000A, dma_channel); - } else if (dma_channel < 8) { - outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4))); - outp(0x00D4, (ushort)(dma_channel - 4)); - } - return; + AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); + AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); } -#endif /* CONFIG_ISA */ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) { @@ -8528,9 +8597,9 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) uchar cur_dvc_qng; uchar asyn_sdtr; uchar scsi_status; - asc_board_t *boardp; + struct asc_board *boardp; - ASC_ASSERT(asc_dvc->drv_ptr != NULL); + BUG_ON(!asc_dvc->drv_ptr); boardp = asc_dvc->drv_ptr; iop_base = asc_dvc->iop_base; @@ -8541,8 +8610,7 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) target_ix = AscReadLramByte(iop_base, (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_TARGET_IX)); - q_cntl = - AscReadLramByte(iop_base, + q_cntl = AscReadLramByte(iop_base, (ushort)(halt_q_addr + (ushort)ASC_SCSIQ_B_CNTL)); tid_no = ASC_TIX_TO_TID(target_ix); target_id = (uchar)ASC_TID_TO_TARGET_ID(tid_no); @@ -8566,14 +8634,13 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); return (0); } else if (int_halt_code == ASC_HALT_EXTMSG_IN) { - AscMemWordCopyPtrFromLram(iop_base, ASCV_MSGIN_BEG, (uchar *)&ext_msg, sizeof(EXT_MSG) >> 1); - if (ext_msg.msg_type == MS_EXTEND && - ext_msg.msg_req == MS_SDTR_CODE && + if (ext_msg.msg_type == EXTENDED_MESSAGE && + ext_msg.msg_req == EXTENDED_SDTR && ext_msg.msg_len == MS_SDTR_LEN) { sdtr_accept = TRUE; if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { @@ -8582,15 +8649,14 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) ext_msg.req_ack_offset = ASC_SYN_MAX_OFFSET; } if ((ext_msg.xfer_period < - asc_dvc->sdtr_period_tbl[asc_dvc-> - host_init_sdtr_index]) + asc_dvc->sdtr_period_tbl[asc_dvc->min_sdtr_index]) || (ext_msg.xfer_period > asc_dvc->sdtr_period_tbl[asc_dvc-> max_sdtr_index])) { sdtr_accept = FALSE; ext_msg.xfer_period = asc_dvc->sdtr_period_tbl[asc_dvc-> - host_init_sdtr_index]; + min_sdtr_index]; } if (sdtr_accept) { sdtr_data = @@ -8614,7 +8680,6 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) AscSetChipSDTR(iop_base, asyn_sdtr, tid_no); } else { if (sdtr_accept && (q_cntl & QC_MSG_OUT)) { - q_cntl &= ~QC_MSG_OUT; asc_dvc->sdtr_done |= target_id; asc_dvc->init_sdtr |= target_id; @@ -8629,7 +8694,6 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) tid_no); boardp->sdtr_data[tid_no] = sdtr_data; } else { - q_cntl |= QC_MSG_OUT; AscMsgOutSDTR(asc_dvc, ext_msg.xfer_period, @@ -8655,8 +8719,8 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) q_cntl); AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); return (0); - } else if (ext_msg.msg_type == MS_EXTEND && - ext_msg.msg_req == MS_WDTR_CODE && + } else if (ext_msg.msg_type == EXTENDED_MESSAGE && + ext_msg.msg_req == EXTENDED_WDTR && ext_msg.msg_len == MS_WDTR_LEN) { ext_msg.wdtr_width = 0; @@ -8749,9 +8813,9 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) (uchar *)&out_msg, sizeof(EXT_MSG) >> 1); - if ((out_msg.msg_type == MS_EXTEND) && + if ((out_msg.msg_type == EXTENDED_MESSAGE) && (out_msg.msg_len == MS_SDTR_LEN) && - (out_msg.msg_req == MS_SDTR_CODE)) { + (out_msg.msg_req == EXTENDED_SDTR)) { asc_dvc->init_sdtr &= ~target_id; asc_dvc->sdtr_done &= ~target_id; @@ -8797,9 +8861,9 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) cur_dvc_qng); /* - * Set the device queue depth to the number of - * active requests when the QUEUE FULL condition - * was encountered. + * Set the device queue depth to the + * number of active requests when the + * QUEUE FULL condition was encountered. */ boardp->queue_full |= target_id; boardp->queue_full_cnt[tid_no] = @@ -8825,9 +8889,8 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) int i; q_no = AscReadLramByte(iop_base, (ushort)ASCV_REQ_SG_LIST_QP); - if (q_no == ASC_QLINK_END) { - return (0); - } + if (q_no == ASC_QLINK_END) + return 0; q_addr = ASC_QNO_TO_QADDR(q_no); @@ -8879,8 +8942,8 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) sg_entry_cnt = ASC_MAX_SG_LIST - 1; /* - * Keep track of remaining number of SG elements that will - * need to be handled on the next interrupt. + * Keep track of remaining number of SG elements that + * will need to be handled on the next interrupt. */ scsiq->remain_sg_entry_cnt -= (ASC_MAX_SG_LIST - 1); } else { @@ -8971,6 +9034,34 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) return (0); } +/* + * void + * DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) + * + * Calling/Exit State: + * none + * + * Description: + * Input an ASC_QDONE_INFO structure from the chip + */ +static void +DvcGetQinfo(PortAddr iop_base, ushort s_addr, uchar *inbuf, int words) +{ + int i; + ushort word; + + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + if (i == 10) { + continue; + } + word = inpw(iop_base + IOP_RAM_DATA); + inbuf[i] = word & 0xff; + inbuf[i + 1] = (word >> 8) & 0xff; + } + ASC_DBG_PRT_HEX(2, "DvcGetQinfo", inbuf, 2 * words); +} + static uchar _AscCopyLramScsiDoneQ(PortAddr iop_base, ushort q_addr, @@ -9014,7 +9105,124 @@ _AscCopyLramScsiDoneQ(PortAddr iop_base, ASC_SCSIQ_DW_REMAIN_XFER_CNT)); scsiq->remain_bytes &= max_dma_count; - return (sg_queue_cnt); + return sg_queue_cnt; +} + +/* + * asc_isr_callback() - Second Level Interrupt Handler called by AscISR(). + * + * Interrupt callback function for the Narrow SCSI Asc Library. + */ +static void asc_isr_callback(ASC_DVC_VAR *asc_dvc_varp, ASC_QDONE_INFO *qdonep) +{ + struct asc_board *boardp; + struct scsi_cmnd *scp; + struct Scsi_Host *shost; + + ASC_DBG(1, "asc_dvc_varp 0x%p, qdonep 0x%p\n", asc_dvc_varp, qdonep); + ASC_DBG_PRT_ASC_QDONE_INFO(2, qdonep); + + scp = advansys_srb_to_ptr(asc_dvc_varp, qdonep->d2.srb_ptr); + if (!scp) + return; + + ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); + + shost = scp->device->host; + ASC_STATS(shost, callback); + ASC_DBG(1, "shost 0x%p\n", shost); + + boardp = shost_priv(shost); + BUG_ON(asc_dvc_varp != &boardp->dvc_var.asc_dvc_var); + + dma_unmap_single(boardp->dev, scp->SCp.dma_handle, + sizeof(scp->sense_buffer), DMA_FROM_DEVICE); + /* + * 'qdonep' contains the command's ending status. + */ + switch (qdonep->d3.done_stat) { + case QD_NO_ERROR: + ASC_DBG(2, "QD_NO_ERROR\n"); + scp->result = 0; + + /* + * Check for an underrun condition. + * + * If there was no error and an underrun condition, then + * return the number of underrun bytes. + */ + if (scsi_bufflen(scp) != 0 && qdonep->remain_bytes != 0 && + qdonep->remain_bytes <= scsi_bufflen(scp)) { + ASC_DBG(1, "underrun condition %u bytes\n", + (unsigned)qdonep->remain_bytes); + scsi_set_resid(scp, qdonep->remain_bytes); + } + break; + + case QD_WITH_ERROR: + ASC_DBG(2, "QD_WITH_ERROR\n"); + switch (qdonep->d3.host_stat) { + case QHSTA_NO_ERROR: + if (qdonep->d3.scsi_stat == SAM_STAT_CHECK_CONDITION) { + ASC_DBG(2, "SAM_STAT_CHECK_CONDITION\n"); + ASC_DBG_PRT_SENSE(2, scp->sense_buffer, + sizeof(scp->sense_buffer)); + /* + * Note: The 'status_byte()' macro used by + * target drivers defined in scsi.h shifts the + * status byte returned by host drivers right + * by 1 bit. This is why target drivers also + * use right shifted status byte definitions. + * For instance target drivers use + * CHECK_CONDITION, defined to 0x1, instead of + * the SCSI defined check condition value of + * 0x2. Host drivers are supposed to return + * the status byte as it is defined by SCSI. + */ + scp->result = DRIVER_BYTE(DRIVER_SENSE) | + STATUS_BYTE(qdonep->d3.scsi_stat); + } else { + scp->result = STATUS_BYTE(qdonep->d3.scsi_stat); + } + break; + + default: + /* QHSTA error occurred */ + ASC_DBG(1, "host_stat 0x%x\n", qdonep->d3.host_stat); + scp->result = HOST_BYTE(DID_BAD_TARGET); + break; + } + break; + + case QD_ABORTED_BY_HOST: + ASC_DBG(1, "QD_ABORTED_BY_HOST\n"); + scp->result = + HOST_BYTE(DID_ABORT) | MSG_BYTE(qdonep->d3. + scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + + default: + ASC_DBG(1, "done_stat 0x%x\n", qdonep->d3.done_stat); + scp->result = + HOST_BYTE(DID_ERROR) | MSG_BYTE(qdonep->d3. + scsi_msg) | + STATUS_BYTE(qdonep->d3.scsi_stat); + break; + } + + /* + * If the 'init_tidmask' bit isn't already set for the target and the + * current request finished normally, then set the bit for the target + * to indicate that a device is present. + */ + if ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(scp->device->id)) == 0 && + qdonep->d3.done_stat == QD_NO_ERROR && + qdonep->d3.host_stat == QHSTA_NO_ERROR) { + boardp->init_tidmask |= ADV_TID_TO_TIDMASK(scp->device->id); + } + + asc_scsi_done(scp); } static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) @@ -9035,10 +9243,8 @@ static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) ASC_QDONE_INFO scsiq_buf; ASC_QDONE_INFO *scsiq; int false_overrun; - ASC_ISR_CALLBACK asc_isr_callback; iop_base = asc_dvc->iop_base; - asc_isr_callback = asc_dvc->isr_callback; n_q_used = 1; scsiq = (ASC_QDONE_INFO *)&scsiq_buf; done_q_tail = (uchar)AscGetVarDoneQTail(iop_base); @@ -9141,7 +9347,7 @@ static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) AscSetChipControl(iop_base, (uchar)(CC_SCSI_RESET | CC_HALT)); - DvcDelayNanoSecond(asc_dvc, 60000); + udelay(60); AscSetChipControl(iop_base, CC_HALT); AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); @@ -9150,7 +9356,7 @@ static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) } } if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); + asc_isr_callback(asc_dvc, scsiq); } else { if ((AscReadLramByte(iop_base, (ushort)(q_addr + (ushort) @@ -9168,7 +9374,7 @@ static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) AscSetLibErrorCode(asc_dvc, ASCQ_ERR_Q_STATUS); FATAL_ERR_QDONE: if ((scsiq->cntl & QC_NO_CALLBACK) == 0) { - (*asc_isr_callback) (asc_dvc, scsiq); + asc_isr_callback(asc_dvc, scsiq); } return (0x80); } @@ -9190,22 +9396,19 @@ static int AscISR(ASC_DVC_VAR *asc_dvc) iop_base = asc_dvc->iop_base; int_pending = FALSE; - if (AscIsIntPending(iop_base) == 0) { + if (AscIsIntPending(iop_base) == 0) return int_pending; - } - if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) - || (asc_dvc->isr_callback == 0) - ) { - return (ERR); + if ((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) { + return ERR; } if (asc_dvc->in_critical_cnt != 0) { AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_ON_CRITICAL); - return (ERR); + return ERR; } if (asc_dvc->is_in_int) { AscSetLibErrorCode(asc_dvc, ASCQ_ERR_ISR_RE_ENTRY); - return (ERR); + return ERR; } asc_dvc->is_in_int = TRUE; ctrl_reg = AscGetChipControl(iop_base); @@ -9220,7 +9423,7 @@ static int AscISR(ASC_DVC_VAR *asc_dvc) saved_ctrl_reg &= (uchar)(~CC_HALT); while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) && (i-- > 0)) { - DvcSleepMilliSecond(100); + mdelay(100); } AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); AscSetChipControl(iop_base, CC_HALT); @@ -9235,9 +9438,7 @@ static int AscISR(ASC_DVC_VAR *asc_dvc) (uchar)(~ASC_HOST_FLAG_IN_ISR); AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, (uchar)(host_flag | (uchar)ASC_HOST_FLAG_IN_ISR)); - if ((chipstat & CSW_INT_PENDING) - || (int_pending) - ) { + if ((chipstat & CSW_INT_PENDING) || (int_pending)) { AscAckInterrupt(iop_base); int_pending = TRUE; if ((chipstat & CSW_HALTED) && (ctrl_reg & CC_SINGLE_STEP)) { @@ -9268,615 +9469,767 @@ static int AscISR(ASC_DVC_VAR *asc_dvc) AscSetChipLramAddr(iop_base, saved_ram_addr); AscSetChipControl(iop_base, saved_ctrl_reg); asc_dvc->is_in_int = FALSE; - return (int_pending); + return int_pending; } -/* 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, -}; +/* + * advansys_reset() + * + * Reset the bus associated with the command 'scp'. + * + * This function runs its own thread. Interrupts must be blocked but + * sleeping is allowed and no locking other than for host structures is + * required. Returns SUCCESS or FAILED. + */ +static int advansys_reset(struct scsi_cmnd *scp) +{ + struct Scsi_Host *shost = scp->device->host; + struct asc_board *boardp = shost_priv(shost); + unsigned long flags; + int status; + int ret = SUCCESS; -static ushort _asc_mcode_size = sizeof(_asc_mcode_buf); -static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; + ASC_DBG(1, "0x%p\n", scp); -#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 -static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = { - INQUIRY, - REQUEST_SENSE, - READ_CAPACITY, - READ_TOC, - MODE_SELECT, - MODE_SENSE, - MODE_SELECT_10, - MODE_SENSE_10, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF, - 0xFF -}; + ASC_STATS(shost, reset); -static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq) -{ - PortAddr iop_base; - ulong last_int_level; - int sta; - int n_q_required; - int disable_syn_offset_one_fix; - int i; - ASC_PADDR addr; - ASC_EXE_CALLBACK asc_exe_callback; - ushort sg_entry_cnt = 0; - ushort sg_entry_cnt_minus_one = 0; - uchar target_ix; - uchar tid_no; - uchar sdtr_data; - uchar extra_bytes; - uchar scsi_cmd; - uchar disable_cmd; - ASC_SG_HEAD *sg_head; - ASC_DCNT data_cnt; + scmd_printk(KERN_INFO, scp, "SCSI bus reset started...\n"); - iop_base = asc_dvc->iop_base; - sg_head = scsiq->sg_head; - asc_exe_callback = asc_dvc->exe_callback; - if (asc_dvc->err_code != 0) - return (ERR); - if (scsiq == (ASC_SCSI_Q *)0L) { - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_SCSIQ_NULL_PTR); - return (ERR); - } - scsiq->q1.q_no = 0; - if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { - scsiq->q1.extra_bytes = 0; - } - sta = 0; - target_ix = scsiq->q2.target_ix; - tid_no = ASC_TIX_TO_TID(target_ix); - n_q_required = 1; - if (scsiq->cdbptr[0] == REQUEST_SENSE) { - if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { - asc_dvc->sdtr_done &= ~scsiq->q1.target_id; - sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); - AscMsgOutSDTR(asc_dvc, - asc_dvc-> - sdtr_period_tbl[(sdtr_data >> 4) & - (uchar)(asc_dvc-> - max_sdtr_index - - 1)], - (uchar)(sdtr_data & (uchar) - ASC_SYN_MAX_OFFSET)); - scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); + if (ASC_NARROW_BOARD(boardp)) { + ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; + + /* Reset the chip and SCSI bus. */ + ASC_DBG(1, "before AscInitAsc1000Driver()\n"); + status = AscInitAsc1000Driver(asc_dvc); + + /* Refer to ASC_IERR_* defintions for meaning of 'err_code'. */ + if (asc_dvc->err_code) { + scmd_printk(KERN_INFO, scp, "SCSI bus reset error: " + "0x%x\n", asc_dvc->err_code); + ret = FAILED; + } else if (status) { + scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: " + "0x%x\n", status); + } else { + scmd_printk(KERN_INFO, scp, "SCSI bus reset " + "successful\n"); + } + + ASC_DBG(1, "after AscInitAsc1000Driver()\n"); + spin_lock_irqsave(shost->host_lock, flags); + } else { + /* + * If the suggest reset bus flags are set, then reset the bus. + * Otherwise only reset the device. + */ + ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var; + + /* + * Reset the target's SCSI bus. + */ + ASC_DBG(1, "before AdvResetChipAndSB()\n"); + switch (AdvResetChipAndSB(adv_dvc)) { + case ASC_TRUE: + scmd_printk(KERN_INFO, scp, "SCSI bus reset " + "successful\n"); + break; + case ASC_FALSE: + default: + scmd_printk(KERN_INFO, scp, "SCSI bus reset error\n"); + ret = FAILED; + break; } + spin_lock_irqsave(shost->host_lock, flags); + AdvISR(adv_dvc); } - last_int_level = DvcEnterCritical(); - if (asc_dvc->in_critical_cnt != 0) { - DvcLeaveCritical(last_int_level); - AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); - return (ERR); + + /* Save the time of the most recently completed reset. */ + boardp->last_reset = jiffies; + spin_unlock_irqrestore(shost->host_lock, flags); + + ASC_DBG(1, "ret %d\n", ret); + + return ret; +} + +/* + * advansys_biosparam() + * + * Translate disk drive geometry if the "BIOS greater than 1 GB" + * support is enabled for a drive. + * + * ip (information pointer) is an int array with the following definition: + * ip[0]: heads + * ip[1]: sectors + * ip[2]: cylinders + */ +static int +advansys_biosparam(struct scsi_device *sdev, struct block_device *bdev, + sector_t capacity, int ip[]) +{ + struct asc_board *boardp = shost_priv(sdev->host); + + ASC_DBG(1, "begin\n"); + ASC_STATS(sdev->host, biosparam); + if (ASC_NARROW_BOARD(boardp)) { + if ((boardp->dvc_var.asc_dvc_var.dvc_cntl & + ASC_CNTL_BIOS_GT_1GB) && capacity > 0x200000) { + ip[0] = 255; + ip[1] = 63; + } else { + ip[0] = 64; + ip[1] = 32; + } + } else { + if ((boardp->dvc_var.adv_dvc_var.bios_ctrl & + BIOS_CTRL_EXTENDED_XLAT) && capacity > 0x200000) { + ip[0] = 255; + ip[1] = 63; + } else { + ip[0] = 64; + ip[1] = 32; + } } - asc_dvc->in_critical_cnt++; - if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { - if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (ERR); + ip[2] = (unsigned long)capacity / (ip[0] * ip[1]); + ASC_DBG(1, "end\n"); + return 0; +} + +/* + * First-level interrupt handler. + * + * 'dev_id' is a pointer to the interrupting adapter's Scsi_Host. + */ +static irqreturn_t advansys_interrupt(int irq, void *dev_id) +{ + struct Scsi_Host *shost = dev_id; + struct asc_board *boardp = shost_priv(shost); + irqreturn_t result = IRQ_NONE; + + ASC_DBG(2, "boardp 0x%p\n", boardp); + spin_lock(shost->host_lock); + if (ASC_NARROW_BOARD(boardp)) { + if (AscIsIntPending(shost->io_port)) { + result = IRQ_HANDLED; + ASC_STATS(shost, interrupt); + ASC_DBG(1, "before AscISR()\n"); + AscISR(&boardp->dvc_var.asc_dvc_var); } -#if !CC_VERY_LONG_SG_LIST - if (sg_entry_cnt > ASC_MAX_SG_LIST) { - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (ERR); + } else { + ASC_DBG(1, "before AdvISR()\n"); + if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { + result = IRQ_HANDLED; + ASC_STATS(shost, interrupt); } -#endif /* !CC_VERY_LONG_SG_LIST */ - if (sg_entry_cnt == 1) { - scsiq->q1.data_addr = - (ADV_PADDR)sg_head->sg_list[0].addr; - scsiq->q1.data_cnt = - (ADV_DCNT)sg_head->sg_list[0].bytes; - scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); + } + spin_unlock(shost->host_lock); + + ASC_DBG(1, "end\n"); + return result; +} + +static int AscHostReqRiscHalt(PortAddr iop_base) +{ + int count = 0; + int sta = 0; + uchar saved_stop_code; + + if (AscIsChipHalted(iop_base)) + return (1); + saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP); + do { + if (AscIsChipHalted(iop_base)) { + sta = 1; + break; } - sg_entry_cnt_minus_one = sg_entry_cnt - 1; + mdelay(100); + } while (count++ < 20); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); + return (sta); +} + +static int +AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data) +{ + int sta = FALSE; + + if (AscHostReqRiscHalt(iop_base)) { + sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); + AscStartChip(iop_base); } - scsi_cmd = scsiq->cdbptr[0]; - disable_syn_offset_one_fix = FALSE; - if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && - !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { - if (scsiq->q1.cntl & QC_SG_HEAD) { - data_cnt = 0; - for (i = 0; i < sg_entry_cnt; i++) { - data_cnt += - (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i]. - bytes); - } + return sta; +} + +static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev) +{ + char type = sdev->type; + ASC_SCSI_BIT_ID_TYPE tid_bits = 1 << sdev->id; + + if (!(asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN)) + return; + if (asc_dvc->init_sdtr & tid_bits) + return; + + if ((type == TYPE_ROM) && (strncmp(sdev->vendor, "HP ", 3) == 0)) + asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; + + asc_dvc->pci_fix_asyn_xfer |= tid_bits; + if ((type == TYPE_PROCESSOR) || (type == TYPE_SCANNER) || + (type == TYPE_ROM) || (type == TYPE_TAPE)) + asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; + + if (asc_dvc->pci_fix_asyn_xfer & tid_bits) + AscSetRunChipSynRegAtID(asc_dvc->iop_base, sdev->id, + ASYN_SDTR_DATA_FIX_PCI_REV_AB); +} + +static void +advansys_narrow_slave_configure(struct scsi_device *sdev, ASC_DVC_VAR *asc_dvc) +{ + ASC_SCSI_BIT_ID_TYPE tid_bit = 1 << sdev->id; + ASC_SCSI_BIT_ID_TYPE orig_use_tagged_qng = asc_dvc->use_tagged_qng; + + if (sdev->lun == 0) { + ASC_SCSI_BIT_ID_TYPE orig_init_sdtr = asc_dvc->init_sdtr; + if ((asc_dvc->cfg->sdtr_enable & tid_bit) && sdev->sdtr) { + asc_dvc->init_sdtr |= tid_bit; } else { - data_cnt = le32_to_cpu(scsiq->q1.data_cnt); + asc_dvc->init_sdtr &= ~tid_bit; } - if (data_cnt != 0UL) { - if (data_cnt < 512UL) { - disable_syn_offset_one_fix = TRUE; - } else { - for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; - i++) { - disable_cmd = - _syn_offset_one_disable_cmd[i]; - if (disable_cmd == 0xFF) { - break; - } - if (scsi_cmd == disable_cmd) { - disable_syn_offset_one_fix = - TRUE; - break; - } - } + + if (orig_init_sdtr != asc_dvc->init_sdtr) + AscAsyncFix(asc_dvc, sdev); + } + + if (sdev->tagged_supported) { + if (asc_dvc->cfg->cmd_qng_enabled & tid_bit) { + if (sdev->lun == 0) { + asc_dvc->cfg->can_tagged_qng |= tid_bit; + asc_dvc->use_tagged_qng |= tid_bit; } + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, + asc_dvc->max_dvc_qng[sdev->id]); + } + } else { + if (sdev->lun == 0) { + asc_dvc->cfg->can_tagged_qng &= ~tid_bit; + asc_dvc->use_tagged_qng &= ~tid_bit; } + scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); } - if (disable_syn_offset_one_fix) { - scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; - scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | - ASC_TAG_FLAG_DISABLE_DISCONNECT); + + if ((sdev->lun == 0) && + (orig_use_tagged_qng != asc_dvc->use_tagged_qng)) { + AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, + asc_dvc->cfg->disc_enable); + AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, + asc_dvc->use_tagged_qng); + AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, + asc_dvc->cfg->can_tagged_qng); + + asc_dvc->max_dvc_qng[sdev->id] = + asc_dvc->cfg->max_tag_qng[sdev->id]; + AscWriteLramByte(asc_dvc->iop_base, + (ushort)(ASCV_MAX_DVC_QNG_BEG + sdev->id), + asc_dvc->max_dvc_qng[sdev->id]); + } +} + +/* + * Wide Transfers + * + * If the EEPROM enabled WDTR for the device and the device supports wide + * bus (16 bit) transfers, then turn on the device's 'wdtr_able' bit and + * write the new value to the microcode. + */ +static void +advansys_wide_enable_wdtr(AdvPortAddr iop_base, unsigned short tidmask) +{ + unsigned short cfg_word; + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); + if ((cfg_word & tidmask) != 0) + return; + + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); + + /* + * Clear the microcode SDTR and WDTR negotiation done indicators for + * the target to cause it to negotiate with the new setting set above. + * WDTR when accepted causes the target to enter asynchronous mode, so + * SDTR must be negotiated. + */ + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); + AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, cfg_word); +} + +/* + * Synchronous Transfers + * + * If the EEPROM enabled SDTR for the device and the device + * supports synchronous transfers, then turn on the device's + * 'sdtr_able' bit. Write the new value to the microcode. + */ +static void +advansys_wide_enable_sdtr(AdvPortAddr iop_base, unsigned short tidmask) +{ + unsigned short cfg_word; + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); + if ((cfg_word & tidmask) != 0) + return; + + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); + + /* + * Clear the microcode "SDTR negotiation" done indicator for the + * target to cause it to negotiate with the new setting set above. + */ + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); + cfg_word &= ~tidmask; + AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, cfg_word); +} + +/* + * PPR (Parallel Protocol Request) Capable + * + * If the device supports DT mode, then it must be PPR capable. + * The PPR message will be used in place of the SDTR and WDTR + * messages to negotiate synchronous speed and offset, transfer + * width, and protocol options. + */ +static void advansys_wide_enable_ppr(ADV_DVC_VAR *adv_dvc, + AdvPortAddr iop_base, unsigned short tidmask) +{ + AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able); + adv_dvc->ppr_able |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, adv_dvc->ppr_able); +} + +static void +advansys_wide_slave_configure(struct scsi_device *sdev, ADV_DVC_VAR *adv_dvc) +{ + AdvPortAddr iop_base = adv_dvc->iop_base; + unsigned short tidmask = 1 << sdev->id; + + if (sdev->lun == 0) { + /* + * Handle WDTR, SDTR, and Tag Queuing. If the feature + * is enabled in the EEPROM and the device supports the + * feature, then enable it in the microcode. + */ + + if ((adv_dvc->wdtr_able & tidmask) && sdev->wdtr) + advansys_wide_enable_wdtr(iop_base, tidmask); + if ((adv_dvc->sdtr_able & tidmask) && sdev->sdtr) + advansys_wide_enable_sdtr(iop_base, tidmask); + if (adv_dvc->chip_type == ADV_CHIP_ASC38C1600 && sdev->ppr) + advansys_wide_enable_ppr(adv_dvc, iop_base, tidmask); + + /* + * Tag Queuing is disabled for the BIOS which runs in polled + * mode and would see no benefit from Tag Queuing. Also by + * disabling Tag Queuing in the BIOS devices with Tag Queuing + * bugs will at least work with the BIOS. + */ + if ((adv_dvc->tagqng_able & tidmask) && + sdev->tagged_supported) { + unsigned short cfg_word; + AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); + cfg_word |= tidmask; + AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, + cfg_word); + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + sdev->id, + adv_dvc->max_dvc_qng); + } + } + + if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) { + scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, + adv_dvc->max_dvc_qng); } else { - scsiq->q2.tag_code &= 0x27; + scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); } - if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { - if ((scsi_cmd == READ_6) || - (scsi_cmd == READ_10)) { - addr = - (ADV_PADDR)le32_to_cpu(sg_head-> - sg_list - [sg_entry_cnt_minus_one]. - addr) + - (ADV_DCNT)le32_to_cpu(sg_head-> - sg_list - [sg_entry_cnt_minus_one]. - bytes); - extra_bytes = - (uchar)((ushort)addr & 0x0003); - if ((extra_bytes != 0) - && - ((scsiq->q2. - tag_code & - ASC_TAG_FLAG_EXTRA_BYTES) - == 0)) { - scsiq->q2.tag_code |= - ASC_TAG_FLAG_EXTRA_BYTES; - scsiq->q1.extra_bytes = - extra_bytes; - data_cnt = - le32_to_cpu(sg_head-> - sg_list - [sg_entry_cnt_minus_one]. - bytes); - data_cnt -= - (ASC_DCNT) extra_bytes; - sg_head-> - sg_list - [sg_entry_cnt_minus_one]. - bytes = - cpu_to_le32(data_cnt); - } - } - } +} + +/* + * Set the number of commands to queue per device for the + * specified host adapter. + */ +static int advansys_slave_configure(struct scsi_device *sdev) +{ + struct asc_board *boardp = shost_priv(sdev->host); + + if (ASC_NARROW_BOARD(boardp)) + advansys_narrow_slave_configure(sdev, + &boardp->dvc_var.asc_dvc_var); + else + advansys_wide_slave_configure(sdev, + &boardp->dvc_var.adv_dvc_var); + + return 0; +} + +static __le32 advansys_get_sense_buffer_dma(struct scsi_cmnd *scp) +{ + struct asc_board *board = shost_priv(scp->device->host); + scp->SCp.dma_handle = dma_map_single(board->dev, scp->sense_buffer, + sizeof(scp->sense_buffer), DMA_FROM_DEVICE); + dma_cache_sync(board->dev, scp->sense_buffer, + sizeof(scp->sense_buffer), DMA_FROM_DEVICE); + return cpu_to_le32(scp->SCp.dma_handle); +} + +static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp, + struct asc_scsi_q *asc_scsi_q) +{ + struct asc_dvc_var *asc_dvc = &boardp->dvc_var.asc_dvc_var; + int use_sg; + + memset(asc_scsi_q, 0, sizeof(*asc_scsi_q)); + + /* + * Point the ASC_SCSI_Q to the 'struct scsi_cmnd'. + */ + asc_scsi_q->q2.srb_ptr = advansys_ptr_to_srb(asc_dvc, scp); + if (asc_scsi_q->q2.srb_ptr == BAD_SRB) { + scp->result = HOST_BYTE(DID_SOFT_ERROR); + return ASC_ERROR; + } + + /* + * Build the ASC_SCSI_Q request. + */ + asc_scsi_q->cdbptr = &scp->cmnd[0]; + asc_scsi_q->q2.cdb_len = scp->cmd_len; + asc_scsi_q->q1.target_id = ASC_TID_TO_TARGET_ID(scp->device->id); + asc_scsi_q->q1.target_lun = scp->device->lun; + asc_scsi_q->q2.target_ix = + ASC_TIDLUN_TO_IX(scp->device->id, scp->device->lun); + asc_scsi_q->q1.sense_addr = advansys_get_sense_buffer_dma(scp); + asc_scsi_q->q1.sense_len = sizeof(scp->sense_buffer); + + /* + * If there are any outstanding requests for the current target, + * then every 255th request send an ORDERED request. This heuristic + * tries to retain the benefit of request sorting while preventing + * request starvation. 255 is the max number of tags or pending commands + * a device may have outstanding. + * + * The request count is incremented below for every successfully + * started request. + * + */ + if ((asc_dvc->cur_dvc_qng[scp->device->id] > 0) && + (boardp->reqcnt[scp->device->id] % 255) == 0) { + asc_scsi_q->q2.tag_code = MSG_ORDERED_TAG; + } else { + asc_scsi_q->q2.tag_code = MSG_SIMPLE_TAG; + } + + /* Build ASC_SCSI_Q */ + use_sg = scsi_dma_map(scp); + if (use_sg != 0) { + int sgcnt; + struct scatterlist *slp; + struct asc_sg_head *asc_sg_head; + + if (use_sg > scp->device->host->sg_tablesize) { + scmd_printk(KERN_ERR, scp, "use_sg %d > " + "sg_tablesize %d\n", use_sg, + scp->device->host->sg_tablesize); + scsi_dma_unmap(scp); + scp->result = HOST_BYTE(DID_ERROR); + return ASC_ERROR; } - sg_head->entry_to_copy = sg_head->entry_cnt; -#if CC_VERY_LONG_SG_LIST + + asc_sg_head = kzalloc(sizeof(asc_scsi_q->sg_head) + + use_sg * sizeof(struct asc_sg_list), GFP_ATOMIC); + if (!asc_sg_head) { + scsi_dma_unmap(scp); + scp->result = HOST_BYTE(DID_SOFT_ERROR); + return ASC_ERROR; + } + + asc_scsi_q->q1.cntl |= QC_SG_HEAD; + asc_scsi_q->sg_head = asc_sg_head; + asc_scsi_q->q1.data_cnt = 0; + asc_scsi_q->q1.data_addr = 0; + /* This is a byte value, otherwise it would need to be swapped. */ + asc_sg_head->entry_cnt = asc_scsi_q->q1.sg_queue_cnt = use_sg; + ASC_STATS_ADD(scp->device->host, xfer_elem, + asc_sg_head->entry_cnt); + /* - * Set the sg_entry_cnt to the maximum possible. The rest of - * the SG elements will be copied when the RISC completes the - * SG elements that fit and halts. + * Convert scatter-gather list into ASC_SG_HEAD list. */ - if (sg_entry_cnt > ASC_MAX_SG_LIST) { - sg_entry_cnt = ASC_MAX_SG_LIST; + scsi_for_each_sg(scp, slp, use_sg, sgcnt) { + asc_sg_head->sg_list[sgcnt].addr = + cpu_to_le32(sg_dma_address(slp)); + asc_sg_head->sg_list[sgcnt].bytes = + cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, xfer_sect, + DIV_ROUND_UP(sg_dma_len(slp), 512)); } -#endif /* CC_VERY_LONG_SG_LIST */ - n_q_required = AscSgListToQueue(sg_entry_cnt); - if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= - (uint) n_q_required) - || ((scsiq->q1.cntl & QC_URGENT) != 0)) { - if ((sta = - AscSendScsiQueue(asc_dvc, scsiq, - n_q_required)) == 1) { - asc_dvc->in_critical_cnt--; - if (asc_exe_callback != 0) { - (*asc_exe_callback) (asc_dvc, scsiq); - } - DvcLeaveCritical(last_int_level); - return (sta); + } + + ASC_STATS(scp->device->host, xfer_cnt); + + ASC_DBG_PRT_ASC_SCSI_Q(2, asc_scsi_q); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + + return ASC_NOERROR; +} + +/* + * Build scatter-gather list for Adv Library (Wide Board). + * + * Additional ADV_SG_BLOCK structures will need to be allocated + * if the total number of scatter-gather elements exceeds + * NO_OF_SG_PER_BLOCK (15). The ADV_SG_BLOCK structures are + * assumed to be physically contiguous. + * + * Return: + * ADV_SUCCESS(1) - SG List successfully created + * ADV_ERROR(-1) - SG List creation failed + */ +static int +adv_get_sglist(struct asc_board *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, + int use_sg) +{ + adv_sgblk_t *sgblkp; + ADV_SCSI_REQ_Q *scsiqp; + struct scatterlist *slp; + int sg_elem_cnt; + ADV_SG_BLOCK *sg_block, *prev_sg_block; + ADV_PADDR sg_block_paddr; + int i; + + scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); + slp = scsi_sglist(scp); + sg_elem_cnt = use_sg; + prev_sg_block = NULL; + reqp->sgblkp = NULL; + + for (;;) { + /* + * Allocate a 'adv_sgblk_t' structure from the board free + * list. One 'adv_sgblk_t' structure holds NO_OF_SG_PER_BLOCK + * (15) scatter-gather elements. + */ + if ((sgblkp = boardp->adv_sgblkp) == NULL) { + ASC_DBG(1, "no free adv_sgblk_t\n"); + ASC_STATS(scp->device->host, adv_build_nosg); + + /* + * Allocation failed. Free 'adv_sgblk_t' structures + * already allocated for the request. + */ + while ((sgblkp = reqp->sgblkp) != NULL) { + /* Remove 'sgblkp' from the request list. */ + reqp->sgblkp = sgblkp->next_sgblkp; + + /* Add 'sgblkp' to the board free list. */ + sgblkp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgblkp; } + return ASC_BUSY; } - } else { - if (asc_dvc->bug_fix_cntl) { - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { - if ((scsi_cmd == READ_6) || - (scsi_cmd == READ_10)) { - addr = - le32_to_cpu(scsiq->q1.data_addr) + - le32_to_cpu(scsiq->q1.data_cnt); - extra_bytes = - (uchar)((ushort)addr & 0x0003); - if ((extra_bytes != 0) - && - ((scsiq->q2. - tag_code & - ASC_TAG_FLAG_EXTRA_BYTES) - == 0)) { - data_cnt = - le32_to_cpu(scsiq->q1. - data_cnt); - if (((ushort)data_cnt & 0x01FF) - == 0) { - scsiq->q2.tag_code |= - ASC_TAG_FLAG_EXTRA_BYTES; - data_cnt -= (ASC_DCNT) - extra_bytes; - scsiq->q1.data_cnt = - cpu_to_le32 - (data_cnt); - scsiq->q1.extra_bytes = - extra_bytes; - } - } - } - } + + /* Complete 'adv_sgblk_t' board allocation. */ + boardp->adv_sgblkp = sgblkp->next_sgblkp; + sgblkp->next_sgblkp = NULL; + + /* + * Get 8 byte aligned virtual and physical addresses + * for the allocated ADV_SG_BLOCK structure. + */ + sg_block = (ADV_SG_BLOCK *)ADV_8BALIGN(&sgblkp->sg_block); + sg_block_paddr = virt_to_bus(sg_block); + + /* + * Check if this is the first 'adv_sgblk_t' for the + * request. + */ + if (reqp->sgblkp == NULL) { + /* Request's first scatter-gather block. */ + reqp->sgblkp = sgblkp; + + /* + * Set ADV_SCSI_REQ_T ADV_SG_BLOCK virtual and physical + * address pointers. + */ + scsiqp->sg_list_ptr = sg_block; + scsiqp->sg_real_addr = cpu_to_le32(sg_block_paddr); + } else { + /* Request's second or later scatter-gather block. */ + sgblkp->next_sgblkp = reqp->sgblkp; + reqp->sgblkp = sgblkp; + + /* + * Point the previous ADV_SG_BLOCK structure to + * the newly allocated ADV_SG_BLOCK structure. + */ + prev_sg_block->sg_ptr = cpu_to_le32(sg_block_paddr); } - n_q_required = 1; - if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || - ((scsiq->q1.cntl & QC_URGENT) != 0)) { - if ((sta = AscSendScsiQueue(asc_dvc, scsiq, - n_q_required)) == 1) { - asc_dvc->in_critical_cnt--; - if (asc_exe_callback != 0) { - (*asc_exe_callback) (asc_dvc, scsiq); - } - DvcLeaveCritical(last_int_level); - return (sta); + + for (i = 0; i < NO_OF_SG_PER_BLOCK; i++) { + sg_block->sg_list[i].sg_addr = + cpu_to_le32(sg_dma_address(slp)); + sg_block->sg_list[i].sg_count = + cpu_to_le32(sg_dma_len(slp)); + ASC_STATS_ADD(scp->device->host, xfer_sect, + DIV_ROUND_UP(sg_dma_len(slp), 512)); + + if (--sg_elem_cnt == 0) { /* Last ADV_SG_BLOCK and scatter-gather entry. */ + sg_block->sg_cnt = i + 1; + sg_block->sg_ptr = 0L; /* Last ADV_SG_BLOCK in list. */ + return ADV_SUCCESS; } + slp++; } + sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; + prev_sg_block = sg_block; } - asc_dvc->in_critical_cnt--; - DvcLeaveCritical(last_int_level); - return (sta); } +/* + * Build a request structure for the Adv Library (Wide Board). + * + * If an adv_req_t can not be allocated to issue the request, + * then return ASC_BUSY. If an error occurs, then return ASC_ERROR. + * + * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the + * microcode for DMA addresses or math operations are byte swapped + * to little-endian order. + */ static int -AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required) +adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp, + ADV_SCSI_REQ_Q **adv_scsiqpp) { - PortAddr iop_base; - uchar free_q_head; - uchar next_qp; - uchar tid_no; - uchar target_ix; - int sta; + adv_req_t *reqp; + ADV_SCSI_REQ_Q *scsiqp; + int i; + int ret; + int use_sg; - iop_base = asc_dvc->iop_base; - target_ix = scsiq->q2.target_ix; - tid_no = ASC_TIX_TO_TID(target_ix); - sta = 0; - free_q_head = (uchar)AscGetVarFreeQHead(iop_base); - if (n_q_required > 1) { - if ((next_qp = AscAllocMultipleFreeQueue(iop_base, - free_q_head, (uchar) - (n_q_required))) - != (uchar)ASC_QLINK_END) { - asc_dvc->last_q_shortage = 0; - scsiq->sg_head->queue_cnt = n_q_required - 1; - scsiq->q1.q_no = free_q_head; - if ((sta = AscPutReadySgListQueue(asc_dvc, scsiq, - free_q_head)) == 1) { - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng += (uchar)(n_q_required); - asc_dvc->cur_dvc_qng[tid_no]++; - } - return (sta); + /* + * Allocate an adv_req_t structure from the board to execute + * the command. + */ + if (boardp->adv_reqp == NULL) { + ASC_DBG(1, "no free adv_req_t\n"); + ASC_STATS(scp->device->host, adv_build_noreq); + return ASC_BUSY; + } else { + reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp->next_reqp; + reqp->next_reqp = NULL; + } + + /* + * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. + */ + scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); + + /* + * Initialize the structure. + */ + scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; + + /* + * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. + */ + scsiqp->srb_ptr = ADV_VADDR_TO_U32(reqp); + + /* + * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. + */ + reqp->cmndp = scp; + + /* + * Build the ADV_SCSI_REQ_Q request. + */ + + /* Set CDB length and copy it to the request structure. */ + scsiqp->cdb_len = scp->cmd_len; + /* Copy first 12 CDB bytes to cdb[]. */ + for (i = 0; i < scp->cmd_len && i < 12; i++) { + scsiqp->cdb[i] = scp->cmnd[i]; + } + /* Copy last 4 CDB bytes, if present, to cdb16[]. */ + for (; i < scp->cmd_len; i++) { + scsiqp->cdb16[i - 12] = scp->cmnd[i]; + } + + scsiqp->target_id = scp->device->id; + scsiqp->target_lun = scp->device->lun; + + scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); + scsiqp->sense_len = sizeof(scp->sense_buffer); + + /* Build ADV_SCSI_REQ_Q */ + + use_sg = scsi_dma_map(scp); + if (use_sg == 0) { + /* Zero-length transfer */ + reqp->sgblkp = NULL; + scsiqp->data_cnt = 0; + scsiqp->vdata_addr = NULL; + + scsiqp->data_addr = 0; + scsiqp->sg_list_ptr = NULL; + scsiqp->sg_real_addr = 0; + } else { + if (use_sg > ADV_MAX_SG_LIST) { + scmd_printk(KERN_ERR, scp, "use_sg %d > " + "ADV_MAX_SG_LIST %d\n", use_sg, + scp->device->host->sg_tablesize); + scsi_dma_unmap(scp); + scp->result = HOST_BYTE(DID_ERROR); + + /* + * Free the 'adv_req_t' structure by adding it back + * to the board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; + + return ASC_ERROR; } - } else if (n_q_required == 1) { - if ((next_qp = AscAllocFreeQueue(iop_base, - free_q_head)) != - ASC_QLINK_END) { - scsiq->q1.q_no = free_q_head; - if ((sta = AscPutReadyQueue(asc_dvc, scsiq, - free_q_head)) == 1) { - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng++; - asc_dvc->cur_dvc_qng[tid_no]++; - } - return (sta); + + scsiqp->data_cnt = cpu_to_le32(scsi_bufflen(scp)); + + ret = adv_get_sglist(boardp, reqp, scp, use_sg); + if (ret != ADV_SUCCESS) { + /* + * Free the adv_req_t structure by adding it back to + * the board free list. + */ + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; + + return ret; } + + ASC_STATS_ADD(scp->device->host, xfer_elem, use_sg); } - return (sta); + + ASC_STATS(scp->device->host, xfer_cnt); + + ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + + *adv_scsiqpp = scsiqp; + + return ASC_NOERROR; } static int AscSgListToQueue(int sg_list) @@ -9886,7 +10239,7 @@ static int AscSgListToQueue(int sg_list) n_sg_list_qs = ((sg_list - 1) / ASC_SG_LIST_PER_Q); if (((sg_list - 1) % ASC_SG_LIST_PER_Q) != 0) n_sg_list_qs++; - return (n_sg_list_qs + 1); + return n_sg_list_qs + 1; } static uint @@ -9901,7 +10254,7 @@ AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) tid_no = ASC_TIX_TO_TID(target_ix); if ((asc_dvc->unit_not_ready & target_id) || (asc_dvc->queue_full_or_busy & target_id)) { - return (0); + return 0; } if (n_qs == 1) { cur_used_qs = (uint) asc_dvc->cur_total_qng + @@ -9914,9 +10267,9 @@ AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) cur_free_qs = (uint) asc_dvc->max_total_qng - cur_used_qs; if (asc_dvc->cur_dvc_qng[tid_no] >= asc_dvc->max_dvc_qng[tid_no]) { - return (0); + return 0; } - return (cur_free_qs); + return cur_free_qs; } if (n_qs > 1) { if ((n_qs > asc_dvc->last_q_shortage) @@ -9924,7 +10277,62 @@ AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) asc_dvc->last_q_shortage = n_qs; } } - return (0); + return 0; +} + +static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head) +{ + ushort q_addr; + uchar next_qp; + uchar q_status; + + q_addr = ASC_QNO_TO_QADDR(free_q_head); + q_status = (uchar)AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_STATUS)); + next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD)); + if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) + return next_qp; + return ASC_QLINK_END; +} + +static uchar +AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q) +{ + uchar i; + + for (i = 0; i < n_free_q; i++) { + free_q_head = AscAllocFreeQueue(iop_base, free_q_head); + if (free_q_head == ASC_QLINK_END) + break; + } + return free_q_head; +} + +/* + * void + * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) + * + * Calling/Exit State: + * none + * + * Description: + * Output an ASC_SCSI_Q structure to the chip + */ +static void +DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) +{ + int i; + + ASC_DBG_PRT_HEX(2, "DvcPutScsiQ", outbuf, 2 * words); + AscSetChipLramAddr(iop_base, s_addr); + for (i = 0; i < 2 * words; i += 2) { + if (i == 4 || i == 20) { + continue; + } + outpw(iop_base + IOP_RAM_DATA, + ((ushort)outbuf[i + 1] << 8) | outbuf[i]); + } } static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) @@ -9966,7 +10374,7 @@ static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS), (ushort)(((ushort)scsiq->q1. q_no << 8) | (ushort)QS_READY)); - return (1); + return 1; } static int @@ -10104,491 +10512,651 @@ AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) } static int -AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data) +AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required) { - int sta = FALSE; + PortAddr iop_base; + uchar free_q_head; + uchar next_qp; + uchar tid_no; + uchar target_ix; + int sta; - if (AscHostReqRiscHalt(iop_base)) { - sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); - AscStartChip(iop_base); - return (sta); + iop_base = asc_dvc->iop_base; + target_ix = scsiq->q2.target_ix; + tid_no = ASC_TIX_TO_TID(target_ix); + sta = 0; + free_q_head = (uchar)AscGetVarFreeQHead(iop_base); + if (n_q_required > 1) { + next_qp = AscAllocMultipleFreeQueue(iop_base, free_q_head, + (uchar)n_q_required); + if (next_qp != ASC_QLINK_END) { + asc_dvc->last_q_shortage = 0; + scsiq->sg_head->queue_cnt = n_q_required - 1; + scsiq->q1.q_no = free_q_head; + sta = AscPutReadySgListQueue(asc_dvc, scsiq, + free_q_head); + } + } else if (n_q_required == 1) { + next_qp = AscAllocFreeQueue(iop_base, free_q_head); + if (next_qp != ASC_QLINK_END) { + scsiq->q1.q_no = free_q_head; + sta = AscPutReadyQueue(asc_dvc, scsiq, free_q_head); + } } - return (sta); + if (sta == 1) { + AscPutVarFreeQHead(iop_base, next_qp); + asc_dvc->cur_total_qng += n_q_required; + asc_dvc->cur_dvc_qng[tid_no]++; + } + return sta; } -static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data) +#define ASC_SYN_OFFSET_ONE_DISABLE_LIST 16 +static uchar _syn_offset_one_disable_cmd[ASC_SYN_OFFSET_ONE_DISABLE_LIST] = { + INQUIRY, + REQUEST_SENSE, + READ_CAPACITY, + READ_TOC, + MODE_SELECT, + MODE_SENSE, + MODE_SELECT_10, + MODE_SENSE_10, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF, + 0xFF +}; + +static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq) { - ASC_SCSI_BIT_ID_TYPE org_id; + PortAddr iop_base; + int sta; + int n_q_required; + int disable_syn_offset_one_fix; int i; - int sta = TRUE; + ASC_PADDR addr; + ushort sg_entry_cnt = 0; + ushort sg_entry_cnt_minus_one = 0; + uchar target_ix; + uchar tid_no; + uchar sdtr_data; + uchar extra_bytes; + uchar scsi_cmd; + uchar disable_cmd; + ASC_SG_HEAD *sg_head; + ASC_DCNT data_cnt; - AscSetBank(iop_base, 1); - org_id = AscReadChipDvcID(iop_base); - for (i = 0; i <= ASC_MAX_TID; i++) { - if (org_id == (0x01 << i)) - break; + iop_base = asc_dvc->iop_base; + sg_head = scsiq->sg_head; + if (asc_dvc->err_code != 0) + return (ERR); + scsiq->q1.q_no = 0; + if ((scsiq->q2.tag_code & ASC_TAG_FLAG_EXTRA_BYTES) == 0) { + scsiq->q1.extra_bytes = 0; } - org_id = (ASC_SCSI_BIT_ID_TYPE) i; - AscWriteChipDvcID(iop_base, id); - if (AscReadChipDvcID(iop_base) == (0x01 << id)) { - AscSetBank(iop_base, 0); - AscSetChipSyn(iop_base, sdtr_data); - if (AscGetChipSyn(iop_base) != sdtr_data) { - sta = FALSE; + sta = 0; + target_ix = scsiq->q2.target_ix; + tid_no = ASC_TIX_TO_TID(target_ix); + n_q_required = 1; + if (scsiq->cdbptr[0] == REQUEST_SENSE) { + if ((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) { + asc_dvc->sdtr_done &= ~scsiq->q1.target_id; + sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); + AscMsgOutSDTR(asc_dvc, + asc_dvc-> + sdtr_period_tbl[(sdtr_data >> 4) & + (uchar)(asc_dvc-> + max_sdtr_index - + 1)], + (uchar)(sdtr_data & (uchar) + ASC_SYN_MAX_OFFSET)); + scsiq->q1.cntl |= (QC_MSG_OUT | QC_URGENT); } + } + if (asc_dvc->in_critical_cnt != 0) { + AscSetLibErrorCode(asc_dvc, ASCQ_ERR_CRITICAL_RE_ENTRY); + return (ERR); + } + asc_dvc->in_critical_cnt++; + if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { + if ((sg_entry_cnt = sg_head->entry_cnt) == 0) { + asc_dvc->in_critical_cnt--; + return (ERR); + } +#if !CC_VERY_LONG_SG_LIST + if (sg_entry_cnt > ASC_MAX_SG_LIST) { + asc_dvc->in_critical_cnt--; + return (ERR); + } +#endif /* !CC_VERY_LONG_SG_LIST */ + if (sg_entry_cnt == 1) { + scsiq->q1.data_addr = + (ADV_PADDR)sg_head->sg_list[0].addr; + scsiq->q1.data_cnt = + (ADV_DCNT)sg_head->sg_list[0].bytes; + scsiq->q1.cntl &= ~(QC_SG_HEAD | QC_SG_SWAP_QUEUE); + } + sg_entry_cnt_minus_one = sg_entry_cnt - 1; + } + scsi_cmd = scsiq->cdbptr[0]; + disable_syn_offset_one_fix = FALSE; + if ((asc_dvc->pci_fix_asyn_xfer & scsiq->q1.target_id) && + !(asc_dvc->pci_fix_asyn_xfer_always & scsiq->q1.target_id)) { + if (scsiq->q1.cntl & QC_SG_HEAD) { + data_cnt = 0; + for (i = 0; i < sg_entry_cnt; i++) { + data_cnt += + (ADV_DCNT)le32_to_cpu(sg_head->sg_list[i]. + bytes); + } + } else { + data_cnt = le32_to_cpu(scsiq->q1.data_cnt); + } + if (data_cnt != 0UL) { + if (data_cnt < 512UL) { + disable_syn_offset_one_fix = TRUE; + } else { + for (i = 0; i < ASC_SYN_OFFSET_ONE_DISABLE_LIST; + i++) { + disable_cmd = + _syn_offset_one_disable_cmd[i]; + if (disable_cmd == 0xFF) { + break; + } + if (scsi_cmd == disable_cmd) { + disable_syn_offset_one_fix = + TRUE; + break; + } + } + } + } + } + if (disable_syn_offset_one_fix) { + scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; + scsiq->q2.tag_code |= (ASC_TAG_FLAG_DISABLE_ASYN_USE_SYN_FIX | + ASC_TAG_FLAG_DISABLE_DISCONNECT); } else { - sta = FALSE; + scsiq->q2.tag_code &= 0x27; } - AscSetBank(iop_base, 1); - AscWriteChipDvcID(iop_base, org_id); - AscSetBank(iop_base, 0); + if ((scsiq->q1.cntl & QC_SG_HEAD) != 0) { + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { + if ((scsi_cmd == READ_6) || + (scsi_cmd == READ_10)) { + addr = + (ADV_PADDR)le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + addr) + + (ADV_DCNT)le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes); + extra_bytes = + (uchar)((ushort)addr & 0x0003); + if ((extra_bytes != 0) + && + ((scsiq->q2. + tag_code & + ASC_TAG_FLAG_EXTRA_BYTES) + == 0)) { + scsiq->q2.tag_code |= + ASC_TAG_FLAG_EXTRA_BYTES; + scsiq->q1.extra_bytes = + extra_bytes; + data_cnt = + le32_to_cpu(sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes); + data_cnt -= + (ASC_DCNT) extra_bytes; + sg_head-> + sg_list + [sg_entry_cnt_minus_one]. + bytes = + cpu_to_le32(data_cnt); + } + } + } + } + sg_head->entry_to_copy = sg_head->entry_cnt; +#if CC_VERY_LONG_SG_LIST + /* + * Set the sg_entry_cnt to the maximum possible. The rest of + * the SG elements will be copied when the RISC completes the + * SG elements that fit and halts. + */ + if (sg_entry_cnt > ASC_MAX_SG_LIST) { + sg_entry_cnt = ASC_MAX_SG_LIST; + } +#endif /* CC_VERY_LONG_SG_LIST */ + n_q_required = AscSgListToQueue(sg_entry_cnt); + if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, n_q_required) >= + (uint) n_q_required) + || ((scsiq->q1.cntl & QC_URGENT) != 0)) { + if ((sta = + AscSendScsiQueue(asc_dvc, scsiq, + n_q_required)) == 1) { + asc_dvc->in_critical_cnt--; + return (sta); + } + } + } else { + if (asc_dvc->bug_fix_cntl) { + if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_IF_NOT_DWB) { + if ((scsi_cmd == READ_6) || + (scsi_cmd == READ_10)) { + addr = + le32_to_cpu(scsiq->q1.data_addr) + + le32_to_cpu(scsiq->q1.data_cnt); + extra_bytes = + (uchar)((ushort)addr & 0x0003); + if ((extra_bytes != 0) + && + ((scsiq->q2. + tag_code & + ASC_TAG_FLAG_EXTRA_BYTES) + == 0)) { + data_cnt = + le32_to_cpu(scsiq->q1. + data_cnt); + if (((ushort)data_cnt & 0x01FF) + == 0) { + scsiq->q2.tag_code |= + ASC_TAG_FLAG_EXTRA_BYTES; + data_cnt -= (ASC_DCNT) + extra_bytes; + scsiq->q1.data_cnt = + cpu_to_le32 + (data_cnt); + scsiq->q1.extra_bytes = + extra_bytes; + } + } + } + } + } + n_q_required = 1; + if ((AscGetNumOfFreeQueue(asc_dvc, target_ix, 1) >= 1) || + ((scsiq->q1.cntl & QC_URGENT) != 0)) { + if ((sta = AscSendScsiQueue(asc_dvc, scsiq, + n_q_required)) == 1) { + asc_dvc->in_critical_cnt--; + return (sta); + } + } + } + asc_dvc->in_critical_cnt--; return (sta); } -static ushort AscInitLram(ASC_DVC_VAR *asc_dvc) +/* + * AdvExeScsiQueue() - Send a request to the RISC microcode program. + * + * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q, + * add the carrier to the ICQ (Initiator Command Queue), and tickle the + * RISC to notify it a new command is ready to be executed. + * + * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be + * set to SCSI_MAX_RETRY. + * + * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode + * for DMA addresses or math operations are byte swapped to little-endian + * order. + * + * Return: + * ADV_SUCCESS(1) - The request was successfully queued. + * ADV_BUSY(0) - Resource unavailable; Retry again after pending + * request completes. + * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure + * host IC error. + */ +static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) { - uchar i; - ushort s_addr; - PortAddr iop_base; - ushort warn_code; + AdvPortAddr iop_base; + ADV_PADDR req_paddr; + ADV_CARR_T *new_carrp; - iop_base = asc_dvc->iop_base; - warn_code = 0; - AscMemWordSetLram(iop_base, ASC_QADR_BEG, 0, - (ushort)(((int)(asc_dvc->max_total_qng + 2 + 1) * - 64) >> 1) - ); - i = ASC_MIN_ACTIVE_QNO; - s_addr = ASC_QADR_BEG + ASC_QBLK_SIZE; - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), - (uchar)(i + 1)); - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), - (uchar)(asc_dvc->max_total_qng)); - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), - (uchar)i); - i++; - s_addr += ASC_QBLK_SIZE; - for (; i < asc_dvc->max_total_qng; i++, s_addr += ASC_QBLK_SIZE) { - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), - (uchar)(i + 1)); - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), - (uchar)(i - 1)); - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), - (uchar)i); - } - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_FWD), - (uchar)ASC_QLINK_END); - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_BWD), - (uchar)(asc_dvc->max_total_qng - 1)); - AscWriteLramByte(iop_base, (ushort)(s_addr + ASC_SCSIQ_B_QNO), - (uchar)asc_dvc->max_total_qng); - i++; - s_addr += ASC_QBLK_SIZE; - for (; i <= (uchar)(asc_dvc->max_total_qng + 3); - i++, s_addr += ASC_QBLK_SIZE) { - AscWriteLramByte(iop_base, - (ushort)(s_addr + (ushort)ASC_SCSIQ_B_FWD), i); - AscWriteLramByte(iop_base, - (ushort)(s_addr + (ushort)ASC_SCSIQ_B_BWD), i); - AscWriteLramByte(iop_base, - (ushort)(s_addr + (ushort)ASC_SCSIQ_B_QNO), i); + /* + * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. + */ + if (scsiq->target_id > ADV_MAX_TID) { + scsiq->host_status = QHSTA_M_INVALID_DEVICE; + scsiq->done_status = QD_WITH_ERROR; + return ADV_ERROR; } - return (warn_code); -} - -static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc) -{ - PortAddr iop_base; - int i; - ushort lram_addr; iop_base = asc_dvc->iop_base; - AscPutRiscVarFreeQHead(iop_base, 1); - AscPutRiscVarDoneQTail(iop_base, asc_dvc->max_total_qng); - AscPutVarFreeQHead(iop_base, 1); - AscPutVarDoneQTail(iop_base, asc_dvc->max_total_qng); - AscWriteLramByte(iop_base, ASCV_BUSY_QHEAD_B, - (uchar)((int)asc_dvc->max_total_qng + 1)); - AscWriteLramByte(iop_base, ASCV_DISC1_QHEAD_B, - (uchar)((int)asc_dvc->max_total_qng + 2)); - AscWriteLramByte(iop_base, (ushort)ASCV_TOTAL_READY_Q_B, - asc_dvc->max_total_qng); - AscWriteLramWord(iop_base, ASCV_ASCDVC_ERR_CODE_W, 0); - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, 0); - AscWriteLramByte(iop_base, ASCV_SCSIBUSY_B, 0); - AscWriteLramByte(iop_base, ASCV_WTM_FLAG_B, 0); - AscPutQDoneInProgress(iop_base, 0); - lram_addr = ASC_QADR_BEG; - for (i = 0; i < 32; i++, lram_addr += 2) { - AscWriteLramWord(iop_base, lram_addr, 0); - } - return (0); -} -static int AscSetLibErrorCode(ASC_DVC_VAR *asc_dvc, ushort err_code) -{ - if (asc_dvc->err_code == 0) { - asc_dvc->err_code = err_code; - AscWriteLramWord(asc_dvc->iop_base, ASCV_ASCDVC_ERR_CODE_W, - err_code); + /* + * Allocate a carrier ensuring at least one carrier always + * remains on the freelist and initialize fields. + */ + if ((new_carrp = asc_dvc->carr_freelist) == NULL) { + return ADV_BUSY; } - return (err_code); -} + asc_dvc->carr_freelist = (ADV_CARR_T *) + ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa)); + asc_dvc->carr_pending_cnt++; -static uchar -AscMsgOutSDTR(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar sdtr_offset) -{ - EXT_MSG sdtr_buf; - uchar sdtr_period_index; - PortAddr iop_base; + /* + * Set the carrier to be a stopper by setting 'next_vpa' + * to the stopper value. The current stopper will be changed + * below to point to the new stopper. + */ + new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - iop_base = asc_dvc->iop_base; - sdtr_buf.msg_type = MS_EXTEND; - sdtr_buf.msg_len = MS_SDTR_LEN; - sdtr_buf.msg_req = MS_SDTR_CODE; - sdtr_buf.xfer_period = sdtr_period; - sdtr_offset &= ASC_SYN_MAX_OFFSET; - sdtr_buf.req_ack_offset = sdtr_offset; - if ((sdtr_period_index = - AscGetSynPeriodIndex(asc_dvc, sdtr_period)) <= - asc_dvc->max_sdtr_index) { - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *)&sdtr_buf, - sizeof(EXT_MSG) >> 1); - return ((sdtr_period_index << 4) | sdtr_offset); - } else { + /* + * Clear the ADV_SCSI_REQ_Q done flag. + */ + scsiq->a_flag &= ~ADV_SCSIQ_DONE; - sdtr_buf.req_ack_offset = 0; - AscMemWordCopyPtrToLram(iop_base, - ASCV_MSGOUT_BEG, - (uchar *)&sdtr_buf, - sizeof(EXT_MSG) >> 1); - return (0); - } -} + req_paddr = virt_to_bus(scsiq); + BUG_ON(req_paddr & 31); + /* Wait for assertion before making little-endian */ + req_paddr = cpu_to_le32(req_paddr); -static uchar -AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset) -{ - uchar byte; - uchar sdtr_period_ix; + /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */ + scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq)); + scsiq->scsiq_rptr = req_paddr; - sdtr_period_ix = AscGetSynPeriodIndex(asc_dvc, sdtr_period); - if ((sdtr_period_ix > asc_dvc->max_sdtr_index) - ) { - return (0xFF); - } - byte = (sdtr_period_ix << 4) | (syn_offset & ASC_SYN_MAX_OFFSET); - return (byte); -} + scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp)); + /* + * Every ADV_CARR_T.carr_pa is byte swapped to little-endian + * order during initialization. + */ + scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; -static void AscSetChipSDTR(PortAddr iop_base, uchar sdtr_data, uchar tid_no) -{ - AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); - AscPutMCodeSDTRDoneAtID(iop_base, tid_no, sdtr_data); - return; -} + /* + * Use the current stopper to send the ADV_SCSI_REQ_Q command to + * the microcode. The newly allocated stopper will become the new + * stopper. + */ + asc_dvc->icq_sp->areq_vpa = req_paddr; -static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) -{ - uchar *period_table; - int max_index; - int min_index; - int i; + /* + * Set the 'next_vpa' pointer for the old stopper to be the + * physical address of the new stopper. The RISC can only + * follow physical addresses. + */ + asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; - period_table = asc_dvc->sdtr_period_tbl; - max_index = (int)asc_dvc->max_sdtr_index; - min_index = (int)asc_dvc->host_init_sdtr_index; - if ((syn_time <= period_table[max_index])) { - for (i = min_index; i < (max_index - 1); i++) { - if (syn_time <= period_table[i]) { - return ((uchar)i); - } + /* + * Set the host adapter stopper pointer to point to the new carrier. + */ + asc_dvc->icq_sp = new_carrp; + + if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || + asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + /* + * Tickle the RISC to tell it to read its Command Queue Head pointer. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); + if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { + /* + * Clear the tickle value. In the ASC-3550 the RISC flag + * command 'clr_tickle_a' does not work unless the host + * value is cleared. + */ + AdvWriteByteRegister(iop_base, IOPB_TICKLE, + ADV_TICKLE_NOP); } - return ((uchar)max_index); - } else { - return ((uchar)(max_index + 1)); + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + /* + * Notify the RISC a carrier is ready by writing the physical + * address of the new carrier stopper to the COMMA register. + */ + AdvWriteDWordRegister(iop_base, IOPDW_COMMA, + le32_to_cpu(new_carrp->carr_pa)); } + + return ADV_SUCCESS; } -static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head) +/* + * Execute a single 'Scsi_Cmnd'. + */ +static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) { - ushort q_addr; - uchar next_qp; - uchar q_status; + int ret, err_code; + struct asc_board *boardp = shost_priv(scp->device->host); - q_addr = ASC_QNO_TO_QADDR(free_q_head); - q_status = (uchar)AscReadLramByte(iop_base, - (ushort)(q_addr + - ASC_SCSIQ_B_STATUS)); - next_qp = AscReadLramByte(iop_base, (ushort)(q_addr + ASC_SCSIQ_B_FWD)); - if (((q_status & QS_READY) == 0) && (next_qp != ASC_QLINK_END)) { - return (next_qp); - } - return (ASC_QLINK_END); -} + ASC_DBG(1, "scp 0x%p\n", scp); -static uchar -AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q) -{ - uchar i; + if (ASC_NARROW_BOARD(boardp)) { + ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; + struct asc_scsi_q asc_scsi_q; - for (i = 0; i < n_free_q; i++) { - if ((free_q_head = AscAllocFreeQueue(iop_base, free_q_head)) - == ASC_QLINK_END) { - return (ASC_QLINK_END); + /* asc_build_req() can not return ASC_BUSY. */ + ret = asc_build_req(boardp, scp, &asc_scsi_q); + if (ret == ASC_ERROR) { + ASC_STATS(scp->device->host, build_error); + return ASC_ERROR; } - } - return (free_q_head); -} -static int AscHostReqRiscHalt(PortAddr iop_base) -{ - int count = 0; - int sta = 0; - uchar saved_stop_code; + ret = AscExeScsiQueue(asc_dvc, &asc_scsi_q); + kfree(asc_scsi_q.sg_head); + err_code = asc_dvc->err_code; + } else { + ADV_DVC_VAR *adv_dvc = &boardp->dvc_var.adv_dvc_var; + ADV_SCSI_REQ_Q *adv_scsiqp; - if (AscIsChipHalted(iop_base)) - return (1); - saved_stop_code = AscReadLramByte(iop_base, ASCV_STOP_CODE_B); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_HOST_REQ_RISC_HALT | ASC_STOP_REQ_RISC_STOP); - do { - if (AscIsChipHalted(iop_base)) { - sta = 1; + switch (adv_build_req(boardp, scp, &adv_scsiqp)) { + case ASC_NOERROR: + ASC_DBG(3, "adv_build_req ASC_NOERROR\n"); break; + case ASC_BUSY: + ASC_DBG(1, "adv_build_req ASC_BUSY\n"); + /* + * The asc_stats fields 'adv_build_noreq' and + * 'adv_build_nosg' count wide board busy conditions. + * They are updated in adv_build_req and + * adv_get_sglist, respectively. + */ + return ASC_BUSY; + case ASC_ERROR: + default: + ASC_DBG(1, "adv_build_req ASC_ERROR\n"); + ASC_STATS(scp->device->host, build_error); + return ASC_ERROR; } - DvcSleepMilliSecond(100); - } while (count++ < 20); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); - return (sta); -} -static int AscStopQueueExe(PortAddr iop_base) -{ - int count = 0; + ret = AdvExeScsiQueue(adv_dvc, adv_scsiqp); + err_code = adv_dvc->err_code; + } - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, - ASC_STOP_REQ_RISC_STOP); - do { - if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & - ASC_STOP_ACK_RISC_STOP) { - return (1); - } - DvcSleepMilliSecond(100); - } while (count++ < 20); + switch (ret) { + case ASC_NOERROR: + ASC_STATS(scp->device->host, exe_noerror); + /* + * Increment monotonically increasing per device + * successful request counter. Wrapping doesn't matter. + */ + boardp->reqcnt[scp->device->id]++; + ASC_DBG(1, "ExeScsiQueue() ASC_NOERROR\n"); + break; + case ASC_BUSY: + ASC_STATS(scp->device->host, exe_busy); + break; + case ASC_ERROR: + scmd_printk(KERN_ERR, scp, "ExeScsiQueue() ASC_ERROR, " + "err_code 0x%x\n", err_code); + ASC_STATS(scp->device->host, exe_error); + scp->result = HOST_BYTE(DID_ERROR); + break; + default: + scmd_printk(KERN_ERR, scp, "ExeScsiQueue() unknown, " + "err_code 0x%x\n", err_code); + ASC_STATS(scp->device->host, exe_unknown); + scp->result = HOST_BYTE(DID_ERROR); + break; } - return (0); -} -static void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec) -{ - udelay(micro_sec); + ASC_DBG(1, "end\n"); + return ret; } -static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec) +/* + * advansys_queuecommand() - interrupt-driven I/O entrypoint. + * + * This function always returns 0. Command return status is saved + * in the 'scp' result field. + */ +static int +advansys_queuecommand(struct scsi_cmnd *scp, void (*done)(struct scsi_cmnd *)) { - udelay((nano_sec + 999) / 1000); -} + struct Scsi_Host *shost = scp->device->host; + int asc_res, result = 0; -#ifdef CONFIG_ISA -static ASC_DCNT __init AscGetEisaProductID(PortAddr iop_base) -{ - PortAddr eisa_iop; - ushort product_id_high, product_id_low; - ASC_DCNT product_id; - - eisa_iop = ASC_GET_EISA_SLOT(iop_base) | ASC_EISA_PID_IOP_MASK; - product_id_low = inpw(eisa_iop); - product_id_high = inpw(eisa_iop + 2); - product_id = ((ASC_DCNT) product_id_high << 16) | - (ASC_DCNT) product_id_low; - return (product_id); -} + ASC_STATS(shost, queuecommand); + scp->scsi_done = done; -static PortAddr __init AscSearchIOPortAddrEISA(PortAddr iop_base) -{ - ASC_DCNT eisa_product_id; + asc_res = asc_execute_scsi_cmnd(scp); - if (iop_base == 0) { - iop_base = ASC_EISA_MIN_IOP_ADDR; - } else { - if (iop_base == ASC_EISA_MAX_IOP_ADDR) - return (0); - if ((iop_base & 0x0050) == 0x0050) { - iop_base += ASC_EISA_BIG_IOP_GAP; - } else { - iop_base += ASC_EISA_SMALL_IOP_GAP; - } - } - while (iop_base <= ASC_EISA_MAX_IOP_ADDR) { - eisa_product_id = AscGetEisaProductID(iop_base); - if ((eisa_product_id == ASC_EISA_ID_740) || - (eisa_product_id == ASC_EISA_ID_750)) { - if (AscFindSignature(iop_base)) { - inpw(iop_base + 4); - return (iop_base); - } - } - if (iop_base == ASC_EISA_MAX_IOP_ADDR) - return (0); - if ((iop_base & 0x0050) == 0x0050) { - iop_base += ASC_EISA_BIG_IOP_GAP; - } else { - iop_base += ASC_EISA_SMALL_IOP_GAP; - } + switch (asc_res) { + case ASC_NOERROR: + break; + case ASC_BUSY: + result = SCSI_MLQUEUE_HOST_BUSY; + break; + case ASC_ERROR: + default: + asc_scsi_done(scp); + break; } - return (0); + + return result; } -#endif /* CONFIG_ISA */ -static int AscStartChip(PortAddr iop_base) +static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base) { - AscSetChipControl(iop_base, 0); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - return (0); - } - return (1); + PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) (ASC_EISA_CFG_IOP_MASK); + return inpw(eisa_cfg_iop); } -static int AscStopChip(PortAddr iop_base) +/* + * Return the BIOS address of the adapter at the specified + * I/O port and with the specified bus type. + */ +static unsigned short __devinit +AscGetChipBiosAddress(PortAddr iop_base, unsigned short bus_type) { - uchar cc_val; + unsigned short cfg_lsw; + unsigned short bios_addr; - cc_val = - AscGetChipControl(iop_base) & - (~(CC_SINGLE_STEP | CC_TEST | CC_DIAG)); - AscSetChipControl(iop_base, (uchar)(cc_val | CC_HALT)); - AscSetChipIH(iop_base, INS_HALT); - AscSetChipIH(iop_base, INS_RFLAG_WTM); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) == 0) { - return (0); - } - return (1); -} + /* + * The PCI BIOS is re-located by the motherboard BIOS. Because + * of this the driver can not determine where a PCI BIOS is + * loaded and executes. + */ + if (bus_type & ASC_IS_PCI) + return 0; -static int AscIsChipHalted(PortAddr iop_base) -{ - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { - return (1); - } + if ((bus_type & ASC_IS_EISA) != 0) { + cfg_lsw = AscGetEisaChipCfg(iop_base); + cfg_lsw &= 0x000F; + bios_addr = ASC_BIOS_MIN_ADDR + cfg_lsw * ASC_BIOS_BANK_SIZE; + return bios_addr; } - return (0); -} -static void AscSetChipIH(PortAddr iop_base, ushort ins_code) -{ - AscSetBank(iop_base, 1); - AscWriteChipIH(iop_base, ins_code); - AscSetBank(iop_base, 0); - return; + cfg_lsw = AscGetChipCfgLsw(iop_base); + + /* + * ISA PnP uses the top bit as the 32K BIOS flag + */ + if (bus_type == ASC_IS_ISAPNP) + cfg_lsw &= 0x7FFF; + bios_addr = ASC_BIOS_MIN_ADDR + (cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE; + return bios_addr; } -static void AscAckInterrupt(PortAddr iop_base) +static uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id) { - uchar host_flag; - uchar risc_flag; - ushort loop; + ushort cfg_lsw; - loop = 0; - do { - risc_flag = AscReadLramByte(iop_base, ASCV_RISC_FLAG_B); - if (loop++ > 0x7FFF) { - break; - } - } while ((risc_flag & ASC_RISC_FLAG_GEN_INT) != 0); - host_flag = - AscReadLramByte(iop_base, - ASCV_HOST_FLAG_B) & (~ASC_HOST_FLAG_ACK_INT); - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, - (uchar)(host_flag | ASC_HOST_FLAG_ACK_INT)); - AscSetChipStatus(iop_base, CIW_INT_ACK); - loop = 0; - while (AscGetChipStatus(iop_base) & CSW_INT_PENDING) { - AscSetChipStatus(iop_base, CIW_INT_ACK); - if (loop++ > 3) { - break; - } + if (AscGetChipScsiID(iop_base) == new_host_id) { + return (new_host_id); } - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); - return; + cfg_lsw = AscGetChipCfgLsw(iop_base); + cfg_lsw &= 0xF8FF; + cfg_lsw |= (ushort)((new_host_id & ASC_MAX_TID) << 8); + AscSetChipCfgLsw(iop_base, cfg_lsw); + return (AscGetChipScsiID(iop_base)); } -static void AscDisableInterrupt(PortAddr iop_base) +static unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base) { - ushort cfg; + unsigned char sc; - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); - return; + AscSetBank(iop_base, 1); + sc = inp(iop_base + IOP_REG_SC); + AscSetBank(iop_base, 0); + return sc; } -static void AscEnableInterrupt(PortAddr iop_base) +static unsigned char __devinit +AscGetChipVersion(PortAddr iop_base, unsigned short bus_type) { - ushort cfg; - - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); - return; + if (bus_type & ASC_IS_EISA) { + PortAddr eisa_iop; + unsigned char revision; + eisa_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) ASC_EISA_REV_IOP_MASK; + revision = inp(eisa_iop); + return ASC_CHIP_MIN_VER_EISA - 1 + revision; + } + return AscGetChipVerNo(iop_base); } -static void AscSetBank(PortAddr iop_base, uchar bank) +#ifdef CONFIG_ISA +static void __devinit AscEnableIsaDma(uchar dma_channel) { - uchar val; - - val = AscGetChipControl(iop_base) & - (~ - (CC_SINGLE_STEP | CC_TEST | CC_DIAG | CC_SCSI_RESET | - CC_CHIP_RESET)); - if (bank == 1) { - val |= CC_BANK_ONE; - } else if (bank == 2) { - val |= CC_DIAG | CC_BANK_ONE; - } else { - val &= ~CC_BANK_ONE; + if (dma_channel < 4) { + outp(0x000B, (ushort)(0xC0 | dma_channel)); + outp(0x000A, dma_channel); + } else if (dma_channel < 8) { + outp(0x00D6, (ushort)(0xC0 | (dma_channel - 4))); + outp(0x00D4, (ushort)(dma_channel - 4)); } - AscSetChipControl(iop_base, val); - return; } +#endif /* CONFIG_ISA */ -static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc) +static int AscStopQueueExe(PortAddr iop_base) { - PortAddr iop_base; - int i = 10; + int count = 0; - iop_base = asc_dvc->iop_base; - while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) - && (i-- > 0)) { - DvcSleepMilliSecond(100); + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) == 0) { + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, + ASC_STOP_REQ_RISC_STOP); + do { + if (AscReadLramByte(iop_base, ASCV_STOP_CODE_B) & + ASC_STOP_ACK_RISC_STOP) { + return (1); + } + mdelay(100); + } while (count++ < 20); } - AscStopChip(iop_base); - AscSetChipControl(iop_base, CC_CHIP_RESET | CC_SCSI_RESET | CC_HALT); - DvcDelayNanoSecond(asc_dvc, 60000); - AscSetChipIH(iop_base, INS_RFLAG_WTM); - AscSetChipIH(iop_base, INS_HALT); - AscSetChipControl(iop_base, CC_CHIP_RESET | CC_HALT); - AscSetChipControl(iop_base, CC_HALT); - DvcSleepMilliSecond(200); - AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); - AscSetChipStatus(iop_base, 0); - return (AscIsChipHalted(iop_base)); + return (0); } -static ASC_DCNT __init AscGetMaxDmaCount(ushort bus_type) +static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type) { if (bus_type & ASC_IS_ISA) - return (ASC_MAX_ISA_DMA_COUNT); + return ASC_MAX_ISA_DMA_COUNT; else if (bus_type & (ASC_IS_EISA | ASC_IS_VL)) - return (ASC_MAX_VL_DMA_COUNT); - return (ASC_MAX_PCI_DMA_COUNT); + return ASC_MAX_VL_DMA_COUNT; + return ASC_MAX_PCI_DMA_COUNT; } #ifdef CONFIG_ISA -static ushort __init AscGetIsaDmaChannel(PortAddr iop_base) +static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base) { ushort channel; @@ -10600,7 +11168,7 @@ static ushort __init AscGetIsaDmaChannel(PortAddr iop_base) return (channel + 4); } -static ushort __init AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) +static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) { ushort cfg_lsw; uchar value; @@ -10615,19 +11183,10 @@ static ushort __init AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) AscSetChipCfgLsw(iop_base, cfg_lsw); return (AscGetIsaDmaChannel(iop_base)); } - return (0); -} - -static uchar __init AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value) -{ - speed_value &= 0x07; - AscSetBank(iop_base, 1); - AscWriteChipDmaSpeed(iop_base, speed_value); - AscSetBank(iop_base, 0); - return (AscGetIsaDmaSpeed(iop_base)); + return 0; } -static uchar __init AscGetIsaDmaSpeed(PortAddr iop_base) +static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base) { uchar speed_value; @@ -10635,223 +11194,20 @@ static uchar __init AscGetIsaDmaSpeed(PortAddr iop_base) speed_value = AscReadChipDmaSpeed(iop_base); speed_value &= 0x07; AscSetBank(iop_base, 0); - return (speed_value); + return speed_value; } -#endif /* CONFIG_ISA */ -static ushort __init -AscReadPCIConfigWord(ASC_DVC_VAR *asc_dvc, ushort pci_config_offset) +static uchar __devinit AscSetIsaDmaSpeed(PortAddr iop_base, uchar speed_value) { - uchar lsb, msb; - - lsb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset); - msb = DvcReadPCIConfigByte(asc_dvc, pci_config_offset + 1); - return ((ushort)((msb << 8) | lsb)); -} - -static ushort __init AscInitGetConfig(ASC_DVC_VAR *asc_dvc) -{ - ushort warn_code; - PortAddr iop_base; - ushort PCIDeviceID; - ushort PCIVendorID; - uchar PCIRevisionID; - uchar prevCmdRegBits; - - warn_code = 0; - iop_base = asc_dvc->iop_base; - asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; - if (asc_dvc->err_code != 0) { - return (UW_ERR); - } - if (asc_dvc->bus_type == ASC_IS_PCI) { - PCIVendorID = AscReadPCIConfigWord(asc_dvc, - AscPCIConfigVendorIDRegister); - - PCIDeviceID = AscReadPCIConfigWord(asc_dvc, - AscPCIConfigDeviceIDRegister); - - PCIRevisionID = DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigRevisionIDRegister); - - if (PCIVendorID != PCI_VENDOR_ID_ASP) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - prevCmdRegBits = DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister); - - if ((prevCmdRegBits & AscPCICmdRegBits_IOMemBusMaster) != - AscPCICmdRegBits_IOMemBusMaster) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister, - (prevCmdRegBits | - AscPCICmdRegBits_IOMemBusMaster)); - - if ((DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister) - & AscPCICmdRegBits_IOMemBusMaster) - != AscPCICmdRegBits_IOMemBusMaster) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - if ((PCIDeviceID == PCI_DEVICE_ID_ASP_1200A) || - (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940)) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer, 0x00); - if (DvcReadPCIConfigByte - (asc_dvc, AscPCIConfigLatencyTimer) - != 0x00) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } else if (PCIDeviceID == PCI_DEVICE_ID_ASP_ABP940U) { - if (DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer) < - 0x20) { - DvcWritePCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer, - 0x20); - - if (DvcReadPCIConfigByte(asc_dvc, - AscPCIConfigLatencyTimer) - < 0x20) { - warn_code |= - ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - } - } - - if (AscFindSignature(iop_base)) { - warn_code |= AscInitAscDvcVar(asc_dvc); - warn_code |= AscInitFromEEP(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; - if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) { - asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; - } - } else { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } - return (warn_code); -} - -static ushort __init AscInitSetConfig(ASC_DVC_VAR *asc_dvc) -{ - ushort warn_code = 0; - - asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; - if (asc_dvc->err_code != 0) - return (UW_ERR); - if (AscFindSignature(asc_dvc->iop_base)) { - warn_code |= AscInitFromAscDvcVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; - } else { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } - return (warn_code); + speed_value &= 0x07; + AscSetBank(iop_base, 1); + AscWriteChipDmaSpeed(iop_base, speed_value); + AscSetBank(iop_base, 0); + return AscGetIsaDmaSpeed(iop_base); } - -static ushort __init AscInitFromAscDvcVar(ASC_DVC_VAR *asc_dvc) -{ - PortAddr iop_base; - ushort cfg_msw; - ushort warn_code; - ushort pci_device_id = 0; - - iop_base = asc_dvc->iop_base; -#ifdef CONFIG_PCI - if (asc_dvc->cfg->dev) - pci_device_id = to_pci_dev(asc_dvc->cfg->dev)->device; -#endif - warn_code = 0; - cfg_msw = AscGetChipCfgMsw(iop_base); - if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { - cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - warn_code |= ASC_WARN_CFG_MSW_RECOVER; - AscSetChipCfgMsw(iop_base, cfg_msw); - } - if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != - asc_dvc->cfg->cmd_qng_enabled) { - asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; - warn_code |= ASC_WARN_CMD_QNG_CONFLICT; - } - if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { - warn_code |= ASC_WARN_AUTO_CONFIG; - } - if ((asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL)) != 0) { - if (AscSetChipIRQ(iop_base, asc_dvc->irq_no, asc_dvc->bus_type) - != asc_dvc->irq_no) { - asc_dvc->err_code |= ASC_IERR_SET_IRQ_NO; - } - } - if (asc_dvc->bus_type & ASC_IS_PCI) { - cfg_msw &= 0xFFC0; - AscSetChipCfgMsw(iop_base, cfg_msw); - if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { - } else { - if ((pci_device_id == PCI_DEVICE_ID_ASP_1200A) || - (pci_device_id == PCI_DEVICE_ID_ASP_ABP940)) { - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; - asc_dvc->bug_fix_cntl |= - ASC_BUG_FIX_ASYN_USE_SYN; - } - } - } else if (asc_dvc->bus_type == ASC_IS_ISAPNP) { - if (AscGetChipVersion(iop_base, asc_dvc->bus_type) - == ASC_CHIP_VER_ASYN_BUG) { - asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; - } - } - if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != - asc_dvc->cfg->chip_scsi_id) { - asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; - } -#ifdef CONFIG_ISA - if (asc_dvc->bus_type & ASC_IS_ISA) { - AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); - AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); - } #endif /* CONFIG_ISA */ - return (warn_code); -} - -static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) -{ - ushort warn_code; - PortAddr iop_base; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - if ((asc_dvc->dvc_cntl & ASC_CNTL_RESET_SCSI) && - !(asc_dvc->init_state & ASC_INIT_RESET_SCSI_DONE)) { - AscResetChipAndScsiBus(asc_dvc); - DvcSleepMilliSecond((ASC_DCNT) - ((ushort)asc_dvc->scsi_reset_wait * 1000)); - } - asc_dvc->init_state |= ASC_INIT_STATE_BEG_LOAD_MC; - if (asc_dvc->err_code != 0) - return (UW_ERR); - if (!AscFindSignature(asc_dvc->iop_base)) { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - return (warn_code); - } - AscDisableInterrupt(iop_base); - warn_code |= AscInitLram(asc_dvc); - if (asc_dvc->err_code != 0) - return (UW_ERR); - ASC_DBG1(1, "AscInitAsc1000Driver: _asc_mcode_chksum 0x%lx\n", - (ulong)_asc_mcode_chksum); - if (AscLoadMicroCode(iop_base, 0, _asc_mcode_buf, - _asc_mcode_size) != _asc_mcode_chksum) { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return (warn_code); - } - warn_code |= AscInitMicroCodeVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; - AscEnableInterrupt(iop_base); - return (warn_code); -} -static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) +static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) { int i; PortAddr iop_base; @@ -10882,7 +11238,7 @@ static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) asc_dvc->queue_full_or_busy = 0; asc_dvc->redo_scam = 0; asc_dvc->res2 = 0; - asc_dvc->host_init_sdtr_index = 0; + asc_dvc->min_sdtr_index = 0; asc_dvc->cfg->can_tagged_qng = 0; asc_dvc->cfg->cmd_qng_enabled = 0; asc_dvc->dvc_cntl = ASC_DEF_DVC_CNTL; @@ -10894,39 +11250,14 @@ static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) asc_dvc->cfg->sdtr_enable = ASC_SCSI_WIDTH_BIT_SET; asc_dvc->cfg->disc_enable = ASC_SCSI_WIDTH_BIT_SET; asc_dvc->cfg->chip_scsi_id = ASC_DEF_CHIP_SCSI_ID; - asc_dvc->cfg->lib_serial_no = ASC_LIB_SERIAL_NUMBER; - asc_dvc->cfg->lib_version = (ASC_LIB_VERSION_MAJOR << 8) | - ASC_LIB_VERSION_MINOR; chip_version = AscGetChipVersion(iop_base, asc_dvc->bus_type); asc_dvc->cfg->chip_version = chip_version; - asc_dvc->sdtr_period_tbl[0] = SYN_XFER_NS_0; - asc_dvc->sdtr_period_tbl[1] = SYN_XFER_NS_1; - asc_dvc->sdtr_period_tbl[2] = SYN_XFER_NS_2; - asc_dvc->sdtr_period_tbl[3] = SYN_XFER_NS_3; - asc_dvc->sdtr_period_tbl[4] = SYN_XFER_NS_4; - asc_dvc->sdtr_period_tbl[5] = SYN_XFER_NS_5; - asc_dvc->sdtr_period_tbl[6] = SYN_XFER_NS_6; - asc_dvc->sdtr_period_tbl[7] = SYN_XFER_NS_7; + asc_dvc->sdtr_period_tbl = asc_syn_xfer_period; asc_dvc->max_sdtr_index = 7; if ((asc_dvc->bus_type & ASC_IS_PCI) && (chip_version >= ASC_CHIP_VER_PCI_ULTRA_3150)) { asc_dvc->bus_type = ASC_IS_PCI_ULTRA; - asc_dvc->sdtr_period_tbl[0] = SYN_ULTRA_XFER_NS_0; - asc_dvc->sdtr_period_tbl[1] = SYN_ULTRA_XFER_NS_1; - asc_dvc->sdtr_period_tbl[2] = SYN_ULTRA_XFER_NS_2; - asc_dvc->sdtr_period_tbl[3] = SYN_ULTRA_XFER_NS_3; - asc_dvc->sdtr_period_tbl[4] = SYN_ULTRA_XFER_NS_4; - asc_dvc->sdtr_period_tbl[5] = SYN_ULTRA_XFER_NS_5; - asc_dvc->sdtr_period_tbl[6] = SYN_ULTRA_XFER_NS_6; - asc_dvc->sdtr_period_tbl[7] = SYN_ULTRA_XFER_NS_7; - asc_dvc->sdtr_period_tbl[8] = SYN_ULTRA_XFER_NS_8; - asc_dvc->sdtr_period_tbl[9] = SYN_ULTRA_XFER_NS_9; - asc_dvc->sdtr_period_tbl[10] = SYN_ULTRA_XFER_NS_10; - asc_dvc->sdtr_period_tbl[11] = SYN_ULTRA_XFER_NS_11; - asc_dvc->sdtr_period_tbl[12] = SYN_ULTRA_XFER_NS_12; - asc_dvc->sdtr_period_tbl[13] = SYN_ULTRA_XFER_NS_13; - asc_dvc->sdtr_period_tbl[14] = SYN_ULTRA_XFER_NS_14; - asc_dvc->sdtr_period_tbl[15] = SYN_ULTRA_XFER_NS_15; + asc_dvc->sdtr_period_tbl = asc_syn_ultra_xfer_period; asc_dvc->max_sdtr_index = 15; if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) { AscSetExtraControl(iop_base, @@ -10943,12 +11274,12 @@ static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) } asc_dvc->cfg->isa_dma_speed = ASC_DEF_ISA_DMA_SPEED; - if (AscGetChipBusType(iop_base) == ASC_IS_ISAPNP) { - AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); - asc_dvc->bus_type = ASC_IS_ISAPNP; - } #ifdef CONFIG_ISA if ((asc_dvc->bus_type & ASC_IS_ISA) != 0) { + if (chip_version >= ASC_CHIP_MIN_VER_ISA_PNP) { + AscSetChipIFC(iop_base, IFC_INIT_DEFAULT); + asc_dvc->bus_type = ASC_IS_ISAPNP; + } asc_dvc->cfg->isa_dma_channel = (uchar)AscGetIsaDmaChannel(iop_base); } @@ -10960,231 +11291,92 @@ static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) asc_dvc->scsiq_busy_tail[i] = (ASC_SCSI_Q *)0L; asc_dvc->cfg->max_tag_qng[i] = ASC_MAX_INRAM_TAG_QNG; } - return (warn_code); + return warn_code; } -static ushort __init AscInitFromEEP(ASC_DVC_VAR *asc_dvc) +static int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg) { - ASCEEP_CONFIG eep_config_buf; - ASCEEP_CONFIG *eep_config; - PortAddr iop_base; - ushort chksum; - ushort warn_code; - ushort cfg_msw, cfg_lsw; - int i; - int write_eep = 0; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); - AscStopQueueExe(iop_base); - if ((AscStopChip(iop_base) == FALSE) || - (AscGetChipScsiCtrl(iop_base) != 0)) { - asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; - AscResetChipAndScsiBus(asc_dvc); - DvcSleepMilliSecond((ASC_DCNT) - ((ushort)asc_dvc->scsi_reset_wait * 1000)); - } - if (AscIsChipHalted(iop_base) == FALSE) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return (warn_code); - } - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; - return (warn_code); - } - eep_config = (ASCEEP_CONFIG *)&eep_config_buf; - cfg_msw = AscGetChipCfgMsw(iop_base); - cfg_lsw = AscGetChipCfgLsw(iop_base); - if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { - cfg_msw &= (~(ASC_CFG_MSW_CLR_MASK)); - warn_code |= ASC_WARN_CFG_MSW_RECOVER; - AscSetChipCfgMsw(iop_base, cfg_msw); - } - chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); - ASC_DBG1(1, "AscInitFromEEP: chksum 0x%x\n", chksum); - if (chksum == 0) { - chksum = 0xaa55; - } - if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { - warn_code |= ASC_WARN_AUTO_CONFIG; - if (asc_dvc->cfg->chip_version == 3) { - if (eep_config->cfg_lsw != cfg_lsw) { - warn_code |= ASC_WARN_EEPROM_RECOVER; - eep_config->cfg_lsw = - AscGetChipCfgLsw(iop_base); - } - if (eep_config->cfg_msw != cfg_msw) { - warn_code |= ASC_WARN_EEPROM_RECOVER; - eep_config->cfg_msw = - AscGetChipCfgMsw(iop_base); - } - } - } - eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; - eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; - ASC_DBG1(1, "AscInitFromEEP: eep_config->chksum 0x%x\n", - eep_config->chksum); - if (chksum != eep_config->chksum) { - if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == - ASC_CHIP_VER_PCI_ULTRA_3050) { - ASC_DBG(1, - "AscInitFromEEP: chksum error ignored; EEPROM-less board\n"); - eep_config->init_sdtr = 0xFF; - eep_config->disc_enable = 0xFF; - eep_config->start_motor = 0xFF; - eep_config->use_cmd_qng = 0; - eep_config->max_total_qng = 0xF0; - eep_config->max_tag_qng = 0x20; - eep_config->cntl = 0xBFFF; - ASC_EEP_SET_CHIP_ID(eep_config, 7); - eep_config->no_scam = 0; - eep_config->adapter_info[0] = 0; - eep_config->adapter_info[1] = 0; - eep_config->adapter_info[2] = 0; - eep_config->adapter_info[3] = 0; - eep_config->adapter_info[4] = 0; - /* Indicate EEPROM-less board. */ - eep_config->adapter_info[5] = 0xBB; - } else { - ASC_PRINT - ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n"); - write_eep = 1; - warn_code |= ASC_WARN_EEPROM_CHKSUM; - } - } - asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr; - asc_dvc->cfg->disc_enable = eep_config->disc_enable; - asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; - asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config); - asc_dvc->start_motor = eep_config->start_motor; - asc_dvc->dvc_cntl = eep_config->cntl; - asc_dvc->no_scam = eep_config->no_scam; - asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; - asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; - asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; - asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; - asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; - asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; - if (!AscTestExternalLram(asc_dvc)) { - if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == - ASC_IS_PCI_ULTRA)) { - eep_config->max_total_qng = - ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; - eep_config->max_tag_qng = - ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; - } else { - eep_config->cfg_msw |= 0x0800; - cfg_msw |= 0x0800; - AscSetChipCfgMsw(iop_base, cfg_msw); - eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; - eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; - } - } else { - } - if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { - eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; - } - if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { - eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; - } - if (eep_config->max_tag_qng > eep_config->max_total_qng) { - eep_config->max_tag_qng = eep_config->max_total_qng; - } - if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { - eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; - } - asc_dvc->max_total_qng = eep_config->max_total_qng; - if ((eep_config->use_cmd_qng & eep_config->disc_enable) != - eep_config->use_cmd_qng) { - eep_config->disc_enable = eep_config->use_cmd_qng; - warn_code |= ASC_WARN_CMD_QNG_CONFLICT; - } - if (asc_dvc->bus_type & (ASC_IS_ISA | ASC_IS_VL | ASC_IS_EISA)) { - asc_dvc->irq_no = AscGetChipIRQ(iop_base, asc_dvc->bus_type); - } - ASC_EEP_SET_CHIP_ID(eep_config, - ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID); - asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config); - if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && - !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { - asc_dvc->host_init_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; - } + int retry; - for (i = 0; i <= ASC_MAX_TID; i++) { - asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; - asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; - asc_dvc->cfg->sdtr_period_offset[i] = - (uchar)(ASC_DEF_SDTR_OFFSET | - (asc_dvc->host_init_sdtr_index << 4)); - } - eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); - if (write_eep) { - if ((i = - AscSetEEPConfig(iop_base, eep_config, - asc_dvc->bus_type)) != 0) { - ASC_PRINT1 - ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", - i); - } else { - ASC_PRINT - ("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); - } + for (retry = 0; retry < ASC_EEP_MAX_RETRY; retry++) { + unsigned char read_back; + AscSetChipEEPCmd(iop_base, cmd_reg); + mdelay(1); + read_back = AscGetChipEEPCmd(iop_base); + if (read_back == cmd_reg) + return 1; } - return (warn_code); + return 0; } -static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) +static void __devinit AscWaitEEPRead(void) { - int i; - ushort warn_code; - PortAddr iop_base; - ASC_PADDR phy_addr; - ASC_DCNT phy_size; - - iop_base = asc_dvc->iop_base; - warn_code = 0; - for (i = 0; i <= ASC_MAX_TID; i++) { - AscPutMCodeInitSDTRAtID(iop_base, i, - asc_dvc->cfg->sdtr_period_offset[i] - ); - } + mdelay(1); +} - AscInitQLinkVar(asc_dvc); - AscWriteLramByte(iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(iop_base, ASCV_HOSTSCSI_ID_B, - ASC_TID_TO_TARGET_ID(asc_dvc->cfg->chip_scsi_id)); +static ushort __devinit AscReadEEPWord(PortAddr iop_base, uchar addr) +{ + ushort read_wval; + uchar cmd_reg; - /* Align overrun buffer on an 8 byte boundary. */ - phy_addr = virt_to_bus(asc_dvc->cfg->overrun_buf); - phy_addr = cpu_to_le32((phy_addr + 7) & ~0x7); - AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, - (uchar *)&phy_addr, 1); - phy_size = cpu_to_le32(ASC_OVERRUN_BSIZE - 8); - AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_BSIZE_D, - (uchar *)&phy_size, 1); + AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); + AscWaitEEPRead(); + cmd_reg = addr | ASC_EEP_CMD_READ; + AscWriteEEPCmdReg(iop_base, cmd_reg); + AscWaitEEPRead(); + read_wval = AscGetChipEEPData(iop_base); + AscWaitEEPRead(); + return read_wval; +} - asc_dvc->cfg->mcode_date = - AscReadLramWord(iop_base, (ushort)ASCV_MC_DATE_W); - asc_dvc->cfg->mcode_version = - AscReadLramWord(iop_base, (ushort)ASCV_MC_VER_W); +static ushort __devinit +AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) +{ + ushort wval; + ushort sum; + ushort *wbuf; + int cfg_beg; + int cfg_end; + int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; + int s_addr; - AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); - if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { - asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; - return (warn_code); + wbuf = (ushort *)cfg_buf; + sum = 0; + /* Read two config words; Byte-swapping done by AscReadEEPWord(). */ + for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { + *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); + sum += *wbuf; } - if (AscStartChip(iop_base) != 1) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return (warn_code); + if (bus_type & ASC_IS_VL) { + cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; + cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; + } else { + cfg_beg = ASC_EEP_DVC_CFG_BEG; + cfg_end = ASC_EEP_MAX_DVC_ADDR; } - - return (warn_code); + for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { + wval = AscReadEEPWord(iop_base, (uchar)s_addr); + if (s_addr <= uchar_end_in_config) { + /* + * Swap all char fields - must unswap bytes already swapped + * by AscReadEEPWord(). + */ + *wbuf = le16_to_cpu(wval); + } else { + /* Don't swap word field at the end - cntl field. */ + *wbuf = wval; + } + sum += wval; /* Checksum treats all EEPROM data as words. */ + } + /* + * Read the checksum word which will be compared against 'sum' + * by the caller. Word field already swapped. + */ + *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); + return sum; } -static int __init AscTestExternalLram(ASC_DVC_VAR *asc_dvc) +static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc) { PortAddr iop_base; ushort q_addr; @@ -11197,7 +11389,7 @@ static int __init AscTestExternalLram(ASC_DVC_VAR *asc_dvc) saved_word = AscReadLramWord(iop_base, q_addr); AscSetChipLramAddr(iop_base, q_addr); AscSetChipLramData(iop_base, 0x55AA); - DvcSleepMilliSecond(10); + mdelay(10); AscSetChipLramAddr(iop_base, q_addr); if (AscGetChipLramData(iop_base) == 0x55AA) { sta = 1; @@ -11206,26 +11398,12 @@ static int __init AscTestExternalLram(ASC_DVC_VAR *asc_dvc) return (sta); } -static int __init AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg) +static void __devinit AscWaitEEPWrite(void) { - uchar read_back; - int retry; - - retry = 0; - while (TRUE) { - AscSetChipEEPCmd(iop_base, cmd_reg); - DvcSleepMilliSecond(1); - read_back = AscGetChipEEPCmd(iop_base); - if (read_back == cmd_reg) { - return (1); - } - if (retry++ > ASC_EEP_MAX_RETRY) { - return (0); - } - } + mdelay(20); } -static int __init AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) +static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) { ushort read_back; int retry; @@ -11233,7 +11411,7 @@ static int __init AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) retry = 0; while (TRUE) { AscSetChipEEPData(iop_base, data_reg); - DvcSleepMilliSecond(1); + mdelay(1); read_back = AscGetChipEEPData(iop_base); if (read_back == data_reg) { return (1); @@ -11244,34 +11422,7 @@ static int __init AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) } } -static void __init AscWaitEEPRead(void) -{ - DvcSleepMilliSecond(1); - return; -} - -static void __init AscWaitEEPWrite(void) -{ - DvcSleepMilliSecond(20); - return; -} - -static ushort __init AscReadEEPWord(PortAddr iop_base, uchar addr) -{ - ushort read_wval; - uchar cmd_reg; - - AscWriteEEPCmdReg(iop_base, ASC_EEP_CMD_WRITE_DISABLE); - AscWaitEEPRead(); - cmd_reg = addr | ASC_EEP_CMD_READ; - AscWriteEEPCmdReg(iop_base, cmd_reg); - AscWaitEEPRead(); - read_wval = AscGetChipEEPData(iop_base); - AscWaitEEPRead(); - return (read_wval); -} - -static ushort __init +static ushort __devinit AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val) { ushort read_wval; @@ -11292,54 +11443,7 @@ AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val) return (read_wval); } -static ushort __init -AscGetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) -{ - ushort wval; - ushort sum; - ushort *wbuf; - int cfg_beg; - int cfg_end; - int uchar_end_in_config = ASC_EEP_MAX_DVC_ADDR - 2; - int s_addr; - - wbuf = (ushort *)cfg_buf; - sum = 0; - /* Read two config words; Byte-swapping done by AscReadEEPWord(). */ - for (s_addr = 0; s_addr < 2; s_addr++, wbuf++) { - *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); - sum += *wbuf; - } - if (bus_type & ASC_IS_VL) { - cfg_beg = ASC_EEP_DVC_CFG_BEG_VL; - cfg_end = ASC_EEP_MAX_DVC_ADDR_VL; - } else { - cfg_beg = ASC_EEP_DVC_CFG_BEG; - cfg_end = ASC_EEP_MAX_DVC_ADDR; - } - for (s_addr = cfg_beg; s_addr <= (cfg_end - 1); s_addr++, wbuf++) { - wval = AscReadEEPWord(iop_base, (uchar)s_addr); - if (s_addr <= uchar_end_in_config) { - /* - * Swap all char fields - must unswap bytes already swapped - * by AscReadEEPWord(). - */ - *wbuf = le16_to_cpu(wval); - } else { - /* Don't swap word field at the end - cntl field. */ - *wbuf = wval; - } - sum += wval; /* Checksum treats all EEPROM data as words. */ - } - /* - * Read the checksum word which will be compared against 'sum' - * by the caller. Word field already swapped. - */ - *wbuf = AscReadEEPWord(iop_base, (uchar)s_addr); - return (sum); -} - -static int __init +static int __devinit AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { int n_error; @@ -11432,10 +11536,10 @@ AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) if (AscReadEEPWord(iop_base, (uchar)s_addr) != sum) { n_error++; } - return (n_error); + return n_error; } -static int __init +static int __devinit AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { int retry; @@ -11451,2386 +11555,326 @@ AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) break; } } - return (n_error); + return n_error; } -static void -AscAsyncFix(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq) +static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc) { - uchar dvc_type; - ASC_SCSI_BIT_ID_TYPE tid_bits; - - dvc_type = ASC_INQ_DVC_TYPE(inq); - tid_bits = ASC_TIX_TO_TARGET_ID(tid_no); - - if (asc_dvc->bug_fix_cntl & ASC_BUG_FIX_ASYN_USE_SYN) { - if (!(asc_dvc->init_sdtr & tid_bits)) { - if ((dvc_type == TYPE_ROM) && - (AscCompareString((uchar *)inq->vendor_id, - (uchar *)"HP ", 3) == 0)) { - asc_dvc->pci_fix_asyn_xfer_always |= tid_bits; - } - asc_dvc->pci_fix_asyn_xfer |= tid_bits; - if ((dvc_type == TYPE_PROCESSOR) || - (dvc_type == TYPE_SCANNER) || - (dvc_type == TYPE_ROM) || (dvc_type == TYPE_TAPE)) { - asc_dvc->pci_fix_asyn_xfer &= ~tid_bits; - } + ASCEEP_CONFIG eep_config_buf; + ASCEEP_CONFIG *eep_config; + PortAddr iop_base; + ushort chksum; + ushort warn_code; + ushort cfg_msw, cfg_lsw; + int i; + int write_eep = 0; - if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { - AscSetRunChipSynRegAtID(asc_dvc->iop_base, - tid_no, - ASYN_SDTR_DATA_FIX_PCI_REV_AB); + iop_base = asc_dvc->iop_base; + warn_code = 0; + AscWriteLramWord(iop_base, ASCV_HALTCODE_W, 0x00FE); + AscStopQueueExe(iop_base); + if ((AscStopChip(iop_base) == FALSE) || + (AscGetChipScsiCtrl(iop_base) != 0)) { + asc_dvc->init_state |= ASC_INIT_RESET_SCSI_DONE; + AscResetChipAndScsiBus(asc_dvc); + mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ + } + if (AscIsChipHalted(iop_base) == FALSE) { + asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; + return (warn_code); + } + AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); + if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { + asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; + return (warn_code); + } + eep_config = (ASCEEP_CONFIG *)&eep_config_buf; + cfg_msw = AscGetChipCfgMsw(iop_base); + cfg_lsw = AscGetChipCfgLsw(iop_base); + if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { + cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; + warn_code |= ASC_WARN_CFG_MSW_RECOVER; + AscSetChipCfgMsw(iop_base, cfg_msw); + } + chksum = AscGetEEPConfig(iop_base, eep_config, asc_dvc->bus_type); + ASC_DBG(1, "chksum 0x%x\n", chksum); + if (chksum == 0) { + chksum = 0xaa55; + } + if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { + warn_code |= ASC_WARN_AUTO_CONFIG; + if (asc_dvc->cfg->chip_version == 3) { + if (eep_config->cfg_lsw != cfg_lsw) { + warn_code |= ASC_WARN_EEPROM_RECOVER; + eep_config->cfg_lsw = + AscGetChipCfgLsw(iop_base); + } + if (eep_config->cfg_msw != cfg_msw) { + warn_code |= ASC_WARN_EEPROM_RECOVER; + eep_config->cfg_msw = + AscGetChipCfgMsw(iop_base); } } } - return; -} - -static int AscTagQueuingSafe(ASC_SCSI_INQUIRY *inq) -{ - if ((inq->add_len >= 32) && - (AscCompareString((uchar *)inq->vendor_id, - (uchar *)"QUANTUM XP34301", 15) == 0) && - (AscCompareString((uchar *)inq->product_rev_level, - (uchar *)"1071", 4) == 0)) { - return 0; - } - return 1; -} - -static void -AscInquiryHandling(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq) -{ - ASC_SCSI_BIT_ID_TYPE tid_bit = ASC_TIX_TO_TARGET_ID(tid_no); - ASC_SCSI_BIT_ID_TYPE orig_init_sdtr, orig_use_tagged_qng; - - orig_init_sdtr = asc_dvc->init_sdtr; - orig_use_tagged_qng = asc_dvc->use_tagged_qng; - - asc_dvc->init_sdtr &= ~tid_bit; - asc_dvc->cfg->can_tagged_qng &= ~tid_bit; - asc_dvc->use_tagged_qng &= ~tid_bit; - - if (ASC_INQ_RESPONSE_FMT(inq) >= 2 || ASC_INQ_ANSI_VER(inq) >= 2) { - if ((asc_dvc->cfg->sdtr_enable & tid_bit) && ASC_INQ_SYNC(inq)) { - asc_dvc->init_sdtr |= tid_bit; + eep_config->cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; + eep_config->cfg_lsw |= ASC_CFG0_HOST_INT_ON; + ASC_DBG(1, "eep_config->chksum 0x%x\n", eep_config->chksum); + if (chksum != eep_config->chksum) { + if (AscGetChipVersion(iop_base, asc_dvc->bus_type) == + ASC_CHIP_VER_PCI_ULTRA_3050) { + ASC_DBG(1, "chksum error ignored; EEPROM-less board\n"); + eep_config->init_sdtr = 0xFF; + eep_config->disc_enable = 0xFF; + eep_config->start_motor = 0xFF; + eep_config->use_cmd_qng = 0; + eep_config->max_total_qng = 0xF0; + eep_config->max_tag_qng = 0x20; + eep_config->cntl = 0xBFFF; + ASC_EEP_SET_CHIP_ID(eep_config, 7); + eep_config->no_scam = 0; + eep_config->adapter_info[0] = 0; + eep_config->adapter_info[1] = 0; + eep_config->adapter_info[2] = 0; + eep_config->adapter_info[3] = 0; + eep_config->adapter_info[4] = 0; + /* Indicate EEPROM-less board. */ + eep_config->adapter_info[5] = 0xBB; + } else { + ASC_PRINT + ("AscInitFromEEP: EEPROM checksum error; Will try to re-write EEPROM.\n"); + write_eep = 1; + warn_code |= ASC_WARN_EEPROM_CHKSUM; } - if ((asc_dvc->cfg->cmd_qng_enabled & tid_bit) && - ASC_INQ_CMD_QUEUE(inq)) { - if (AscTagQueuingSafe(inq)) { - asc_dvc->use_tagged_qng |= tid_bit; - asc_dvc->cfg->can_tagged_qng |= tid_bit; - } + } + asc_dvc->cfg->sdtr_enable = eep_config->init_sdtr; + asc_dvc->cfg->disc_enable = eep_config->disc_enable; + asc_dvc->cfg->cmd_qng_enabled = eep_config->use_cmd_qng; + asc_dvc->cfg->isa_dma_speed = ASC_EEP_GET_DMA_SPD(eep_config); + asc_dvc->start_motor = eep_config->start_motor; + asc_dvc->dvc_cntl = eep_config->cntl; + asc_dvc->no_scam = eep_config->no_scam; + asc_dvc->cfg->adapter_info[0] = eep_config->adapter_info[0]; + asc_dvc->cfg->adapter_info[1] = eep_config->adapter_info[1]; + asc_dvc->cfg->adapter_info[2] = eep_config->adapter_info[2]; + asc_dvc->cfg->adapter_info[3] = eep_config->adapter_info[3]; + asc_dvc->cfg->adapter_info[4] = eep_config->adapter_info[4]; + asc_dvc->cfg->adapter_info[5] = eep_config->adapter_info[5]; + if (!AscTestExternalLram(asc_dvc)) { + if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == + ASC_IS_PCI_ULTRA)) { + eep_config->max_total_qng = + ASC_MAX_PCI_ULTRA_INRAM_TOTAL_QNG; + eep_config->max_tag_qng = + ASC_MAX_PCI_ULTRA_INRAM_TAG_QNG; + } else { + eep_config->cfg_msw |= 0x0800; + cfg_msw |= 0x0800; + AscSetChipCfgMsw(iop_base, cfg_msw); + eep_config->max_total_qng = ASC_MAX_PCI_INRAM_TOTAL_QNG; + eep_config->max_tag_qng = ASC_MAX_INRAM_TAG_QNG; } + } else { } - if (orig_use_tagged_qng != asc_dvc->use_tagged_qng) { - AscWriteLramByte(asc_dvc->iop_base, ASCV_DISC_ENABLE_B, - asc_dvc->cfg->disc_enable); - AscWriteLramByte(asc_dvc->iop_base, ASCV_USE_TAGGED_QNG_B, - asc_dvc->use_tagged_qng); - AscWriteLramByte(asc_dvc->iop_base, ASCV_CAN_TAGGED_QNG_B, - asc_dvc->cfg->can_tagged_qng); - - asc_dvc->max_dvc_qng[tid_no] = - asc_dvc->cfg->max_tag_qng[tid_no]; - AscWriteLramByte(asc_dvc->iop_base, - (ushort)(ASCV_MAX_DVC_QNG_BEG + tid_no), - asc_dvc->max_dvc_qng[tid_no]); + if (eep_config->max_total_qng < ASC_MIN_TOTAL_QNG) { + eep_config->max_total_qng = ASC_MIN_TOTAL_QNG; } - if (orig_init_sdtr != asc_dvc->init_sdtr) { - AscAsyncFix(asc_dvc, tid_no, inq); + if (eep_config->max_total_qng > ASC_MAX_TOTAL_QNG) { + eep_config->max_total_qng = ASC_MAX_TOTAL_QNG; } - return; -} - -static int AscCompareString(uchar *str1, uchar *str2, int len) -{ - int i; - int diff; - - for (i = 0; i < len; i++) { - diff = (int)(str1[i] - str2[i]); - if (diff != 0) - return (diff); + if (eep_config->max_tag_qng > eep_config->max_total_qng) { + eep_config->max_tag_qng = eep_config->max_total_qng; } - return (0); -} - -static uchar AscReadLramByte(PortAddr iop_base, ushort addr) -{ - uchar byte_data; - ushort word_data; - - if (isodd_word(addr)) { - AscSetChipLramAddr(iop_base, addr - 1); - word_data = AscGetChipLramData(iop_base); - byte_data = (uchar)((word_data >> 8) & 0xFF); - } else { - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - byte_data = (uchar)(word_data & 0xFF); + if (eep_config->max_tag_qng < ASC_MIN_TAG_Q_PER_DVC) { + eep_config->max_tag_qng = ASC_MIN_TAG_Q_PER_DVC; + } + asc_dvc->max_total_qng = eep_config->max_total_qng; + if ((eep_config->use_cmd_qng & eep_config->disc_enable) != + eep_config->use_cmd_qng) { + eep_config->disc_enable = eep_config->use_cmd_qng; + warn_code |= ASC_WARN_CMD_QNG_CONFLICT; + } + ASC_EEP_SET_CHIP_ID(eep_config, + ASC_EEP_GET_CHIP_ID(eep_config) & ASC_MAX_TID); + asc_dvc->cfg->chip_scsi_id = ASC_EEP_GET_CHIP_ID(eep_config); + if (((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) && + !(asc_dvc->dvc_cntl & ASC_CNTL_SDTR_ENABLE_ULTRA)) { + asc_dvc->min_sdtr_index = ASC_SDTR_ULTRA_PCI_10MB_INDEX; } - return (byte_data); -} - -static ushort AscReadLramWord(PortAddr iop_base, ushort addr) -{ - ushort word_data; - - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - return (word_data); -} - -#if CC_VERY_LONG_SG_LIST -static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr) -{ - ushort val_low, val_high; - ASC_DCNT dword_data; - AscSetChipLramAddr(iop_base, addr); - val_low = AscGetChipLramData(iop_base); - val_high = AscGetChipLramData(iop_base); - dword_data = ((ASC_DCNT) val_high << 16) | (ASC_DCNT) val_low; - return (dword_data); + for (i = 0; i <= ASC_MAX_TID; i++) { + asc_dvc->dos_int13_table[i] = eep_config->dos_int13_table[i]; + asc_dvc->cfg->max_tag_qng[i] = eep_config->max_tag_qng; + asc_dvc->cfg->sdtr_period_offset[i] = + (uchar)(ASC_DEF_SDTR_OFFSET | + (asc_dvc->min_sdtr_index << 4)); + } + eep_config->cfg_msw = AscGetChipCfgMsw(iop_base); + if (write_eep) { + if ((i = AscSetEEPConfig(iop_base, eep_config, + asc_dvc->bus_type)) != 0) { + ASC_PRINT1 + ("AscInitFromEEP: Failed to re-write EEPROM with %d errors.\n", + i); + } else { + ASC_PRINT + ("AscInitFromEEP: Successfully re-wrote EEPROM.\n"); + } + } + return (warn_code); } -#endif /* CC_VERY_LONG_SG_LIST */ -static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val) +static int __devinit AscInitGetConfig(struct Scsi_Host *shost) { - AscSetChipLramAddr(iop_base, addr); - AscSetChipLramData(iop_base, word_val); - return; -} + struct asc_board *board = shost_priv(shost); + ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var; + unsigned short warn_code = 0; -static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val) -{ - ushort word_data; + asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; + if (asc_dvc->err_code != 0) + return asc_dvc->err_code; - if (isodd_word(addr)) { - addr--; - word_data = AscReadLramWord(iop_base, addr); - word_data &= 0x00FF; - word_data |= (((ushort)byte_val << 8) & 0xFF00); + if (AscFindSignature(asc_dvc->iop_base)) { + warn_code |= AscInitAscDvcVar(asc_dvc); + warn_code |= AscInitFromEEP(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_GET_CFG; + if (asc_dvc->scsi_reset_wait > ASC_MAX_SCSI_RESET_WAIT) + asc_dvc->scsi_reset_wait = ASC_MAX_SCSI_RESET_WAIT; } else { - word_data = AscReadLramWord(iop_base, addr); - word_data &= 0xFF00; - word_data |= ((ushort)byte_val & 0x00FF); + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; } - AscWriteLramWord(iop_base, addr, word_data); - return; -} -/* - * Copy 2 bytes to LRAM. - * - * The source data is assumed to be in little-endian order in memory - * 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) -{ - int i; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - /* - * On a little-endian system the second argument below - * produces a little-endian ushort which is written to - * LRAM in little-endian order. On a big-endian system - * the second argument produces a big-endian ushort which - * is "transparently" byte-swapped by outpw() and written - * in little-endian order to LRAM. - */ - outpw(iop_base + IOP_RAM_DATA, - ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); + switch (warn_code) { + case 0: /* No error */ + break; + case ASC_WARN_IO_PORT_ROTATE: + shost_printk(KERN_WARNING, shost, "I/O port address " + "modified\n"); + break; + case ASC_WARN_AUTO_CONFIG: + shost_printk(KERN_WARNING, shost, "I/O port increment switch " + "enabled\n"); + break; + case ASC_WARN_EEPROM_CHKSUM: + shost_printk(KERN_WARNING, shost, "EEPROM checksum error\n"); + break; + case ASC_WARN_IRQ_MODIFIED: + shost_printk(KERN_WARNING, shost, "IRQ modified\n"); + break; + case ASC_WARN_CMD_QNG_CONFLICT: + shost_printk(KERN_WARNING, shost, "tag queuing enabled w/o " + "disconnects\n"); + break; + default: + shost_printk(KERN_WARNING, shost, "unknown warning: 0x%x\n", + warn_code); + break; } - return; -} -/* - * Copy 4 bytes to LRAM. - * - * The source data is assumed to be in little-endian order in memory - * and is maintained in little-endian order when writen to LRAM. - */ -static void -AscMemDWordCopyPtrToLram(PortAddr iop_base, - ushort s_addr, uchar *s_buffer, int dwords) -{ - int i; + if (asc_dvc->err_code != 0) + shost_printk(KERN_ERR, shost, "error 0x%x at init_state " + "0x%x\n", asc_dvc->err_code, asc_dvc->init_state); - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 4 * dwords; i += 4) { - outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); /* LSW */ - outpw(iop_base + IOP_RAM_DATA, ((ushort)s_buffer[i + 3] << 8) | s_buffer[i + 2]); /* MSW */ - } - return; + return asc_dvc->err_code; } -/* - * Copy 2 bytes from LRAM. - * - * The source data is assumed to be in little-endian order in LRAM - * and is maintained in little-endian order when written to memory. - */ -static void -AscMemWordCopyPtrFromLram(PortAddr iop_base, - ushort s_addr, uchar *d_buffer, int words) +static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *shost) { - int i; - ushort word; + struct asc_board *board = shost_priv(shost); + ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var; + PortAddr iop_base = asc_dvc->iop_base; + unsigned short cfg_msw; + unsigned short warn_code = 0; - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { - word = inpw(iop_base + IOP_RAM_DATA); - d_buffer[i] = word & 0xff; - d_buffer[i + 1] = (word >> 8) & 0xff; + asc_dvc->init_state |= ASC_INIT_STATE_BEG_SET_CFG; + if (asc_dvc->err_code != 0) + return asc_dvc->err_code; + if (!AscFindSignature(asc_dvc->iop_base)) { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + return asc_dvc->err_code; } - return; -} - -static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words) -{ - ASC_DCNT sum; - int i; - sum = 0L; - for (i = 0; i < words; i++, s_addr += 2) { - sum += AscReadLramWord(iop_base, s_addr); + cfg_msw = AscGetChipCfgMsw(iop_base); + if ((cfg_msw & ASC_CFG_MSW_CLR_MASK) != 0) { + cfg_msw &= ~ASC_CFG_MSW_CLR_MASK; + warn_code |= ASC_WARN_CFG_MSW_RECOVER; + AscSetChipCfgMsw(iop_base, cfg_msw); } - return (sum); -} - -static void -AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words) -{ - int i; - - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < words; i++) { - AscSetChipLramData(iop_base, set_wval); + if ((asc_dvc->cfg->cmd_qng_enabled & asc_dvc->cfg->disc_enable) != + asc_dvc->cfg->cmd_qng_enabled) { + asc_dvc->cfg->disc_enable = asc_dvc->cfg->cmd_qng_enabled; + warn_code |= ASC_WARN_CMD_QNG_CONFLICT; } - return; -} - -/* - * --- Adv Library Functions - */ - -/* a_mcode.h */ - -/* 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, + if (AscGetChipStatus(iop_base) & CSW_AUTO_CONFIG) { + warn_code |= ASC_WARN_AUTO_CONFIG; + } +#ifdef CONFIG_PCI + if (asc_dvc->bus_type & ASC_IS_PCI) { + cfg_msw &= 0xFFC0; + AscSetChipCfgMsw(iop_base, cfg_msw); + if ((asc_dvc->bus_type & ASC_IS_PCI_ULTRA) == ASC_IS_PCI_ULTRA) { + } else { + if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) || + (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) { + asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_IF_NOT_DWB; + asc_dvc->bug_fix_cntl |= + ASC_BUG_FIX_ASYN_USE_SYN; + } + } + } else +#endif /* CONFIG_PCI */ + if (asc_dvc->bus_type == ASC_IS_ISAPNP) { + if (AscGetChipVersion(iop_base, asc_dvc->bus_type) + == ASC_CHIP_VER_ASYN_BUG) { + asc_dvc->bug_fix_cntl |= ASC_BUG_FIX_ASYN_USE_SYN; + } + } + if (AscSetChipScsiID(iop_base, asc_dvc->cfg->chip_scsi_id) != + asc_dvc->cfg->chip_scsi_id) { + asc_dvc->err_code |= ASC_IERR_SET_SCSI_ID; + } +#ifdef CONFIG_ISA + if (asc_dvc->bus_type & ASC_IS_ISA) { + AscSetIsaDmaChannel(iop_base, asc_dvc->cfg->isa_dma_channel); + AscSetIsaDmaSpeed(iop_base, asc_dvc->cfg->isa_dma_speed); + } +#endif /* CONFIG_ISA */ - 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, -}; + asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; -static unsigned short _adv_asc38C0800_size = sizeof(_adv_asc38C0800_buf); /* 0x14E1 */ -static ADV_DCNT _adv_asc38C0800_chksum = 0x050D3FD8UL; /* Expanded little-endian checksum. */ + switch (warn_code) { + case 0: /* No error. */ + break; + case ASC_WARN_IO_PORT_ROTATE: + shost_printk(KERN_WARNING, shost, "I/O port address " + "modified\n"); + break; + case ASC_WARN_AUTO_CONFIG: + shost_printk(KERN_WARNING, shost, "I/O port increment switch " + "enabled\n"); + break; + case ASC_WARN_EEPROM_CHKSUM: + shost_printk(KERN_WARNING, shost, "EEPROM checksum error\n"); + break; + case ASC_WARN_IRQ_MODIFIED: + shost_printk(KERN_WARNING, shost, "IRQ modified\n"); + break; + case ASC_WARN_CMD_QNG_CONFLICT: + shost_printk(KERN_WARNING, shost, "tag queuing w/o " + "disconnects\n"); + break; + default: + shost_printk(KERN_WARNING, shost, "unknown warning: 0x%x\n", + warn_code); + break; + } -/* 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, -}; + if (asc_dvc->err_code != 0) + shost_printk(KERN_ERR, shost, "error 0x%x at init_state " + "0x%x\n", asc_dvc->err_code, asc_dvc->init_state); -static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */ -static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */ + return asc_dvc->err_code; +} -/* a_init.c */ /* * EEPROM Configuration. * @@ -13847,7 +11891,7 @@ static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian * on big-endian platforms so char fields read as words are actually being * unswapped on big-endian platforms. */ -static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __initdata = { +static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = { ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ 0x0000, /* cfg_msw */ 0xFFFF, /* disc_enable */ @@ -13885,7 +11929,7 @@ static ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __initdata = { 0 /* num_of_err */ }; -static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __initdata = { +static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = { 0, /* cfg_lsw */ 0, /* cfg_msw */ 0, /* -disc_enable */ @@ -13923,7 +11967,7 @@ static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __initdata = { 0 /* num_of_err */ }; -static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __initdata = { +static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = { ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ 0x0000, /* 01 cfg_msw */ 0xFFFF, /* 02 disc_enable */ @@ -13988,7 +12032,7 @@ static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __initdata = { 0 /* 63 reserved */ }; -static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __initdata = { +static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = { 0, /* 00 cfg_lsw */ 0, /* 01 cfg_msw */ 0, /* 02 disc_enable */ @@ -14053,7 +12097,7 @@ static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __initdata = { 0 /* 63 reserved */ }; -static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __initdata = { +static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = { ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ 0x0000, /* 01 cfg_msw */ 0xFFFF, /* 02 disc_enable */ @@ -14118,7 +12162,7 @@ static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __initdata = { 0 /* 63 reserved */ }; -static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __initdata = { +static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = { 0, /* 00 cfg_lsw */ 0, /* 01 cfg_msw */ 0, /* 02 disc_enable */ @@ -14183,1944 +12227,365 @@ static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __initdata = { 0 /* 63 reserved */ }; +#ifdef CONFIG_PCI /* - * Initialize the ADV_DVC_VAR structure. - * - * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. - * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. + * Wait for EEPROM command to complete */ -static int __init AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) +static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base) { - ushort warn_code; - AdvPortAddr iop_base; - uchar pci_cmd_reg; - int status; - - warn_code = 0; - asc_dvc->err_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * PCI Command Register - * - * Note: AscPCICmdRegBits_BusMastering definition (0x0007) includes - * I/O Space Control, Memory Space Control and Bus Master Control bits. - */ - - if (((pci_cmd_reg = DvcAdvReadPCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister)) - & AscPCICmdRegBits_BusMastering) - != AscPCICmdRegBits_BusMastering) { - pci_cmd_reg |= AscPCICmdRegBits_BusMastering; - - DvcAdvWritePCIConfigByte(asc_dvc, - AscPCIConfigCommandRegister, - pci_cmd_reg); - - if (((DvcAdvReadPCIConfigByte - (asc_dvc, AscPCIConfigCommandRegister)) - & AscPCICmdRegBits_BusMastering) - != AscPCICmdRegBits_BusMastering) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - - /* - * PCI Latency Timer - * - * If the "latency timer" register is 0x20 or above, then we don't need - * to change it. Otherwise, set it to 0x20 (i.e. set it to 0x20 if it - * comes up less than 0x20). - */ - if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < 0x20) { - DvcAdvWritePCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer, - 0x20); - if (DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigLatencyTimer) < - 0x20) { - warn_code |= ASC_WARN_SET_PCI_CONFIG_SPACE; - } - } - - /* - * Save the state of the PCI Configuration Command Register - * "Parity Error Response Control" Bit. If the bit is clear (0), - * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore - * DMA parity errors. - */ - asc_dvc->cfg->control_flag = 0; - if (((DvcAdvReadPCIConfigByte(asc_dvc, AscPCIConfigCommandRegister) - & AscPCICmdRegBits_ParErrRespCtrl)) == 0) { - asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; - } - - asc_dvc->cfg->lib_version = (ADV_LIB_VERSION_MAJOR << 8) | - ADV_LIB_VERSION_MINOR; - asc_dvc->cfg->chip_version = - AdvGetChipVersion(iop_base, asc_dvc->bus_type); - - ASC_DBG2(1, "AdvInitGetConfig: iopb_chip_id_1: 0x%x 0x%x\n", - (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1), - (ushort)ADV_CHIP_ID_BYTE); - - ASC_DBG2(1, "AdvInitGetConfig: iopw_chip_id_0: 0x%x 0x%x\n", - (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0), - (ushort)ADV_CHIP_ID_WORD); - - /* - * Reset the chip to start and allow register writes. - */ - if (AdvFindSignature(iop_base) == 0) { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - return ADV_ERROR; - } else { - /* - * The caller must set 'chip_type' to a valid setting. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC3550 && - asc_dvc->chip_type != ADV_CHIP_ASC38C0800 && - asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { - asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - /* - * Reset Chip. - */ - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, - ADV_CTRL_REG_CMD_RESET); - DvcSleepMilliSecond(100); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, - ADV_CTRL_REG_CMD_WR_IO_REG); + int eep_delay_ms; - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { - if ((status = - AdvInitFrom38C1600EEP(asc_dvc)) == ADV_ERROR) { - return ADV_ERROR; - } - } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { - if ((status = - AdvInitFrom38C0800EEP(asc_dvc)) == ADV_ERROR) { - return ADV_ERROR; - } - } else { - if ((status = AdvInitFrom3550EEP(asc_dvc)) == ADV_ERROR) { - return ADV_ERROR; - } + for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) { + if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & + ASC_EEP_CMD_DONE) { + break; } - warn_code |= status; + mdelay(1); } - - return warn_code; + if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == + 0) + BUG(); } /* - * Initialize the ASC-3550. - * - * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. - * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. - * - * Needed after initialization for error recovery. + * Read the EEPROM from specified location */ -static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) +static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - int word; - int j; - int adv_asc3550_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able = 0, sdtr_able, tagqng_able; - uchar max_cmd[ADV_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) { - return ADV_ERROR; - } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_READ | eep_word_addr); + AdvWaitEEPCmd(iop_base); + return AdvReadWordRegister(iop_base, IOPW_EE_DATA); +} - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC3550. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC3550) { - asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } +/* + * Write the EEPROM from 'cfg_buf'. + */ +void __devinit +AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) +{ + ushort *wbuf; + ushort addr, chksum; + ushort *charfields; - warn_code = 0; - iop_base = asc_dvc->iop_base; + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; + chksum = 0; - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), - bios_mem[i]); - } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); /* - * Save current per TID negotiated values. + * Write EEPROM from word 0 to word 20. */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == 0x55AA) { - ushort bios_version, major, minor; - - bios_version = - bios_mem[(ASC_MC_BIOS_VERSION - ASC_MC_BIOSMEM) / 2]; - major = (bios_version >> 12) & 0xF; - minor = (bios_version >> 8) & 0xF; - if (major < 3 || (major == 3 && minor == 1)) { - /* BIOS 3.1 and earlier location of 'wdtr_able' variable. */ - AdvReadWordLram(iop_base, 0x120, wdtr_able); - } else { - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - } - } - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; - /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - /* Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc3550_size; i++) { - if (_adv_asc3550_buf[i] == 0xff) { - for (j = 0; j < _adv_asc3550_buf[i + 1]; j++) { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf - [i + - 3] << 8) | - _adv_asc3550_buf - [i + 2])); - word++; - } - i += 3; - } else if (_adv_asc3550_buf[i] == 0xfe) { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf[i + - 2] - << 8) | - _adv_asc3550_buf[i + - 1])); - i += 2; - word++; + if (*charfields++) { + word = cpu_to_le16(*wbuf); } else { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2])); - word++; + word = *wbuf; } + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + mdelay(ADV_EEP_DELAY_MS); } /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc3550_expanded_size = word; - - /* - * Clear the rest of ASC-3550 Internal RAM (8KB). - */ - for (; word < ADV_3550_MEMSIZE; word += 2) { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc3550_expanded_size; word += 2) { - sum += AdvReadWordAutoIncLram(iop_base); - } - - if (sum != _adv_asc3550_chksum) { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), - bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read and save microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, - asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, - asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC3550. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-3550, setting the START_CTL_EMFU [3:2] bits sets a FIFO - * threshold of 128 bytes. This register is only accessible to the host. + * Write EEPROM checksum at word 21. */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - START_CTL_EMFU | READ_CMD_MRM); + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. + * Write EEPROM OEM name at words 22 to 29. */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, - asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, - asc_dvc->sdtr_able); - } + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; - /* - * Set microcode operating variables for SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 based on the ULTRA EEPROM per TID - * bitmask. These values determine the maximum SDTR speed negotiated - * with a device. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - * - * 4-bit speed SDTR speed name - * =========== =============== - * 0000b (0x0) SDTR disabled - * 0001b (0x1) 5 Mhz - * 0010b (0x2) 10 Mhz - * 0011b (0x3) 20 Mhz (Ultra) - * 0100b (0x4) 40 Mhz (LVD/Ultra2) - * 0101b (0x5) 80 Mhz (LVD2/Ultra3) - * 0110b (0x6) Undefined - * . - * 1111b (0xF) Undefined - */ - word = 0; - for (tid = 0; tid <= ADV_MAX_TID; tid++) { - if (ADV_TID_TO_TIDMASK(tid) & asc_dvc->ultra_able) { - /* Set Ultra speed for TID 'tid'. */ - word |= (0x3 << (4 * (tid % 4))); + if (*charfields++) { + word = cpu_to_le16(*wbuf); } else { - /* Set Fast speed for TID 'tid'. */ - word |= (0x2 << (4 * (tid % 4))); - } - if (tid == 3) { /* Check if done with sdtr_speed1. */ - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, word); - word = 0; - } else if (tid == 7) { /* Check if done with sdtr_speed2. */ - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, word); - word = 0; - } else if (tid == 11) { /* Check if done with sdtr_speed3. */ - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, word); - word = 0; - } else if (tid == 15) { /* Check if done with sdtr_speed4. */ - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, word); - /* End of loop. */ - } - } - - /* - * Set microcode operating variable for the disconnect per TID bitmask. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, - asc_dvc->cfg->disc_enable); - - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); - - /* - * Determine SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - - /* Read current SCSI_CFG1 Register value. */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - - /* - * If all three connectors are in use, return an error. - */ - if ((scsi_cfg1 & CABLE_ILLEGAL_A) == 0 || - (scsi_cfg1 & CABLE_ILLEGAL_B) == 0) { - asc_dvc->err_code |= ASC_IERR_ILLEGAL_CONNECTION; - return ADV_ERROR; - } - - /* - * If the internal narrow cable is reversed all of the SCSI_CTRL - * register signals will be set. Check for and return an error if - * this condition is found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } - - /* - * If this is a differential board and a single-ended device - * is attached to one of the connectors, return an error. - */ - if ((scsi_cfg1 & DIFF_MODE) && (scsi_cfg1 & DIFF_SENSE) == 0) { - asc_dvc->err_code |= ASC_IERR_SINGLE_END_DEVICE; - return ADV_ERROR; - } - - /* - * If automatic termination control is enabled, then set the - * termination value based on a table listed in a_condor.h. - * - * If manual termination was specified with an EEPROM setting - * then 'termination' was set-up in AdvInitFrom3550EEPROM() and - * is ready to be 'ored' into SCSI_CFG1. - */ - if (asc_dvc->cfg->termination == 0) { - /* - * The software always controls termination by setting TERM_CTL_SEL. - * If TERM_CTL_SEL were set to 0, the hardware would set termination. - */ - asc_dvc->cfg->termination |= TERM_CTL_SEL; - - switch (scsi_cfg1 & CABLE_DETECT) { - /* TERM_CTL_H: on, TERM_CTL_L: on */ - case 0x3: - case 0x7: - case 0xB: - case 0xD: - case 0xE: - case 0xF: - asc_dvc->cfg->termination |= (TERM_CTL_H | TERM_CTL_L); - break; - - /* TERM_CTL_H: on, TERM_CTL_L: off */ - case 0x1: - case 0x5: - case 0x9: - case 0xA: - case 0xC: - asc_dvc->cfg->termination |= TERM_CTL_H; - break; - - /* TERM_CTL_H: off, TERM_CTL_L: off */ - case 0x2: - case 0x6: - break; + word = *wbuf; } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); } + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); +} - /* - * Clear any set TERM_CTL_H and TERM_CTL_L bits. - */ - scsi_cfg1 &= ~TERM_CTL; - - /* - * Invert the TERM_CTL_H and TERM_CTL_L bits and then - * set 'scsi_cfg1'. The TERM_POL bit does not need to be - * referenced, because the hardware internally inverts - * the Termination High and Low bits if TERM_POL is set. - */ - scsi_cfg1 |= (TERM_CTL_SEL | (~asc_dvc->cfg->termination & TERM_CTL)); - - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set filter value and possibly modified termination control - * bits in the Microcode SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, - FLTR_DISABLE | scsi_cfg1); +/* + * Write the EEPROM from 'cfg_buf'. + */ +void __devinit +AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) +{ + ushort *wbuf; + ushort *charfields; + ushort addr, chksum; - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-3550 has 8KB internal memory. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - BIOS_EN | RAM_SZ_8KB); + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; + chksum = 0; - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); /* - * Build carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. + * Write EEPROM from word 0 to word 20. */ - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { - buf_size = ADV_CARRIER_BUFSIZE; - } else { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } - - do { - /* - * Get physical address of the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = - cpu_to_le32(DvcGetPhyAddr - (asc_dvc, NULL, (uchar *)carrp, - (ADV_SDCNT *)&contig_len, - ADV_IS_CARRIER_FLAG)); - - buf_size -= sizeof(ADV_CARR_T); + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) { - carrp++; - continue; + if (*charfields++) { + word = cpu_to_le16(*wbuf); + } else { + word = *wbuf; } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = - cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); - - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ - - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); - - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Set RISC ICQ physical address start value. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); - - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + mdelay(ADV_EEP_DELAY_MS); } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. + * Write EEPROM checksum at word 21. */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; /* - * Set RISC IRQ physical address start value. + * Write EEPROM OEM name at words 22 to 29. */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; - - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | - ADV_INTR_ENABLE_GLOBAL_INTR)); - - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); - - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { - /* - * If the BIOS Signature is present in memory, restore the - * BIOS Handshake Configuration Table and do not perform - * a SCSI Bus Reset. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == - 0x55AA) { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, - tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) { - AdvWriteByteLram(iop_base, - ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } + if (*charfields++) { + word = cpu_to_le16(*wbuf); } else { - if (AdvResetSB(asc_dvc) != ADV_TRUE) { - warn_code = ASC_WARN_BUSRESET_ERROR; - } + word = *wbuf; } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); } - - return warn_code; + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); } /* - * Initialize the ASC-38C0800. - * - * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. - * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. - * - * Needed after initialization for error recovery. + * Write the EEPROM from 'cfg_buf'. */ -static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) +void __devinit +AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - int word; - int j; - int adv_asc38C0800_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar byte; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able, sdtr_able, tagqng_able; - uchar max_cmd[ADV_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) { - return ADV_ERROR; - } - - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC38C0800. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC38C0800) { - asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - warn_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), - bios_mem[i]); - } - - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * RAM BIST (RAM Built-In Self Test) - * - * Address : I/O base + offset 0x38h register (byte). - * Function: Bit 7-6(RW) : RAM mode - * Normal Mode : 0x00 - * Pre-test Mode : 0x40 - * RAM Test Mode : 0x80 - * Bit 5 : unused - * Bit 4(RO) : Done bit - * Bit 3-0(RO) : Status - * Host Error : 0x08 - * Int_RAM Error : 0x04 - * RISC Error : 0x02 - * SCSI Error : 0x01 - * No Error : 0x00 - * - * Note: RAM BIST code should be put right here, before loading the - * microcode and after saving the RISC memory BIOS region. - */ - - /* - * LRAM Pre-test - * - * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. - * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return - * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset - * to NORMAL_MODE, return an error too. - */ - for (i = 0; i < 2; i++) { - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 - || (byte & 0x0F) != PRE_TEST_VALUE) { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) - != NORMAL_VALUE) { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } - } - - /* - * LRAM Test - It takes about 1.5 ms to run through the test. - * - * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. - * If Done bit not set or Status not 0, save register byte, set the - * err_code, and return an error. - */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ + ushort *wbuf; + ushort *charfields; + ushort addr, chksum; - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { - /* Get here if Done bit not set or Status not 0. */ - asc_dvc->bist_err_code = byte; /* for BIOS display message */ - asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; - return ADV_ERROR; - } + wbuf = (ushort *)cfg_buf; + charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; + chksum = 0; - /* We need to reset back to normal mode after LRAM test passes. */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); + AdvWaitEEPCmd(iop_base); /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - * + * Write EEPROM from word 0 to word 20. */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + for (addr = ADV_EEP_DVC_CFG_BEGIN; + addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { + ushort word; - /* Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc38C0800_size; i++) { - if (_adv_asc38C0800_buf[i] == 0xff) { - for (j = 0; j < _adv_asc38C0800_buf[i + 1]; j++) { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf - [i + - 3] << 8) | - _adv_asc38C0800_buf - [i + 2])); - word++; - } - i += 3; - } else if (_adv_asc38C0800_buf[i] == 0xfe) { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf - [i + - 2] << 8) | - _adv_asc38C0800_buf[i - + - 1])); - i += 2; - word++; + if (*charfields++) { + word = cpu_to_le16(*wbuf); } else { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C0800_buf[(_adv_asc38C0800_buf[i] * 2) + 1] << 8) | _adv_asc38C0800_buf[_adv_asc38C0800_buf[i] * 2])); - word++; - } - } - - /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc38C0800_expanded_size = word; - - /* - * Clear the rest of ASC-38C0800 Internal RAM (16KB). - */ - for (; word < ADV_38C0800_MEMSIZE; word += 2) { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc38C0800_expanded_size; word += 2) { - sum += AdvReadWordAutoIncLram(iop_base); - } - ASC_DBG2(1, "AdvInitAsc38C0800Driver: word %d, i %d\n", word, i); - - ASC_DBG2(1, - "AdvInitAsc38C0800Driver: sum 0x%lx, _adv_asc38C0800_chksum 0x%lx\n", - (ulong)sum, (ulong)_adv_asc38C0800_chksum); - - if (sum != _adv_asc38C0800_chksum) { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), - bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, - asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, - asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC38C0800. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800); - - /* - * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. - * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current - * cable detection and then we are able to read C_DET[3:0]. - * - * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 - * Microcode Default Value' section below. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, - scsi_cfg1 | DIS_TERM_DRV); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-38C0800, set FIFO_THRESH_80B [6:4] bits and START_CTL_TH [3:2] - * bits for the default FIFO threshold. - * - * Note: ASC-38C0800 FIFO threshold has been changed to 256 bytes. - * - * For DMA Errata #4 set the BC_THRESH_ENB bit. - */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - BC_THRESH_ENB | FIFO_THRESH_80B | START_CTL_TH | - READ_CMD_MRM); - - /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, - asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, - asc_dvc->sdtr_able); - } - - /* - * Set microcode operating variables for DISC and SDTR_SPEED1, - * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM - * configuration values. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, - asc_dvc->cfg->disc_enable); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); - - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); - - /* - * Determine SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - - /* Read current SCSI_CFG1 Register value. */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - - /* - * If the internal narrow cable is reversed all of the SCSI_CTRL - * register signals will be set. Check for and return an error if - * this condition is found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } - - /* - * All kind of combinations of devices attached to one of four connectors - * are acceptable except HVD device attached. For example, LVD device can - * be attached to SE connector while SE device attached to LVD connector. - * If LVD device attached to SE connector, it only runs up to Ultra speed. - * - * If an HVD device is attached to one of LVD connectors, return an error. - * However, there is no way to detect HVD device attached to SE connectors. - */ - if (scsi_cfg1 & HVD) { - asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; - return ADV_ERROR; - } - - /* - * If either SE or LVD automatic termination control is enabled, then - * set the termination value based on a table listed in a_condor.h. - * - * If manual termination was specified with an EEPROM setting then - * 'termination' was set-up in AdvInitFrom38C0800EEPROM() and is ready to - * be 'ored' into SCSI_CFG1. - */ - if ((asc_dvc->cfg->termination & TERM_SE) == 0) { - /* SE automatic termination control is enabled. */ - switch (scsi_cfg1 & C_DET_SE) { - /* TERM_SE_HI: on, TERM_SE_LO: on */ - case 0x1: - case 0x2: - case 0x3: - asc_dvc->cfg->termination |= TERM_SE; - break; - - /* TERM_SE_HI: on, TERM_SE_LO: off */ - case 0x0: - asc_dvc->cfg->termination |= TERM_SE_HI; - break; - } - } - - if ((asc_dvc->cfg->termination & TERM_LVD) == 0) { - /* LVD automatic termination control is enabled. */ - switch (scsi_cfg1 & C_DET_LVD) { - /* TERM_LVD_HI: on, TERM_LVD_LO: on */ - case 0x4: - case 0x8: - case 0xC: - asc_dvc->cfg->termination |= TERM_LVD; - break; - - /* TERM_LVD_HI: off, TERM_LVD_LO: off */ - case 0x0: - break; - } - } - - /* - * Clear any set TERM_SE and TERM_LVD bits. - */ - scsi_cfg1 &= (~TERM_SE & ~TERM_LVD); - - /* - * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'. - */ - scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0); - - /* - * Clear BIG_ENDIAN, DIS_TERM_DRV, Terminator Polarity and HVD/LVD/SE bits - * and set possibly modified termination control bits in the Microcode - * SCSI_CFG1 Register Value. - */ - scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL & ~HVD_LVD_SE); - - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set possibly modified termination control and reset DIS_TERM_DRV - * bits in the Microcode SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); - - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-38C0800 has 16KB internal memory. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - BIOS_EN | RAM_SZ_16KB); - - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); - - /* - * Build the carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. - */ - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { - buf_size = ADV_CARRIER_BUFSIZE; - } else { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } - - do { - /* - * Get physical address for the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = - cpu_to_le32(DvcGetPhyAddr - (asc_dvc, NULL, (uchar *)carrp, - (ADV_SDCNT *)&contig_len, - ADV_IS_CARRIER_FLAG)); - - buf_size -= sizeof(ADV_CARR_T); - - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) { - carrp++; - continue; + word = *wbuf; } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = - cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); - - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ - - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); - - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Set RISC ICQ physical address start value. - * carr_pa is LE, must be native before write - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); - - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; + chksum += *wbuf; /* Checksum is calculated from word values. */ + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + mdelay(ADV_EEP_DELAY_MS); } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. + * Write EEPROM checksum at word 21. */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); + wbuf++; + charfields++; /* - * Set RISC IRQ physical address start value. - * - * carr_pa is LE, must be native before write * + * Write EEPROM OEM name at words 22 to 29. */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; - - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | - ADV_INTR_ENABLE_GLOBAL_INTR)); - - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); - - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + for (addr = ADV_EEP_DVC_CTL_BEGIN; + addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { + ushort word; - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { - /* - * If the BIOS Signature is present in memory, restore the - * BIOS Handshake Configuration Table and do not perform - * a SCSI Bus Reset. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == - 0x55AA) { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, - tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) { - AdvWriteByteLram(iop_base, - ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } + if (*charfields++) { + word = cpu_to_le16(*wbuf); } else { - if (AdvResetSB(asc_dvc) != ADV_TRUE) { - warn_code = ASC_WARN_BUSRESET_ERROR; - } + word = *wbuf; } + AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, + ASC_EEP_CMD_WRITE | addr); + AdvWaitEEPCmd(iop_base); } - - return warn_code; + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); } /* - * Initialize the ASC-38C1600. - * - * On failure set the ASC_DVC_VAR field 'err_code' and return ADV_ERROR. - * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. + * Read EEPROM configuration into the specified buffer. * - * Needed after initialization for error recovery. + * Return a checksum based on the EEPROM configuration read. */ -static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) +static ushort __devinit +AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) { - AdvPortAddr iop_base; - ushort warn_code; - ADV_DCNT sum; - int begin_addr; - int end_addr; - ushort code_sum; - long word; - int j; - int adv_asc38C1600_expanded_size; - ADV_CARR_T *carrp; - ADV_DCNT contig_len; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; - int i; - ushort scsi_cfg1; - uchar byte; - uchar tid; - ushort bios_mem[ASC_MC_BIOSLEN / 2]; /* BIOS RISC Memory 0x40-0x8F. */ - ushort wdtr_able, sdtr_able, ppr_able, tagqng_able; - uchar max_cmd[ASC_MAX_TID + 1]; - - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) { - return ADV_ERROR; - } - - /* - * The caller must set 'chip_type' to ADV_CHIP_ASC38C1600. - */ - if (asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { - asc_dvc->err_code = ASC_IERR_BAD_CHIPTYPE; - return ADV_ERROR; - } - - warn_code = 0; - iop_base = asc_dvc->iop_base; - - /* - * Save the RISC memory BIOS region before writing the microcode. - * The BIOS may already be loaded and using its RISC LRAM region - * so its region must be saved and restored. - * - * Note: This code makes the assumption, which is currently true, - * that a chip reset does not clear RISC LRAM. - */ - for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), - bios_mem[i]); - } - - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ASC_MAX_TID; tid++) { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - /* - * RAM BIST (Built-In Self Test) - * - * Address : I/O base + offset 0x38h register (byte). - * Function: Bit 7-6(RW) : RAM mode - * Normal Mode : 0x00 - * Pre-test Mode : 0x40 - * RAM Test Mode : 0x80 - * Bit 5 : unused - * Bit 4(RO) : Done bit - * Bit 3-0(RO) : Status - * Host Error : 0x08 - * Int_RAM Error : 0x04 - * RISC Error : 0x02 - * SCSI Error : 0x01 - * No Error : 0x00 - * - * Note: RAM BIST code should be put right here, before loading the - * microcode and after saving the RISC memory BIOS region. - */ + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; - /* - * LRAM Pre-test - * - * Write PRE_TEST_MODE (0x40) to register and wait for 10 milliseconds. - * If Done bit not set or low nibble not PRE_TEST_VALUE (0x05), return - * an error. Reset to NORMAL_MODE (0x00) and do again. If cannot reset - * to NORMAL_MODE, return an error too. - */ - for (i = 0; i < 2; i++) { - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, PRE_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 - || (byte & 0x0F) != PRE_TEST_VALUE) { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; - } + charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before reading back. */ - if (AdvReadByteRegister(iop_base, IOPB_RAM_BIST) - != NORMAL_VALUE) { - asc_dvc->err_code |= ASC_IERR_BIST_PRE_TEST; - return ADV_ERROR; + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); + } else { + *wbuf = wval; } } + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; - /* - * LRAM Test - It takes about 1.5 ms to run through the test. - * - * Write RAM_TEST_MODE (0x80) to register and wait for 10 milliseconds. - * If Done bit not set or Status not 0, save register byte, set the - * err_code, and return an error. - */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, RAM_TEST_MODE); - DvcSleepMilliSecond(10); /* Wait for 10ms before checking status. */ - - byte = AdvReadByteRegister(iop_base, IOPB_RAM_BIST); - if ((byte & RAM_TEST_DONE) == 0 || (byte & RAM_TEST_STATUS) != 0) { - /* Get here if Done bit not set or Status not 0. */ - asc_dvc->bist_err_code = byte; /* for BIOS display message */ - asc_dvc->err_code |= ASC_IERR_BIST_RAM_TEST; - return ADV_ERROR; + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); + } } + return chksum; +} - /* We need to reset back to normal mode after LRAM test passes. */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); +/* + * Read EEPROM configuration into the specified buffer. + * + * Return a checksum based on the EEPROM configuration read. + */ +static ushort __devinit +AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) +{ + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; - /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - * - */ - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; - /* - * Assume the following compressed format of the microcode buffer: - * - * 254 word (508 byte) table indexed by byte code followed - * by the following byte codes: - * - * 1-Byte Code: - * 00: Emit word 0 in table. - * 01: Emit word 1 in table. - * . - * FD: Emit word 253 in table. - * - * Multi-Byte Code: - * FE WW WW: (3 byte code) Word to emit is the next word WW WW. - * FF BB WW WW: (4 byte code) Emit BB count times next word WW WW. - */ - word = 0; - for (i = 253 * 2; i < _adv_asc38C1600_size; i++) { - if (_adv_asc38C1600_buf[i] == 0xff) { - for (j = 0; j < _adv_asc38C1600_buf[i + 1]; j++) { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf - [i + - 3] << 8) | - _adv_asc38C1600_buf - [i + 2])); - word++; - } - i += 3; - } else if (_adv_asc38C1600_buf[i] == 0xfe) { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf - [i + - 2] << 8) | - _adv_asc38C1600_buf[i - + - 1])); - i += 2; - word++; + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); } else { - AdvWriteWordAutoIncLram(iop_base, (((ushort) - _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2])); - word++; + *wbuf = wval; } } + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; - /* - * Set 'word' for later use to clear the rest of memory and save - * the expanded mcode size. - */ - word *= 2; - adv_asc38C1600_expanded_size = word; - - /* - * Clear the rest of ASC-38C1600 Internal RAM (32KB). - */ - for (; word < ADV_38C1600_MEMSIZE; word += 2) { - AdvWriteWordAutoIncLram(iop_base, 0); - } - - /* - * Verify the microcode checksum. - */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); - - for (word = 0; word < adv_asc38C1600_expanded_size; word += 2) { - sum += AdvReadWordAutoIncLram(iop_base); - } - - if (sum != _adv_asc38C1600_chksum) { - asc_dvc->err_code |= ASC_IERR_MCODE_CHKSUM; - return ADV_ERROR; - } - - /* - * Restore the RISC memory BIOS region. - */ - for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { - AdvWriteWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), - bios_mem[i]); - } - - /* - * Calculate and write the microcode code checksum to the microcode - * code checksum location ASC_MC_CODE_CHK_SUM (0x2C). - */ - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, begin_addr); - AdvReadWordLram(iop_base, ASC_MC_CODE_END_ADDR, end_addr); - code_sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, begin_addr); - for (word = begin_addr; word < end_addr; word += 2) { - code_sum += AdvReadWordAutoIncLram(iop_base); - } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); - - /* - * Read microcode version and date. - */ - AdvReadWordLram(iop_base, ASC_MC_VERSION_DATE, - asc_dvc->cfg->mcode_date); - AdvReadWordLram(iop_base, ASC_MC_VERSION_NUM, - asc_dvc->cfg->mcode_version); - - /* - * Set the chip type to indicate the ASC38C1600. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600); - - /* - * Write 1 to bit 14 'DIS_TERM_DRV' in the SCSI_CFG1 register. - * When DIS_TERM_DRV set to 1, C_DET[3:0] will reflect current - * cable detection and then we are able to read C_DET[3:0]. - * - * Note: We will reset DIS_TERM_DRV to 0 in the 'Set SCSI_CFG1 - * Microcode Default Value' section below. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - AdvWriteWordRegister(iop_base, IOPW_SCSI_CFG1, - scsi_cfg1 | DIS_TERM_DRV); - - /* - * If the PCI Configuration Command Register "Parity Error Response - * Control" Bit was clear (0), then set the microcode variable - * 'control_flag' CONTROL_FLAG_IGNORE_PERR flag to tell the microcode - * to ignore DMA parity errors. - */ - if (asc_dvc->cfg->control_flag & CONTROL_FLAG_IGNORE_PERR) { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_IGNORE_PERR; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * If the BIOS control flag AIPP (Asynchronous Information - * Phase Protection) disable bit is not set, then set the firmware - * 'control_flag' CONTROL_FLAG_ENABLE_AIPP bit to enable - * AIPP checking and encoding. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_AIPP_DIS) == 0) { - AdvReadWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - word |= CONTROL_FLAG_ENABLE_AIPP; - AdvWriteWordLram(iop_base, ASC_MC_CONTROL_FLAG, word); - } - - /* - * For ASC-38C1600 use DMA_CFG0 default values: FIFO_THRESH_80B [6:4], - * and START_CTL_TH [3:2]. - */ - AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, - FIFO_THRESH_80B | START_CTL_TH | READ_CMD_MRM); - - /* - * Microcode operating variables for WDTR, SDTR, and command tag - * queuing will be set in AdvInquiryHandling() based on what a - * device reports it is capable of in Inquiry byte 7. - * - * If SCSI Bus Resets have been disabled, then directly set - * SDTR and WDTR from the EEPROM configuration. This will allow - * the BIOS and warm boot to work without a SCSI bus hang on - * the Inquiry caused by host and target mismatched DTR values. - * Without the SCSI Bus Reset, before an Inquiry a device can't - * be assumed to be in Asynchronous, Narrow mode. - */ - if ((asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) == 0) { - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, - asc_dvc->wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, - asc_dvc->sdtr_able); - } - - /* - * Set microcode operating variables for DISC and SDTR_SPEED1, - * SDTR_SPEED2, SDTR_SPEED3, and SDTR_SPEED4 based on the EEPROM - * configuration values. - * - * The SDTR per TID bitmask overrides the SDTR_SPEED1, SDTR_SPEED2, - * SDTR_SPEED3, and SDTR_SPEED4 values so it is safe to set them - * without determining here whether the device supports SDTR. - */ - AdvWriteWordLram(iop_base, ASC_MC_DISC_ENABLE, - asc_dvc->cfg->disc_enable); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED1, asc_dvc->sdtr_speed1); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED2, asc_dvc->sdtr_speed2); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED3, asc_dvc->sdtr_speed3); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_SPEED4, asc_dvc->sdtr_speed4); - - /* - * Set SCSI_CFG0 Microcode Default Value. - * - * The microcode will set the SCSI_CFG0 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG0, - PARITY_EN | QUEUE_128 | SEL_TMO_LONG | OUR_ID_EN | - asc_dvc->chip_scsi_id); - - /* - * Calculate SCSI_CFG1 Microcode Default Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - * - * Each ASC-38C1600 function has only two cable detect bits. - * The bus mode override bits are in IOPB_SOFT_OVER_WR. - */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); - - /* - * If the cable is reversed all of the SCSI_CTRL register signals - * will be set. Check for and return an error if this condition is - * found. - */ - if ((AdvReadWordRegister(iop_base, IOPW_SCSI_CTRL) & 0x3F07) == 0x3F07) { - asc_dvc->err_code |= ASC_IERR_REVERSED_CABLE; - return ADV_ERROR; - } - - /* - * Each ASC-38C1600 function has two connectors. Only an HVD device - * can not be connected to either connector. An LVD device or SE device - * may be connected to either connecor. If an SE device is connected, - * then at most Ultra speed (20 Mhz) can be used on both connectors. - * - * If an HVD device is attached, return an error. - */ - if (scsi_cfg1 & HVD) { - asc_dvc->err_code |= ASC_IERR_HVD_DEVICE; - return ADV_ERROR; - } - - /* - * Each function in the ASC-38C1600 uses only the SE cable detect and - * termination because there are two connectors for each function. Each - * function may use either LVD or SE mode. Corresponding the SE automatic - * termination control EEPROM bits are used for each function. Each - * function has its own EEPROM. If SE automatic control is enabled for - * the function, then set the termination value based on a table listed - * in a_condor.h. - * - * If manual termination is specified in the EEPROM for the function, - * then 'termination' was set-up in AscInitFrom38C1600EEPROM() and is - * ready to be 'ored' into SCSI_CFG1. - */ - if ((asc_dvc->cfg->termination & TERM_SE) == 0) { - /* SE automatic termination control is enabled. */ - switch (scsi_cfg1 & C_DET_SE) { - /* TERM_SE_HI: on, TERM_SE_LO: on */ - case 0x1: - case 0x2: - case 0x3: - asc_dvc->cfg->termination |= TERM_SE; - break; - - case 0x0: - if (ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) == 0) { - /* Function 0 - TERM_SE_HI: off, TERM_SE_LO: off */ - } else { - /* Function 1 - TERM_SE_HI: on, TERM_SE_LO: off */ - asc_dvc->cfg->termination |= TERM_SE_HI; - } - break; + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); } } + return chksum; +} - /* - * Clear any set TERM_SE bits. - */ - scsi_cfg1 &= ~TERM_SE; - - /* - * Invert the TERM_SE bits and then set 'scsi_cfg1'. - */ - scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE); - - /* - * Clear Big Endian and Terminator Polarity bits and set possibly - * modified termination control bits in the Microcode SCSI_CFG1 - * Register Value. - * - * Big Endian bit is not used even on big endian machines. - */ - scsi_cfg1 &= (~BIG_ENDIAN & ~DIS_TERM_DRV & ~TERM_POL); - - /* - * Set SCSI_CFG1 Microcode Default Value - * - * Set possibly modified termination control bits in the Microcode - * SCSI_CFG1 Register Value. - * - * The microcode will set the SCSI_CFG1 register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SCSI_CFG1, scsi_cfg1); - - /* - * Set MEM_CFG Microcode Default Value - * - * The microcode will set the MEM_CFG register using this value - * after it is started below. - * - * MEM_CFG may be accessed as a word or byte, but only bits 0-7 - * are defined. - * - * ASC-38C1600 has 32KB internal memory. - * - * XXX - Since ASC38C1600 Rev.3 has a Local RAM failure issue, we come - * out a special 16K Adv Library and Microcode version. After the issue - * resolved, we should turn back to the 32K support. Both a_condor.h and - * mcode.sas files also need to be updated. - * - * AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - * BIOS_EN | RAM_SZ_32KB); - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_MEM_CFG, - BIOS_EN | RAM_SZ_16KB); - - /* - * Set SEL_MASK Microcode Default Value - * - * The microcode will set the SEL_MASK register using this value - * after it is started below. - */ - AdvWriteWordLram(iop_base, ASC_MC_DEFAULT_SEL_MASK, - ADV_TID_TO_TIDMASK(asc_dvc->chip_scsi_id)); - - /* - * Build the carrier freelist. - * - * Driver must have already allocated memory and set 'carrier_buf'. - */ - - ASC_ASSERT(asc_dvc->carrier_buf != NULL); - - carrp = (ADV_CARR_T *) ADV_16BALIGN(asc_dvc->carrier_buf); - asc_dvc->carr_freelist = NULL; - if (carrp == (ADV_CARR_T *) asc_dvc->carrier_buf) { - buf_size = ADV_CARRIER_BUFSIZE; - } else { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); - } - - do { - /* - * Get physical address for the carrier 'carrp'. - */ - contig_len = sizeof(ADV_CARR_T); - carr_paddr = - cpu_to_le32(DvcGetPhyAddr - (asc_dvc, NULL, (uchar *)carrp, - (ADV_SDCNT *)&contig_len, - ADV_IS_CARRIER_FLAG)); +/* + * Read EEPROM configuration into the specified buffer. + * + * Return a checksum based on the EEPROM configuration read. + */ +static ushort __devinit +AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) +{ + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; - buf_size -= sizeof(ADV_CARR_T); + charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; + wbuf = (ushort *)cfg_buf; + chksum = 0; - /* - * If the current carrier is not physically contiguous, then - * maybe there was a page crossing. Try the next carrier aligned - * start address. - */ - if (contig_len < sizeof(ADV_CARR_T)) { - carrp++; - continue; + for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; + eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { + wval = AdvReadEEPWord(iop_base, eep_addr); + chksum += wval; /* Checksum is calculated from word values. */ + if (*charfields++) { + *wbuf = le16_to_cpu(wval); + } else { + *wbuf = wval; } - - carrp->carr_pa = carr_paddr; - carrp->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(carrp)); - - /* - * Insert the carrier at the beginning of the freelist. - */ - carrp->next_vpa = - cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = carrp; - - carrp++; - } - while (buf_size > 0); - - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->icq_sp->next_vpa)); - - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Set RISC ICQ physical address start value. Initialize the - * COMMA register to the same value otherwise the RISC will - * prematurely detect a command is available. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_ICQ, asc_dvc->icq_sp->carr_pa); - AdvWriteDWordRegister(iop_base, IOPDW_COMMA, - le32_to_cpu(asc_dvc->icq_sp->carr_pa)); - - /* - * Set-up the RISC->Host Initiator Response Queue (IRQ). - */ - if ((asc_dvc->irq_sp = asc_dvc->carr_freelist) == NULL) { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->next_vpa)); - - /* - * The first command completed by the RISC will be placed in - * the stopper. - * - * Note: Set 'next_vpa' to ASC_CQ_STOPPER. When the request is - * completed the RISC will set the ASC_RQ_STOPPER bit. - */ - asc_dvc->irq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Set RISC IRQ physical address start value. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IRQ, asc_dvc->irq_sp->carr_pa); - asc_dvc->carr_pending_cnt = 0; - - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | - ADV_INTR_ENABLE_GLOBAL_INTR)); - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); - - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + /* Read checksum word. */ + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + wbuf++; + charfields++; - /* - * Reset the SCSI Bus if the EEPROM indicates that SCSI Bus - * Resets should be performed. The RISC has to be running - * to issue a SCSI Bus Reset. - */ - if (asc_dvc->bios_ctrl & BIOS_CTRL_RESET_SCSI_BUS) { - /* - * If the BIOS Signature is present in memory, restore the - * per TID microcode operating variables. - */ - if (bios_mem[(ASC_MC_BIOS_SIGNATURE - ASC_MC_BIOSMEM) / 2] == - 0x55AA) { - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, - tagqng_able); - for (tid = 0; tid <= ASC_MAX_TID; tid++) { - AdvWriteByteLram(iop_base, - ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - } else { - if (AdvResetSB(asc_dvc) != ADV_TRUE) { - warn_code = ASC_WARN_BUSRESET_ERROR; - } + /* Read rest of EEPROM not covered by the checksum. */ + for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; + eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { + *wbuf = AdvReadEEPWord(iop_base, eep_addr); + if (*charfields++) { + *wbuf = le16_to_cpu(*wbuf); } } - - return warn_code; + return chksum; } /* @@ -16135,12 +12600,11 @@ static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -static int __init AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) +static int __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) { AdvPortAddr iop_base; ushort warn_code; ADVEEP_3550_CONFIG eep_config; - int i; iop_base = asc_dvc->iop_base; @@ -16157,15 +12621,12 @@ static int __init AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) /* * Set EEPROM default values. */ - for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) { - *((uchar *)&eep_config + i) = - *((uchar *)&Default_3550_EEPROM_Config + i); - } + memcpy(&eep_config, &Default_3550_EEPROM_Config, + sizeof(ADVEEP_3550_CONFIG)); /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. + * Assume the 6 byte board serial number that was read from + * EEPROM is correct even if the EEPROM checksum failed. */ eep_config.serial_number_word3 = AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); @@ -16289,12 +12750,11 @@ static int __init AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -static int __init AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) +static int __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) { AdvPortAddr iop_base; ushort warn_code; ADVEEP_38C0800_CONFIG eep_config; - int i; uchar tid, termination; ushort sdtr_speed = 0; @@ -16314,15 +12774,12 @@ static int __init AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) /* * Set EEPROM default values. */ - for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) { - *((uchar *)&eep_config + i) = - *((uchar *)&Default_38C0800_EEPROM_Config + i); - } + memcpy(&eep_config, &Default_38C0800_EEPROM_Config, + sizeof(ADVEEP_38C0800_CONFIG)); /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. + * Assume the 6 byte board serial number that was read from + * EEPROM is correct even if the EEPROM checksum failed. */ eep_config.serial_number_word3 = AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); @@ -16492,12 +12949,11 @@ static int __init AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) * * Note: Chip is stopped on entry. */ -static int __init AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) +static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) { AdvPortAddr iop_base; ushort warn_code; ADVEEP_38C1600_CONFIG eep_config; - int i; uchar tid, termination; ushort sdtr_speed = 0; @@ -16512,75 +12968,52 @@ static int __init AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) */ if (AdvGet38C1600EEPConfig(iop_base, &eep_config) != eep_config.check_sum) { + struct pci_dev *pdev = adv_dvc_to_pdev(asc_dvc); warn_code |= ASC_WARN_EEPROM_CHKSUM; /* * Set EEPROM default values. */ - for (i = 0; i < sizeof(ADVEEP_38C1600_CONFIG); i++) { - if (i == 1 - && ASC_PCI_ID2FUNC(asc_dvc->cfg->pci_slot_info) != - 0) { - /* - * Set Function 1 EEPROM Word 0 MSB - * - * Clear the BIOS_ENABLE (bit 14) and INTAB (bit 11) - * EEPROM bits. - * - * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 and - * old Mac system booting problem. The Expansion ROM must - * be disabled in Function 1 for these systems. - * - */ - *((uchar *)&eep_config + i) = - ((* - ((uchar *)&Default_38C1600_EEPROM_Config - + - i)) & - (~ - (((ADV_EEPROM_BIOS_ENABLE | - ADV_EEPROM_INTAB) >> 8) & 0xFF))); + memcpy(&eep_config, &Default_38C1600_EEPROM_Config, + sizeof(ADVEEP_38C1600_CONFIG)); - /* - * Set the INTAB (bit 11) if the GPIO 0 input indicates - * the Function 1 interrupt line is wired to INTA. - * - * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input: - * 1 - Function 1 interrupt line wired to INT A. - * 0 - Function 1 interrupt line wired to INT B. - * - * Note: Adapter boards always have Function 0 wired to INTA. - * Put all 5 GPIO bits in input mode and then read - * their input values. - */ - AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, - 0); - if (AdvReadByteRegister - (iop_base, IOPB_GPIO_DATA) & 0x01) { - /* Function 1 interrupt wired to INTA; Set EEPROM bit. */ - *((uchar *)&eep_config + i) |= - ((ADV_EEPROM_INTAB >> 8) & 0xFF); - } - } else { - *((uchar *)&eep_config + i) = - *((uchar *)&Default_38C1600_EEPROM_Config - + i); - } + if (PCI_FUNC(pdev->devfn) != 0) { + u8 ints; + /* + * Disable Bit 14 (BIOS_ENABLE) to fix SPARC Ultra 60 + * and old Mac system booting problem. The Expansion + * ROM must be disabled in Function 1 for these systems + */ + eep_config.cfg_lsw &= ~ADV_EEPROM_BIOS_ENABLE; + /* + * Clear the INTAB (bit 11) if the GPIO 0 input + * indicates the Function 1 interrupt line is wired + * to INTB. + * + * Set/Clear Bit 11 (INTAB) from the GPIO bit 0 input: + * 1 - Function 1 interrupt line wired to INT A. + * 0 - Function 1 interrupt line wired to INT B. + * + * Note: Function 0 is always wired to INTA. + * Put all 5 GPIO bits in input mode and then read + * their input values. + */ + AdvWriteByteRegister(iop_base, IOPB_GPIO_CNTL, 0); + ints = AdvReadByteRegister(iop_base, IOPB_GPIO_DATA); + if ((ints & 0x01) == 0) + eep_config.cfg_lsw &= ~ADV_EEPROM_INTAB; } /* - * Assume the 6 byte board serial number that was read - * from EEPROM is correct even if the EEPROM checksum - * failed. + * Assume the 6 byte board serial number that was read from + * EEPROM is correct even if the EEPROM checksum failed. */ eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); AdvSet38C1600EEPConfig(iop_base, &eep_config); } @@ -16729,1176 +13162,281 @@ static int __init AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) } /* - * Read EEPROM configuration into the specified buffer. - * - * Return a checksum based on the EEPROM configuration read. - */ -static ushort __init -AdvGet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) -{ - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; - wbuf = (ushort *)cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; - charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; -} - -/* - * Read EEPROM configuration into the specified buffer. + * Initialize the ADV_DVC_VAR structure. * - * Return a checksum based on the EEPROM configuration read. - */ -static ushort __init -AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) -{ - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; - wbuf = (ushort *)cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; - charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; -} - -/* - * Read EEPROM configuration into the specified buffer. + * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. * - * Return a checksum based on the EEPROM configuration read. - */ -static ushort __init -AdvGet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) -{ - ushort wval, chksum; - ushort *wbuf; - int eep_addr; - ushort *charfields; - - charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; - wbuf = (ushort *)cfg_buf; - chksum = 0; - - for (eep_addr = ADV_EEP_DVC_CFG_BEGIN; - eep_addr < ADV_EEP_DVC_CFG_END; eep_addr++, wbuf++) { - wval = AdvReadEEPWord(iop_base, eep_addr); - chksum += wval; /* Checksum is calculated from word values. */ - if (*charfields++) { - *wbuf = le16_to_cpu(wval); - } else { - *wbuf = wval; - } - } - /* Read checksum word. */ - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - wbuf++; - charfields++; - - /* Read rest of EEPROM not covered by the checksum. */ - for (eep_addr = ADV_EEP_DVC_CTL_BEGIN; - eep_addr < ADV_EEP_MAX_WORD_ADDR; eep_addr++, wbuf++) { - *wbuf = AdvReadEEPWord(iop_base, eep_addr); - if (*charfields++) { - *wbuf = le16_to_cpu(*wbuf); - } - } - return chksum; -} - -/* - * Read the EEPROM from specified location - */ -static ushort __init AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) -{ - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_READ | eep_word_addr); - AdvWaitEEPCmd(iop_base); - return AdvReadWordRegister(iop_base, IOPW_EE_DATA); -} - -/* - * Wait for EEPROM command to complete - */ -static void __init AdvWaitEEPCmd(AdvPortAddr iop_base) -{ - int eep_delay_ms; - - for (eep_delay_ms = 0; eep_delay_ms < ADV_EEP_DELAY_MS; eep_delay_ms++) { - if (AdvReadWordRegister(iop_base, IOPW_EE_CMD) & - ASC_EEP_CMD_DONE) { - break; - } - DvcSleepMilliSecond(1); - } - if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == - 0) { - ASC_ASSERT(0); - } - return; -} - -/* - * Write the EEPROM from 'cfg_buf'. + * For a non-fatal error return a warning code. If there are no warnings + * then 0 is returned. */ -void __init -AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) +static int __devinit +AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost) { - ushort *wbuf; - ushort addr, chksum; - ushort *charfields; - - wbuf = (ushort *)cfg_buf; - charfields = (ushort *)&ADVEEP_3550_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); - - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); - } + struct asc_board *board = shost_priv(shost); + ADV_DVC_VAR *asc_dvc = &board->dvc_var.adv_dvc_var; + unsigned short warn_code = 0; + AdvPortAddr iop_base = asc_dvc->iop_base; + u16 cmd; + int status; - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; - charfields++; + asc_dvc->err_code = 0; /* - * Write EEPROM OEM name at words 22 to 29. + * Save the state of the PCI Configuration Command Register + * "Parity Error Response Control" Bit. If the bit is clear (0), + * in AdvInitAsc3550/38C0800Driver() tell the microcode to ignore + * DMA parity errors. */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; -} - -/* - * Write the EEPROM from 'cfg_buf'. - */ -void __init -AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) -{ - ushort *wbuf; - ushort *charfields; - ushort addr, chksum; - - wbuf = (ushort *)cfg_buf; - charfields = (ushort *)&ADVEEP_38C0800_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); + asc_dvc->cfg->control_flag = 0; + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + if ((cmd & PCI_COMMAND_PARITY) == 0) + asc_dvc->cfg->control_flag |= CONTROL_FLAG_IGNORE_PERR; - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { - ushort word; + asc_dvc->cfg->chip_version = + AdvGetChipVersion(iop_base, asc_dvc->bus_type); - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); - } + ASC_DBG(1, "iopb_chip_id_1: 0x%x 0x%x\n", + (ushort)AdvReadByteRegister(iop_base, IOPB_CHIP_ID_1), + (ushort)ADV_CHIP_ID_BYTE); - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; - charfields++; + ASC_DBG(1, "iopw_chip_id_0: 0x%x 0x%x\n", + (ushort)AdvReadWordRegister(iop_base, IOPW_CHIP_ID_0), + (ushort)ADV_CHIP_ID_WORD); /* - * Write EEPROM OEM name at words 22 to 29. + * Reset the chip to start and allow register writes. */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { - ushort word; - - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; + if (AdvFindSignature(iop_base) == 0) { + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; + return ADV_ERROR; + } else { + /* + * The caller must set 'chip_type' to a valid setting. + */ + if (asc_dvc->chip_type != ADV_CHIP_ASC3550 && + asc_dvc->chip_type != ADV_CHIP_ASC38C0800 && + asc_dvc->chip_type != ADV_CHIP_ASC38C1600) { + asc_dvc->err_code |= ASC_IERR_BAD_CHIPTYPE; + return ADV_ERROR; } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; -} -/* - * Write the EEPROM from 'cfg_buf'. - */ -void __init -AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) -{ - ushort *wbuf; - ushort *charfields; - ushort addr, chksum; - - wbuf = (ushort *)cfg_buf; - charfields = (ushort *)&ADVEEP_38C1600_Config_Field_IsChar; - chksum = 0; - - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_ABLE); - AdvWaitEEPCmd(iop_base); - - /* - * Write EEPROM from word 0 to word 20. - */ - for (addr = ADV_EEP_DVC_CFG_BEGIN; - addr < ADV_EEP_DVC_CFG_END; addr++, wbuf++) { - ushort word; + /* + * Reset Chip. + */ + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_RESET); + mdelay(100); + AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, + ADV_CTRL_REG_CMD_WR_IO_REG); - if (*charfields++) { - word = cpu_to_le16(*wbuf); + if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { + status = AdvInitFrom38C1600EEP(asc_dvc); + } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { + status = AdvInitFrom38C0800EEP(asc_dvc); } else { - word = *wbuf; + status = AdvInitFrom3550EEP(asc_dvc); } - chksum += *wbuf; /* Checksum is calculated from word values. */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - DvcSleepMilliSecond(ADV_EEP_DELAY_MS); + warn_code |= status; } - /* - * Write EEPROM checksum at word 21. - */ - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, chksum); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - wbuf++; - charfields++; + if (warn_code != 0) + shost_printk(KERN_WARNING, shost, "warning: 0x%x\n", warn_code); - /* - * Write EEPROM OEM name at words 22 to 29. - */ - for (addr = ADV_EEP_DVC_CTL_BEGIN; - addr < ADV_EEP_MAX_WORD_ADDR; addr++, wbuf++) { - ushort word; + if (asc_dvc->err_code) + shost_printk(KERN_ERR, shost, "error code 0x%x\n", + asc_dvc->err_code); - if (*charfields++) { - word = cpu_to_le16(*wbuf); - } else { - word = *wbuf; - } - AdvWriteWordRegister(iop_base, IOPW_EE_DATA, word); - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, - ASC_EEP_CMD_WRITE | addr); - AdvWaitEEPCmd(iop_base); - } - AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); - AdvWaitEEPCmd(iop_base); - return; + return asc_dvc->err_code; } +#endif -/* a_advlib.c */ -/* - * AdvExeScsiQueue() - Send a request to the RISC microcode program. - * - * Allocate a carrier structure, point the carrier to the ADV_SCSI_REQ_Q, - * add the carrier to the ICQ (Initiator Command Queue), and tickle the - * RISC to notify it a new command is ready to be executed. - * - * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be - * set to SCSI_MAX_RETRY. - * - * Multi-byte fields in the ASC_SCSI_REQ_Q that are used by the microcode - * for DMA addresses or math operations are byte swapped to little-endian - * order. - * - * Return: - * ADV_SUCCESS(1) - The request was successfully queued. - * ADV_BUSY(0) - Resource unavailable; Retry again after pending - * request completes. - * ADV_ERROR(-1) - Invalid ADV_SCSI_REQ_Q request structure - * host IC error. - */ -static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) -{ - ulong last_int_level; - AdvPortAddr iop_base; - ADV_DCNT req_size; - ADV_PADDR req_paddr; - ADV_CARR_T *new_carrp; - - ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */ - - /* - * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. - */ - if (scsiq->target_id > ADV_MAX_TID) { - scsiq->host_status = QHSTA_M_INVALID_DEVICE; - scsiq->done_status = QD_WITH_ERROR; - return ADV_ERROR; - } - - iop_base = asc_dvc->iop_base; - - last_int_level = DvcEnterCritical(); - - /* - * Allocate a carrier ensuring at least one carrier always - * remains on the freelist and initialize fields. - */ - if ((new_carrp = asc_dvc->carr_freelist) == NULL) { - DvcLeaveCritical(last_int_level); - return ADV_BUSY; - } - asc_dvc->carr_freelist = (ADV_CARR_T *) - ADV_U32_TO_VADDR(le32_to_cpu(new_carrp->next_vpa)); - asc_dvc->carr_pending_cnt++; - - /* - * Set the carrier to be a stopper by setting 'next_vpa' - * to the stopper value. The current stopper will be changed - * below to point to the new stopper. - */ - new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); - - /* - * Clear the ADV_SCSI_REQ_Q done flag. - */ - scsiq->a_flag &= ~ADV_SCSIQ_DONE; - - req_size = sizeof(ADV_SCSI_REQ_Q); - req_paddr = DvcGetPhyAddr(asc_dvc, scsiq, (uchar *)scsiq, - (ADV_SDCNT *)&req_size, ADV_IS_SCSIQ_FLAG); - - ASC_ASSERT(ADV_32BALIGN(req_paddr) == req_paddr); - ASC_ASSERT(req_size >= sizeof(ADV_SCSI_REQ_Q)); - - /* Wait for assertion before making little-endian */ - req_paddr = cpu_to_le32(req_paddr); - - /* Save virtual and physical address of ADV_SCSI_REQ_Q and carrier. */ - scsiq->scsiq_ptr = cpu_to_le32(ADV_VADDR_TO_U32(scsiq)); - scsiq->scsiq_rptr = req_paddr; - - scsiq->carr_va = cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->icq_sp)); - /* - * Every ADV_CARR_T.carr_pa is byte swapped to little-endian - * order during initialization. - */ - scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; - - /* - * Use the current stopper to send the ADV_SCSI_REQ_Q command to - * the microcode. The newly allocated stopper will become the new - * stopper. - */ - asc_dvc->icq_sp->areq_vpa = req_paddr; - +static struct scsi_host_template advansys_template = { + .proc_name = DRV_NAME, +#ifdef CONFIG_PROC_FS + .proc_info = advansys_proc_info, +#endif + .name = DRV_NAME, + .info = advansys_info, + .queuecommand = advansys_queuecommand, + .eh_bus_reset_handler = advansys_reset, + .bios_param = advansys_biosparam, + .slave_configure = advansys_slave_configure, /* - * Set the 'next_vpa' pointer for the old stopper to be the - * physical address of the new stopper. The RISC can only - * follow physical addresses. + * Because the driver may control an ISA adapter 'unchecked_isa_dma' + * must be set. The flag will be cleared in advansys_board_found + * for non-ISA adapters. */ - asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; - + .unchecked_isa_dma = 1, /* - * Set the host adapter stopper pointer to point to the new carrier. + * All adapters controlled by this driver are capable of large + * scatter-gather lists. According to the mid-level SCSI documentation + * this obviates any performance gain provided by setting + * 'use_clustering'. But empirically while CPU utilization is increased + * by enabling clustering, I/O throughput increases as well. */ - asc_dvc->icq_sp = new_carrp; - - if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || - asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { - /* - * Tickle the RISC to tell it to read its Command Queue Head pointer. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_A); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { - /* - * Clear the tickle value. In the ASC-3550 the RISC flag - * command 'clr_tickle_a' does not work unless the host - * value is cleared. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, - ADV_TICKLE_NOP); - } - } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { - /* - * Notify the RISC a carrier is ready by writing the physical - * address of the new carrier stopper to the COMMA register. - */ - AdvWriteDWordRegister(iop_base, IOPDW_COMMA, - le32_to_cpu(new_carrp->carr_pa)); - } - - DvcLeaveCritical(last_int_level); - - return ADV_SUCCESS; -} + .use_clustering = ENABLE_CLUSTERING, +}; -/* - * Reset SCSI Bus and purge all outstanding requests. - * - * Return Value: - * ADV_TRUE(1) - All requests are purged and SCSI Bus is reset. - * ADV_FALSE(0) - Microcode command failed. - * ADV_ERROR(-1) - Microcode command timed-out. Microcode or IC - * may be hung which requires driver recovery. - */ -static int AdvResetSB(ADV_DVC_VAR *asc_dvc) +static int __devinit advansys_wide_init_chip(struct Scsi_Host *shost) { - int status; + struct asc_board *board = shost_priv(shost); + struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var; + int req_cnt = 0; + adv_req_t *reqp = NULL; + int sg_cnt = 0; + adv_sgblk_t *sgp; + int warn_code, err_code; /* - * Send the SCSI Bus Reset idle start idle command which asserts - * the SCSI Bus Reset signal. + * Allocate buffer carrier structures. The total size + * is about 4 KB, so allocate all at once. */ - status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_START, 0L); - if (status != ADV_TRUE) { - return status; - } + adv_dvc->carrier_buf = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL); + ASC_DBG(1, "carrier_buf 0x%p\n", adv_dvc->carrier_buf); - /* - * Delay for the specified SCSI Bus Reset hold time. - * - * The hold time delay is done on the host because the RISC has no - * microsecond accurate timer. - */ - DvcDelayMicroSecond(asc_dvc, (ushort)ASC_SCSI_RESET_HOLD_TIME_US); + if (!adv_dvc->carrier_buf) + goto kmalloc_failed; /* - * Send the SCSI Bus Reset end idle command which de-asserts - * the SCSI Bus Reset signal and purges any pending requests. + * Allocate up to 'max_host_qng' request structures for the Wide + * board. The total size is about 16 KB, so allocate all at once. + * If the allocation fails decrement and try again. */ - status = AdvSendIdleCmd(asc_dvc, (ushort)IDLE_CMD_SCSI_RESET_END, 0L); - if (status != ADV_TRUE) { - return status; - } - - DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000); - - return status; -} - -/* - * Reset chip and SCSI Bus. - * - * Return Value: - * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful. - * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure. - */ -static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) -{ - int status; - ushort wdtr_able, sdtr_able, tagqng_able; - ushort ppr_able = 0; - uchar tid, max_cmd[ADV_MAX_TID + 1]; - AdvPortAddr iop_base; - ushort bios_sig; + for (req_cnt = adv_dvc->max_host_qng; req_cnt > 0; req_cnt--) { + reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL); - iop_base = asc_dvc->iop_base; + ASC_DBG(1, "reqp 0x%p, req_cnt %d, bytes %lu\n", reqp, req_cnt, + (ulong)sizeof(adv_req_t) * req_cnt); - /* - * Save current per TID negotiated values. - */ - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); - } - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) { - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); + if (reqp) + break; } - /* - * Force the AdvInitAsc3550/38C0800Driver() function to - * perform a SCSI Bus Reset by clearing the BIOS signature word. - * The initialization functions assumes a SCSI Bus Reset is not - * needed if the BIOS signature word is present. - */ - AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); - AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); + if (!reqp) + goto kmalloc_failed; - /* - * Stop chip and reset it. - */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_STOP); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, ADV_CTRL_REG_CMD_RESET); - DvcSleepMilliSecond(100); - AdvWriteWordRegister(iop_base, IOPW_CTRL_REG, - ADV_CTRL_REG_CMD_WR_IO_REG); + adv_dvc->orig_reqp = reqp; /* - * Reset Adv Library error code, if any, and try - * re-initializing the chip. + * Allocate up to ADV_TOT_SG_BLOCK request structures for + * the Wide board. Each structure is about 136 bytes. */ - asc_dvc->err_code = 0; - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { - status = AdvInitAsc38C1600Driver(asc_dvc); - } else if (asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { - status = AdvInitAsc38C0800Driver(asc_dvc); - } else { - status = AdvInitAsc3550Driver(asc_dvc); - } + board->adv_sgblkp = NULL; + for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) { + sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL); - /* Translate initialization return value to status value. */ - if (status == 0) { - status = ADV_TRUE; - } else { - status = ADV_FALSE; - } + if (!sgp) + break; - /* - * Restore the BIOS signature word. - */ - AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + sgp->next_sgblkp = board->adv_sgblkp; + board->adv_sgblkp = sgp; - /* - * Restore per TID negotiated values. - */ - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); } - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - for (tid = 0; tid <= ADV_MAX_TID; tid++) { - AdvWriteByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + tid, - max_cmd[tid]); - } - - return status; -} - -/* - * Adv Library Interrupt Service Routine - * - * This function is called by a driver's interrupt service routine. - * The function disables and re-enables interrupts. - * - * When a microcode idle command is completed, the ADV_DVC_VAR - * 'idle_cmd_done' field is set to ADV_TRUE. - * - * Note: AdvISR() can be called when interrupts are disabled or even - * when there is no hardware interrupt condition present. It will - * always check for completed idle commands and microcode requests. - * This is an important feature that shouldn't be changed because it - * allows commands to be completed from polling mode loops. - * - * Return: - * ADV_TRUE(1) - interrupt was pending - * ADV_FALSE(0) - no interrupt was pending - */ -static int AdvISR(ADV_DVC_VAR *asc_dvc) -{ - AdvPortAddr iop_base; - uchar int_stat; - ushort target_bit; - ADV_CARR_T *free_carrp; - ADV_VADDR irq_next_vpa; - int flags; - ADV_SCSI_REQ_Q *scsiq; - - flags = DvcEnterCritical(); - - iop_base = asc_dvc->iop_base; - /* Reading the register clears the interrupt. */ - int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); + ASC_DBG(1, "sg_cnt %d * %lu = %lu bytes\n", sg_cnt, sizeof(adv_sgblk_t), + sizeof(adv_sgblk_t) * sg_cnt); - if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | - ADV_INTR_STATUS_INTRC)) == 0) { - DvcLeaveCritical(flags); - return ADV_FALSE; - } + if (!board->adv_sgblkp) + goto kmalloc_failed; /* - * Notify the driver of an asynchronous microcode condition by - * calling the ADV_DVC_VAR.async_callback function. The function - * is passed the microcode ASC_MC_INTRB_CODE byte value. + * Point 'adv_reqp' to the request structures and + * link them together. */ - if (int_stat & ADV_INTR_STATUS_INTRB) { - uchar intrb_code; - - AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); - - if (asc_dvc->chip_type == ADV_CHIP_ASC3550 || - asc_dvc->chip_type == ADV_CHIP_ASC38C0800) { - if (intrb_code == ADV_ASYNC_CARRIER_READY_FAILURE && - asc_dvc->carr_pending_cnt != 0) { - AdvWriteByteRegister(iop_base, IOPB_TICKLE, - ADV_TICKLE_A); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { - AdvWriteByteRegister(iop_base, - IOPB_TICKLE, - ADV_TICKLE_NOP); - } - } - } - - if (asc_dvc->async_callback != 0) { - (*asc_dvc->async_callback) (asc_dvc, intrb_code); - } + req_cnt--; + reqp[req_cnt].next_reqp = NULL; + for (; req_cnt > 0; req_cnt--) { + reqp[req_cnt - 1].next_reqp = &reqp[req_cnt]; } + board->adv_reqp = &reqp[0]; - /* - * Check if the IRQ stopper carrier contains a completed request. - */ - while (((irq_next_vpa = - le32_to_cpu(asc_dvc->irq_sp->next_vpa)) & ASC_RQ_DONE) != 0) { - /* - * Get a pointer to the newly completed ADV_SCSI_REQ_Q structure. - * The RISC will have set 'areq_vpa' to a virtual address. - * - * The firmware will have copied the ASC_SCSI_REQ_Q.scsiq_ptr - * field to the carrier ADV_CARR_T.areq_vpa field. The conversion - * below complements the conversion of ASC_SCSI_REQ_Q.scsiq_ptr' - * in AdvExeScsiQueue(). - */ - scsiq = (ADV_SCSI_REQ_Q *) - ADV_U32_TO_VADDR(le32_to_cpu(asc_dvc->irq_sp->areq_vpa)); - - /* - * Request finished with good status and the queue was not - * DMAed to host memory by the firmware. Set all status fields - * to indicate good status. - */ - if ((irq_next_vpa & ASC_RQ_GOOD) != 0) { - scsiq->done_status = QD_NO_ERROR; - scsiq->host_status = scsiq->scsi_status = 0; - scsiq->data_cnt = 0L; - } - - /* - * Advance the stopper pointer to the next carrier - * ignoring the lower four bits. Free the previous - * stopper carrier. - */ - free_carrp = asc_dvc->irq_sp; - asc_dvc->irq_sp = (ADV_CARR_T *) - ADV_U32_TO_VADDR(ASC_GET_CARRP(irq_next_vpa)); - - free_carrp->next_vpa = - cpu_to_le32(ADV_VADDR_TO_U32(asc_dvc->carr_freelist)); - asc_dvc->carr_freelist = free_carrp; - asc_dvc->carr_pending_cnt--; - - ASC_ASSERT(scsiq != NULL); - target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); - - /* - * Clear request microcode control flag. - */ - scsiq->cntl = 0; - - /* - * If the command that completed was a SCSI INQUIRY and - * LUN 0 was sent the command, then process the INQUIRY - * command information for the device. - * - * Note: If data returned were either VPD or CmdDt data, - * don't process the INQUIRY command information for - * the device, otherwise may erroneously set *_able bits. - */ - if (scsiq->done_status == QD_NO_ERROR && - scsiq->cdb[0] == INQUIRY && - scsiq->target_lun == 0 && - (scsiq->cdb[1] & ADV_INQ_RTN_VPD_AND_CMDDT) - == ADV_INQ_RTN_STD_INQUIRY_DATA) { - AdvInquiryHandling(asc_dvc, scsiq); - } - - /* - * Notify the driver of the completed request by passing - * the ADV_SCSI_REQ_Q pointer to its callback function. - */ - scsiq->a_flag |= ADV_SCSIQ_DONE; - (*asc_dvc->isr_callback) (asc_dvc, scsiq); - /* - * Note: After the driver callback function is called, 'scsiq' - * can no longer be referenced. - * - * Fall through and continue processing other completed - * requests... - */ - - /* - * Disable interrupts again in case the driver inadvertently - * enabled interrupts in its callback function. - * - * The DvcEnterCritical() return value is ignored, because - * the 'flags' saved when AdvISR() was first entered will be - * used to restore the interrupt flag on exit. - */ - (void)DvcEnterCritical(); + if (adv_dvc->chip_type == ADV_CHIP_ASC3550) { + ASC_DBG(2, "AdvInitAsc3550Driver()\n"); + warn_code = AdvInitAsc3550Driver(adv_dvc); + } else if (adv_dvc->chip_type == ADV_CHIP_ASC38C0800) { + ASC_DBG(2, "AdvInitAsc38C0800Driver()\n"); + warn_code = AdvInitAsc38C0800Driver(adv_dvc); + } else { + ASC_DBG(2, "AdvInitAsc38C1600Driver()\n"); + warn_code = AdvInitAsc38C1600Driver(adv_dvc); } - DvcLeaveCritical(flags); - return ADV_TRUE; -} + err_code = adv_dvc->err_code; -/* - * Send an idle command to the chip and wait for completion. - * - * Command completion is polled for once per microsecond. - * - * The function can be called from anywhere including an interrupt handler. - * But the function is not re-entrant, so it uses the DvcEnter/LeaveCritical() - * functions to prevent reentrancy. - * - * Return Values: - * ADV_TRUE - command completed successfully - * ADV_FALSE - command failed - * ADV_ERROR - command timed out - */ -static int -AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, - ushort idle_cmd, ADV_DCNT idle_cmd_parameter) -{ - ulong last_int_level; - int result; - ADV_DCNT i, j; - AdvPortAddr iop_base; - - last_int_level = DvcEnterCritical(); - - iop_base = asc_dvc->iop_base; - - /* - * Clear the idle command status which is set by the microcode - * to a non-zero value to indicate when the command is completed. - * The non-zero result is one of the IDLE_CMD_STATUS_* values - * defined in a_advlib.h. - */ - AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0); - - /* - * Write the idle command value after the idle command parameter - * has been written to avoid a race condition. If the order is not - * followed, the microcode may process the idle command before the - * parameters have been written to LRAM. - */ - AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, - cpu_to_le32(idle_cmd_parameter)); - AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); - - /* - * Tickle the RISC to tell it to process the idle command. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_B); - if (asc_dvc->chip_type == ADV_CHIP_ASC3550) { - /* - * Clear the tickle value. In the ASC-3550 the RISC flag - * command 'clr_tickle_b' does not work unless the host - * value is cleared. - */ - AdvWriteByteRegister(iop_base, IOPB_TICKLE, ADV_TICKLE_NOP); + if (warn_code || err_code) { + shost_printk(KERN_WARNING, shost, "error: warn 0x%x, error " + "0x%x\n", warn_code, err_code); } - /* Wait for up to 100 millisecond for the idle command to timeout. */ - for (i = 0; i < SCSI_WAIT_100_MSEC; i++) { - /* Poll once each microsecond for command completion. */ - for (j = 0; j < SCSI_US_PER_MSEC; j++) { - AdvReadWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, - result); - if (result != 0) { - DvcLeaveCritical(last_int_level); - return result; - } - DvcDelayMicroSecond(asc_dvc, (ushort)1); - } - } + goto exit; - ASC_ASSERT(0); /* The idle command should never timeout. */ - DvcLeaveCritical(last_int_level); - return ADV_ERROR; + kmalloc_failed: + shost_printk(KERN_ERR, shost, "error: kmalloc() failed\n"); + err_code = ADV_ERROR; + exit: + return err_code; } -/* - * Inquiry Information Byte 7 Handling - * - * Handle SCSI Inquiry Command information for a device by setting - * microcode operating variables that affect WDTR, SDTR, and Tag - * Queuing. - */ -static void AdvInquiryHandling(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) +static void advansys_wide_free_mem(struct asc_board *board) { - AdvPortAddr iop_base; - uchar tid; - ADV_SCSI_INQUIRY *inq; - ushort tidmask; - ushort cfg_word; - - /* - * AdvInquiryHandling() requires up to INQUIRY information Byte 7 - * to be available. - * - * If less than 8 bytes of INQUIRY information were requested or less - * than 8 bytes were transferred, then return. cdb[4] is the request - * length and the ADV_SCSI_REQ_Q 'data_cnt' field is set by the - * microcode to the transfer residual count. - */ - - if (scsiq->cdb[4] < 8 || - (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) { - return; - } - - iop_base = asc_dvc->iop_base; - tid = scsiq->target_id; - - inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr; - - /* - * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices. - */ - if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) { - return; - } else { - /* - * INQUIRY Byte 7 Handling - * - * Use a device's INQUIRY byte 7 to determine whether it - * supports WDTR, SDTR, and Tag Queuing. If the feature - * is enabled in the EEPROM and the device supports the - * feature, then enable it in the microcode. - */ - - tidmask = ADV_TID_TO_TIDMASK(tid); - - /* - * Wide Transfers - * - * If the EEPROM enabled WDTR for the device and the device - * supports wide bus (16 bit) transfers, then turn on the - * device's 'wdtr_able' bit and write the new value to the - * microcode. - */ - if ((asc_dvc->wdtr_able & tidmask) && ADV_INQ_WIDE16(inq)) { - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); - if ((cfg_word & tidmask) == 0) { - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, - cfg_word); - - /* - * Clear the microcode "SDTR negotiation" and "WDTR - * negotiation" done indicators for the target to cause - * it to negotiate with the new setting set above. - * WDTR when accepted causes the target to enter - * asynchronous mode, so SDTR must be negotiated. - */ - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, - cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, - cfg_word); - AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, - cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_WDTR_DONE, - cfg_word); - } - } - - /* - * Synchronous Transfers - * - * If the EEPROM enabled SDTR for the device and the device - * supports synchronous transfers, then turn on the device's - * 'sdtr_able' bit. Write the new value to the microcode. - */ - if ((asc_dvc->sdtr_able & tidmask) && ADV_INQ_SYNC(inq)) { - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, cfg_word); - if ((cfg_word & tidmask) == 0) { - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_ABLE, - cfg_word); - - /* - * Clear the microcode "SDTR negotiation" done indicator - * for the target to cause it to negotiate with the new - * setting set above. - */ - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, - cfg_word); - cfg_word &= ~tidmask; - AdvWriteWordLram(iop_base, ASC_MC_SDTR_DONE, - cfg_word); - } - } - /* - * If the Inquiry data included enough space for the SPI-3 - * Clocking field, then check if DT mode is supported. - */ - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600 && - (scsiq->cdb[4] >= 57 || - (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) >= 57)) { - /* - * PPR (Parallel Protocol Request) Capable - * - * If the device supports DT mode, then it must be PPR capable. - * The PPR message will be used in place of the SDTR and WDTR - * messages to negotiate synchronous speed and offset, transfer - * width, and protocol options. - */ - if (ADV_INQ_CLOCKING(inq) & ADV_INQ_CLOCKING_DT_ONLY) { - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, - asc_dvc->ppr_able); - asc_dvc->ppr_able |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_PPR_ABLE, - asc_dvc->ppr_able); - } - } - - /* - * If the EEPROM enabled Tag Queuing for the device and the - * device supports Tag Queueing, then turn on the device's - * 'tagqng_enable' bit in the microcode and set the microcode - * maximum command count to the ADV_DVC_VAR 'max_dvc_qng' - * value. - * - * Tag Queuing is disabled for the BIOS which runs in polled - * mode and would see no benefit from Tag Queuing. Also by - * disabling Tag Queuing in the BIOS devices with Tag Queuing - * bugs will at least work with the BIOS. - */ - if ((asc_dvc->tagqng_able & tidmask) && ADV_INQ_CMD_QUEUE(inq)) { - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, cfg_word); - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_TAGQNG_ABLE, - cfg_word); - - AdvWriteByteLram(iop_base, - ASC_MC_NUMBER_OF_MAX_CMD + tid, - asc_dvc->max_dvc_qng); - } + struct adv_dvc_var *adv_dvc = &board->dvc_var.adv_dvc_var; + kfree(adv_dvc->carrier_buf); + adv_dvc->carrier_buf = NULL; + kfree(adv_dvc->orig_reqp); + adv_dvc->orig_reqp = board->adv_reqp = NULL; + while (board->adv_sgblkp) { + adv_sgblk_t *sgp = board->adv_sgblkp; + board->adv_sgblkp = sgp->next_sgblkp; + kfree(sgp); } } -MODULE_LICENSE("Dual BSD/GPL"); - -static struct Scsi_Host *__devinit -advansys_board_found(int iop, struct device *dev, int bus_type) +static int __devinit advansys_board_found(struct Scsi_Host *shost, + unsigned int iop, int bus_type) { - struct Scsi_Host *shost; - struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL; - asc_board_t *boardp; + struct pci_dev *pdev; + struct asc_board *boardp = shost_priv(shost); ASC_DVC_VAR *asc_dvc_varp = NULL; ADV_DVC_VAR *adv_dvc_varp = NULL; - adv_sgblk_t *sgp = NULL; - int share_irq = FALSE; - int iolen = 0; - ADV_PADDR pci_memory_address; - int warn_code, err_code; - int ret; + int share_irq, warn_code, ret; - /* - * Adapter found. - * - * Register the adapter, get its configuration, and - * initialize it. - */ - ASC_DBG(2, "advansys_board_found: scsi_register()\n"); - shost = scsi_register(&driver_template, sizeof(asc_board_t)); - - if (!shost) - return NULL; - - /* Save a pointer to the Scsi_Host of each board found. */ - asc_host[asc_board_count++] = shost; - - /* Initialize private per board data */ - boardp = ASC_BOARDP(shost); - memset(boardp, 0, sizeof(asc_board_t)); - boardp->id = asc_board_count - 1; - - /* Initialize spinlock. */ - spin_lock_init(&boardp->lock); - - /* - * Handle both narrow and wide boards. - * - * If a Wide board was detected, set the board structure - * wide board flag. Set-up the board structure based on - * the board type. - */ -#ifdef CONFIG_PCI - if (bus_type == ASC_IS_PCI && - (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW || - pdev->device == PCI_DEVICE_ID_38C0800_REV1 || - pdev->device == PCI_DEVICE_ID_38C1600_REV1)) { - boardp->flags |= ASC_IS_WIDE_BOARD; - } -#endif /* CONFIG_PCI */ + pdev = (bus_type == ASC_IS_PCI) ? to_pci_dev(boardp->dev) : NULL; if (ASC_NARROW_BOARD(boardp)) { - ASC_DBG(1, "advansys_board_found: narrow board\n"); + ASC_DBG(1, "narrow board\n"); asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; asc_dvc_varp->bus_type = bus_type; asc_dvc_varp->drv_ptr = boardp; asc_dvc_varp->cfg = &boardp->dvc_cfg.asc_dvc_cfg; - asc_dvc_varp->cfg->overrun_buf = &overrun_buf[0]; asc_dvc_varp->iop_base = iop; - asc_dvc_varp->isr_callback = asc_isr_callback; } else { - ASC_DBG(1, "advansys_board_found: wide board\n"); +#ifdef CONFIG_PCI adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; adv_dvc_varp->drv_ptr = boardp; adv_dvc_varp->cfg = &boardp->dvc_cfg.adv_dvc_cfg; - adv_dvc_varp->isr_callback = adv_isr_callback; - adv_dvc_varp->async_callback = adv_async_callback; -#ifdef CONFIG_PCI if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW) { - ASC_DBG(1, "advansys_board_found: ASC-3550\n"); + ASC_DBG(1, "wide board ASC-3550\n"); adv_dvc_varp->chip_type = ADV_CHIP_ASC3550; } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) { - ASC_DBG(1, "advansys_board_found: ASC-38C0800\n"); + ASC_DBG(1, "wide board ASC-38C0800\n"); adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800; } else { - ASC_DBG(1, "advansys_board_found: ASC-38C1600\n"); + ASC_DBG(1, "wide board ASC-38C1600\n"); adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600; } -#endif /* CONFIG_PCI */ - /* - * Map the board's registers into virtual memory for - * PCI slave access. Only memory accesses are used to - * access the board's registers. - * - * Note: The PCI register base address is not always - * page aligned, but the address passed to ioremap() - * must be page aligned. It is guaranteed that the - * PCI register base address will not cross a page - * boundary. - */ - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - iolen = ADV_3550_IOLEN; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - iolen = ADV_38C0800_IOLEN; - } else { - iolen = ADV_38C1600_IOLEN; - } -#ifdef CONFIG_PCI - pci_memory_address = pci_resource_start(pdev, 1); - ASC_DBG1(1, - "advansys_board_found: pci_memory_address: 0x%lx\n", - (ulong)pci_memory_address); - if ((boardp->ioremap_addr = - ioremap(pci_memory_address & PAGE_MASK, PAGE_SIZE)) == 0) { - ASC_PRINT3 - ("advansys_board_found: board %d: ioremap(%x, %d) returned NULL\n", - boardp->id, pci_memory_address, iolen); - scsi_unregister(shost); - asc_board_count--; - return NULL; + boardp->asc_n_io_port = pci_resource_len(pdev, 1); + boardp->ioremap_addr = ioremap(pci_resource_start(pdev, 1), + boardp->asc_n_io_port); + if (!boardp->ioremap_addr) { + shost_printk(KERN_ERR, shost, "ioremap(%lx, %d) " + "returned NULL\n", + (long)pci_resource_start(pdev, 1), + boardp->asc_n_io_port); + ret = -ENODEV; + goto err_shost; } - ASC_DBG1(1, - "advansys_board_found: ioremap_addr: 0x%lx\n", - (ulong)boardp->ioremap_addr); - adv_dvc_varp->iop_base = (AdvPortAddr) - (boardp->ioremap_addr + - (pci_memory_address - (pci_memory_address & PAGE_MASK))); - ASC_DBG1(1, - "advansys_board_found: iop_base: 0x%lx\n", - adv_dvc_varp->iop_base); -#endif /* CONFIG_PCI */ + adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr; + ASC_DBG(1, "iop_base: 0x%p\n", adv_dvc_varp->iop_base); /* * Even though it isn't used to access wide boards, other @@ -17907,9 +13445,9 @@ advansys_board_found(int iop, struct device *dev, int bus_type) */ boardp->ioport = iop; - ASC_DBG2(1, - "advansys_board_found: iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n", - (ushort)inp(iop + 1), (ushort)inpw(iop)); + ASC_DBG(1, "iopb_chip_id_1 0x%x, iopw_chip_id_0 0x%x\n", + (ushort)inp(iop + 1), (ushort)inpw(iop)); +#endif /* CONFIG_PCI */ } #ifdef CONFIG_PROC_FS @@ -17917,18 +13455,16 @@ advansys_board_found(int iop, struct device *dev, int bus_type) * Allocate buffer for printing information from * /proc/scsi/advansys/[0...]. */ - if ((boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) { - ASC_PRINT3 - ("advansys_board_found: board %d: kmalloc(%d, %d) returned NULL\n", - boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC); - scsi_unregister(shost); - asc_board_count--; - return NULL; + boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL); + if (!boardp->prtbuf) { + shost_printk(KERN_ERR, shost, "kmalloc(%d) returned NULL\n", + ASC_PRTBUF_SIZE); + ret = -ENOMEM; + goto err_unmap; } #endif /* CONFIG_PROC_FS */ if (ASC_NARROW_BOARD(boardp)) { - asc_dvc_varp->cfg->dev = dev; /* * Set the board bus type and PCI IRQ before * calling AscInitGetConfig(). @@ -17937,127 +13473,56 @@ advansys_board_found(int iop, struct device *dev, int bus_type) #ifdef CONFIG_ISA case ASC_IS_ISA: shost->unchecked_isa_dma = TRUE; - share_irq = FALSE; + share_irq = 0; break; case ASC_IS_VL: shost->unchecked_isa_dma = FALSE; - share_irq = FALSE; + share_irq = 0; break; case ASC_IS_EISA: shost->unchecked_isa_dma = FALSE; - share_irq = TRUE; + share_irq = IRQF_SHARED; break; #endif /* CONFIG_ISA */ #ifdef CONFIG_PCI case ASC_IS_PCI: - shost->irq = asc_dvc_varp->irq_no = pdev->irq; - asc_dvc_varp->cfg->pci_slot_info = - ASC_PCI_MKID(pdev->bus->number, - PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn)); shost->unchecked_isa_dma = FALSE; - share_irq = TRUE; + share_irq = IRQF_SHARED; break; #endif /* CONFIG_PCI */ default: - ASC_PRINT2 - ("advansys_board_found: board %d: unknown adapter type: %d\n", - boardp->id, asc_dvc_varp->bus_type); + shost_printk(KERN_ERR, shost, "unknown adapter type: " + "%d\n", asc_dvc_varp->bus_type); shost->unchecked_isa_dma = TRUE; - share_irq = FALSE; + share_irq = 0; break; } - } else { - adv_dvc_varp->cfg->dev = dev; - /* - * For Wide boards set PCI information before calling - * AdvInitGetConfig(). - */ -#ifdef CONFIG_PCI - shost->irq = adv_dvc_varp->irq_no = pdev->irq; - adv_dvc_varp->cfg->pci_slot_info = - ASC_PCI_MKID(pdev->bus->number, - PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn)); - shost->unchecked_isa_dma = FALSE; - share_irq = TRUE; -#endif /* CONFIG_PCI */ - } - /* - * Read the board configuration. - */ - if (ASC_NARROW_BOARD(boardp)) { /* * NOTE: AscInitGetConfig() may change the board's * bus_type value. The bus_type value should no * longer be used. If the bus_type field must be * referenced only use the bit-wise AND operator "&". */ - ASC_DBG(2, "advansys_board_found: AscInitGetConfig()\n"); - switch (ret = AscInitGetConfig(asc_dvc_varp)) { - case 0: /* No error */ - break; - case ASC_WARN_IO_PORT_ROTATE: - ASC_PRINT1 - ("AscInitGetConfig: board %d: I/O port address modified\n", - boardp->id); - break; - case ASC_WARN_AUTO_CONFIG: - ASC_PRINT1 - ("AscInitGetConfig: board %d: I/O port increment switch enabled\n", - boardp->id); - break; - case ASC_WARN_EEPROM_CHKSUM: - ASC_PRINT1 - ("AscInitGetConfig: board %d: EEPROM checksum error\n", - boardp->id); - break; - case ASC_WARN_IRQ_MODIFIED: - ASC_PRINT1 - ("AscInitGetConfig: board %d: IRQ modified\n", - boardp->id); - break; - case ASC_WARN_CMD_QNG_CONFLICT: - ASC_PRINT1 - ("AscInitGetConfig: board %d: tag queuing enabled w/o disconnects\n", - boardp->id); - break; - default: - ASC_PRINT2 - ("AscInitGetConfig: board %d: unknown warning: 0x%x\n", - boardp->id, ret); - break; - } - if ((err_code = asc_dvc_varp->err_code) != 0) { - ASC_PRINT3 - ("AscInitGetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", - boardp->id, - asc_dvc_varp->init_state, asc_dvc_varp->err_code); - } + ASC_DBG(2, "AscInitGetConfig()\n"); + ret = AscInitGetConfig(shost) ? -ENODEV : 0; } else { - ASC_DBG(2, "advansys_board_found: AdvInitGetConfig()\n"); - if ((ret = AdvInitGetConfig(adv_dvc_varp)) != 0) { - ASC_PRINT2 - ("AdvInitGetConfig: board %d: warning: 0x%x\n", - boardp->id, ret); - } - if ((err_code = adv_dvc_varp->err_code) != 0) { - ASC_PRINT2 - ("AdvInitGetConfig: board %d error: err_code 0x%x\n", - boardp->id, adv_dvc_varp->err_code); - } - } +#ifdef CONFIG_PCI + /* + * For Wide boards set PCI information before calling + * AdvInitGetConfig(). + */ + shost->unchecked_isa_dma = FALSE; + share_irq = IRQF_SHARED; + ASC_DBG(2, "AdvInitGetConfig()\n"); - if (err_code != 0) { -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shost); - asc_board_count--; - return NULL; + ret = AdvInitGetConfig(pdev, shost) ? -ENODEV : 0; +#endif /* CONFIG_PCI */ } + if (ret) + goto err_free_proc; + /* * Save the EEPROM configuration so that it can be displayed * from /proc/scsi/advansys/[0...]. @@ -18098,61 +13563,10 @@ advansys_board_found(int iop, struct device *dev, int bus_type) /* * Modify board configuration. */ - ASC_DBG(2, "advansys_board_found: AscInitSetConfig()\n"); - switch (ret = AscInitSetConfig(asc_dvc_varp)) { - case 0: /* No error. */ - break; - case ASC_WARN_IO_PORT_ROTATE: - ASC_PRINT1 - ("AscInitSetConfig: board %d: I/O port address modified\n", - boardp->id); - break; - case ASC_WARN_AUTO_CONFIG: - ASC_PRINT1 - ("AscInitSetConfig: board %d: I/O port increment switch enabled\n", - boardp->id); - break; - case ASC_WARN_EEPROM_CHKSUM: - ASC_PRINT1 - ("AscInitSetConfig: board %d: EEPROM checksum error\n", - boardp->id); - break; - case ASC_WARN_IRQ_MODIFIED: - ASC_PRINT1 - ("AscInitSetConfig: board %d: IRQ modified\n", - boardp->id); - break; - case ASC_WARN_CMD_QNG_CONFLICT: - ASC_PRINT1 - ("AscInitSetConfig: board %d: tag queuing w/o disconnects\n", - boardp->id); - break; - default: - ASC_PRINT2 - ("AscInitSetConfig: board %d: unknown warning: 0x%x\n", - boardp->id, ret); - break; - } - if (asc_dvc_varp->err_code != 0) { - ASC_PRINT3 - ("AscInitSetConfig: board %d error: init_state 0x%x, err_code 0x%x\n", - boardp->id, - asc_dvc_varp->init_state, asc_dvc_varp->err_code); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shost); - asc_board_count--; - return NULL; - } - - /* - * Finish initializing the 'Scsi_Host' structure. - */ - /* AscInitSetConfig() will set the IRQ for non-PCI boards. */ - if ((asc_dvc_varp->bus_type & ASC_IS_PCI) == 0) { - shost->irq = asc_dvc_varp->irq_no; - } + ASC_DBG(2, "AscInitSetConfig()\n"); + ret = AscInitSetConfig(pdev, shost) ? -ENODEV : 0; + if (ret) + goto err_free_proc; } else { ADVEEP_3550_CONFIG *ep_3550; ADVEEP_38C0800_CONFIG *ep_38C0800; @@ -18246,11 +13660,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type) */ boardp->init_tidmask |= ADV_TID_TO_TIDMASK(adv_dvc_varp->chip_scsi_id); - - /* - * Finish initializing the 'Scsi_Host' structure. - */ - shost->irq = adv_dvc_varp->irq_no; } /* @@ -18262,6 +13671,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type) if (ASC_NARROW_BOARD(boardp)) { shost->max_id = ASC_MAX_TID + 1; shost->max_lun = ASC_MAX_LUN + 1; + shost->max_cmd_len = ASC_MAX_CDB_LEN; shost->io_port = asc_dvc_varp->iop_base; boardp->asc_n_io_port = ASC_IOADR_GAP; @@ -18272,6 +13682,7 @@ advansys_board_found(int iop, struct device *dev, int bus_type) } else { shost->max_id = ADV_MAX_TID + 1; shost->max_lun = ADV_MAX_LUN + 1; + shost->max_cmd_len = ADV_MAX_CDB_LEN; /* * Save the I/O Port address and length even though @@ -18280,7 +13691,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type) * PCI Memory Mapped I/O. */ shost->io_port = iop; - boardp->asc_n_io_port = iolen; shost->this_id = adv_dvc_varp->chip_scsi_id; @@ -18289,15 +13699,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type) } /* - * 'n_io_port' currently is one byte. - * - * Set a value to 'n_io_port', but never referenced it because - * it may be truncated. - */ - shost->n_io_port = boardp->asc_n_io_port <= 255 ? - boardp->asc_n_io_port : 255; - - /* * Following v1.3.89, 'cmd_per_lun' is no longer needed * and should be set to zero. * @@ -18343,14 +13744,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type) shost->sg_tablesize = SG_ALL; } - ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize); + ASC_DBG(1, "sg_tablesize: %d\n", shost->sg_tablesize); /* BIOS start address. */ if (ASC_NARROW_BOARD(boardp)) { - shost->base = ((ulong) - AscGetChipBiosAddress(asc_dvc_varp-> - iop_base, - asc_dvc_varp->bus_type)); + shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base, + asc_dvc_varp->bus_type); } else { /* * Fill-in BIOS board variables. The Wide BIOS saves @@ -18365,12 +13764,10 @@ advansys_board_found(int iop, struct device *dev, int bus_type) AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN, boardp->bios_codelen); - ASC_DBG2(1, - "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n", + ASC_DBG(1, "bios_signature 0x%x, bios_version 0x%x\n", boardp->bios_signature, boardp->bios_version); - ASC_DBG2(1, - "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n", + ASC_DBG(1, "bios_codeseg 0x%x, bios_codelen 0x%x\n", boardp->bios_codeseg, boardp->bios_codelen); /* @@ -18392,30 +13789,6 @@ advansys_board_found(int iop, struct device *dev, int bus_type) * Register Board Resources - I/O Port, DMA, IRQ */ - /* - * Register I/O port range. - * - * For Wide boards the I/O ports are not used to access - * the board, but request the region anyway. - * - * 'shost->n_io_port' is not referenced, because it may be truncated. - */ - ASC_DBG2(2, - "advansys_board_found: request_region port 0x%lx, len 0x%x\n", - (ulong)shost->io_port, boardp->asc_n_io_port); - if (request_region(shost->io_port, boardp->asc_n_io_port, - "advansys") == NULL) { - ASC_PRINT3 - ("advansys_board_found: board %d: request_region() failed, port 0x%lx, len 0x%x\n", - boardp->id, (ulong)shost->io_port, boardp->asc_n_io_port); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shost); - asc_board_count--; - return NULL; - } - /* Register DMA Channel for Narrow boards. */ shost->dma_channel = NO_ISA_DMA; /* Default to no ISA DMA. */ #ifdef CONFIG_ISA @@ -18423,19 +13796,12 @@ advansys_board_found(int iop, struct device *dev, int bus_type) /* Register DMA channel for ISA bus. */ if (asc_dvc_varp->bus_type & ASC_IS_ISA) { shost->dma_channel = asc_dvc_varp->cfg->isa_dma_channel; - if ((ret = - request_dma(shost->dma_channel, "advansys")) != 0) { - ASC_PRINT3 - ("advansys_board_found: board %d: request_dma() %d failed %d\n", - boardp->id, shost->dma_channel, ret); - release_region(shost->io_port, - boardp->asc_n_io_port); -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shost); - asc_board_count--; - return NULL; + ret = request_dma(shost->dma_channel, DRV_NAME); + if (ret) { + shost_printk(KERN_ERR, shost, "request_dma() " + "%d failed %d\n", + shost->dma_channel, ret); + goto err_free_proc; } AscEnableIsaDma(shost->dma_channel); } @@ -18443,573 +13809,392 @@ advansys_board_found(int iop, struct device *dev, int bus_type) #endif /* CONFIG_ISA */ /* Register IRQ Number. */ - ASC_DBG1(2, "advansys_board_found: request_irq() %d\n", shost->irq); - /* - * If request_irq() fails with the IRQF_DISABLED flag set, - * then try again without the IRQF_DISABLED flag set. This - * allows IRQ sharing to work even with other drivers that - * do not set the IRQF_DISABLED flag. - * - * If IRQF_DISABLED is not set, then interrupts are enabled - * before the driver interrupt function is called. - */ - if (((ret = request_irq(shost->irq, advansys_interrupt, - IRQF_DISABLED | (share_irq == - TRUE ? - IRQF_SHARED : - 0), "advansys", boardp)) != 0) - && - ((ret = - request_irq(shost->irq, advansys_interrupt, - (share_irq == TRUE ? IRQF_SHARED : 0), - "advansys", boardp)) != 0)) { + ASC_DBG(2, "request_irq(%d, %p)\n", boardp->irq, shost); + + ret = request_irq(boardp->irq, advansys_interrupt, share_irq, + DRV_NAME, shost); + + if (ret) { if (ret == -EBUSY) { - ASC_PRINT2 - ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n", - boardp->id, shost->irq); + shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x " + "already in use\n", boardp->irq); } else if (ret == -EINVAL) { - ASC_PRINT2 - ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n", - boardp->id, shost->irq); + shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x " + "not valid\n", boardp->irq); } else { - ASC_PRINT3 - ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n", - boardp->id, shost->irq, ret); + shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x " + "failed with %d\n", boardp->irq, ret); } - release_region(shost->io_port, boardp->asc_n_io_port); - iounmap(boardp->ioremap_addr); - if (shost->dma_channel != NO_ISA_DMA) { - free_dma(shost->dma_channel); - } -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shost); - asc_board_count--; - return NULL; + goto err_free_dma; } /* * Initialize board RISC chip and enable interrupts. */ if (ASC_NARROW_BOARD(boardp)) { - ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n"); + ASC_DBG(2, "AscInitAsc1000Driver()\n"); warn_code = AscInitAsc1000Driver(asc_dvc_varp); - err_code = asc_dvc_varp->err_code; - if (warn_code || err_code) { - ASC_PRINT4 - ("advansys_board_found: board %d error: init_state 0x%x, warn 0x%x, error 0x%x\n", - boardp->id, - asc_dvc_varp->init_state, warn_code, err_code); + if (warn_code || asc_dvc_varp->err_code) { + shost_printk(KERN_ERR, shost, "error: init_state 0x%x, " + "warn 0x%x, error 0x%x\n", + asc_dvc_varp->init_state, warn_code, + asc_dvc_varp->err_code); + if (asc_dvc_varp->err_code) + ret = -ENODEV; } } else { - ADV_CARR_T *carrp; - int req_cnt = 0; - adv_req_t *reqp = NULL; - int sg_cnt = 0; - - /* - * Allocate buffer carrier structures. The total size - * is about 4 KB, so allocate all at once. - */ - carrp = (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC); - ASC_DBG1(1, "advansys_board_found: carrp 0x%lx\n", (ulong)carrp); - - if (carrp == NULL) { - goto kmalloc_error; - } + if (advansys_wide_init_chip(shost)) + ret = -ENODEV; + } - /* - * Allocate up to 'max_host_qng' request structures for - * the Wide board. The total size is about 16 KB, so - * allocate all at once. If the allocation fails decrement - * and try again. - */ - for (req_cnt = adv_dvc_varp->max_host_qng; - req_cnt > 0; req_cnt--) { + if (ret) + goto err_free_wide_mem; - reqp = (adv_req_t *) - kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC); + ASC_DBG_PRT_SCSI_HOST(2, shost); - ASC_DBG3(1, - "advansys_board_found: reqp 0x%lx, req_cnt %d, bytes %lu\n", - (ulong)reqp, req_cnt, - (ulong)sizeof(adv_req_t) * req_cnt); + ret = scsi_add_host(shost, boardp->dev); + if (ret) + goto err_free_wide_mem; - if (reqp != NULL) { - break; - } - } - if (reqp == NULL) { - goto kmalloc_error; - } + scsi_scan_host(shost); + return 0; - /* - * Allocate up to ADV_TOT_SG_BLOCK request structures for - * the Wide board. Each structure is about 136 bytes. - */ - boardp->adv_sgblkp = NULL; - for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) { + err_free_wide_mem: + advansys_wide_free_mem(boardp); + free_irq(boardp->irq, shost); + err_free_dma: + if (shost->dma_channel != NO_ISA_DMA) + free_dma(shost->dma_channel); + err_free_proc: + kfree(boardp->prtbuf); + err_unmap: + if (boardp->ioremap_addr) + iounmap(boardp->ioremap_addr); + err_shost: + return ret; +} - sgp = (adv_sgblk_t *) - kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC); +/* + * advansys_release() + * + * Release resources allocated for a single AdvanSys adapter. + */ +static int advansys_release(struct Scsi_Host *shost) +{ + struct asc_board *board = shost_priv(shost); + ASC_DBG(1, "begin\n"); + scsi_remove_host(shost); + free_irq(board->irq, shost); + if (shost->dma_channel != NO_ISA_DMA) { + ASC_DBG(1, "free_dma()\n"); + free_dma(shost->dma_channel); + } + if (ASC_NARROW_BOARD(board)) { + dma_unmap_single(board->dev, + board->dvc_var.asc_dvc_var.overrun_dma, + ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); + } else { + iounmap(board->ioremap_addr); + advansys_wide_free_mem(board); + } + kfree(board->prtbuf); + scsi_host_put(shost); + ASC_DBG(1, "end\n"); + return 0; +} - if (sgp == NULL) { - break; - } +#define ASC_IOADR_TABLE_MAX_IX 11 - sgp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgp; +static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = { + 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190, + 0x0210, 0x0230, 0x0250, 0x0330 +}; - } - ASC_DBG3(1, - "advansys_board_found: sg_cnt %d * %u = %u bytes\n", - sg_cnt, sizeof(adv_sgblk_t), - (unsigned)(sizeof(adv_sgblk_t) * sg_cnt)); +/* + * The ISA IRQ number is found in bits 2 and 3 of the CfgLsw. It decodes as: + * 00: 10 + * 01: 11 + * 10: 12 + * 11: 15 + */ +static unsigned int __devinit advansys_isa_irq_no(PortAddr iop_base) +{ + unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base); + unsigned int chip_irq = ((cfg_lsw >> 2) & 0x03) + 10; + if (chip_irq == 13) + chip_irq = 15; + return chip_irq; +} - /* - * If no request structures or scatter-gather structures could - * be allocated, then return an error. Otherwise continue with - * initialization. - */ - kmalloc_error: - if (carrp == NULL) { - ASC_PRINT1 - ("advansys_board_found: board %d error: failed to kmalloc() carrier buffer.\n", - boardp->id); - err_code = ADV_ERROR; - } else if (reqp == NULL) { - kfree(carrp); - ASC_PRINT1 - ("advansys_board_found: board %d error: failed to kmalloc() adv_req_t buffer.\n", - boardp->id); - err_code = ADV_ERROR; - } else if (boardp->adv_sgblkp == NULL) { - kfree(carrp); - kfree(reqp); - ASC_PRINT1 - ("advansys_board_found: board %d error: failed to kmalloc() adv_sgblk_t buffers.\n", - boardp->id); - err_code = ADV_ERROR; - } else { +static int __devinit advansys_isa_probe(struct device *dev, unsigned int id) +{ + int err = -ENODEV; + PortAddr iop_base = _asc_def_iop_base[id]; + struct Scsi_Host *shost; + struct asc_board *board; - /* Save carrier buffer pointer. */ - boardp->orig_carrp = carrp; + if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) { + ASC_DBG(1, "I/O port 0x%x busy\n", iop_base); + return -ENODEV; + } + ASC_DBG(1, "probing I/O port 0x%x\n", iop_base); + if (!AscFindSignature(iop_base)) + goto release_region; + if (!(AscGetChipVersion(iop_base, ASC_IS_ISA) & ASC_CHIP_VER_ISA_BIT)) + goto release_region; - /* - * Save original pointer for kfree() in case the - * driver is built as a module and can be unloaded. - */ - boardp->orig_reqp = reqp; + err = -ENOMEM; + shost = scsi_host_alloc(&advansys_template, sizeof(*board)); + if (!shost) + goto release_region; - adv_dvc_varp->carrier_buf = carrp; + board = shost_priv(shost); + board->irq = advansys_isa_irq_no(iop_base); + board->dev = dev; - /* - * Point 'adv_reqp' to the request structures and - * link them together. - */ - req_cnt--; - reqp[req_cnt].next_reqp = NULL; - for (; req_cnt > 0; req_cnt--) { - reqp[req_cnt - 1].next_reqp = &reqp[req_cnt]; - } - boardp->adv_reqp = &reqp[0]; - - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - ASC_DBG(2, - "advansys_board_found: AdvInitAsc3550Driver()\n"); - warn_code = AdvInitAsc3550Driver(adv_dvc_varp); - } else if (adv_dvc_varp->chip_type == - ADV_CHIP_ASC38C0800) { - ASC_DBG(2, - "advansys_board_found: AdvInitAsc38C0800Driver()\n"); - warn_code = - AdvInitAsc38C0800Driver(adv_dvc_varp); - } else { - ASC_DBG(2, - "advansys_board_found: AdvInitAsc38C1600Driver()\n"); - warn_code = - AdvInitAsc38C1600Driver(adv_dvc_varp); - } - err_code = adv_dvc_varp->err_code; + err = advansys_board_found(shost, iop_base, ASC_IS_ISA); + if (err) + goto free_host; - if (warn_code || err_code) { - ASC_PRINT3 - ("advansys_board_found: board %d error: warn 0x%x, error 0x%x\n", - boardp->id, warn_code, err_code); - } - } - } + dev_set_drvdata(dev, shost); + return 0; - if (err_code != 0) { - release_region(shost->io_port, boardp->asc_n_io_port); - if (ASC_WIDE_BOARD(boardp)) { - iounmap(boardp->ioremap_addr); - kfree(boardp->orig_carrp); - boardp->orig_carrp = NULL; - if (boardp->orig_reqp) { - kfree(boardp->orig_reqp); - boardp->orig_reqp = boardp->adv_reqp = NULL; - } - while ((sgp = boardp->adv_sgblkp) != NULL) { - boardp->adv_sgblkp = sgp->next_sgblkp; - kfree(sgp); - } - } - if (shost->dma_channel != NO_ISA_DMA) { - free_dma(shost->dma_channel); - } -#ifdef CONFIG_PROC_FS - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - free_irq(shost->irq, boardp); - scsi_unregister(shost); - asc_board_count--; - return NULL; - } - ASC_DBG_PRT_SCSI_HOST(2, shost); + free_host: + scsi_host_put(shost); + release_region: + release_region(iop_base, ASC_IOADR_GAP); + return err; +} - return shost; +static int __devexit advansys_isa_remove(struct device *dev, unsigned int id) +{ + int ioport = _asc_def_iop_base[id]; + advansys_release(dev_get_drvdata(dev)); + release_region(ioport, ASC_IOADR_GAP); + return 0; } +static struct isa_driver advansys_isa_driver = { + .probe = advansys_isa_probe, + .remove = __devexit_p(advansys_isa_remove), + .driver = { + .owner = THIS_MODULE, + .name = DRV_NAME, + }, +}; + /* - * advansys_detect() - * - * Detect function for AdvanSys adapters. - * - * Argument is a pointer to the host driver's scsi_hosts entry. - * - * Return number of adapters found. - * - * Note: Because this function is called during system initialization - * it must not call SCSI mid-level functions including scsi_malloc() - * and scsi_free(). + * The VLB IRQ number is found in bits 2 to 4 of the CfgLsw. It decodes as: + * 000: invalid + * 001: 10 + * 010: 11 + * 011: 12 + * 100: invalid + * 101: 14 + * 110: 15 + * 111: invalid */ -static int __init advansys_detect(struct scsi_host_template *tpnt) +static unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base) { - static int detect_called = ASC_FALSE; - int iop; - int bus; - int ioport = 0; - struct device *dev = NULL; -#ifdef CONFIG_PCI - int pci_init_search = 0; - struct pci_dev *pci_devicep[ASC_NUM_BOARD_SUPPORTED]; - int pci_card_cnt_max = 0; - int pci_card_cnt = 0; - struct pci_dev *pdev = NULL; - int pci_device_id_cnt = 0; - unsigned int pci_device_id[ASC_PCI_DEVICE_ID_CNT] = { - PCI_DEVICE_ID_ASP_1200A, - PCI_DEVICE_ID_ASP_ABP940, - PCI_DEVICE_ID_ASP_ABP940U, - PCI_DEVICE_ID_ASP_ABP940UW, - PCI_DEVICE_ID_38C0800_REV1, - PCI_DEVICE_ID_38C1600_REV1 - }; -#endif /* CONFIG_PCI */ - - if (detect_called == ASC_FALSE) { - detect_called = ASC_TRUE; - } else { - printk - ("AdvanSys SCSI: advansys_detect() multiple calls ignored\n"); + unsigned short cfg_lsw = AscGetChipCfgLsw(iop_base); + unsigned int chip_irq = ((cfg_lsw >> 2) & 0x07) + 9; + if ((chip_irq < 10) || (chip_irq == 13) || (chip_irq > 15)) return 0; - } - - ASC_DBG(1, "advansys_detect: begin\n"); + return chip_irq; +} - asc_board_count = 0; +static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id) +{ + int err = -ENODEV; + PortAddr iop_base = _asc_def_iop_base[id]; + struct Scsi_Host *shost; + struct asc_board *board; + if (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) { + ASC_DBG(1, "I/O port 0x%x busy\n", iop_base); + return -ENODEV; + } + ASC_DBG(1, "probing I/O port 0x%x\n", iop_base); + if (!AscFindSignature(iop_base)) + goto release_region; /* - * If I/O port probing has been modified, then verify and - * clean-up the 'asc_ioport' list. + * I don't think this condition can actually happen, but the old + * driver did it, and the chances of finding a VLB setup in 2007 + * to do testing with is slight to none. */ - if (asc_iopflag == ASC_TRUE) { - for (ioport = 0; ioport < ASC_NUM_IOPORT_PROBE; ioport++) { - ASC_DBG2(1, "advansys_detect: asc_ioport[%d] 0x%x\n", - ioport, asc_ioport[ioport]); - if (asc_ioport[ioport] != 0) { - for (iop = 0; iop < ASC_IOADR_TABLE_MAX_IX; - iop++) { - if (_asc_def_iop_base[iop] == - asc_ioport[ioport]) { - break; - } - } - if (iop == ASC_IOADR_TABLE_MAX_IX) { - printk - ("AdvanSys SCSI: specified I/O Port 0x%X is invalid\n", - asc_ioport[ioport]); - asc_ioport[ioport] = 0; - } - } - } - ioport = 0; - } + if (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL) + goto release_region; - for (bus = 0; bus < ASC_NUM_BUS; bus++) { + err = -ENOMEM; + shost = scsi_host_alloc(&advansys_template, sizeof(*board)); + if (!shost) + goto release_region; - ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", - bus, asc_bus_name[bus]); - iop = 0; + board = shost_priv(shost); + board->irq = advansys_vlb_irq_no(iop_base); + board->dev = dev; - while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { + err = advansys_board_found(shost, iop_base, ASC_IS_VL); + if (err) + goto free_host; - ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", - asc_board_count); + dev_set_drvdata(dev, shost); + return 0; - switch (asc_bus[bus]) { - case ASC_IS_ISA: - case ASC_IS_VL: -#ifdef CONFIG_ISA - if (asc_iopflag == ASC_FALSE) { - iop = - AscSearchIOPortAddr(iop, - asc_bus[bus]); - } else { - /* - * ISA and VL I/O port scanning has either been - * eliminated or limited to selected ports on - * the LILO command line, /etc/lilo.conf, or - * by setting variables when the module was loaded. - */ - ASC_DBG(1, - "advansys_detect: I/O port scanning modified\n"); - ioport_try_again: - iop = 0; - for (; ioport < ASC_NUM_IOPORT_PROBE; - ioport++) { - if ((iop = - asc_ioport[ioport]) != 0) { - break; - } - } - if (iop) { - ASC_DBG1(1, - "advansys_detect: probing I/O port 0x%x...\n", - iop); - if (!request_region - (iop, ASC_IOADR_GAP, - "advansys")) { - printk - ("AdvanSys SCSI: specified I/O Port 0x%X is busy\n", - iop); - /* Don't try this I/O port twice. */ - asc_ioport[ioport] = 0; - goto ioport_try_again; - } else if (AscFindSignature(iop) - == ASC_FALSE) { - printk - ("AdvanSys SCSI: specified I/O Port 0x%X has no adapter\n", - iop); - /* Don't try this I/O port twice. */ - release_region(iop, - ASC_IOADR_GAP); - asc_ioport[ioport] = 0; - goto ioport_try_again; - } else { - /* - * If this isn't an ISA board, then it must be - * a VL board. If currently looking an ISA - * board is being looked for then try for - * another ISA board in 'asc_ioport'. - */ - if (asc_bus[bus] == - ASC_IS_ISA - && - (AscGetChipVersion - (iop, - ASC_IS_ISA) & - ASC_CHIP_VER_ISA_BIT) - == 0) { - /* - * Don't clear 'asc_ioport[ioport]'. Try - * this board again for VL. Increment - * 'ioport' past this board. - */ - ioport++; - release_region - (iop, - ASC_IOADR_GAP); - goto ioport_try_again; - } - } - /* - * This board appears good, don't try the I/O port - * again by clearing its value. Increment 'ioport' - * for the next iteration. - */ - asc_ioport[ioport++] = 0; - } - } -#endif /* CONFIG_ISA */ - break; + free_host: + scsi_host_put(shost); + release_region: + release_region(iop_base, ASC_IOADR_GAP); + return -ENODEV; +} - case ASC_IS_EISA: -#ifdef CONFIG_ISA - iop = AscSearchIOPortAddr(iop, asc_bus[bus]); -#endif /* CONFIG_ISA */ - break; +static struct isa_driver advansys_vlb_driver = { + .probe = advansys_vlb_probe, + .remove = __devexit_p(advansys_isa_remove), + .driver = { + .owner = THIS_MODULE, + .name = "advansys_vlb", + }, +}; - case ASC_IS_PCI: -#ifdef CONFIG_PCI - if (pci_init_search == 0) { - int i, j; - - pci_init_search = 1; - - /* Find all PCI cards. */ - while (pci_device_id_cnt < - ASC_PCI_DEVICE_ID_CNT) { - if ((pdev = - pci_find_device - (PCI_VENDOR_ID_ASP, - pci_device_id - [pci_device_id_cnt], - pdev)) == NULL) { - pci_device_id_cnt++; - } else { - if (pci_enable_device - (pdev) == 0) { - pci_devicep - [pci_card_cnt_max++] - = pdev; - } - } - } +static struct eisa_device_id advansys_eisa_table[] __devinitdata = { + { "ABP7401" }, + { "ABP7501" }, + { "" } +}; - /* - * Sort PCI cards in ascending order by PCI Bus, Slot, - * and Device Number. - */ - for (i = 0; i < pci_card_cnt_max - 1; - i++) { - for (j = i + 1; - j < pci_card_cnt_max; - j++) { - if ((pci_devicep[j]-> - bus->number < - pci_devicep[i]-> - bus->number) - || - ((pci_devicep[j]-> - bus->number == - pci_devicep[i]-> - bus->number) - && - (pci_devicep[j]-> - devfn < - pci_devicep[i]-> - devfn))) { - pdev = - pci_devicep - [i]; - pci_devicep[i] = - pci_devicep - [j]; - pci_devicep[j] = - pdev; - } - } - } +MODULE_DEVICE_TABLE(eisa, advansys_eisa_table); - pci_card_cnt = 0; - } else { - pci_card_cnt++; - } +/* + * EISA is a little more tricky than PCI; each EISA device may have two + * channels, and this driver is written to make each channel its own Scsi_Host + */ +struct eisa_scsi_data { + struct Scsi_Host *host[2]; +}; - if (pci_card_cnt == pci_card_cnt_max) { - iop = 0; - } else { - pdev = pci_devicep[pci_card_cnt]; - - ASC_DBG2(2, - "advansys_detect: devfn %d, bus number %d\n", - pdev->devfn, - pdev->bus->number); - iop = pci_resource_start(pdev, 0); - ASC_DBG2(1, - "advansys_detect: vendorID %X, deviceID %X\n", - pdev->vendor, - pdev->device); - ASC_DBG2(2, - "advansys_detect: iop %X, irqLine %d\n", - iop, pdev->irq); - } - if (pdev) - dev = &pdev->dev; +/* + * The EISA IRQ number is found in bits 8 to 10 of the CfgLsw. It decodes as: + * 000: 10 + * 001: 11 + * 010: 12 + * 011: invalid + * 100: 14 + * 101: 15 + * 110: invalid + * 111: invalid + */ +static unsigned int __devinit advansys_eisa_irq_no(struct eisa_device *edev) +{ + unsigned short cfg_lsw = inw(edev->base_addr + 0xc86); + unsigned int chip_irq = ((cfg_lsw >> 8) & 0x07) + 10; + if ((chip_irq == 13) || (chip_irq > 15)) + return 0; + return chip_irq; +} -#endif /* CONFIG_PCI */ - break; +static int __devinit advansys_eisa_probe(struct device *dev) +{ + int i, ioport, irq = 0; + int err; + struct eisa_device *edev = to_eisa_device(dev); + struct eisa_scsi_data *data; - default: - ASC_PRINT1 - ("advansys_detect: unknown bus type: %d\n", - asc_bus[bus]); - break; - } - ASC_DBG1(1, "advansys_detect: iop 0x%x\n", iop); + err = -ENOMEM; + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) + goto fail; + ioport = edev->base_addr + 0xc30; - /* - * Adapter not found, try next bus type. - */ - if (iop == 0) { - break; - } + err = -ENODEV; + for (i = 0; i < 2; i++, ioport += 0x20) { + struct asc_board *board; + struct Scsi_Host *shost; + if (!request_region(ioport, ASC_IOADR_GAP, DRV_NAME)) { + printk(KERN_WARNING "Region %x-%x busy\n", ioport, + ioport + ASC_IOADR_GAP - 1); + continue; + } + if (!AscFindSignature(ioport)) { + release_region(ioport, ASC_IOADR_GAP); + continue; + } - advansys_board_found(iop, dev, asc_bus[bus]); + /* + * I don't know why we need to do this for EISA chips, but + * not for any others. It looks to be equivalent to + * AscGetChipCfgMsw, but I may have overlooked something, + * so I'm not converting it until I get an EISA board to + * test with. + */ + inw(ioport + 4); + + if (!irq) + irq = advansys_eisa_irq_no(edev); + + err = -ENOMEM; + shost = scsi_host_alloc(&advansys_template, sizeof(*board)); + if (!shost) + goto release_region; + + board = shost_priv(shost); + board->irq = irq; + board->dev = dev; + + err = advansys_board_found(shost, ioport, ASC_IS_EISA); + if (!err) { + data->host[i] = shost; + continue; } + + scsi_host_put(shost); + release_region: + release_region(ioport, ASC_IOADR_GAP); + break; } - ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", - asc_board_count); - return asc_board_count; + if (err) + goto free_data; + dev_set_drvdata(dev, data); + return 0; + + free_data: + kfree(data->host[0]); + kfree(data->host[1]); + kfree(data); + fail: + return err; } -/* - * advansys_release() - * - * Release resources allocated for a single AdvanSys adapter. - */ -static int advansys_release(struct Scsi_Host *shost) +static __devexit int advansys_eisa_remove(struct device *dev) { - asc_board_t *boardp; + int i; + struct eisa_scsi_data *data = dev_get_drvdata(dev); - ASC_DBG(1, "advansys_release: begin\n"); - boardp = ASC_BOARDP(shost); - free_irq(shost->irq, boardp); - if (shost->dma_channel != NO_ISA_DMA) { - ASC_DBG(1, "advansys_release: free_dma()\n"); - free_dma(shost->dma_channel); + for (i = 0; i < 2; i++) { + int ioport; + struct Scsi_Host *shost = data->host[i]; + if (!shost) + continue; + ioport = shost->io_port; + advansys_release(shost); + release_region(ioport, ASC_IOADR_GAP); } - release_region(shost->io_port, boardp->asc_n_io_port); - if (ASC_WIDE_BOARD(boardp)) { - adv_sgblk_t *sgp = NULL; - iounmap(boardp->ioremap_addr); - kfree(boardp->orig_carrp); - boardp->orig_carrp = NULL; - if (boardp->orig_reqp) { - kfree(boardp->orig_reqp); - boardp->orig_reqp = boardp->adv_reqp = NULL; - } - while ((sgp = boardp->adv_sgblkp) != NULL) { - boardp->adv_sgblkp = sgp->next_sgblkp; - kfree(sgp); - } - } -#ifdef CONFIG_PROC_FS - ASC_ASSERT(boardp->prtbuf != NULL); - kfree(boardp->prtbuf); -#endif /* CONFIG_PROC_FS */ - scsi_unregister(shost); - ASC_DBG(1, "advansys_release: end\n"); + kfree(data); return 0; } -#ifdef CONFIG_PCI +static struct eisa_driver advansys_eisa_driver = { + .id_table = advansys_eisa_table, + .driver = { + .name = DRV_NAME, + .probe = advansys_eisa_probe, + .remove = __devexit_p(advansys_eisa_remove), + } +}; + /* PCI Devices supported by this driver */ static struct pci_device_id advansys_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A, @@ -19028,4 +14213,131 @@ static struct pci_device_id advansys_pci_tbl[] __devinitdata = { }; MODULE_DEVICE_TABLE(pci, advansys_pci_tbl); -#endif /* CONFIG_PCI */ + +static void __devinit advansys_set_latency(struct pci_dev *pdev) +{ + if ((pdev->device == PCI_DEVICE_ID_ASP_1200A) || + (pdev->device == PCI_DEVICE_ID_ASP_ABP940)) { + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0); + } else { + u8 latency; + pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency); + if (latency < 0x20) + pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0x20); + } +} + +static int __devinit +advansys_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) +{ + int err, ioport; + struct Scsi_Host *shost; + struct asc_board *board; + + err = pci_enable_device(pdev); + if (err) + goto fail; + err = pci_request_regions(pdev, DRV_NAME); + if (err) + goto disable_device; + pci_set_master(pdev); + advansys_set_latency(pdev); + + err = -ENODEV; + if (pci_resource_len(pdev, 0) == 0) + goto release_region; + + ioport = pci_resource_start(pdev, 0); + + err = -ENOMEM; + shost = scsi_host_alloc(&advansys_template, sizeof(*board)); + if (!shost) + goto release_region; + + board = shost_priv(shost); + board->irq = pdev->irq; + board->dev = &pdev->dev; + + if (pdev->device == PCI_DEVICE_ID_ASP_ABP940UW || + pdev->device == PCI_DEVICE_ID_38C0800_REV1 || + pdev->device == PCI_DEVICE_ID_38C1600_REV1) { + board->flags |= ASC_IS_WIDE_BOARD; + } + + err = advansys_board_found(shost, ioport, ASC_IS_PCI); + if (err) + goto free_host; + + pci_set_drvdata(pdev, shost); + return 0; + + free_host: + scsi_host_put(shost); + release_region: + pci_release_regions(pdev); + disable_device: + pci_disable_device(pdev); + fail: + return err; +} + +static void __devexit advansys_pci_remove(struct pci_dev *pdev) +{ + advansys_release(pci_get_drvdata(pdev)); + pci_release_regions(pdev); + pci_disable_device(pdev); +} + +static struct pci_driver advansys_pci_driver = { + .name = DRV_NAME, + .id_table = advansys_pci_tbl, + .probe = advansys_pci_probe, + .remove = __devexit_p(advansys_pci_remove), +}; + +static int __init advansys_init(void) +{ + int error; + + error = isa_register_driver(&advansys_isa_driver, + ASC_IOADR_TABLE_MAX_IX); + if (error) + goto fail; + + error = isa_register_driver(&advansys_vlb_driver, + ASC_IOADR_TABLE_MAX_IX); + if (error) + goto unregister_isa; + + error = eisa_driver_register(&advansys_eisa_driver); + if (error) + goto unregister_vlb; + + error = pci_register_driver(&advansys_pci_driver); + if (error) + goto unregister_eisa; + + return 0; + + unregister_eisa: + eisa_driver_unregister(&advansys_eisa_driver); + unregister_vlb: + isa_unregister_driver(&advansys_vlb_driver); + unregister_isa: + isa_unregister_driver(&advansys_isa_driver); + fail: + return error; +} + +static void __exit advansys_exit(void) +{ + pci_unregister_driver(&advansys_pci_driver); + eisa_driver_unregister(&advansys_eisa_driver); + isa_unregister_driver(&advansys_vlb_driver); + isa_unregister_driver(&advansys_isa_driver); +} + +module_init(advansys_init); +module_exit(advansys_exit); + +MODULE_LICENSE("GPL"); diff --git a/drivers/scsi/aha152x.c b/drivers/scsi/aha152x.c index d30a30786dda..f08e71e0205a 100644 --- a/drivers/scsi/aha152x.c +++ b/drivers/scsi/aha152x.c @@ -907,9 +907,10 @@ out_host_put: void aha152x_release(struct Scsi_Host *shpnt) { - if(!shpnt) + if (!shpnt) return; + scsi_remove_host(shpnt); if (shpnt->irq) free_irq(shpnt->irq, shpnt); @@ -923,7 +924,6 @@ void aha152x_release(struct Scsi_Host *shpnt) pnp_device_detach(HOSTDATA(shpnt)->pnpdev); #endif - scsi_remove_host(shpnt); list_del(&HOSTDATA(shpnt)->host_list); scsi_host_put(shpnt); } diff --git a/drivers/scsi/aic7xxx_old.c b/drivers/scsi/aic7xxx_old.c index 4998bb850c49..1a71b0236c97 100644 --- a/drivers/scsi/aic7xxx_old.c +++ b/drivers/scsi/aic7xxx_old.c @@ -8416,10 +8416,9 @@ aic7xxx_alloc(struct scsi_host_template *sht, struct aic7xxx_host *temp) *p = *temp; p->host = host; - p->scb_data = kmalloc(sizeof(scb_data_type), GFP_ATOMIC); - if (p->scb_data != NULL) + p->scb_data = kzalloc(sizeof(scb_data_type), GFP_ATOMIC); + if (!p->scb_data) { - memset(p->scb_data, 0, sizeof(scb_data_type)); scbq_init (&p->scb_data->free_scbs); } else @@ -9196,10 +9195,9 @@ aic7xxx_detect(struct scsi_host_template *template) printk(KERN_INFO " this driver, we are ignoring it.\n"); } } - else if ( (temp_p = kmalloc(sizeof(struct aic7xxx_host), + else if ( (temp_p = kzalloc(sizeof(struct aic7xxx_host), GFP_ATOMIC)) != NULL ) { - memset(temp_p, 0, sizeof(struct aic7xxx_host)); temp_p->chip = aic_pdevs[i].chip | AHC_PCI; temp_p->flags = aic_pdevs[i].flags; temp_p->features = aic_pdevs[i].features; diff --git a/drivers/scsi/aic94xx/aic94xx_hwi.h b/drivers/scsi/aic94xx/aic94xx_hwi.h index c6c3d18222fa..491e5d8a98bc 100644 --- a/drivers/scsi/aic94xx/aic94xx_hwi.h +++ b/drivers/scsi/aic94xx/aic94xx_hwi.h @@ -40,18 +40,6 @@ #define ASD_MAX_PHYS 8 #define ASD_PCBA_SN_SIZE 12 -/* Those are to be further named properly, the "RAZORx" part, and - * subsequently included in include/linux/pci_ids.h. - */ -#define PCI_DEVICE_ID_ADAPTEC2_RAZOR10 0x410 -#define PCI_DEVICE_ID_ADAPTEC2_RAZOR12 0x412 -#define PCI_DEVICE_ID_ADAPTEC2_RAZOR1E 0x41E -#define PCI_DEVICE_ID_ADAPTEC2_RAZOR1F 0x41F -#define PCI_DEVICE_ID_ADAPTEC2_RAZOR30 0x430 -#define PCI_DEVICE_ID_ADAPTEC2_RAZOR32 0x432 -#define PCI_DEVICE_ID_ADAPTEC2_RAZOR3E 0x43E -#define PCI_DEVICE_ID_ADAPTEC2_RAZOR3F 0x43F - struct asd_ha_addrspace { void __iomem *addr; unsigned long start; /* pci resource start */ diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c index 63bcde246447..b70d6e7f96e9 100644 --- a/drivers/scsi/aic94xx/aic94xx_init.c +++ b/drivers/scsi/aic94xx/aic94xx_init.c @@ -583,7 +583,7 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, asd_ha = kzalloc(sizeof(*asd_ha), GFP_KERNEL); if (!asd_ha) { asd_printk("out of memory\n"); - goto Err; + goto Err_put; } asd_ha->pcidev = dev; asd_ha->sas_ha.dev = &asd_ha->pcidev->dev; @@ -600,14 +600,12 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, shost->max_cmd_len = 16; err = scsi_add_host(shost, &dev->dev); - if (err) { - scsi_host_put(shost); + if (err) goto Err_free; - } err = asd_dev->setup(asd_ha); if (err) - goto Err_free; + goto Err_remove; err = -ENODEV; if (!pci_set_dma_mask(dev, DMA_64BIT_MASK) @@ -618,14 +616,14 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, ; else { asd_printk("no suitable DMA mask for %s\n", pci_name(dev)); - goto Err_free; + goto Err_remove; } pci_set_drvdata(dev, asd_ha); err = asd_map_ha(asd_ha); if (err) - goto Err_free; + goto Err_remove; err = asd_create_ha_caches(asd_ha); if (err) @@ -692,9 +690,12 @@ Err_free_cache: asd_destroy_ha_caches(asd_ha); Err_unmap: asd_unmap_ha(asd_ha); +Err_remove: + scsi_remove_host(shost); Err_free: kfree(asd_ha); - scsi_remove_host(shost); +Err_put: + scsi_host_put(shost); Err: pci_disable_device(dev); return err; @@ -829,22 +830,15 @@ static struct sas_domain_function_template aic94xx_transport_functions = { }; static const struct pci_device_id aic94xx_pci_table[] __devinitdata = { - {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR10), - 0, 0, 1}, - {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR12), - 0, 0, 1}, - {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1E), - 0, 0, 1}, - {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR1F), - 0, 0, 1}, - {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR30), - 0, 0, 2}, - {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR32), - 0, 0, 2}, - {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR3E), - 0, 0, 2}, - {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, PCI_DEVICE_ID_ADAPTEC2_RAZOR3F), - 0, 0, 2}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x410),0, 0, 1}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x412),0, 0, 1}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x416),0, 0, 1}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x41E),0, 0, 1}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x41F),0, 0, 1}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x430),0, 0, 2}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x432),0, 0, 2}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x43E),0, 0, 2}, + {PCI_DEVICE(PCI_VENDOR_ID_ADAPTEC2, 0x43F),0, 0, 2}, {} }; diff --git a/drivers/scsi/aic94xx/aic94xx_task.c b/drivers/scsi/aic94xx/aic94xx_task.c index ab13824df856..f2b23e01401a 100644 --- a/drivers/scsi/aic94xx/aic94xx_task.c +++ b/drivers/scsi/aic94xx/aic94xx_task.c @@ -207,7 +207,7 @@ static void asd_get_response_tasklet(struct asd_ascb *ascb, "stat(0x%x) is not CHECK_CONDITION" "\n", SAS_ADDR(task->dev->sas_addr), - ts->stat); + iu->status); } } } else { diff --git a/drivers/scsi/arcmsr/arcmsr.h b/drivers/scsi/arcmsr/arcmsr.h index f0b8bf4534f0..ace7a15b413e 100644 --- a/drivers/scsi/arcmsr/arcmsr.h +++ b/drivers/scsi/arcmsr/arcmsr.h @@ -9,7 +9,7 @@ ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved. ** ** Web site: www.areca.com.tw -** E-mail: erich@areca.com.tw +** E-mail: support@areca.com.tw ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License version 2 as @@ -45,19 +45,26 @@ #include <linux/interrupt.h> struct class_device_attribute; - -#define ARCMSR_MAX_OUTSTANDING_CMD 256 -#define ARCMSR_MAX_FREECCB_NUM 288 -#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.14" +/*The limit of outstanding scsi command that firmware can handle*/ +#define ARCMSR_MAX_OUTSTANDING_CMD 256 +#define ARCMSR_MAX_FREECCB_NUM 320 +#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.15 2007/08/30" #define ARCMSR_SCSI_INITIATOR_ID 255 #define ARCMSR_MAX_XFER_SECTORS 512 -#define ARCMSR_MAX_XFER_SECTORS_B 4096 -#define ARCMSR_MAX_TARGETID 17 -#define ARCMSR_MAX_TARGETLUN 8 -#define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD -#define ARCMSR_MAX_QBUFFER 4096 -#define ARCMSR_MAX_SG_ENTRIES 38 - +#define ARCMSR_MAX_XFER_SECTORS_B 4096 +#define ARCMSR_MAX_TARGETID 17 +#define ARCMSR_MAX_TARGETLUN 8 +#define ARCMSR_MAX_CMD_PERLUN ARCMSR_MAX_OUTSTANDING_CMD +#define ARCMSR_MAX_QBUFFER 4096 +#define ARCMSR_MAX_SG_ENTRIES 38 +#define ARCMSR_MAX_HBB_POSTQUEUE 264 +/* +********************************************************************************** +** +********************************************************************************** +*/ +#define ARC_SUCCESS 0 +#define ARC_FAILURE 1 /* ******************************************************************************* ** split 64bits dma addressing @@ -90,7 +97,7 @@ struct CMD_MESSAGE_FIELD uint8_t messagedatabuffer[1032]; }; /* IOP message transfer */ -#define ARCMSR_MESSAGE_FAIL 0x0001 +#define ARCMSR_MESSAGE_FAIL 0x0001 /* DeviceType */ #define ARECA_SATA_RAID 0x90000000 /* FunctionCode */ @@ -163,27 +170,27 @@ struct QBUFFER }; /* ******************************************************************************* -** FIRMWARE INFO +** FIRMWARE INFO for Intel IOP R 80331 processor (Type A) ******************************************************************************* */ struct FIRMWARE_INFO { - uint32_t signature; /*0, 00-03*/ - uint32_t request_len; /*1, 04-07*/ - uint32_t numbers_queue; /*2, 08-11*/ + uint32_t signature; /*0, 00-03*/ + uint32_t request_len; /*1, 04-07*/ + uint32_t numbers_queue; /*2, 08-11*/ uint32_t sdram_size; /*3, 12-15*/ - uint32_t ide_channels; /*4, 16-19*/ - char vendor[40]; /*5, 20-59*/ - char model[8]; /*15, 60-67*/ - char firmware_ver[16]; /*17, 68-83*/ - char device_map[16]; /*21, 84-99*/ + uint32_t ide_channels; /*4, 16-19*/ + char vendor[40]; /*5, 20-59*/ + char model[8]; /*15, 60-67*/ + char firmware_ver[16]; /*17, 68-83*/ + char device_map[16]; /*21, 84-99*/ }; /* signature of set and get firmware config */ -#define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 -#define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 +#define ARCMSR_SIGNATURE_GET_CONFIG 0x87974060 +#define ARCMSR_SIGNATURE_SET_CONFIG 0x87974063 /* message code of inbound message register */ -#define ARCMSR_INBOUND_MESG0_NOP 0x00000000 -#define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 +#define ARCMSR_INBOUND_MESG0_NOP 0x00000000 +#define ARCMSR_INBOUND_MESG0_GET_CONFIG 0x00000001 #define ARCMSR_INBOUND_MESG0_SET_CONFIG 0x00000002 #define ARCMSR_INBOUND_MESG0_ABORT_CMD 0x00000003 #define ARCMSR_INBOUND_MESG0_STOP_BGRB 0x00000004 @@ -203,6 +210,60 @@ struct FIRMWARE_INFO #define ARCMSR_CCBREPLY_FLAG_ERROR 0x10000000 /* outbound firmware ok */ #define ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK 0x80000000 + +/* +************************************************************************ +** SPEC. for Areca Type B adapter +************************************************************************ +*/ +/* ARECA HBB COMMAND for its FIRMWARE */ +/* window of "instruction flags" from driver to iop */ +#define ARCMSR_DRV2IOP_DOORBELL 0x00020400 +#define ARCMSR_DRV2IOP_DOORBELL_MASK 0x00020404 +/* window of "instruction flags" from iop to driver */ +#define ARCMSR_IOP2DRV_DOORBELL 0x00020408 +#define ARCMSR_IOP2DRV_DOORBELL_MASK 0x0002040C +/* ARECA FLAG LANGUAGE */ +/* ioctl transfer */ +#define ARCMSR_IOP2DRV_DATA_WRITE_OK 0x00000001 +/* ioctl transfer */ +#define ARCMSR_IOP2DRV_DATA_READ_OK 0x00000002 +#define ARCMSR_IOP2DRV_CDB_DONE 0x00000004 +#define ARCMSR_IOP2DRV_MESSAGE_CMD_DONE 0x00000008 + +#define ARCMSR_DOORBELL_HANDLE_INT 0x0000000F +#define ARCMSR_DOORBELL_INT_CLEAR_PATTERN 0xFF00FFF0 +#define ARCMSR_MESSAGE_INT_CLEAR_PATTERN 0xFF00FFF7 +/* (ARCMSR_INBOUND_MESG0_GET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_GET_CONFIG 0x00010008 +/* (ARCMSR_INBOUND_MESG0_SET_CONFIG<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_SET_CONFIG 0x00020008 +/* (ARCMSR_INBOUND_MESG0_ABORT_CMD<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_ABORT_CMD 0x00030008 +/* (ARCMSR_INBOUND_MESG0_STOP_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_STOP_BGRB 0x00040008 +/* (ARCMSR_INBOUND_MESG0_FLUSH_CACHE<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_FLUSH_CACHE 0x00050008 +/* (ARCMSR_INBOUND_MESG0_START_BGRB<<16)|ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED) */ +#define ARCMSR_MESSAGE_START_BGRB 0x00060008 +#define ARCMSR_MESSAGE_START_DRIVER_MODE 0x000E0008 +#define ARCMSR_MESSAGE_SET_POST_WINDOW 0x000F0008 +/* ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK */ +#define ARCMSR_MESSAGE_FIRMWARE_OK 0x80000000 +/* ioctl transfer */ +#define ARCMSR_DRV2IOP_DATA_WRITE_OK 0x00000001 +/* ioctl transfer */ +#define ARCMSR_DRV2IOP_DATA_READ_OK 0x00000002 +#define ARCMSR_DRV2IOP_CDB_POSTED 0x00000004 +#define ARCMSR_DRV2IOP_MESSAGE_CMD_POSTED 0x00000008 + +/* data tunnel buffer between user space program and its firmware */ +/* user space data to iop 128bytes */ +#define ARCMSR_IOCTL_WBUFFER 0x0000fe00 +/* iop data to user space 128bytes */ +#define ARCMSR_IOCTL_RBUFFER 0x0000ff00 +/* iop message_rwbuffer for message command */ +#define ARCMSR_MSGCODE_RWBUFFER 0x0000fa00 /* ******************************************************************************* ** ARECA SCSI COMMAND DESCRIPTOR BLOCK size 0x1F8 (504) @@ -214,7 +275,6 @@ struct ARCMSR_CDB uint8_t TargetID; uint8_t LUN; uint8_t Function; - uint8_t CdbLength; uint8_t sgcount; uint8_t Flags; @@ -224,20 +284,18 @@ struct ARCMSR_CDB #define ARCMSR_CDB_FLAG_SIMPLEQ 0x00 #define ARCMSR_CDB_FLAG_HEADQ 0x08 #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 - uint8_t Reserved1; + uint8_t Reserved1; uint32_t Context; uint32_t DataLength; - uint8_t Cdb[16]; - uint8_t DeviceStatus; -#define ARCMSR_DEV_CHECK_CONDITION 0x02 -#define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 -#define ARCMSR_DEV_ABORTED 0xF1 -#define ARCMSR_DEV_INIT_FAIL 0xF2 - uint8_t SenseData[15]; +#define ARCMSR_DEV_CHECK_CONDITION 0x02 +#define ARCMSR_DEV_SELECT_TIMEOUT 0xF0 +#define ARCMSR_DEV_ABORTED 0xF1 +#define ARCMSR_DEV_INIT_FAIL 0xF2 + uint8_t SenseData[15]; union { struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; @@ -246,10 +304,10 @@ struct ARCMSR_CDB }; /* ******************************************************************************* -** Messaging Unit (MU) of the Intel R 80331 I/O processor (80331) +** Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor ******************************************************************************* */ -struct MessageUnit +struct MessageUnit_A { uint32_t resrved0[4]; /*0000 000F*/ uint32_t inbound_msgaddr0; /*0010 0013*/ @@ -274,6 +332,30 @@ struct MessageUnit uint32_t message_rbuffer[32]; /*0F00 0F7F 32*/ uint32_t reserved6[32]; /*0F80 0FFF 32*/ }; + +struct MessageUnit_B +{ + uint32_t post_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; + uint32_t done_qbuffer[ARCMSR_MAX_HBB_POSTQUEUE]; + uint32_t postq_index; + uint32_t doneq_index; + uint32_t *drv2iop_doorbell_reg; + uint32_t *drv2iop_doorbell_mask_reg; + uint32_t *iop2drv_doorbell_reg; + uint32_t *iop2drv_doorbell_mask_reg; + uint32_t *msgcode_rwbuffer_reg; + uint32_t *ioctl_wbuffer_reg; + uint32_t *ioctl_rbuffer_reg; +}; + +struct MessageUnit +{ + union + { + struct MessageUnit_A pmu_A; + struct MessageUnit_B pmu_B; + } u; +}; /* ******************************************************************************* ** Adapter Control Block @@ -281,37 +363,45 @@ struct MessageUnit */ struct AdapterControlBlock { + uint32_t adapter_type; /* adapter A,B..... */ + #define ACB_ADAPTER_TYPE_A 0x00000001 /* hba I IOP */ + #define ACB_ADAPTER_TYPE_B 0x00000002 /* hbb M IOP */ + #define ACB_ADAPTER_TYPE_C 0x00000004 /* hbc P IOP */ + #define ACB_ADAPTER_TYPE_D 0x00000008 /* hbd A IOP */ struct pci_dev * pdev; struct Scsi_Host * host; unsigned long vir2phy_offset; /* Offset is used in making arc cdb physical to virtual calculations */ uint32_t outbound_int_enable; - struct MessageUnit __iomem * pmu; + struct MessageUnit * pmu; /* message unit ATU inbound base address0 */ uint32_t acb_flags; -#define ACB_F_SCSISTOPADAPTER 0x0001 -#define ACB_F_MSG_STOP_BGRB 0x0002 + #define ACB_F_SCSISTOPADAPTER 0x0001 + #define ACB_F_MSG_STOP_BGRB 0x0002 /* stop RAID background rebuild */ -#define ACB_F_MSG_START_BGRB 0x0004 + #define ACB_F_MSG_START_BGRB 0x0004 /* stop RAID background rebuild */ -#define ACB_F_IOPDATA_OVERFLOW 0x0008 + #define ACB_F_IOPDATA_OVERFLOW 0x0008 /* iop message data rqbuffer overflow */ -#define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 + #define ACB_F_MESSAGE_WQBUFFER_CLEARED 0x0010 /* message clear wqbuffer */ -#define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 + #define ACB_F_MESSAGE_RQBUFFER_CLEARED 0x0020 /* message clear rqbuffer */ -#define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 -#define ACB_F_BUS_RESET 0x0080 -#define ACB_F_IOP_INITED 0x0100 + #define ACB_F_MESSAGE_WQBUFFER_READED 0x0040 + #define ACB_F_BUS_RESET 0x0080 + #define ACB_F_IOP_INITED 0x0100 /* iop init */ struct CommandControlBlock * pccb_pool[ARCMSR_MAX_FREECCB_NUM]; /* used for memory free */ struct list_head ccb_free_list; /* head of free ccb list */ + atomic_t ccboutstandingcount; + /*The present outstanding command number that in the IOP that + waiting for being handled by FW*/ void * dma_coherent; /* dma_coherent used for memory free */ @@ -353,7 +443,7 @@ struct CommandControlBlock { struct ARCMSR_CDB arcmsr_cdb; /* - ** 0-503 (size of CDB=504): + ** 0-503 (size of CDB = 504): ** arcmsr messenger scsi command descriptor size 504 bytes */ uint32_t cdb_shifted_phyaddr; @@ -466,7 +556,9 @@ struct SENSE_DATA #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F -extern void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb); +extern void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *); +extern void arcmsr_iop_message_read(struct AdapterControlBlock *); +extern struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *); extern struct class_device_attribute *arcmsr_host_attrs[]; -extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb); +extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb); diff --git a/drivers/scsi/arcmsr/arcmsr_attr.c b/drivers/scsi/arcmsr/arcmsr_attr.c index 06c0dce3b839..d04d1aa28fa4 100644 --- a/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/drivers/scsi/arcmsr/arcmsr_attr.c @@ -8,7 +8,7 @@ ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved ** ** Web site: www.areca.com.tw -** E-mail: erich@areca.com.tw +** E-mail: support@areca.com.tw ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License version 2 as @@ -49,6 +49,7 @@ #include <linux/init.h> #include <linux/errno.h> #include <linux/delay.h> +#include <linux/pci.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> @@ -58,15 +59,14 @@ struct class_device_attribute *arcmsr_host_attrs[]; -static ssize_t -arcmsr_sysfs_iop_message_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, + struct bin_attribute *bin, + char *buf, loff_t off, + size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; uint8_t *pQbuffer,*ptmpQbuffer; int32_t allxfer_len = 0; @@ -85,12 +85,13 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, allxfer_len++; } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) - ®->message_rbuffer; - uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; + struct QBUFFER *prbuffer; + uint8_t *iop_data; int32_t iop_len; acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + prbuffer = arcmsr_get_iop_rqbuffer(acb); + iop_data = (uint8_t *)prbuffer->data; iop_len = readl(&prbuffer->data_len); while (iop_len > 0) { acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); @@ -99,16 +100,15 @@ arcmsr_sysfs_iop_message_read(struct kobject *kobj, iop_data++; iop_len--; } - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); + arcmsr_iop_message_read(acb); } return (allxfer_len); } -static ssize_t -arcmsr_sysfs_iop_message_write(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, + struct bin_attribute *bin, + char *buf, loff_t off, + size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); @@ -126,7 +126,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, wqbuf_lastindex = acb->wqbuf_lastindex; wqbuf_firstindex = acb->wqbuf_firstindex; if (wqbuf_lastindex != wqbuf_firstindex) { - arcmsr_post_Qbuffer(acb); + arcmsr_post_ioctldata2iop(acb); return 0; /*need retry*/ } else { my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) @@ -144,7 +144,7 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { acb->acb_flags &= ~ACB_F_MESSAGE_WQBUFFER_CLEARED; - arcmsr_post_Qbuffer(acb); + arcmsr_post_ioctldata2iop(acb); } return count; } else { @@ -153,15 +153,14 @@ arcmsr_sysfs_iop_message_write(struct kobject *kobj, } } -static ssize_t -arcmsr_sysfs_iop_message_clear(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buf, loff_t off, size_t count) +static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, + struct bin_attribute *bin, + char *buf, loff_t off, + size_t count) { struct class_device *cdev = container_of(kobj,struct class_device,kobj); struct Scsi_Host *host = class_to_shost(cdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; uint8_t *pQbuffer; if (!capable(CAP_SYS_ADMIN)) @@ -169,8 +168,7 @@ arcmsr_sysfs_iop_message_clear(struct kobject *kobj, if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK - , ®->inbound_doorbell); + arcmsr_iop_message_read(acb); } acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED @@ -191,6 +189,7 @@ static struct bin_attribute arcmsr_sysfs_message_read_attr = { .attr = { .name = "mu_read", .mode = S_IRUSR , + .owner = THIS_MODULE, }, .size = 1032, .read = arcmsr_sysfs_iop_message_read, @@ -200,6 +199,7 @@ static struct bin_attribute arcmsr_sysfs_message_write_attr = { .attr = { .name = "mu_write", .mode = S_IWUSR, + .owner = THIS_MODULE, }, .size = 1032, .write = arcmsr_sysfs_iop_message_write, @@ -209,6 +209,7 @@ static struct bin_attribute arcmsr_sysfs_message_clear_attr = { .attr = { .name = "mu_clear", .mode = S_IWUSR, + .owner = THIS_MODULE, }, .size = 1, .write = arcmsr_sysfs_iop_message_clear, @@ -219,31 +220,26 @@ int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb) struct Scsi_Host *host = acb->host; int error; - error = sysfs_create_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_read_attr); + error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); if (error) { printk(KERN_ERR "arcmsr: alloc sysfs mu_read failed\n"); goto error_bin_file_message_read; } - error = sysfs_create_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_write_attr); + error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); if (error) { printk(KERN_ERR "arcmsr: alloc sysfs mu_write failed\n"); goto error_bin_file_message_write; } - error = sysfs_create_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_clear_attr); + error = sysfs_create_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr); if (error) { printk(KERN_ERR "arcmsr: alloc sysfs mu_clear failed\n"); goto error_bin_file_message_clear; } return 0; error_bin_file_message_clear: - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_write_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); error_bin_file_message_write: - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_read_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); error_bin_file_message_read: return error; } @@ -252,12 +248,9 @@ void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb) { struct Scsi_Host *host = acb->host; - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_clear_attr); - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_write_attr); - sysfs_remove_bin_file(&host->shost_classdev.kobj, - &arcmsr_sysfs_message_read_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_clear_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_write_attr); + sysfs_remove_bin_file(&host->shost_classdev.kobj, &arcmsr_sysfs_message_read_attr); } diff --git a/drivers/scsi/arcmsr/arcmsr_hba.c b/drivers/scsi/arcmsr/arcmsr_hba.c index 0ddfc21e9f7d..cfcf40159eab 100644 --- a/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/drivers/scsi/arcmsr/arcmsr_hba.c @@ -9,7 +9,7 @@ ** Copyright (C) 2002 - 2005, Areca Technology Corporation All rights reserved ** ** Web site: www.areca.com.tw -** E-mail: erich@areca.com.tw +** E-mail: support@areca.com.tw ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License version 2 as @@ -71,33 +71,34 @@ #include <scsi/scsicam.h> #include "arcmsr.h" -MODULE_AUTHOR("Erich Chen <erich@areca.com.tw>"); +MODULE_AUTHOR("Erich Chen <support@areca.com.tw>"); MODULE_DESCRIPTION("ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID HOST Adapter"); MODULE_LICENSE("Dual BSD/GPL"); MODULE_VERSION(ARCMSR_DRIVER_VERSION); -static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd); +static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, + struct scsi_cmnd *cmd); +static int arcmsr_iop_confirm(struct AdapterControlBlock *acb); static int arcmsr_abort(struct scsi_cmnd *); static int arcmsr_bus_reset(struct scsi_cmnd *); static int arcmsr_bios_param(struct scsi_device *sdev, - struct block_device *bdev, sector_t capacity, int *info); -static int arcmsr_queue_command(struct scsi_cmnd * cmd, - void (*done) (struct scsi_cmnd *)); + struct block_device *bdev, sector_t capacity, int *info); +static int arcmsr_queue_command(struct scsi_cmnd *cmd, + void (*done) (struct scsi_cmnd *)); static int arcmsr_probe(struct pci_dev *pdev, const struct pci_device_id *id); static void arcmsr_remove(struct pci_dev *pdev); static void arcmsr_shutdown(struct pci_dev *pdev); static void arcmsr_iop_init(struct AdapterControlBlock *acb); static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb); +static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb); static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb); -static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); -static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); +static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb); +static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); static const char *arcmsr_info(struct Scsi_Host *); static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); -static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, - pci_channel_state_t state); -static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev); -static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, int queue_depth) +static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, + int queue_depth) { if (queue_depth > ARCMSR_MAX_CMD_PERLUN) queue_depth = ARCMSR_MAX_CMD_PERLUN; @@ -123,17 +124,25 @@ static struct scsi_host_template arcmsr_scsi_host_template = { .use_clustering = ENABLE_CLUSTERING, .shost_attrs = arcmsr_host_attrs, }; +#ifdef CONFIG_SCSI_ARCMSR_AER +static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev); +static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, + pci_channel_state_t state); + static struct pci_error_handlers arcmsr_pci_error_handlers = { .error_detected = arcmsr_pci_error_detected, .slot_reset = arcmsr_pci_slot_reset, }; - +#endif static struct pci_device_id arcmsr_device_id_table[] = { {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1110)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1120)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1130)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1160)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1170)}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1200)}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1201)}, + {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1202)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1210)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1220)}, {PCI_DEVICE(PCI_VENDOR_ID_ARECA, PCI_DEVICE_ID_ARECA_1230)}, @@ -153,20 +162,20 @@ static struct pci_driver arcmsr_pci_driver = { .probe = arcmsr_probe, .remove = arcmsr_remove, .shutdown = arcmsr_shutdown, + #ifdef CONFIG_SCSI_ARCMSR_AER .err_handler = &arcmsr_pci_error_handlers, + #endif }; static irqreturn_t arcmsr_do_interrupt(int irq, void *dev_id) { irqreturn_t handle_state; - struct AdapterControlBlock *acb; - unsigned long flags; + struct AdapterControlBlock *acb = dev_id; - acb = (struct AdapterControlBlock *)dev_id; - - spin_lock_irqsave(acb->host->host_lock, flags); + spin_lock(acb->host->host_lock); handle_state = arcmsr_interrupt(acb); - spin_unlock_irqrestore(acb->host->host_lock, flags); + spin_unlock(acb->host->host_lock); + return handle_state; } @@ -198,68 +207,159 @@ static int arcmsr_bios_param(struct scsi_device *sdev, return 0; } -static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) +static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb) { struct pci_dev *pdev = acb->pdev; - struct MessageUnit __iomem *reg = acb->pmu; - u32 ccb_phyaddr_hi32; - void *dma_coherent; - dma_addr_t dma_coherent_handle, dma_addr; - struct CommandControlBlock *ccb_tmp; - int i, j; + u16 dev_id; + pci_read_config_word(pdev, PCI_DEVICE_ID, &dev_id); + switch (dev_id) { + case 0x1201 : { + acb->adapter_type = ACB_ADAPTER_TYPE_B; + } + break; + + default : acb->adapter_type = ACB_ADAPTER_TYPE_A; + } +} + +static int arcmsr_alloc_ccb_pool(struct AdapterControlBlock *acb) +{ + + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct pci_dev *pdev = acb->pdev; + void *dma_coherent; + dma_addr_t dma_coherent_handle, dma_addr; + struct CommandControlBlock *ccb_tmp; + uint32_t intmask_org; + int i, j; + + acb->pmu = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); + if (!acb->pmu) { + printk(KERN_NOTICE "arcmsr%d: memory mapping region fail \n", + acb->host->host_no); + } - dma_coherent = dma_alloc_coherent(&pdev->dev, + dma_coherent = dma_alloc_coherent(&pdev->dev, ARCMSR_MAX_FREECCB_NUM * sizeof (struct CommandControlBlock) + 0x20, &dma_coherent_handle, GFP_KERNEL); - if (!dma_coherent) - return -ENOMEM; + if (!dma_coherent) + return -ENOMEM; - acb->dma_coherent = dma_coherent; - acb->dma_coherent_handle = dma_coherent_handle; + acb->dma_coherent = dma_coherent; + acb->dma_coherent_handle = dma_coherent_handle; - if (((unsigned long)dma_coherent & 0x1F)) { - dma_coherent = dma_coherent + - (0x20 - ((unsigned long)dma_coherent & 0x1F)); - dma_coherent_handle = dma_coherent_handle + - (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); - } + if (((unsigned long)dma_coherent & 0x1F)) { + dma_coherent = dma_coherent + + (0x20 - ((unsigned long)dma_coherent & 0x1F)); + dma_coherent_handle = dma_coherent_handle + + (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); + } - dma_addr = dma_coherent_handle; - ccb_tmp = (struct CommandControlBlock *)dma_coherent; - for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { - ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; - ccb_tmp->acb = acb; - acb->pccb_pool[i] = ccb_tmp; - list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); - dma_addr = dma_addr + sizeof (struct CommandControlBlock); - ccb_tmp++; - } + dma_addr = dma_coherent_handle; + ccb_tmp = (struct CommandControlBlock *)dma_coherent; + for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; + ccb_tmp->acb = acb; + acb->pccb_pool[i] = ccb_tmp; + list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); + dma_addr = dma_addr + sizeof(struct CommandControlBlock); + ccb_tmp++; + } - acb->vir2phy_offset = (unsigned long)ccb_tmp - - (unsigned long)dma_addr; - for (i = 0; i < ARCMSR_MAX_TARGETID; i++) - for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) - acb->devstate[i][j] = ARECA_RAID_GOOD; + acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; + for (i = 0; i < ARCMSR_MAX_TARGETID; i++) + for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) + acb->devstate[i][j] = ARECA_RAID_GONE; - /* - ** here we need to tell iop 331 our ccb_tmp.HighPart - ** if ccb_tmp.HighPart is not zero - */ - ccb_phyaddr_hi32 = (uint32_t) ((dma_coherent_handle >> 16) >> 16); - if (ccb_phyaddr_hi32 != 0) { - writel(ARCMSR_SIGNATURE_SET_CONFIG, ®->message_rwbuffer[0]); - writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]); - writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) - printk(KERN_NOTICE "arcmsr%d: " - "'set ccb high part physical address' timeout\n", - acb->host->host_no); - } + /* + ** here we need to tell iop 331 our ccb_tmp.HighPart + ** if ccb_tmp.HighPart is not zero + */ + intmask_org = arcmsr_disable_outbound_ints(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + + struct pci_dev *pdev = acb->pdev; + struct MessageUnit_B *reg; + void *mem_base0, *mem_base1; + void *dma_coherent; + dma_addr_t dma_coherent_handle, dma_addr; + uint32_t intmask_org; + struct CommandControlBlock *ccb_tmp; + int i, j; + + dma_coherent = dma_alloc_coherent(&pdev->dev, + ((ARCMSR_MAX_FREECCB_NUM * + sizeof(struct CommandControlBlock) + 0x20) + + sizeof(struct MessageUnit_B)), + &dma_coherent_handle, GFP_KERNEL); + if (!dma_coherent) + return -ENOMEM; - writel(readl(®->outbound_intmask) | - ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); + acb->dma_coherent = dma_coherent; + acb->dma_coherent_handle = dma_coherent_handle; + + if (((unsigned long)dma_coherent & 0x1F)) { + dma_coherent = dma_coherent + + (0x20 - ((unsigned long)dma_coherent & 0x1F)); + dma_coherent_handle = dma_coherent_handle + + (0x20 - ((unsigned long)dma_coherent_handle & 0x1F)); + } + + reg = (struct MessageUnit_B *)(dma_coherent + + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); + + dma_addr = dma_coherent_handle; + ccb_tmp = (struct CommandControlBlock *)dma_coherent; + for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + ccb_tmp->cdb_shifted_phyaddr = dma_addr >> 5; + ccb_tmp->acb = acb; + acb->pccb_pool[i] = ccb_tmp; + list_add_tail(&ccb_tmp->list, &acb->ccb_free_list); + dma_addr = dma_addr + sizeof(struct CommandControlBlock); + ccb_tmp++; + } + + reg = (struct MessageUnit_B *)(dma_coherent + + ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); + acb->pmu = (struct MessageUnit *)reg; + mem_base0 = ioremap(pci_resource_start(pdev, 0), + pci_resource_len(pdev, 0)); + mem_base1 = ioremap(pci_resource_start(pdev, 2), + pci_resource_len(pdev, 2)); + reg->drv2iop_doorbell_reg = (uint32_t *)((char *)mem_base0 + + ARCMSR_DRV2IOP_DOORBELL); + reg->drv2iop_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + + ARCMSR_DRV2IOP_DOORBELL_MASK); + reg->iop2drv_doorbell_reg = (uint32_t *)((char *)mem_base0 + + ARCMSR_IOP2DRV_DOORBELL); + reg->iop2drv_doorbell_mask_reg = (uint32_t *)((char *)mem_base0 + + ARCMSR_IOP2DRV_DOORBELL_MASK); + reg->ioctl_wbuffer_reg = (uint32_t *)((char *)mem_base1 + + ARCMSR_IOCTL_WBUFFER); + reg->ioctl_rbuffer_reg = (uint32_t *)((char *)mem_base1 + + ARCMSR_IOCTL_RBUFFER); + reg->msgcode_rwbuffer_reg = (uint32_t *)((char *)mem_base1 + + ARCMSR_MSGCODE_RWBUFFER); + + acb->vir2phy_offset = (unsigned long)ccb_tmp -(unsigned long)dma_addr; + for (i = 0; i < ARCMSR_MAX_TARGETID; i++) + for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) + acb->devstate[i][j] = ARECA_RAID_GOOD; + + /* + ** here we need to tell iop 331 our ccb_tmp.HighPart + ** if ccb_tmp.HighPart is not zero + */ + intmask_org = arcmsr_disable_outbound_ints(acb); + } + break; + } return 0; } @@ -310,16 +410,11 @@ static int arcmsr_probe(struct pci_dev *pdev, host->unique_id = (bus << 8) | dev_fun; host->irq = pdev->irq; error = pci_request_regions(pdev, "arcmsr"); - if (error) + if (error) { goto out_host_put; - - acb->pmu = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - if (!acb->pmu) { - printk(KERN_NOTICE "arcmsr%d: memory" - " mapping region fail \n", acb->host->host_no); - goto out_release_regions; } + arcmsr_define_adapter_type(acb); + acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); @@ -328,10 +423,10 @@ static int arcmsr_probe(struct pci_dev *pdev, error = arcmsr_alloc_ccb_pool(acb); if (error) - goto out_iounmap; + goto out_release_regions; error = request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb); + IRQF_SHARED, "arcmsr", acb); if (error) goto out_free_ccb_pool; @@ -349,14 +444,15 @@ static int arcmsr_probe(struct pci_dev *pdev, goto out_free_sysfs; scsi_scan_host(host); + #ifdef CONFIG_SCSI_ARCMSR_AER pci_enable_pcie_error_reporting(pdev); + #endif return 0; out_free_sysfs: out_free_irq: free_irq(pdev->irq, acb); out_free_ccb_pool: arcmsr_free_ccb_pool(acb); - out_iounmap: iounmap(acb->pmu); out_release_regions: pci_release_regions(pdev); @@ -368,17 +464,84 @@ static int arcmsr_probe(struct pci_dev *pdev, return error; } -static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) +static uint8_t arcmsr_hba_wait_msgint_ready(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + uint32_t Index; + uint8_t Retries = 0x00; + + do { + for (Index = 0; Index < 100; Index++) { + if (readl(®->outbound_intstatus) & + ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { + writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT, + ®->outbound_intstatus); + return 0x00; + } + msleep(10); + }/*max 1 seconds*/ + + } while (Retries++ < 20);/*max 20 sec*/ + return 0xff; +} + +static uint8_t arcmsr_hbb_wait_msgint_ready(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + uint32_t Index; + uint8_t Retries = 0x00; + + do { + for (Index = 0; Index < 100; Index++) { + if (readl(reg->iop2drv_doorbell_reg) + & ARCMSR_IOP2DRV_MESSAGE_CMD_DONE) { + writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN + , reg->iop2drv_doorbell_reg); + return 0x00; + } + msleep(10); + }/*max 1 seconds*/ + + } while (Retries++ < 20);/*max 20 sec*/ + return 0xff; +} + +static void arcmsr_abort_hba_allcmd(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) + if (arcmsr_hba_wait_msgint_ready(acb)) + printk(KERN_NOTICE + "arcmsr%d: wait 'abort all outstanding command' timeout \n" + , acb->host->host_no); +} + +static void arcmsr_abort_hbb_allcmd(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + + writel(ARCMSR_MESSAGE_ABORT_CMD, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) printk(KERN_NOTICE "arcmsr%d: wait 'abort all outstanding command' timeout \n" , acb->host->host_no); } +static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_abort_hba_allcmd(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_abort_hbb_allcmd(acb); + } + } +} + static void arcmsr_pci_unmap_dma(struct CommandControlBlock *ccb) { struct scsi_cmnd *pcmd = ccb->pcmd; @@ -400,28 +563,239 @@ static void arcmsr_ccb_complete(struct CommandControlBlock *ccb, int stand_flag) pcmd->scsi_done(pcmd); } +static void arcmsr_flush_hba_cache(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + int retry_count = 30; + + writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); + do { + if (!arcmsr_hba_wait_msgint_ready(acb)) + break; + else { + retry_count--; + printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ + timeout, retry count down = %d \n", acb->host->host_no, retry_count); + } + } while (retry_count != 0); +} + +static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + int retry_count = 30; + + writel(ARCMSR_MESSAGE_FLUSH_CACHE, reg->drv2iop_doorbell_reg); + do { + if (!arcmsr_hbb_wait_msgint_ready(acb)) + break; + else { + retry_count--; + printk(KERN_NOTICE "arcmsr%d: wait 'flush adapter cache' \ + timeout,retry count down = %d \n", acb->host->host_no, retry_count); + } + } while (retry_count != 0); +} + +static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + arcmsr_flush_hba_cache(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_flush_hbb_cache(acb); + } + } +} + +static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) +{ + + struct scsi_cmnd *pcmd = ccb->pcmd; + struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer; + + pcmd->result = DID_OK << 16; + if (sensebuffer) { + int sense_data_length = + sizeof(struct SENSE_DATA) < sizeof(pcmd->sense_buffer) + ? sizeof(struct SENSE_DATA) : sizeof(pcmd->sense_buffer); + memset(sensebuffer, 0, sizeof(pcmd->sense_buffer)); + memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length); + sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; + sensebuffer->Valid = 1; + } +} + +static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) +{ + u32 orig_mask = 0; + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A : { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + orig_mask = readl(®->outbound_intmask)|\ + ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; + writel(orig_mask|ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, \ + ®->outbound_intmask); + } + break; + + case ACB_ADAPTER_TYPE_B : { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + orig_mask = readl(reg->iop2drv_doorbell_mask_reg) & \ + (~ARCMSR_IOP2DRV_MESSAGE_CMD_DONE); + writel(0, reg->iop2drv_doorbell_mask_reg); + } + break; + } + return orig_mask; +} + +static void arcmsr_report_ccb_state(struct AdapterControlBlock *acb, \ + struct CommandControlBlock *ccb, uint32_t flag_ccb) +{ + + uint8_t id, lun; + id = ccb->pcmd->device->id; + lun = ccb->pcmd->device->lun; + if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { + if (acb->devstate[id][lun] == ARECA_RAID_GONE) + acb->devstate[id][lun] = ARECA_RAID_GOOD; + ccb->pcmd->result = DID_OK << 16; + arcmsr_ccb_complete(ccb, 1); + } else { + switch (ccb->arcmsr_cdb.DeviceStatus) { + case ARCMSR_DEV_SELECT_TIMEOUT: { + acb->devstate[id][lun] = ARECA_RAID_GONE; + ccb->pcmd->result = DID_NO_CONNECT << 16; + arcmsr_ccb_complete(ccb, 1); + } + break; + + case ARCMSR_DEV_ABORTED: + + case ARCMSR_DEV_INIT_FAIL: { + acb->devstate[id][lun] = ARECA_RAID_GONE; + ccb->pcmd->result = DID_BAD_TARGET << 16; + arcmsr_ccb_complete(ccb, 1); + } + break; + + case ARCMSR_DEV_CHECK_CONDITION: { + acb->devstate[id][lun] = ARECA_RAID_GOOD; + arcmsr_report_sense_info(ccb); + arcmsr_ccb_complete(ccb, 1); + } + break; + + default: + printk(KERN_NOTICE + "arcmsr%d: scsi id = %d lun = %d" + " isr get command error done, " + "but got unknown DeviceStatus = 0x%x \n" + , acb->host->host_no + , id + , lun + , ccb->arcmsr_cdb.DeviceStatus); + acb->devstate[id][lun] = ARECA_RAID_GONE; + ccb->pcmd->result = DID_NO_CONNECT << 16; + arcmsr_ccb_complete(ccb, 1); + break; + } + } +} + +static void arcmsr_drain_donequeue(struct AdapterControlBlock *acb, uint32_t flag_ccb) + +{ + struct CommandControlBlock *ccb; + + ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5)); + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if (ccb->startdone == ARCMSR_CCB_ABORTED) { + struct scsi_cmnd *abortcmd = ccb->pcmd; + if (abortcmd) { + abortcmd->result |= DID_ABORT << 16; + arcmsr_ccb_complete(ccb, 1); + printk(KERN_NOTICE "arcmsr%d: ccb ='0x%p' \ + isr got aborted command \n", acb->host->host_no, ccb); + } + } + printk(KERN_NOTICE "arcmsr%d: isr get an illegal ccb command \ + done acb = '0x%p'" + "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x" + " ccboutstandingcount = %d \n" + , acb->host->host_no + , acb + , ccb + , ccb->acb + , ccb->startdone + , atomic_read(&acb->ccboutstandingcount)); + } + arcmsr_report_ccb_state(acb, ccb, flag_ccb); +} + +static void arcmsr_done4abort_postqueue(struct AdapterControlBlock *acb) +{ + int i = 0; + uint32_t flag_ccb; + + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = \ + (struct MessageUnit_A *)acb->pmu; + uint32_t outbound_intstatus; + outbound_intstatus = readl(®->outbound_intstatus) & \ + acb->outbound_int_enable; + /*clear and abort all outbound posted Q*/ + writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ + while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) \ + && (i++ < ARCMSR_MAX_OUTSTANDING_CMD)) { + arcmsr_drain_donequeue(acb, flag_ccb); + } + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + /*clear all outbound posted Q*/ + for (i = 0; i < ARCMSR_MAX_HBB_POSTQUEUE; i++) { + if ((flag_ccb = readl(®->done_qbuffer[i])) != 0) { + writel(0, ®->done_qbuffer[i]); + arcmsr_drain_donequeue(acb, flag_ccb); + } + writel(0, ®->post_qbuffer[i]); + } + reg->doneq_index = 0; + reg->postq_index = 0; + } + break; + } +} static void arcmsr_remove(struct pci_dev *pdev) { struct Scsi_Host *host = pci_get_drvdata(pdev); struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; int poll_count = 0; arcmsr_free_sysfs_attr(acb); scsi_remove_host(host); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); - writel(readl(®->outbound_intmask) | - ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); + arcmsr_disable_outbound_ints(acb); acb->acb_flags |= ACB_F_SCSISTOPADAPTER; acb->acb_flags &= ~ACB_F_IOP_INITED; - for (poll_count = 0; poll_count < 256; poll_count++) { + for (poll_count = 0; poll_count < ARCMSR_MAX_OUTSTANDING_CMD; poll_count++) { if (!atomic_read(&acb->ccboutstandingcount)) break; - arcmsr_interrupt(acb); + arcmsr_interrupt(acb);/* FIXME: need spinlock */ msleep(25); } @@ -429,8 +803,7 @@ static void arcmsr_remove(struct pci_dev *pdev) int i; arcmsr_abort_allcmd(acb); - for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) - readl(®->outbound_queueport); + arcmsr_done4abort_postqueue(acb); for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { struct CommandControlBlock *ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { @@ -477,75 +850,32 @@ static void arcmsr_module_exit(void) module_init(arcmsr_module_init); module_exit(arcmsr_module_exit); -static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) -{ - struct MessageUnit __iomem *reg = acb->pmu; - u32 orig_mask = readl(®->outbound_intmask); - - writel(orig_mask | ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, - ®->outbound_intmask); - return orig_mask; -} - -static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, - u32 orig_mask) +static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ + u32 intmask_org) { - struct MessageUnit __iomem *reg = acb->pmu; u32 mask; - mask = orig_mask & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | - ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - writel(mask, ®->outbound_intmask); -} + switch (acb->adapter_type) { -static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) -{ - struct MessageUnit __iomem *reg = acb->pmu; - - writel(ARCMSR_INBOUND_MESG0_FLUSH_CACHE, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) - printk(KERN_NOTICE - "arcmsr%d: wait 'flush adapter cache' timeout \n" - , acb->host->host_no); -} - -static void arcmsr_report_sense_info(struct CommandControlBlock *ccb) -{ - struct scsi_cmnd *pcmd = ccb->pcmd; - struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)pcmd->sense_buffer; + case ACB_ADAPTER_TYPE_A : { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | + ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); + writel(mask, ®->outbound_intmask); + acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; + } + break; - pcmd->result = DID_OK << 16; - if (sensebuffer) { - int sense_data_length = - sizeof (struct SENSE_DATA) < sizeof (pcmd->sense_buffer) - ? sizeof (struct SENSE_DATA) : sizeof (pcmd->sense_buffer); - memset(sensebuffer, 0, sizeof (pcmd->sense_buffer)); - memcpy(sensebuffer, ccb->arcmsr_cdb.SenseData, sense_data_length); - sensebuffer->ErrorCode = SCSI_SENSE_CURRENT_ERRORS; - sensebuffer->Valid = 1; + case ACB_ADAPTER_TYPE_B : { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + mask = intmask_org | (ARCMSR_IOP2DRV_DATA_WRITE_OK | \ + ARCMSR_IOP2DRV_DATA_READ_OK | ARCMSR_IOP2DRV_CDB_DONE); + writel(mask, reg->iop2drv_doorbell_mask_reg); + acb->outbound_int_enable = (intmask_org | mask) & 0x0000000f; + } } } -static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb) -{ - struct MessageUnit __iomem *reg = acb->pmu; - uint32_t Index; - uint8_t Retries = 0x00; - - do { - for (Index = 0; Index < 100; Index++) { - if (readl(®->outbound_intstatus) - & ARCMSR_MU_OUTBOUND_MESSAGE0_INT) { - writel(ARCMSR_MU_OUTBOUND_MESSAGE0_INT - , ®->outbound_intstatus); - return 0x00; - } - msleep_interruptible(10); - }/*max 1 seconds*/ - } while (Retries++ < 20);/*max 20 sec*/ - return 0xff; -} - static void arcmsr_build_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) { @@ -556,7 +886,7 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, int nseg; ccb->pcmd = pcmd; - memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB)); + memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); arcmsr_cdb->Bus = 0; arcmsr_cdb->TargetID = pcmd->device->id; arcmsr_cdb->LUN = pcmd->device->lun; @@ -609,52 +939,85 @@ static void arcmsr_build_ccb(struct AdapterControlBlock *acb, static void arcmsr_post_ccb(struct AdapterControlBlock *acb, struct CommandControlBlock *ccb) { - struct MessageUnit __iomem *reg = acb->pmu; uint32_t cdb_shifted_phyaddr = ccb->cdb_shifted_phyaddr; struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; - atomic_inc(&acb->ccboutstandingcount); ccb->startdone = ARCMSR_CCB_START; - if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) - writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, + + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; + + if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) + writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE, ®->inbound_queueport); - else - writel(cdb_shifted_phyaddr, ®->inbound_queueport); -} + else { + writel(cdb_shifted_phyaddr, ®->inbound_queueport); + } + } + break; -void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb) -{ - struct MessageUnit __iomem *reg = acb->pmu; - struct QBUFFER __iomem *pwbuffer = (struct QBUFFER __iomem *) ®->message_wbuffer; - uint8_t __iomem *iop_data = (uint8_t __iomem *) pwbuffer->data; - int32_t allxfer_len = 0; + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + uint32_t ending_index, index = reg->postq_index; - if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { - acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); - while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) - && (allxfer_len < 124)) { - writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data); - acb->wqbuf_firstindex++; - acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; - iop_data++; - allxfer_len++; + ending_index = ((index + 1) % ARCMSR_MAX_HBB_POSTQUEUE); + writel(0, ®->post_qbuffer[ending_index]); + if (arcmsr_cdb->Flags & ARCMSR_CDB_FLAG_SGL_BSIZE) { + writel(cdb_shifted_phyaddr | ARCMSR_CCBPOST_FLAG_SGL_BSIZE,\ + ®->post_qbuffer[index]); + } + else { + writel(cdb_shifted_phyaddr, ®->post_qbuffer[index]); } - writel(allxfer_len, &pwbuffer->data_len); - writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK - , ®->inbound_doorbell); + index++; + index %= ARCMSR_MAX_HBB_POSTQUEUE;/*if last index number set it to 0 */ + reg->postq_index = index; + writel(ARCMSR_DRV2IOP_CDB_POSTED, reg->drv2iop_doorbell_reg); + } + break; } } -static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) +static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; - + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) + + if (arcmsr_hba_wait_msgint_ready(acb)) { printk(KERN_NOTICE "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" , acb->host->host_no); + } +} + +static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + writel(ARCMSR_MESSAGE_STOP_BGRB, reg->drv2iop_doorbell_reg); + + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE + "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" + , acb->host->host_no); + } +} + +static void arcmsr_stop_adapter_bgrb(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_stop_hba_bgrb(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_stop_hbb_bgrb(acb); + } + break; + } } static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) @@ -665,151 +1028,260 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) acb->dma_coherent_handle); } -static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) +void arcmsr_iop_message_read(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; - struct CommandControlBlock *ccb; - uint32_t flag_ccb, outbound_intstatus, outbound_doorbell; + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); + } + break; - outbound_intstatus = readl(®->outbound_intstatus) - & acb->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus); - if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { - outbound_doorbell = readl(®->outbound_doorbell); - writel(outbound_doorbell, ®->outbound_doorbell); - if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { - struct QBUFFER __iomem * prbuffer = - (struct QBUFFER __iomem *) ®->message_rbuffer; - uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; - int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; - - rqbuf_lastindex = acb->rqbuf_lastindex; - rqbuf_firstindex = acb->rqbuf_firstindex; - iop_len = readl(&prbuffer->data_len); - my_empty_len = (rqbuf_firstindex - rqbuf_lastindex - 1) - &(ARCMSR_MAX_QBUFFER - 1); - if (my_empty_len >= iop_len) { - while (iop_len > 0) { - acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); - acb->rqbuf_lastindex++; - acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; - iop_data++; - iop_len--; - } - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); - } else - acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; - } - if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { - acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; - if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { - struct QBUFFER __iomem * pwbuffer = - (struct QBUFFER __iomem *) ®->message_wbuffer; - uint8_t __iomem * iop_data = (uint8_t __iomem *) pwbuffer->data; - int32_t allxfer_len = 0; - - acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); - while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) - && (allxfer_len < 124)) { - writeb(acb->wqbuffer[acb->wqbuf_firstindex], iop_data); - acb->wqbuf_firstindex++; - acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; - iop_data++; - allxfer_len++; - } - writel(allxfer_len, &pwbuffer->data_len); - writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, - ®->inbound_doorbell); - } - if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) - acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); } + break; } - if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { - int id, lun; +} + +static void arcmsr_iop_message_wrote(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; /* - **************************************************************** - ** areca cdb command done - **************************************************************** + ** push inbound doorbell tell iop, driver data write ok + ** and wait reply on next hwinterrupt for next Qbuffer post */ - while (1) { - if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) - break;/*chip FIFO no ccb for completion already*/ - /* check if command done with no error*/ - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + - (flag_ccb << 5)); - if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { - if (ccb->startdone == ARCMSR_CCB_ABORTED) { - struct scsi_cmnd *abortcmd = ccb->pcmd; - if (abortcmd) { - abortcmd->result |= DID_ABORT >> 16; - arcmsr_ccb_complete(ccb, 1); - printk(KERN_NOTICE - "arcmsr%d: ccb ='0x%p' isr got aborted command \n" - , acb->host->host_no, ccb); - } - continue; - } - printk(KERN_NOTICE - "arcmsr%d: isr get an illegal ccb command done acb = '0x%p'" - "ccb = '0x%p' ccbacb = '0x%p' startdone = 0x%x" - " ccboutstandingcount = %d \n" - , acb->host->host_no - , acb - , ccb - , ccb->acb - , ccb->startdone - , atomic_read(&acb->ccboutstandingcount)); - continue; - } - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (acb->devstate[id][lun] == ARECA_RAID_GONE) - acb->devstate[id][lun] = ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - case ARCMSR_DEV_ABORTED: - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); - } - break; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d lun = %d" - " isr get command error done, " - "but got unknown DeviceStatus = 0x%x \n" - , acb->host->host_no - , id - , lun - , ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - break; - } - } - }/*drain reply FIFO*/ + writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, ®->inbound_doorbell); + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + /* + ** push inbound doorbell tell iop, driver data write ok + ** and wait reply on next hwinterrupt for next Qbuffer post + */ + writel(ARCMSR_DRV2IOP_DATA_WRITE_OK, reg->drv2iop_doorbell_reg); + } + break; + } +} + +struct QBUFFER *arcmsr_get_iop_rqbuffer(struct AdapterControlBlock *acb) +{ + static struct QBUFFER *qbuffer; + + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + qbuffer = (struct QBUFFER __iomem *) ®->message_rbuffer; + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + qbuffer = (struct QBUFFER __iomem *) reg->ioctl_rbuffer_reg; + } + break; + } + return qbuffer; +} + +static struct QBUFFER *arcmsr_get_iop_wqbuffer(struct AdapterControlBlock *acb) +{ + static struct QBUFFER *pqbuffer; + + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + pqbuffer = (struct QBUFFER *) ®->message_wbuffer; + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + pqbuffer = (struct QBUFFER __iomem *)reg->ioctl_wbuffer_reg; + } + break; + } + return pqbuffer; +} + +static void arcmsr_iop2drv_data_wrote_handle(struct AdapterControlBlock *acb) +{ + struct QBUFFER *prbuffer; + struct QBUFFER *pQbuffer; + uint8_t *iop_data; + int32_t my_empty_len, iop_len, rqbuf_firstindex, rqbuf_lastindex; + + rqbuf_lastindex = acb->rqbuf_lastindex; + rqbuf_firstindex = acb->rqbuf_firstindex; + prbuffer = arcmsr_get_iop_rqbuffer(acb); + iop_data = (uint8_t *)prbuffer->data; + iop_len = prbuffer->data_len; + my_empty_len = (rqbuf_firstindex - rqbuf_lastindex -1)&(ARCMSR_MAX_QBUFFER -1); + + if (my_empty_len >= iop_len) + { + while (iop_len > 0) { + pQbuffer = (struct QBUFFER *)&acb->rqbuffer[rqbuf_lastindex]; + memcpy(pQbuffer, iop_data,1); + rqbuf_lastindex++; + rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + iop_len--; + } + acb->rqbuf_lastindex = rqbuf_lastindex; + arcmsr_iop_message_read(acb); + } + + else { + acb->acb_flags |= ACB_F_IOPDATA_OVERFLOW; + } +} + +static void arcmsr_iop2drv_data_read_handle(struct AdapterControlBlock *acb) +{ + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_READED; + if (acb->wqbuf_firstindex != acb->wqbuf_lastindex) { + uint8_t *pQbuffer; + struct QBUFFER *pwbuffer; + uint8_t *iop_data; + int32_t allxfer_len = 0; + + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); + pwbuffer = arcmsr_get_iop_wqbuffer(acb); + iop_data = (uint8_t __iomem *)pwbuffer->data; + + while ((acb->wqbuf_firstindex != acb->wqbuf_lastindex) && \ + (allxfer_len < 124)) { + pQbuffer = &acb->wqbuffer[acb->wqbuf_firstindex]; + memcpy(iop_data, pQbuffer, 1); + acb->wqbuf_firstindex++; + acb->wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + allxfer_len++; + } + pwbuffer->data_len = allxfer_len; + + arcmsr_iop_message_wrote(acb); + } + + if (acb->wqbuf_firstindex == acb->wqbuf_lastindex) { + acb->acb_flags |= ACB_F_MESSAGE_WQBUFFER_CLEARED; + } +} + +static void arcmsr_hba_doorbell_isr(struct AdapterControlBlock *acb) +{ + uint32_t outbound_doorbell; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + + outbound_doorbell = readl(®->outbound_doorbell); + writel(outbound_doorbell, ®->outbound_doorbell); + if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_WRITE_OK) { + arcmsr_iop2drv_data_wrote_handle(acb); + } + + if (outbound_doorbell & ARCMSR_OUTBOUND_IOP331_DATA_READ_OK) { + arcmsr_iop2drv_data_read_handle(acb); + } +} + +static void arcmsr_hba_postqueue_isr(struct AdapterControlBlock *acb) +{ + uint32_t flag_ccb; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + + while ((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) { + arcmsr_drain_donequeue(acb, flag_ccb); + } +} + +static void arcmsr_hbb_postqueue_isr(struct AdapterControlBlock *acb) +{ + uint32_t index; + uint32_t flag_ccb; + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + + index = reg->doneq_index; + + while ((flag_ccb = readl(®->done_qbuffer[index])) != 0) { + writel(0, ®->done_qbuffer[index]); + arcmsr_drain_donequeue(acb, flag_ccb); + index++; + index %= ARCMSR_MAX_HBB_POSTQUEUE; + reg->doneq_index = index; + } +} + +static int arcmsr_handle_hba_isr(struct AdapterControlBlock *acb) +{ + uint32_t outbound_intstatus; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + + outbound_intstatus = readl(®->outbound_intstatus) & \ + acb->outbound_int_enable; + if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) { + return 1; + } + writel(outbound_intstatus, ®->outbound_intstatus); + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_DOORBELL_INT) { + arcmsr_hba_doorbell_isr(acb); + } + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { + arcmsr_hba_postqueue_isr(acb); + } + return 0; +} + +static int arcmsr_handle_hbb_isr(struct AdapterControlBlock *acb) +{ + uint32_t outbound_doorbell; + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + + outbound_doorbell = readl(reg->iop2drv_doorbell_reg) & \ + acb->outbound_int_enable; + if (!outbound_doorbell) + return 1; + + writel(~outbound_doorbell, reg->iop2drv_doorbell_reg); + + if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_WRITE_OK) { + arcmsr_iop2drv_data_wrote_handle(acb); + } + if (outbound_doorbell & ARCMSR_IOP2DRV_DATA_READ_OK) { + arcmsr_iop2drv_data_read_handle(acb); + } + if (outbound_doorbell & ARCMSR_IOP2DRV_CDB_DONE) { + arcmsr_hbb_postqueue_isr(acb); + } + + return 0; +} + +static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + if (arcmsr_handle_hba_isr(acb)) { + return IRQ_NONE; + } + } + break; + + case ACB_ADAPTER_TYPE_B: { + if (arcmsr_handle_hbb_isr(acb)) { + return IRQ_NONE; + } + } + break; } - if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) - return IRQ_NONE; return IRQ_HANDLED; } @@ -818,16 +1290,47 @@ static void arcmsr_iop_parking(struct AdapterControlBlock *acb) if (acb) { /* stop adapter background rebuild */ if (acb->acb_flags & ACB_F_MSG_START_BGRB) { + uint32_t intmask_org; acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + intmask_org = arcmsr_disable_outbound_ints(acb); arcmsr_stop_adapter_bgrb(acb); arcmsr_flush_adapter_cache(acb); + arcmsr_enable_outbound_ints(acb, intmask_org); } } } -static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd) +void arcmsr_post_ioctldata2iop(struct AdapterControlBlock *acb) +{ + int32_t wqbuf_firstindex, wqbuf_lastindex; + uint8_t *pQbuffer; + struct QBUFFER *pwbuffer; + uint8_t *iop_data; + int32_t allxfer_len = 0; + + pwbuffer = arcmsr_get_iop_wqbuffer(acb); + iop_data = (uint8_t __iomem *)pwbuffer->data; + if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_READED) { + acb->acb_flags &= (~ACB_F_MESSAGE_WQBUFFER_READED); + wqbuf_firstindex = acb->wqbuf_firstindex; + wqbuf_lastindex = acb->wqbuf_lastindex; + while ((wqbuf_firstindex != wqbuf_lastindex) && (allxfer_len < 124)) { + pQbuffer = &acb->wqbuffer[wqbuf_firstindex]; + memcpy(iop_data, pQbuffer, 1); + wqbuf_firstindex++; + wqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + allxfer_len++; + } + acb->wqbuf_firstindex = wqbuf_firstindex; + pwbuffer->data_len = allxfer_len; + arcmsr_iop_message_wrote(acb); + } +} + +static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ + struct scsi_cmnd *cmd) { - struct MessageUnit __iomem *reg = acb->pmu; struct CMD_MESSAGE_FIELD *pcmdmessagefld; int retvalue = 0, transfer_len = 0; char *buffer; @@ -836,7 +1339,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ (uint32_t ) cmd->cmnd[6] << 16 | (uint32_t ) cmd->cmnd[7] << 8 | (uint32_t ) cmd->cmnd[8]; - /* 4 bytes: Areca io control code */ + /* 4 bytes: Areca io control code */ sg = scsi_sglist(cmd); buffer = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; @@ -852,194 +1355,199 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_ } pcmdmessagefld = (struct CMD_MESSAGE_FIELD *) buffer; switch(controlcode) { + case ARCMSR_MESSAGE_READ_RQBUFFER: { - unsigned long *ver_addr; - dma_addr_t buf_handle; - uint8_t *pQbuffer, *ptmpQbuffer; - int32_t allxfer_len = 0; + unsigned long *ver_addr; + dma_addr_t buf_handle; + uint8_t *pQbuffer, *ptmpQbuffer; + int32_t allxfer_len = 0; + + ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; + } + ptmpQbuffer = (uint8_t *) ver_addr; + while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) + && (allxfer_len < 1031)) { + pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; + memcpy(ptmpQbuffer, pQbuffer, 1); + acb->rqbuf_firstindex++; + acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; + ptmpQbuffer++; + allxfer_len++; + } + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); - if (!ver_addr) { - retvalue = ARCMSR_MESSAGE_FAIL; - goto message_out; - } - ptmpQbuffer = (uint8_t *) ver_addr; - while ((acb->rqbuf_firstindex != acb->rqbuf_lastindex) - && (allxfer_len < 1031)) { - pQbuffer = &acb->rqbuffer[acb->rqbuf_firstindex]; - memcpy(ptmpQbuffer, pQbuffer, 1); - acb->rqbuf_firstindex++; - acb->rqbuf_firstindex %= ARCMSR_MAX_QBUFFER; - ptmpQbuffer++; - allxfer_len++; - } - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER __iomem * prbuffer = (struct QBUFFER __iomem *) - ®->message_rbuffer; - uint8_t __iomem * iop_data = (uint8_t __iomem *)prbuffer->data; - int32_t iop_len; - - acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - iop_len = readl(&prbuffer->data_len); - while (iop_len > 0) { - acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); - acb->rqbuf_lastindex++; - acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; - iop_data++; - iop_len--; - } - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); + struct QBUFFER *prbuffer; + uint8_t *iop_data; + int32_t iop_len; + + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + prbuffer = arcmsr_get_iop_rqbuffer(acb); + iop_data = (uint8_t *)prbuffer->data; + iop_len = readl(&prbuffer->data_len); + while (iop_len > 0) { + acb->rqbuffer[acb->rqbuf_lastindex] = readb(iop_data); + acb->rqbuf_lastindex++; + acb->rqbuf_lastindex %= ARCMSR_MAX_QBUFFER; + iop_data++; + iop_len--; } - memcpy(pcmdmessagefld->messagedatabuffer, - (uint8_t *)ver_addr, allxfer_len); - pcmdmessagefld->cmdmessage.Length = allxfer_len; - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; - pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); + arcmsr_iop_message_read(acb); + } + memcpy(pcmdmessagefld->messagedatabuffer, (uint8_t *)ver_addr, allxfer_len); + pcmdmessagefld->cmdmessage.Length = allxfer_len; + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); } break; - case ARCMSR_MESSAGE_WRITE_WQBUFFER: { - unsigned long *ver_addr; - dma_addr_t buf_handle; - int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; - uint8_t *pQbuffer, *ptmpuserbuffer; - ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); - if (!ver_addr) { - retvalue = ARCMSR_MESSAGE_FAIL; - goto message_out; - } - ptmpuserbuffer = (uint8_t *)ver_addr; - user_len = pcmdmessagefld->cmdmessage.Length; - memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); - wqbuf_lastindex = acb->wqbuf_lastindex; - wqbuf_firstindex = acb->wqbuf_firstindex; - if (wqbuf_lastindex != wqbuf_firstindex) { + case ARCMSR_MESSAGE_WRITE_WQBUFFER: { + unsigned long *ver_addr; + dma_addr_t buf_handle; + int32_t my_empty_len, user_len, wqbuf_firstindex, wqbuf_lastindex; + uint8_t *pQbuffer, *ptmpuserbuffer; + + ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; + } + ptmpuserbuffer = (uint8_t *)ver_addr; + user_len = pcmdmessagefld->cmdmessage.Length; + memcpy(ptmpuserbuffer, pcmdmessagefld->messagedatabuffer, user_len); + wqbuf_lastindex = acb->wqbuf_lastindex; + wqbuf_firstindex = acb->wqbuf_firstindex; + if (wqbuf_lastindex != wqbuf_firstindex) { + struct SENSE_DATA *sensebuffer = + (struct SENSE_DATA *)cmd->sense_buffer; + arcmsr_post_ioctldata2iop(acb); + /* has error report sensedata */ + sensebuffer->ErrorCode = 0x70; + sensebuffer->SenseKey = ILLEGAL_REQUEST; + sensebuffer->AdditionalSenseLength = 0x0A; + sensebuffer->AdditionalSenseCode = 0x20; + sensebuffer->Valid = 1; + retvalue = ARCMSR_MESSAGE_FAIL; + } else { + my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) + &(ARCMSR_MAX_QBUFFER - 1); + if (my_empty_len >= user_len) { + while (user_len > 0) { + pQbuffer = + &acb->wqbuffer[acb->wqbuf_lastindex]; + memcpy(pQbuffer, ptmpuserbuffer, 1); + acb->wqbuf_lastindex++; + acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; + ptmpuserbuffer++; + user_len--; + } + if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { + acb->acb_flags &= + ~ACB_F_MESSAGE_WQBUFFER_CLEARED; + arcmsr_post_ioctldata2iop(acb); + } + } else { + /* has error report sensedata */ struct SENSE_DATA *sensebuffer = (struct SENSE_DATA *)cmd->sense_buffer; - arcmsr_post_Qbuffer(acb); - /* has error report sensedata */ sensebuffer->ErrorCode = 0x70; sensebuffer->SenseKey = ILLEGAL_REQUEST; sensebuffer->AdditionalSenseLength = 0x0A; sensebuffer->AdditionalSenseCode = 0x20; sensebuffer->Valid = 1; retvalue = ARCMSR_MESSAGE_FAIL; - } else { - my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) - &(ARCMSR_MAX_QBUFFER - 1); - if (my_empty_len >= user_len) { - while (user_len > 0) { - pQbuffer = - &acb->wqbuffer[acb->wqbuf_lastindex]; - memcpy(pQbuffer, ptmpuserbuffer, 1); - acb->wqbuf_lastindex++; - acb->wqbuf_lastindex %= ARCMSR_MAX_QBUFFER; - ptmpuserbuffer++; - user_len--; - } - if (acb->acb_flags & ACB_F_MESSAGE_WQBUFFER_CLEARED) { - acb->acb_flags &= - ~ACB_F_MESSAGE_WQBUFFER_CLEARED; - arcmsr_post_Qbuffer(acb); - } - } else { - /* has error report sensedata */ - struct SENSE_DATA *sensebuffer = - (struct SENSE_DATA *)cmd->sense_buffer; - sensebuffer->ErrorCode = 0x70; - sensebuffer->SenseKey = ILLEGAL_REQUEST; - sensebuffer->AdditionalSenseLength = 0x0A; - sensebuffer->AdditionalSenseCode = 0x20; - sensebuffer->Valid = 1; - retvalue = ARCMSR_MESSAGE_FAIL; - } + } } pci_free_consistent(acb->pdev, 1032, ver_addr, buf_handle); } break; + case ARCMSR_MESSAGE_CLEAR_RQBUFFER: { - uint8_t *pQbuffer = acb->rqbuffer; + uint8_t *pQbuffer = acb->rqbuffer; - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, - ®->inbound_doorbell); - } - acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; - acb->rqbuf_firstindex = 0; - acb->rqbuf_lastindex = 0; - memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - pcmdmessagefld->cmdmessage.ReturnCode = - ARCMSR_MESSAGE_RETURNCODE_OK; + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + arcmsr_iop_message_read(acb); + } + acb->acb_flags |= ACB_F_MESSAGE_RQBUFFER_CLEARED; + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } break; + case ARCMSR_MESSAGE_CLEAR_WQBUFFER: { - uint8_t *pQbuffer = acb->wqbuffer; + uint8_t *pQbuffer = acb->wqbuffer; - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK - , ®->inbound_doorbell); - } - acb->acb_flags |= - (ACB_F_MESSAGE_WQBUFFER_CLEARED | - ACB_F_MESSAGE_WQBUFFER_READED); - acb->wqbuf_firstindex = 0; - acb->wqbuf_lastindex = 0; - memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); - pcmdmessagefld->cmdmessage.ReturnCode = - ARCMSR_MESSAGE_RETURNCODE_OK; + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + arcmsr_iop_message_read(acb); + } + acb->acb_flags |= + (ACB_F_MESSAGE_WQBUFFER_CLEARED | + ACB_F_MESSAGE_WQBUFFER_READED); + acb->wqbuf_firstindex = 0; + acb->wqbuf_lastindex = 0; + memset(pQbuffer, 0, ARCMSR_MAX_QBUFFER); + pcmdmessagefld->cmdmessage.ReturnCode = + ARCMSR_MESSAGE_RETURNCODE_OK; } break; + case ARCMSR_MESSAGE_CLEAR_ALLQBUFFER: { - uint8_t *pQbuffer; + uint8_t *pQbuffer; - if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK - , ®->inbound_doorbell); - } - acb->acb_flags |= - (ACB_F_MESSAGE_WQBUFFER_CLEARED - | ACB_F_MESSAGE_RQBUFFER_CLEARED - | ACB_F_MESSAGE_WQBUFFER_READED); - acb->rqbuf_firstindex = 0; - acb->rqbuf_lastindex = 0; - acb->wqbuf_firstindex = 0; - acb->wqbuf_lastindex = 0; - pQbuffer = acb->rqbuffer; - memset(pQbuffer, 0, sizeof (struct QBUFFER)); - pQbuffer = acb->wqbuffer; - memset(pQbuffer, 0, sizeof (struct QBUFFER)); - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { + acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; + arcmsr_iop_message_read(acb); + } + acb->acb_flags |= + (ACB_F_MESSAGE_WQBUFFER_CLEARED + | ACB_F_MESSAGE_RQBUFFER_CLEARED + | ACB_F_MESSAGE_WQBUFFER_READED); + acb->rqbuf_firstindex = 0; + acb->rqbuf_lastindex = 0; + acb->wqbuf_firstindex = 0; + acb->wqbuf_lastindex = 0; + pQbuffer = acb->rqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); + pQbuffer = acb->wqbuffer; + memset(pQbuffer, 0, sizeof(struct QBUFFER)); + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } break; + case ARCMSR_MESSAGE_RETURN_CODE_3F: { - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_3F; } break; + case ARCMSR_MESSAGE_SAY_HELLO: { - int8_t * hello_string = "Hello! I am ARCMSR"; + int8_t *hello_string = "Hello! I am ARCMSR"; - memcpy(pcmdmessagefld->messagedatabuffer, hello_string - , (int16_t)strlen(hello_string)); - pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; + memcpy(pcmdmessagefld->messagedatabuffer, hello_string + , (int16_t)strlen(hello_string)); + pcmdmessagefld->cmdmessage.ReturnCode = ARCMSR_MESSAGE_RETURNCODE_OK; } break; + case ARCMSR_MESSAGE_SAY_GOODBYE: arcmsr_iop_parking(acb); break; + case ARCMSR_MESSAGE_FLUSH_ADAPTER_CACHE: arcmsr_flush_adapter_cache(acb); break; + default: retvalue = ARCMSR_MESSAGE_FAIL; } - message_out: + message_out: sg = scsi_sglist(cmd); kunmap_atomic(buffer - sg->offset, KM_IRQ0); - return retvalue; } @@ -1109,8 +1617,7 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, void (* done)(struct scsi_cmnd *)) { struct Scsi_Host *host = cmd->device->host; - struct AdapterControlBlock *acb = - (struct AdapterControlBlock *) host->hostdata; + struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; struct CommandControlBlock *ccb; int target = cmd->device->id; int lun = cmd->device->lun; @@ -1153,26 +1660,27 @@ static int arcmsr_queue_command(struct scsi_cmnd *cmd, ccb = arcmsr_get_freeccb(acb); if (!ccb) return SCSI_MLQUEUE_HOST_BUSY; + arcmsr_build_ccb(acb, ccb, cmd); arcmsr_post_ccb(acb, ccb); return 0; } -static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) +static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; - char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15]; - char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17]; + char *iop_firm_model = (char *) (®->message_rwbuffer[15]); + char *iop_firm_version = (char *) (®->message_rwbuffer[17]); int count; writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) - printk(KERN_NOTICE - "arcmsr%d: wait " - "'get adapter firmware miscellaneous data' timeout \n" - , acb->host->host_no); + if (arcmsr_hba_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ + miscellaneous data' timeout \n", acb->host->host_no); + } + count = 8; while (count) { *acb_firm_model = readb(iop_firm_model); @@ -1180,6 +1688,7 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) iop_firm_model++; count--; } + count = 16; while (count) { *acb_firm_version = readb(iop_firm_version); @@ -1187,28 +1696,93 @@ static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) iop_firm_version++; count--; } - printk(KERN_INFO - "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" + + printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n" , acb->host->host_no , acb->firm_version); + acb->firm_request_len = readl(®->message_rwbuffer[1]); acb->firm_numbers_queue = readl(®->message_rwbuffer[2]); acb->firm_sdram_size = readl(®->message_rwbuffer[3]); acb->firm_hd_channels = readl(®->message_rwbuffer[4]); } -static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, +static void arcmsr_get_hbb_config(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + uint32_t *lrwbuffer = reg->msgcode_rwbuffer_reg; + char *acb_firm_model = acb->firm_model; + char *acb_firm_version = acb->firm_version; + char *iop_firm_model = (char *) (&lrwbuffer[15]); + /*firm_model,15,60-67*/ + char *iop_firm_version = (char *) (&lrwbuffer[17]); + /*firm_version,17,68-83*/ + int count; + + writel(ARCMSR_MESSAGE_GET_CONFIG, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ + miscellaneous data' timeout \n", acb->host->host_no); + } + + count = 8; + while (count) + { + *acb_firm_model = readb(iop_firm_model); + acb_firm_model++; + iop_firm_model++; + count--; + } + + count = 16; + while (count) + { + *acb_firm_version = readb(iop_firm_version); + acb_firm_version++; + iop_firm_version++; + count--; + } + + printk(KERN_INFO "ARECA RAID ADAPTER%d: FIRMWARE VERSION %s \n", + acb->host->host_no, + acb->firm_version); + + lrwbuffer++; + acb->firm_request_len = readl(lrwbuffer++); + /*firm_request_len,1,04-07*/ + acb->firm_numbers_queue = readl(lrwbuffer++); + /*firm_numbers_queue,2,08-11*/ + acb->firm_sdram_size = readl(lrwbuffer++); + /*firm_sdram_size,3,12-15*/ + acb->firm_hd_channels = readl(lrwbuffer); + /*firm_ide_channels,4,16-19*/ +} + +static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + arcmsr_get_hba_config(acb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_get_hbb_config(acb); + } + break; + } +} + +static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { - struct MessageUnit __iomem *reg = acb->pmu; + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; struct CommandControlBlock *ccb; uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; - int id, lun; - polling_ccb_retry: + polling_hba_ccb_retry: poll_count++; - outbound_intstatus = readl(®->outbound_intstatus) - & acb->outbound_int_enable; + outbound_intstatus = readl(®->outbound_intstatus) & acb->outbound_int_enable; writel(outbound_intstatus, ®->outbound_intstatus);/*clear interrupt*/ while (1) { if ((flag_ccb = readl(®->outbound_queueport)) == 0xFFFFFFFF) { @@ -1218,17 +1792,14 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, msleep(25); if (poll_count > 100) break; - goto polling_ccb_retry; + goto polling_hba_ccb_retry; } } - ccb = (struct CommandControlBlock *) - (acb->vir2phy_offset + (flag_ccb << 5)); - if ((ccb->acb != acb) || - (ccb->startdone != ARCMSR_CCB_START)) { - if ((ccb->startdone == ARCMSR_CCB_ABORTED) || - (ccb == poll_ccb)) { - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" + ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + (flag_ccb << 5)); + poll_ccb_done = (ccb == poll_ccb) ? 1:0; + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if ((ccb->startdone == ARCMSR_CCB_ABORTED) || (ccb == poll_ccb)) { + printk(KERN_NOTICE "arcmsr%d: scsi id = %d lun = %d ccb = '0x%p'" " poll command abort successfully \n" , acb->host->host_no , ccb->pcmd->device->id @@ -1239,176 +1810,280 @@ static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, poll_ccb_done = 1; continue; } - printk(KERN_NOTICE - "arcmsr%d: polling get an illegal ccb" - " command done ccb ='0x%p'" + printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" + " command done ccb = '0x%p'" "ccboutstandingcount = %d \n" , acb->host->host_no , ccb , atomic_read(&acb->ccboutstandingcount)); continue; } - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (acb->devstate[id][lun] == ARECA_RAID_GONE) - acb->devstate[id][lun] = ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - case ARCMSR_DEV_ABORTED: - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); + arcmsr_report_ccb_state(acb, ccb, flag_ccb); + } +} + +static void arcmsr_polling_hbb_ccbdone(struct AdapterControlBlock *acb, \ + struct CommandControlBlock *poll_ccb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + struct CommandControlBlock *ccb; + uint32_t flag_ccb, poll_ccb_done = 0, poll_count = 0; + int index; + + polling_hbb_ccb_retry: + poll_count++; + /* clear doorbell interrupt */ + writel(ARCMSR_DOORBELL_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); + while (1) { + index = reg->doneq_index; + if ((flag_ccb = readl(®->done_qbuffer[index])) == 0) { + if (poll_ccb_done) + break; + else { + msleep(25); + if (poll_count > 100) + break; + goto polling_hbb_ccb_retry; } - break; - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); + } + writel(0, ®->done_qbuffer[index]); + index++; + /*if last index number set it to 0 */ + index %= ARCMSR_MAX_HBB_POSTQUEUE; + reg->doneq_index = index; + /* check ifcommand done with no error*/ + ccb = (struct CommandControlBlock *)\ + (acb->vir2phy_offset + (flag_ccb << 5));/*frame must be 32 bytes aligned*/ + poll_ccb_done = (ccb == poll_ccb) ? 1:0; + if ((ccb->acb != acb) || (ccb->startdone != ARCMSR_CCB_START)) { + if (ccb->startdone == ARCMSR_CCB_ABORTED) { + printk(KERN_NOTICE "arcmsr%d: \ + scsi id = %d lun = %d ccb = '0x%p' poll command abort successfully \n" + ,acb->host->host_no + ,ccb->pcmd->device->id + ,ccb->pcmd->device->lun + ,ccb); + ccb->pcmd->result = DID_ABORT << 16; arcmsr_ccb_complete(ccb, 1); + continue; } - break; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d lun = %d" - " polling and getting command error done" - "but got unknown DeviceStatus = 0x%x \n" + printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" + " command done ccb = '0x%p'" + "ccboutstandingcount = %d \n" , acb->host->host_no - , id - , lun - , ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - break; + , ccb + , atomic_read(&acb->ccboutstandingcount)); + continue; } + arcmsr_report_ccb_state(acb, ccb, flag_ccb); + } /*drain reply FIFO*/ +} + +static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, \ + struct CommandControlBlock *poll_ccb) +{ + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + arcmsr_polling_hba_ccbdone(acb,poll_ccb); + } + break; + + case ACB_ADAPTER_TYPE_B: { + arcmsr_polling_hbb_ccbdone(acb,poll_ccb); } } } -static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb) + +static int arcmsr_iop_confirm(struct AdapterControlBlock *acb) { - int i = 0, found = 0; - int id, lun; - uint32_t flag_ccb, outbound_intstatus; - struct MessageUnit __iomem *reg = acb->pmu; - struct CommandControlBlock *ccb; - /*clear and abort all outbound posted Q*/ - - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && -(i++ < 256)){ - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + -(flag_ccb << 5)); - if (ccb){ - if ((ccb->acb != acb)||(ccb->startdone != \ -ARCMSR_CCB_START)){ - printk(KERN_NOTICE "arcmsr%d: polling get \ -an illegal ccb" "command done ccb = '0x%p'""ccboutstandingcount = %d \n", - acb->host->host_no, ccb, - atomic_read(&acb->ccboutstandingcount)); - continue; + uint32_t cdb_phyaddr, ccb_phyaddr_hi32; + dma_addr_t dma_coherent_handle; + /* + ******************************************************************** + ** here we need to tell iop 331 our freeccb.HighPart + ** if freeccb.HighPart is not zero + ******************************************************************** + */ + dma_coherent_handle = acb->dma_coherent_handle; + cdb_phyaddr = (uint32_t)(dma_coherent_handle); + ccb_phyaddr_hi32 = (uint32_t)((cdb_phyaddr >> 16) >> 16); + /* + *********************************************************************** + ** if adapter type B, set window of "post command Q" + *********************************************************************** + */ + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + if (ccb_phyaddr_hi32 != 0) { + struct MessageUnit_A __iomem *reg = \ + (struct MessageUnit_A *)acb->pmu; + uint32_t intmask_org; + intmask_org = arcmsr_disable_outbound_ints(acb); + writel(ARCMSR_SIGNATURE_SET_CONFIG, \ + ®->message_rwbuffer[0]); + writel(ccb_phyaddr_hi32, ®->message_rwbuffer[1]); + writel(ARCMSR_INBOUND_MESG0_SET_CONFIG, \ + ®->inbound_msgaddr0); + if (arcmsr_hba_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: ""set ccb high \ + part physical address timeout\n", + acb->host->host_no); + return 1; } + arcmsr_enable_outbound_ints(acb, intmask_org); + } + } + break; - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)){ - if (acb->devstate[id][lun] == ARECA_RAID_GONE) - acb->devstate[id][lun] = ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } - else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = ARECA_RAID_GONE; - ccb->pcmd->result = DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; + case ACB_ADAPTER_TYPE_B: { + unsigned long post_queue_phyaddr; + uint32_t *rwbuffer; - case ARCMSR_DEV_ABORTED: + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + uint32_t intmask_org; + intmask_org = arcmsr_disable_outbound_ints(acb); + reg->postq_index = 0; + reg->doneq_index = 0; + writel(ARCMSR_MESSAGE_SET_POST_WINDOW, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d:can not set diver mode\n", \ + acb->host->host_no); + return 1; + } + post_queue_phyaddr = cdb_phyaddr + ARCMSR_MAX_FREECCB_NUM * \ + sizeof(struct CommandControlBlock) + offsetof(struct MessageUnit_B, post_qbuffer) ; + rwbuffer = reg->msgcode_rwbuffer_reg; + /* driver "set config" signature */ + writel(ARCMSR_SIGNATURE_SET_CONFIG, rwbuffer++); + /* normal should be zero */ + writel(ccb_phyaddr_hi32, rwbuffer++); + /* postQ size (256 + 8)*4 */ + writel(post_queue_phyaddr, rwbuffer++); + /* doneQ size (256 + 8)*4 */ + writel(post_queue_phyaddr + 1056, rwbuffer++); + /* ccb maxQ size must be --> [(256 + 8)*4]*/ + writel(1056, rwbuffer); + + writel(ARCMSR_MESSAGE_SET_CONFIG, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: 'set command Q window' \ + timeout \n",acb->host->host_no); + return 1; + } - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; + writel(ARCMSR_MESSAGE_START_DRIVER_MODE, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: 'can not set diver mode \n"\ + ,acb->host->host_no); + return 1; + } + arcmsr_enable_outbound_ints(acb, intmask_org); + } + break; + } + return 0; +} - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = - ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); - } - break; +static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) +{ + uint32_t firmware_state = 0; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi id = %d \ - lun = %d""polling and \ - getting command error \ - done""but got unknown \ - DeviceStatus = 0x%x \n", - acb->host->host_no, id, - lun, ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - break; - } - } - found = 1; - } + switch (acb->adapter_type) { + + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + do { + firmware_state = readl(®->outbound_msgaddr1); + } while ((firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK) == 0); + } + break; + + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + do { + firmware_state = readl(reg->iop2drv_doorbell_reg); + } while ((firmware_state & ARCMSR_MESSAGE_FIRMWARE_OK) == 0); + } + break; } - if (found){ - outbound_intstatus = readl(®->outbound_intstatus) & \ - acb->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus); - /*clear interrupt*/ +} + +static void arcmsr_start_hba_bgrb(struct AdapterControlBlock *acb) +{ + struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + acb->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); + if (arcmsr_hba_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ + rebulid' timeout \n", acb->host->host_no); } - return; } +static void arcmsr_start_hbb_bgrb(struct AdapterControlBlock *acb) +{ + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + acb->acb_flags |= ACB_F_MSG_START_BGRB; + writel(ARCMSR_MESSAGE_START_BGRB, reg->drv2iop_doorbell_reg); + if (arcmsr_hbb_wait_msgint_ready(acb)) { + printk(KERN_NOTICE "arcmsr%d: wait 'start adapter background \ + rebulid' timeout \n",acb->host->host_no); + } +} -static void arcmsr_iop_init(struct AdapterControlBlock *acb) +static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) { - struct MessageUnit __iomem *reg = acb->pmu; - uint32_t intmask_org, mask, outbound_doorbell, firmware_state = 0; + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: + arcmsr_start_hba_bgrb(acb); + break; + case ACB_ADAPTER_TYPE_B: + arcmsr_start_hbb_bgrb(acb); + break; + } +} - do { - firmware_state = readl(®->outbound_msgaddr1); - } while (!(firmware_state & ARCMSR_OUTBOUND_MESG1_FIRMWARE_OK)); - intmask_org = readl(®->outbound_intmask) - | ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE; - arcmsr_get_firmware_spec(acb); +static void arcmsr_clear_doorbell_queue_buffer(struct AdapterControlBlock *acb) +{ + switch (acb->adapter_type) { + case ACB_ADAPTER_TYPE_A: { + struct MessageUnit_A *reg = (struct MessageUnit_A *)acb->pmu; + uint32_t outbound_doorbell; + /* empty doorbell Qbuffer if door bell ringed */ + outbound_doorbell = readl(®->outbound_doorbell); + /*clear doorbell interrupt */ + writel(outbound_doorbell, ®->outbound_doorbell); + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); + } + break; - acb->acb_flags |= ACB_F_MSG_START_BGRB; - writel(ARCMSR_INBOUND_MESG0_START_BGRB, ®->inbound_msgaddr0); - if (arcmsr_wait_msgint_ready(acb)) { - printk(KERN_NOTICE "arcmsr%d: " - "wait 'start adapter background rebulid' timeout\n", - acb->host->host_no); + case ACB_ADAPTER_TYPE_B: { + struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + /*clear interrupt and message state*/ + writel(ARCMSR_MESSAGE_INT_CLEAR_PATTERN, reg->iop2drv_doorbell_reg); + writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); + /* let IOP know data has been read */ + } + break; } +} - outbound_doorbell = readl(®->outbound_doorbell); - writel(outbound_doorbell, ®->outbound_doorbell); - writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, ®->inbound_doorbell); - mask = ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE - | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - writel(intmask_org & mask, ®->outbound_intmask); - acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; +static void arcmsr_iop_init(struct AdapterControlBlock *acb) +{ + uint32_t intmask_org; + + arcmsr_wait_firmware_ready(acb); + arcmsr_iop_confirm(acb); + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); + arcmsr_get_firmware_spec(acb); + /*start background rebuild*/ + arcmsr_start_adapter_bgrb(acb); + /* empty doorbell Qbuffer if door bell ringed */ + arcmsr_clear_doorbell_queue_buffer(acb); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); acb->acb_flags |= ACB_F_IOP_INITED; } @@ -1421,22 +2096,24 @@ static void arcmsr_iop_reset(struct AdapterControlBlock *acb) if (atomic_read(&acb->ccboutstandingcount) != 0) { /* talk to iop 331 outstanding command aborted */ arcmsr_abort_allcmd(acb); + /* wait for 3 sec for all command aborted*/ - msleep_interruptible(3000); + ssleep(3); + /* disable all outbound interrupt */ intmask_org = arcmsr_disable_outbound_ints(acb); /* clear all outbound posted Q */ - arcmsr_done4_abort_postqueue(acb); + arcmsr_done4abort_postqueue(acb); for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { ccb->startdone = ARCMSR_CCB_ABORTED; + arcmsr_ccb_complete(ccb, 1); } } /* enable all outbound interrupt */ arcmsr_enable_outbound_ints(acb, intmask_org); } - } static int arcmsr_bus_reset(struct scsi_cmnd *cmd) @@ -1450,7 +2127,7 @@ static int arcmsr_bus_reset(struct scsi_cmnd *cmd) for (i = 0; i < 400; i++) { if (!atomic_read(&acb->ccboutstandingcount)) break; - arcmsr_interrupt(acb); + arcmsr_interrupt(acb);/* FIXME: need spinlock */ msleep(25); } arcmsr_iop_reset(acb); @@ -1468,7 +2145,7 @@ static void arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, /* ** Wait for 3 sec for all command done. */ - msleep_interruptible(3000); + ssleep(3); intmask = arcmsr_disable_outbound_ints(acb); arcmsr_polling_ccbdone(acb, ccb); @@ -1515,6 +2192,8 @@ static const char *arcmsr_info(struct Scsi_Host *host) switch (acb->pdev->device) { case PCI_DEVICE_ID_ARECA_1110: + case PCI_DEVICE_ID_ARECA_1200: + case PCI_DEVICE_ID_ARECA_1202: case PCI_DEVICE_ID_ARECA_1210: raid6 = 0; /*FALLTHRU*/ @@ -1522,6 +2201,7 @@ static const char *arcmsr_info(struct Scsi_Host *host) case PCI_DEVICE_ID_ARECA_1130: case PCI_DEVICE_ID_ARECA_1160: case PCI_DEVICE_ID_ARECA_1170: + case PCI_DEVICE_ID_ARECA_1201: case PCI_DEVICE_ID_ARECA_1220: case PCI_DEVICE_ID_ARECA_1230: case PCI_DEVICE_ID_ARECA_1260: @@ -1544,287 +2224,82 @@ static const char *arcmsr_info(struct Scsi_Host *host) ARCMSR_DRIVER_VERSION); return buf; } - +#ifdef CONFIG_SCSI_ARCMSR_AER static pci_ers_result_t arcmsr_pci_slot_reset(struct pci_dev *pdev) { - struct Scsi_Host *host; - struct AdapterControlBlock *acb; - uint8_t bus, dev_fun; - int error; - - error = pci_enable_device(pdev); - if (error) - return PCI_ERS_RESULT_DISCONNECT; - pci_set_master(pdev); - - host = scsi_host_alloc(&arcmsr_scsi_host_template, sizeof \ -(struct AdapterControlBlock)); - if (!host) - return PCI_ERS_RESULT_DISCONNECT; - acb = (struct AdapterControlBlock *)host->hostdata; - memset(acb, 0, sizeof (struct AdapterControlBlock)); - - error = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (error) { - error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (error) { - printk(KERN_WARNING - "scsi%d: No suitable DMA mask available\n", - host->host_no); - return PCI_ERS_RESULT_DISCONNECT; - } - } - bus = pdev->bus->number; - dev_fun = pdev->devfn; - acb = (struct AdapterControlBlock *) host->hostdata; - memset(acb, 0, sizeof(struct AdapterControlBlock)); - acb->pdev = pdev; - acb->host = host; - host->max_sectors = ARCMSR_MAX_XFER_SECTORS; - host->max_lun = ARCMSR_MAX_TARGETLUN; - host->max_id = ARCMSR_MAX_TARGETID;/*16:8*/ - host->max_cmd_len = 16; /*this is issue of 64bit LBA, over 2T byte*/ - host->sg_tablesize = ARCMSR_MAX_SG_ENTRIES; - host->can_queue = ARCMSR_MAX_FREECCB_NUM; /* max simultaneous cmds */ - host->cmd_per_lun = ARCMSR_MAX_CMD_PERLUN; - host->this_id = ARCMSR_SCSI_INITIATOR_ID; - host->unique_id = (bus << 8) | dev_fun; - host->irq = pdev->irq; - error = pci_request_regions(pdev, "arcmsr"); - if (error) - return PCI_ERS_RESULT_DISCONNECT; + struct Scsi_Host *host = pci_get_drvdata(pdev); + struct AdapterControlBlock *acb = + (struct AdapterControlBlock *) host->hostdata; + uint32_t intmask_org; + int i, j; - acb->pmu = ioremap(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - if (!acb->pmu) { - printk(KERN_NOTICE "arcmsr%d: memory" - " mapping region fail \n", acb->host->host_no); + if (pci_enable_device(pdev)) { return PCI_ERS_RESULT_DISCONNECT; } + pci_set_master(pdev); + intmask_org = arcmsr_disable_outbound_ints(acb); acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; - INIT_LIST_HEAD(&acb->ccb_free_list); - - error = arcmsr_alloc_ccb_pool(acb); - if (error) - return PCI_ERS_RESULT_DISCONNECT; - - error = request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb); - if (error) - return PCI_ERS_RESULT_DISCONNECT; - - arcmsr_iop_init(acb); - if (strncmp(acb->firm_version, "V1.42", 5) >= 0) - host->max_sectors = ARCMSR_MAX_XFER_SECTORS_B; - - pci_set_drvdata(pdev, host); - - error = scsi_add_host(host, &pdev->dev); - if (error) - return PCI_ERS_RESULT_DISCONNECT; + for (i = 0; i < ARCMSR_MAX_TARGETID; i++) + for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) + acb->devstate[i][j] = ARECA_RAID_GONE; - error = arcmsr_alloc_sysfs_attr(acb); - if (error) - return PCI_ERS_RESULT_DISCONNECT; + arcmsr_wait_firmware_ready(acb); + arcmsr_iop_confirm(acb); + /* disable all outbound interrupt */ + arcmsr_get_firmware_spec(acb); + /*start background rebuild*/ + arcmsr_start_adapter_bgrb(acb); + /* empty doorbell Qbuffer if door bell ringed */ + arcmsr_clear_doorbell_queue_buffer(acb); + /* enable outbound Post Queue,outbound doorbell Interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + acb->acb_flags |= ACB_F_IOP_INITED; - scsi_scan_host(host); + pci_enable_pcie_error_reporting(pdev); return PCI_ERS_RESULT_RECOVERED; } static void arcmsr_pci_ers_need_reset_forepart(struct pci_dev *pdev) { struct Scsi_Host *host = pci_get_drvdata(pdev); - struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; + struct AdapterControlBlock *acb = (struct AdapterControlBlock *)host->hostdata; struct CommandControlBlock *ccb; - /*clear and abort all outbound posted Q*/ - int i = 0, found = 0; - int id, lun; - uint32_t flag_ccb, outbound_intstatus; - - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && - (i++ < 256)){ - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset - + (flag_ccb << 5)); - if (ccb){ - if ((ccb->acb != acb)||(ccb->startdone != - ARCMSR_CCB_START)){ - printk(KERN_NOTICE "arcmsr%d: polling \ - get an illegal ccb"" command done ccb = '0x%p'" - "ccboutstandingcount = %d \n", - acb->host->host_no, ccb, - atomic_read(&acb->ccboutstandingcount)); - continue; - } - - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (acb->devstate[id][lun] == - ARECA_RAID_GONE) - acb->devstate[id][lun] = - ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } - else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - - case ARCMSR_DEV_ABORTED: - - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = - ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); - } - break; + uint32_t intmask_org; + int i = 0; - default: - printk(KERN_NOTICE - "arcmsr%d: scsi \ - id = %d lun = %d" - " polling and \ - getting command \ - error done" - "but got unknown \ - DeviceStatus = 0x%x \n" - , acb->host->host_no, - id, lun, - ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - break; - } - } - found = 1; + if (atomic_read(&acb->ccboutstandingcount) != 0) { + /* talk to iop 331 outstanding command aborted */ + arcmsr_abort_allcmd(acb); + /* wait for 3 sec for all command aborted*/ + ssleep(3); + /* disable all outbound interrupt */ + intmask_org = arcmsr_disable_outbound_ints(acb); + /* clear all outbound posted Q */ + arcmsr_done4abort_postqueue(acb); + for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { + ccb = acb->pccb_pool[i]; + if (ccb->startdone == ARCMSR_CCB_START) { + ccb->startdone = ARCMSR_CCB_ABORTED; + arcmsr_ccb_complete(ccb, 1); } } - if (found){ - outbound_intstatus = readl(®->outbound_intstatus) & - acb->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus); - /*clear interrupt*/ - } - return; + /* enable all outbound interrupt */ + arcmsr_enable_outbound_ints(acb, intmask_org); + } + pci_disable_device(pdev); } - static void arcmsr_pci_ers_disconnect_forepart(struct pci_dev *pdev) { - struct Scsi_Host *host = pci_get_drvdata(pdev); - struct AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; - struct MessageUnit __iomem *reg = acb->pmu; - struct CommandControlBlock *ccb; - /*clear and abort all outbound posted Q*/ - int i = 0, found = 0; - int id, lun; - uint32_t flag_ccb, outbound_intstatus; - - while (((flag_ccb = readl(®->outbound_queueport)) != 0xFFFFFFFF) && - (i++ < 256)){ - ccb = (struct CommandControlBlock *)(acb->vir2phy_offset + - (flag_ccb << 5)); - if (ccb){ - if ((ccb->acb != acb)||(ccb->startdone != - ARCMSR_CCB_START)){ - printk(KERN_NOTICE - "arcmsr%d: polling get an illegal ccb" - " command done ccb = '0x%p'" - "ccboutstandingcount = %d \n", - acb->host->host_no, ccb, - atomic_read(&acb->ccboutstandingcount)); - continue; - } - - id = ccb->pcmd->device->id; - lun = ccb->pcmd->device->lun; - if (!(flag_ccb & ARCMSR_CCBREPLY_FLAG_ERROR)) { - if (acb->devstate[id][lun] == ARECA_RAID_GONE) - acb->devstate[id][lun] = ARECA_RAID_GOOD; - ccb->pcmd->result = DID_OK << 16; - arcmsr_ccb_complete(ccb, 1); - } - else { - switch(ccb->arcmsr_cdb.DeviceStatus) { - case ARCMSR_DEV_SELECT_TIMEOUT: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_NO_CONNECT << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; - - case ARCMSR_DEV_ABORTED: - - case ARCMSR_DEV_INIT_FAIL: { - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - } - break; + struct Scsi_Host *host = pci_get_drvdata(pdev); + struct AdapterControlBlock *acb = \ + (struct AdapterControlBlock *)host->hostdata; - case ARCMSR_DEV_CHECK_CONDITION: { - acb->devstate[id][lun] = - ARECA_RAID_GOOD; - arcmsr_report_sense_info(ccb); - arcmsr_ccb_complete(ccb, 1); - } - break; - - default: - printk(KERN_NOTICE "arcmsr%d: \ - scsi id = %d lun = %d" - " polling and \ - getting command error done" - "but got unknown \ - DeviceStatus = 0x%x \n" - , acb->host->host_no, - id, lun, ccb->arcmsr_cdb.DeviceStatus); - acb->devstate[id][lun] = - ARECA_RAID_GONE; - ccb->pcmd->result = - DID_BAD_TARGET << 16; - arcmsr_ccb_complete(ccb, 1); - break; - } - } - found = 1; - } - } - if (found){ - outbound_intstatus = readl(®->outbound_intstatus) & - acb->outbound_int_enable; - writel(outbound_intstatus, ®->outbound_intstatus); - /*clear interrupt*/ - } - return; + arcmsr_stop_adapter_bgrb(acb); + arcmsr_flush_adapter_cache(acb); } static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, @@ -1840,5 +2315,6 @@ static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, break; default: return PCI_ERS_RESULT_NEED_RESET; - } + } } +#endif diff --git a/drivers/scsi/atari_NCR5380.c b/drivers/scsi/atari_NCR5380.c index 03dbe60c264a..52d0b87e9aa4 100644 --- a/drivers/scsi/atari_NCR5380.c +++ b/drivers/scsi/atari_NCR5380.c @@ -2041,7 +2041,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->done(cmd); + cmd->scsi_done(cmd); return; #endif case PHASE_DATAIN: @@ -2100,7 +2100,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->done(cmd); + cmd->scsi_done(cmd); /* XXX - need to source or sink data here, as appropriate */ } else { #ifdef REAL_DMA @@ -2235,24 +2235,17 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); #ifdef AUTOSENSE + if ((cmd->cmnd[0] == REQUEST_SENSE) && + hostdata->ses.cmd_len) { + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + hostdata->ses.cmd_len = 0 ; + } + if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { + scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); + ASEN_PRINTK("scsi%d: performing request sense\n", HOSTNO); - cmd->cmnd[0] = REQUEST_SENSE; - cmd->cmnd[1] &= 0xe0; - cmd->cmnd[2] = 0; - cmd->cmnd[3] = 0; - cmd->cmnd[4] = sizeof(cmd->sense_buffer); - cmd->cmnd[5] = 0; - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); - - cmd->use_sg = 0; - /* this is initialized from initialize_SCp - cmd->SCp.buffer = NULL; - cmd->SCp.buffers_residual = 0; - */ - cmd->request_buffer = (char *) cmd->sense_buffer; - cmd->request_bufflen = sizeof(cmd->sense_buffer); local_irq_save(flags); LIST(cmd,hostdata->issue_queue); diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c index cac354086737..d858f3d41274 100644 --- a/drivers/scsi/bvme6000_scsi.c +++ b/drivers/scsi/bvme6000_scsi.c @@ -36,19 +36,18 @@ static struct platform_device *bvme6000_scsi_device; static __devinit int bvme6000_probe(struct device *dev) { - struct Scsi_Host * host = NULL; + struct Scsi_Host *host; struct NCR_700_Host_Parameters *hostdata; if (!MACH_IS_BVME6000) goto out; - hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); - if (hostdata == NULL) { + hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + if (!hostdata) { printk(KERN_ERR "bvme6000-scsi: " "Failed to allocate host data\n"); goto out; } - memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); /* Fill in the required pieces of hostdata */ hostdata->base = (void __iomem *)BVME_NCR53C710_BASE; diff --git a/drivers/scsi/constants.c b/drivers/scsi/constants.c index 2a458d66b6ff..024553f9c247 100644 --- a/drivers/scsi/constants.c +++ b/drivers/scsi/constants.c @@ -1235,7 +1235,21 @@ scsi_print_sense_hdr(const char *name, struct scsi_sense_hdr *sshdr) } EXPORT_SYMBOL(scsi_print_sense_hdr); +/* + * Print normalized SCSI sense header with device information and a prefix. + */ void +scsi_cmd_print_sense_hdr(struct scsi_cmnd *scmd, const char *desc, + struct scsi_sense_hdr *sshdr) +{ + scmd_printk(KERN_INFO, scmd, "%s: ", desc); + scsi_show_sense_hdr(sshdr); + scmd_printk(KERN_INFO, scmd, "%s: ", desc); + scsi_show_extd_sense(sshdr->asc, sshdr->ascq); +} +EXPORT_SYMBOL(scsi_cmd_print_sense_hdr); + +static void scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len, struct scsi_sense_hdr *sshdr) { @@ -1258,7 +1272,7 @@ scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len, } } -void +static void scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len, struct scsi_sense_hdr *sshdr) { diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c index 7b8a3457b696..1591824cf4b3 100644 --- a/drivers/scsi/dc395x.c +++ b/drivers/scsi/dc395x.c @@ -778,7 +778,7 @@ static void srb_waiting_insert(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_waiting_insert: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add(&srb->list, &dcb->srb_waiting_list); } @@ -787,7 +787,7 @@ static void srb_waiting_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_waiting_append: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add_tail(&srb->list, &dcb->srb_waiting_list); } @@ -795,7 +795,7 @@ static void srb_waiting_append(struct DeviceCtlBlk *dcb, static void srb_going_append(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) { dprintkdbg(DBG_0, "srb_going_append: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_add_tail(&srb->list, &dcb->srb_going_list); } @@ -805,7 +805,7 @@ static void srb_going_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *srb) struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; dprintkdbg(DBG_0, "srb_going_remove: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_going_list, list) if (i == srb) { @@ -821,7 +821,7 @@ static void srb_waiting_remove(struct DeviceCtlBlk *dcb, struct ScsiReqBlk *i; struct ScsiReqBlk *tmp; dprintkdbg(DBG_0, "srb_waiting_remove: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_for_each_entry_safe(i, tmp, &dcb->srb_waiting_list, list) if (i == srb) { @@ -836,7 +836,7 @@ static void srb_going_to_waiting_move(struct DeviceCtlBlk *dcb, { dprintkdbg(DBG_0, "srb_going_to_waiting_move: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_waiting_list); } @@ -846,7 +846,7 @@ static void srb_waiting_to_going_move(struct DeviceCtlBlk *dcb, { dprintkdbg(DBG_0, "srb_waiting_to_going_move: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); list_move(&srb->list, &dcb->srb_going_list); } @@ -982,7 +982,7 @@ static void build_srb(struct scsi_cmnd *cmd, struct DeviceCtlBlk *dcb, int nseg; enum dma_data_direction dir = cmd->sc_data_direction; dprintkdbg(DBG_0, "build_srb: (pid#%li) <%02i-%i>\n", - cmd->pid, dcb->target_id, dcb->target_lun); + cmd->serial_number, dcb->target_id, dcb->target_lun); srb->dcb = dcb; srb->cmd = cmd; @@ -1086,7 +1086,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_ struct AdapterCtlBlk *acb = (struct AdapterCtlBlk *)cmd->device->host->hostdata; dprintkdbg(DBG_0, "queue_command: (pid#%li) <%02i-%i> cmnd=0x%02x\n", - cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); /* Assume BAD_TARGET; will be cleared later */ cmd->result = DID_BAD_TARGET << 16; @@ -1139,7 +1139,7 @@ static int dc395x_queue_command(struct scsi_cmnd *cmd, void (*done)(struct scsi_ /* process immediately */ send_srb(acb, srb); } - dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->pid); + dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->serial_number); return 0; complete: @@ -1203,7 +1203,7 @@ static void dump_register_info(struct AdapterCtlBlk *acb, else dprintkl(KERN_INFO, "dump: srb=%p cmd=%p (pid#%li) " "cmnd=0x%02x <%02i-%i>\n", - srb, srb->cmd, srb->cmd->pid, + srb, srb->cmd, srb->cmd->serial_number, srb->cmd->cmnd[0], srb->cmd->device->id, srb->cmd->device->lun); printk(" sglist=%p cnt=%i idx=%i len=%zu\n", @@ -1300,7 +1300,7 @@ static int __dc395x_eh_bus_reset(struct scsi_cmnd *cmd) (struct AdapterCtlBlk *)cmd->device->host->hostdata; dprintkl(KERN_INFO, "eh_bus_reset: (pid#%li) target=<%02i-%i> cmd=%p\n", - cmd->pid, cmd->device->id, cmd->device->lun, cmd); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd); if (timer_pending(&acb->waiting_timer)) del_timer(&acb->waiting_timer); @@ -1367,7 +1367,7 @@ static int dc395x_eh_abort(struct scsi_cmnd *cmd) struct DeviceCtlBlk *dcb; struct ScsiReqBlk *srb; dprintkl(KERN_INFO, "eh_abort: (pid#%li) target=<%02i-%i> cmd=%p\n", - cmd->pid, cmd->device->id, cmd->device->lun, cmd); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd); dcb = find_dcb(acb, cmd->device->id, cmd->device->lun); if (!dcb) { @@ -1494,7 +1494,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, u8 s_stat, scsicommand, i, identify_message; u8 *ptr; dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> srb=%p\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun, srb); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, srb); srb->tag_number = TAG_NONE; /* acb->tag_max_num: had error read in eeprom */ @@ -1504,7 +1504,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, #if 1 if (s_stat & 0x20 /* s_stat2 & 0x02000 */ ) { dprintkdbg(DBG_KG, "start_scsi: (pid#%li) BUSY %02x %04x\n", - srb->cmd->pid, s_stat, s_stat2); + srb->cmd->serial_number, s_stat, s_stat2); /* * Try anyway? * @@ -1522,14 +1522,14 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, if (acb->active_dcb) { dprintkl(KERN_DEBUG, "start_scsi: (pid#%li) Attempt to start a" "command while another command (pid#%li) is active.", - srb->cmd->pid, + srb->cmd->serial_number, acb->active_dcb->active_srb ? - acb->active_dcb->active_srb->cmd->pid : 0); + acb->active_dcb->active_srb->cmd->serial_number : 0); return 1; } if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) { dprintkdbg(DBG_KG, "start_scsi: (pid#%li) Failed (busy)\n", - srb->cmd->pid); + srb->cmd->serial_number); return 1; } /* Allow starting of SCSI commands half a second before we allow the mid-level @@ -1603,7 +1603,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, if (tag_number >= dcb->max_command) { dprintkl(KERN_WARNING, "start_scsi: (pid#%li) " "Out of tags target=<%02i-%i>)\n", - srb->cmd->pid, srb->cmd->device->id, + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); srb->state = SRB_READY; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, @@ -1622,7 +1622,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, /*polling:*/ /* Send CDB ..command block ......... */ dprintkdbg(DBG_KG, "start_scsi: (pid#%li) <%02i-%i> cmnd=0x%02x tag=%i\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun, srb->cmd->cmnd[0], srb->tag_number); if (srb->flag & AUTO_REQSENSE) { DC395x_write8(acb, TRM_S1040_SCSI_FIFO, REQUEST_SENSE); @@ -1647,7 +1647,7 @@ static u8 start_scsi(struct AdapterCtlBlk* acb, struct DeviceCtlBlk* dcb, * : Let's process it first! */ dprintkdbg(DBG_0, "start_scsi: (pid#%li) <%02i-%i> Failed - busy\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun); srb->state = SRB_READY; free_tag(dcb, srb); srb->msg_count = 0; @@ -1842,7 +1842,7 @@ static irqreturn_t dc395x_interrupt(int irq, void *dev_id) static void msgout_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { - dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->serial_number); if (srb->state & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT)) *pscsi_status = PH_BUS_FREE; /*.. initial phase */ @@ -1856,18 +1856,18 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, { u16 i; u8 *ptr; - dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->serial_number); clear_fifo(acb, "msgout_phase1"); if (!(srb->state & SRB_MSGOUT)) { srb->state |= SRB_MSGOUT; dprintkl(KERN_DEBUG, "msgout_phase1: (pid#%li) Phase unexpected\n", - srb->cmd->pid); /* So what ? */ + srb->cmd->serial_number); /* So what ? */ } if (!srb->msg_count) { dprintkdbg(DBG_0, "msgout_phase1: (pid#%li) NOP msg\n", - srb->cmd->pid); + srb->cmd->serial_number); DC395x_write8(acb, TRM_S1040_SCSI_FIFO, MSG_NOP); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT); @@ -1887,7 +1887,7 @@ static void msgout_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void command_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { - dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->serial_number); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); } @@ -1898,7 +1898,7 @@ static void command_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, struct DeviceCtlBlk *dcb; u8 *ptr; u16 i; - dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->serial_number); clear_fifo(acb, "command_phase1"); DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_CLRATN); @@ -2042,7 +2042,7 @@ static void data_out_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 scsi_status = *pscsi_status; u32 d_left_counter = 0; dprintkdbg(DBG_0, "data_out_phase0: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); /* * KG: We need to drain the buffers before we draw any conclusions! @@ -2172,7 +2172,7 @@ static void data_out_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "data_out_phase1: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); clear_fifo(acb, "data_out_phase1"); /* do prepare before transfer when data out phase */ data_io_transfer(acb, srb, XFERDATAOUT); @@ -2184,7 +2184,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 scsi_status = *pscsi_status; dprintkdbg(DBG_0, "data_in_phase0: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); /* * KG: DataIn is much more tricky than DataOut. When the device is finished @@ -2205,7 +2205,7 @@ static void data_in_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, if (scsi_status & PARITYERROR) { dprintkl(KERN_INFO, "data_in_phase0: (pid#%li) " - "Parity Error\n", srb->cmd->pid); + "Parity Error\n", srb->cmd->serial_number); srb->status |= PARITY_ERROR; } /* @@ -2395,7 +2395,7 @@ static void data_in_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "data_in_phase1: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); data_io_transfer(acb, srb, XFERDATAIN); } @@ -2407,7 +2407,7 @@ static void data_io_transfer(struct AdapterCtlBlk *acb, u8 bval; dprintkdbg(DBG_0, "data_io_transfer: (pid#%li) <%02i-%i> %c len=%i, sg=(%i/%i)\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun, ((io_dir & DMACMD_DIR) ? 'r' : 'w'), srb->total_xfer_length, srb->sg_index, srb->sg_count); if (srb == acb->tmp_srb) @@ -2580,7 +2580,7 @@ static void status_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "status_phase0: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); srb->target_status = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); srb->end_message = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); /* get message */ srb->state = SRB_COMPLETED; @@ -2594,7 +2594,7 @@ static void status_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { dprintkdbg(DBG_0, "status_phase1: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); srb->state = SRB_STATUS; DC395x_write16(acb, TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important for atn stop */ DC395x_write8(acb, TRM_S1040_SCSI_COMMAND, SCMD_COMP); @@ -2636,7 +2636,7 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb = NULL; struct ScsiReqBlk *i; dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) tag=%i srb=%p\n", - srb->cmd->pid, tag, srb); + srb->cmd->serial_number, tag, srb); if (!(dcb->tag_mask & (1 << tag))) dprintkl(KERN_DEBUG, @@ -2655,7 +2655,7 @@ static struct ScsiReqBlk *msgin_qtag(struct AdapterCtlBlk *acb, goto mingx0; dprintkdbg(DBG_0, "msgin_qtag: (pid#%li) <%02i-%i>\n", - srb->cmd->pid, srb->dcb->target_id, srb->dcb->target_lun); + srb->cmd->serial_number, srb->dcb->target_id, srb->dcb->target_lun); if (dcb->flag & ABORT_DEV_) { /*srb->state = SRB_ABORT_SENT; */ enable_msgout_abort(acb, srb); @@ -2865,7 +2865,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { struct DeviceCtlBlk *dcb = acb->active_dcb; - dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->serial_number); srb->msgin_buf[acb->msg_len++] = DC395x_read8(acb, TRM_S1040_SCSI_FIFO); if (msgin_completed(srb->msgin_buf, acb->msg_len)) { @@ -2933,7 +2933,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, */ dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) " "SAVE POINTER rem=%i Ignore\n", - srb->cmd->pid, srb->total_xfer_length); + srb->cmd->serial_number, srb->total_xfer_length); break; case RESTORE_POINTERS: @@ -2943,7 +2943,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, case ABORT: dprintkdbg(DBG_0, "msgin_phase0: (pid#%li) " "<%02i-%i> ABORT msg\n", - srb->cmd->pid, dcb->target_id, + srb->cmd->serial_number, dcb->target_id, dcb->target_lun); dcb->flag |= ABORT_DEV_; enable_msgout_abort(acb, srb); @@ -2975,7 +2975,7 @@ static void msgin_phase0(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, static void msgin_phase1(struct AdapterCtlBlk *acb, struct ScsiReqBlk *srb, u16 *pscsi_status) { - dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->serial_number); clear_fifo(acb, "msgin_phase1"); DC395x_write32(acb, TRM_S1040_SCSI_COUNTER, 1); if (!(srb->state & SRB_MSGIN)) { @@ -3041,7 +3041,7 @@ static void disconnect(struct AdapterCtlBlk *acb) } srb = dcb->active_srb; acb->active_dcb = NULL; - dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->pid); + dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->serial_number); srb->scsi_phase = PH_BUS_FREE; /* initial phase */ clear_fifo(acb, "disconnect"); @@ -3072,13 +3072,13 @@ static void disconnect(struct AdapterCtlBlk *acb) srb->state = SRB_READY; dprintkl(KERN_DEBUG, "disconnect: (pid#%li) Unexpected\n", - srb->cmd->pid); + srb->cmd->serial_number); srb->target_status = SCSI_STAT_SEL_TIMEOUT; goto disc1; } else { /* Normal selection timeout */ dprintkdbg(DBG_KG, "disconnect: (pid#%li) " - "<%02i-%i> SelTO\n", srb->cmd->pid, + "<%02i-%i> SelTO\n", srb->cmd->serial_number, dcb->target_id, dcb->target_lun); if (srb->retry_count++ > DC395x_MAX_RETRIES || acb->scan_devices) { @@ -3090,7 +3090,7 @@ static void disconnect(struct AdapterCtlBlk *acb) srb_going_to_waiting_move(dcb, srb); dprintkdbg(DBG_KG, "disconnect: (pid#%li) Retry\n", - srb->cmd->pid); + srb->cmd->serial_number); waiting_set_timer(acb, HZ / 20); } } else if (srb->state & SRB_DISCONNECT) { @@ -3144,7 +3144,7 @@ static void reselect(struct AdapterCtlBlk *acb) if (!acb->scan_devices) { dprintkdbg(DBG_KG, "reselect: (pid#%li) <%02i-%i> " "Arb lost but Resel win rsel=%i stat=0x%04x\n", - srb->cmd->pid, dcb->target_id, + srb->cmd->serial_number, dcb->target_id, dcb->target_lun, rsel_tar_lun_id, DC395x_read16(acb, TRM_S1040_SCSI_STATUS)); arblostflag = 1; @@ -3318,7 +3318,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, enum dma_data_direction dir = cmd->sc_data_direction; int ckc_only = 1; - dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid, + dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->serial_number, srb->cmd->device->id, srb->cmd->device->lun); dprintkdbg(DBG_SG, "srb_done: srb=%p sg=%i(%i/%i) buf=%p\n", srb, scsi_sg_count(cmd), srb->sg_index, srb->sg_count, @@ -3499,7 +3499,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (srb->total_xfer_length) dprintkdbg(DBG_KG, "srb_done: (pid#%li) <%02i-%i> " "cmnd=0x%02x Missed %i bytes\n", - cmd->pid, cmd->device->id, cmd->device->lun, + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0], srb->total_xfer_length); } @@ -3509,7 +3509,7 @@ static void srb_done(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, dprintkl(KERN_ERR, "srb_done: ERROR! Completed cmd with tmp_srb\n"); else { dprintkdbg(DBG_0, "srb_done: (pid#%li) done result=0x%08x\n", - cmd->pid, cmd->result); + cmd->serial_number, cmd->result); srb_free_insert(acb, srb); } pci_unmap_srb(acb, srb); @@ -3538,7 +3538,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, p = srb->cmd; dir = p->sc_data_direction; result = MK_RES(0, did_flag, 0, 0); - printk("G:%li(%02i-%i) ", p->pid, + printk("G:%li(%02i-%i) ", p->serial_number, p->device->id, p->device->lun); srb_going_remove(dcb, srb); free_tag(dcb, srb); @@ -3568,7 +3568,7 @@ static void doing_srb_done(struct AdapterCtlBlk *acb, u8 did_flag, p = srb->cmd; result = MK_RES(0, did_flag, 0, 0); - printk("W:%li<%02i-%i>", p->pid, p->device->id, + printk("W:%li<%02i-%i>", p->serial_number, p->device->id, p->device->lun); srb_waiting_remove(dcb, srb); srb_free_insert(acb, srb); @@ -3678,7 +3678,7 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, { struct scsi_cmnd *cmd = srb->cmd; dprintkdbg(DBG_1, "request_sense: (pid#%li) <%02i-%i>\n", - cmd->pid, cmd->device->id, cmd->device->lun); + cmd->serial_number, cmd->device->id, cmd->device->lun); srb->flag |= AUTO_REQSENSE; srb->adapter_status = 0; @@ -3709,7 +3709,7 @@ static void request_sense(struct AdapterCtlBlk *acb, struct DeviceCtlBlk *dcb, if (start_scsi(acb, dcb, srb)) { /* Should only happen, if sb. else grabs the bus */ dprintkl(KERN_DEBUG, "request_sense: (pid#%li) failed <%02i-%i>\n", - srb->cmd->pid, dcb->target_id, dcb->target_lun); + srb->cmd->serial_number, dcb->target_id, dcb->target_lun); srb_going_to_waiting_move(dcb, srb); waiting_set_timer(acb, HZ / 100); } @@ -4717,13 +4717,13 @@ static int dc395x_proc_info(struct Scsi_Host *host, char *buffer, dcb->target_id, dcb->target_lun, list_size(&dcb->srb_waiting_list)); list_for_each_entry(srb, &dcb->srb_waiting_list, list) - SPRINTF(" %li", srb->cmd->pid); + SPRINTF(" %li", srb->cmd->serial_number); if (!list_empty(&dcb->srb_going_list)) SPRINTF("\nDCB (%02i-%i): Going : %i:", dcb->target_id, dcb->target_lun, list_size(&dcb->srb_going_list)); list_for_each_entry(srb, &dcb->srb_going_list, list) - SPRINTF(" %li", srb->cmd->pid); + SPRINTF(" %li", srb->cmd->serial_number); if (!list_empty(&dcb->srb_waiting_list) || !list_empty(&dcb->srb_going_list)) SPRINTF("\n"); } diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c index 502732ac270d..bea9d659af15 100644 --- a/drivers/scsi/dpt_i2o.c +++ b/drivers/scsi/dpt_i2o.c @@ -949,16 +949,14 @@ static int adpt_install_hba(struct pci_dev* pDev) } // Allocate and zero the data structure - pHba = kmalloc(sizeof(adpt_hba), GFP_KERNEL); - if( pHba == NULL) { - if(msg_addr_virt != base_addr_virt){ + pHba = kzalloc(sizeof(adpt_hba), GFP_KERNEL); + if (!pHba) { + if (msg_addr_virt != base_addr_virt) iounmap(msg_addr_virt); - } iounmap(base_addr_virt); pci_release_regions(pDev); return -ENOMEM; } - memset(pHba, 0, sizeof(adpt_hba)); mutex_lock(&adpt_configuration_lock); @@ -2622,14 +2620,13 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) msg=(u32 __iomem *)(pHba->msg_addr_virt+m); - status = kmalloc(4,GFP_KERNEL|ADDR32); - if (status==NULL) { + status = kzalloc(4, GFP_KERNEL|ADDR32); + if (!status) { adpt_send_nop(pHba, m); printk(KERN_WARNING"%s: IOP reset failed - no free memory.\n", pHba->name); return -ENOMEM; } - memset(status, 0, 4); writel(EIGHT_WORD_MSG_SIZE| SGL_OFFSET_6, &msg[0]); writel(I2O_CMD_OUTBOUND_INIT<<24 | HOST_TID<<12 | ADAPTER_TID, &msg[1]); @@ -2668,12 +2665,11 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) kfree(pHba->reply_pool); - pHba->reply_pool = kmalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); - if(!pHba->reply_pool){ - printk(KERN_ERR"%s: Could not allocate reply pool\n",pHba->name); - return -1; + pHba->reply_pool = kzalloc(pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4, GFP_KERNEL|ADDR32); + if (!pHba->reply_pool) { + printk(KERN_ERR "%s: Could not allocate reply pool\n", pHba->name); + return -ENOMEM; } - memset(pHba->reply_pool, 0 , pHba->reply_fifo_size * REPLY_FRAME_SIZE * 4); ptr = pHba->reply_pool; for(i = 0; i < pHba->reply_fifo_size; i++) { @@ -2884,12 +2880,11 @@ static int adpt_i2o_build_sys_table(void) kfree(sys_tbl); - sys_tbl = kmalloc(sys_tbl_len, GFP_KERNEL|ADDR32); - if(!sys_tbl) { + sys_tbl = kzalloc(sys_tbl_len, GFP_KERNEL|ADDR32); + if (!sys_tbl) { printk(KERN_WARNING "SysTab Set failed. Out of memory.\n"); return -ENOMEM; } - memset(sys_tbl, 0, sys_tbl_len); sys_tbl->num_entries = hba_count; sys_tbl->version = I2OVERSION; @@ -3351,7 +3346,7 @@ static int __init adpt_init(void) return count > 0 ? 0 : -ENODEV; } -static void __exit adpt_exit(void) +static void adpt_exit(void) { while (hba_chain) adpt_release(hba_chain); diff --git a/drivers/scsi/dtc.c b/drivers/scsi/dtc.c index 9d52e45c7d36..2596165096d3 100644 --- a/drivers/scsi/dtc.c +++ b/drivers/scsi/dtc.c @@ -137,11 +137,9 @@ static struct override { #ifdef OVERRIDE [] __initdata = OVERRIDE; #else -[4] __initdata = { { -0, IRQ_AUTO}, { -0, IRQ_AUTO}, { -0, IRQ_AUTO}, { -0, IRQ_AUTO}}; +[4] __initdata = { + { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO } +}; #endif #define NO_OVERRIDES ARRAY_SIZE(overrides) @@ -176,7 +174,7 @@ static const struct signature { * Inputs : str - unused, ints - array of integer parameters with ints[0] * equal to the number of ints. * -*/ + */ static void __init dtc_setup(char *str, int *ints) { @@ -233,7 +231,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) } else for (; !addr && (current_base < NO_BASES); ++current_base) { #if (DTCDEBUG & DTCDEBUG_INIT) - printk("scsi-dtc : probing address %08x\n", bases[current_base].address); + printk(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address); #endif if (bases[current_base].noauto) continue; @@ -244,7 +242,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) { addr = bases[current_base].address; #if (DTCDEBUG & DTCDEBUG_INIT) - printk("scsi-dtc : detected board.\n"); + printk(KERN_DEBUG "scsi-dtc : detected board.\n"); #endif goto found; } @@ -253,7 +251,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) } #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) - printk("scsi-dtc : base = %08x\n", addr); + printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr); #endif if (!addr) diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index a83e9f150b97..ec2233114bc9 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c @@ -1758,7 +1758,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt, if (SCpnt->host_scribble) panic("%s: qcomm, pid %ld, SCpnt %p already active.\n", - ha->board_name, SCpnt->pid, SCpnt); + ha->board_name, SCpnt->serial_number, SCpnt); /* i is the mailbox number, look for the first free mailbox starting from last_cp_used */ @@ -1792,7 +1792,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt, if (do_trace) scmd_printk(KERN_INFO, SCpnt, - "qcomm, mbox %d, pid %ld.\n", i, SCpnt->pid); + "qcomm, mbox %d, pid %ld.\n", i, SCpnt->serial_number); cpp->reqsen = 1; cpp->dispri = 1; @@ -1825,7 +1825,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt, unmap_dma(i, ha); SCpnt->host_scribble = NULL; scmd_printk(KERN_INFO, SCpnt, - "qcomm, pid %ld, adapter busy.\n", SCpnt->pid); + "qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number); return 1; } @@ -1841,13 +1841,13 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg) if (SCarg->host_scribble == NULL) { scmd_printk(KERN_INFO, SCarg, - "abort, pid %ld inactive.\n", SCarg->pid); + "abort, pid %ld inactive.\n", SCarg->serial_number); return SUCCESS; } i = *(unsigned int *)SCarg->host_scribble; scmd_printk(KERN_WARNING, SCarg, - "abort, mbox %d, pid %ld.\n", i, SCarg->pid); + "abort, mbox %d, pid %ld.\n", i, SCarg->serial_number); if (i >= shost->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", ha->board_name); @@ -1892,7 +1892,7 @@ static int eata2x_eh_abort(struct scsi_cmnd *SCarg) SCarg->host_scribble = NULL; ha->cp_stat[i] = FREE; printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", - ha->board_name, i, SCarg->pid); + ha->board_name, i, SCarg->serial_number); SCarg->scsi_done(SCarg); return SUCCESS; } @@ -1909,12 +1909,12 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) struct hostdata *ha = (struct hostdata *)shost->hostdata; scmd_printk(KERN_INFO, SCarg, - "reset, enter, pid %ld.\n", SCarg->pid); + "reset, enter, pid %ld.\n", SCarg->serial_number); spin_lock_irq(shost->host_lock); if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->pid); + printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->serial_number); if (ha->in_reset) { printk("%s: reset, exit, already in reset.\n", ha->board_name); @@ -1954,13 +1954,13 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) if (ha->cp_stat[i] == READY || ha->cp_stat[i] == ABORTING) { ha->cp_stat[i] = ABORTING; printk("%s: reset, mbox %d aborting, pid %ld.\n", - ha->board_name, i, SCpnt->pid); + ha->board_name, i, SCpnt->serial_number); } else { ha->cp_stat[i] = IN_RESET; printk("%s: reset, mbox %d in reset, pid %ld.\n", - ha->board_name, i, SCpnt->pid); + ha->board_name, i, SCpnt->serial_number); } if (SCpnt->host_scribble == NULL) @@ -2015,7 +2015,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) printk ("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - ha->board_name, i, SCpnt->pid); + ha->board_name, i, SCpnt->serial_number); } else if (ha->cp_stat[i] == ABORTING) { @@ -2029,7 +2029,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) printk ("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", - ha->board_name, i, SCpnt->pid); + ha->board_name, i, SCpnt->serial_number); } else @@ -2043,7 +2043,7 @@ static int eata2x_eh_host_reset(struct scsi_cmnd *SCarg) do_trace = 0; if (arg_done) - printk("%s: reset, exit, pid %ld done.\n", ha->board_name, SCarg->pid); + printk("%s: reset, exit, pid %ld done.\n", ha->board_name, SCarg->serial_number); else printk("%s: reset, exit.\n", ha->board_name); @@ -2182,7 +2182,7 @@ static int reorder(struct hostdata *ha, unsigned long cursec, cpp = &ha->cp[k]; SCpnt = cpp->SCpnt; ll[n] = SCpnt->request->nr_sectors; - pl[n] = SCpnt->pid; + pl[n] = SCpnt->serial_number; if (!n) continue; @@ -2230,7 +2230,7 @@ static int reorder(struct hostdata *ha, unsigned long cursec, "%s pid %ld mb %d fc %d nr %d sec %ld ns %ld" " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", (ihdlr ? "ihdlr" : "qcomm"), - SCpnt->pid, k, flushcount, + SCpnt->serial_number, k, flushcount, n_ready, SCpnt->request->sector, SCpnt->request->nr_sectors, cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), @@ -2277,7 +2277,7 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec, "%s, pid %ld, mbox %d, adapter" " busy, will abort.\n", (ihdlr ? "ihdlr" : "qcomm"), - SCpnt->pid, k); + SCpnt->serial_number, k); ha->cp_stat[k] = ABORTING; continue; } @@ -2391,11 +2391,11 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost) if (SCpnt->host_scribble == NULL) panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", ha->board_name, - i, SCpnt->pid, SCpnt); + i, SCpnt->serial_number, SCpnt); if (*(unsigned int *)SCpnt->host_scribble != i) panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n", - ha->board_name, i, SCpnt->pid, + ha->board_name, i, SCpnt->serial_number, *(unsigned int *)SCpnt->host_scribble); sync_dma(i, ha); @@ -2445,12 +2445,12 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost) "target_status 0x%x, sense key 0x%x.\n", ha->board_name, SCpnt->device->channel, SCpnt->device->id, - SCpnt->device->lun, SCpnt->pid, + SCpnt->device->lun, SCpnt->serial_number, spp->target_status, SCpnt->sense_buffer[2]); ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0; - if (ha->last_retried_pid == SCpnt->pid) + if (ha->last_retried_pid == SCpnt->serial_number) ha->retries = 0; break; @@ -2485,7 +2485,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost) #endif ha->retries++; - ha->last_retried_pid = SCpnt->pid; + ha->last_retried_pid = SCpnt->serial_number; } else status = DID_ERROR << 16; @@ -2516,7 +2516,7 @@ static irqreturn_t ihdlr(int irq, struct Scsi_Host *shost) scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x," " pid %ld, reg 0x%x, count %d.\n", i, spp->adapter_status, spp->target_status, - SCpnt->pid, reg, ha->iocount); + SCpnt->serial_number, reg, ha->iocount); unmap_dma(i, ha); diff --git a/drivers/scsi/eata_pio.c b/drivers/scsi/eata_pio.c index f33ad01064a9..96180bb47e41 100644 --- a/drivers/scsi/eata_pio.c +++ b/drivers/scsi/eata_pio.c @@ -107,59 +107,44 @@ static struct scsi_host_template driver_template; static int eata_pio_proc_info(struct Scsi_Host *shost, char *buffer, char **start, off_t offset, int length, int rw) { - static u8 buff[512]; - int size, len = 0; - off_t begin = 0, pos = 0; + int len = 0; + off_t begin = 0, pos = 0; - if (rw) - return -ENOSYS; - if (offset == 0) - memset(buff, 0, sizeof(buff)); + if (rw) + return -ENOSYS; - size = sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: " + len += sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: " "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB); - len += size; pos = begin + len; - size = sprintf(buffer + len, "queued commands: %10ld\n" + len += sprintf(buffer + len, "queued commands: %10ld\n" "processed interrupts:%10ld\n", queue_counter, int_counter); - len += size; pos = begin + len; - - size = sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n", + len += sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n", shost->host_no, SD(shost)->name); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Firmware revision: v%s\n", + len += sprintf(buffer + len, "Firmware revision: v%s\n", SD(shost)->revision); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "IO: PIO\n"); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Base IO : %#.4x\n", (u32) shost->base); - len += size; - pos = begin + len; - size = sprintf(buffer + len, "Host Bus: %s\n", + len += sprintf(buffer + len, "IO: PIO\n"); + len += sprintf(buffer + len, "Base IO : %#.4x\n", (u32) shost->base); + len += sprintf(buffer + len, "Host Bus: %s\n", (SD(shost)->bustype == 'P')?"PCI ": (SD(shost)->bustype == 'E')?"EISA":"ISA "); - len += size; - pos = begin + len; + pos = begin + len; - if (pos < offset) { - len = 0; - begin = pos; - } - if (pos > offset + length) - goto stop_output; + if (pos < offset) { + len = 0; + begin = pos; + } + if (pos > offset + length) + goto stop_output; - stop_output: - DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len)); - *start=buffer+(offset-begin); /* Start of wanted data */ - len-=(offset-begin); /* Start slop */ - if(len>length) - len = length; /* Ending slop */ - DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len)); +stop_output: + DBG(DBG_PROC, printk("2pos: %ld offset: %ld len: %d\n", pos, offset, len)); + *start = buffer + (offset - begin); /* Start of wanted data */ + len -= (offset - begin); /* Start slop */ + if (len > length) + len = length; /* Ending slop */ + DBG(DBG_PROC, printk("3pos: %ld offset: %ld len: %d\n", pos, offset, len)); - return (len); + return len; } static int eata_pio_release(struct Scsi_Host *sh) @@ -390,7 +375,7 @@ static int eata_pio_queue(struct scsi_cmnd *cmd, DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd, "eata_pio_queue pid %ld, y %d\n", - cmd->pid, y)); + cmd->serial_number, y)); cmd->scsi_done = (void *) done; @@ -435,10 +420,10 @@ static int eata_pio_queue(struct scsi_cmnd *cmd, cmd->result = DID_BUS_BUSY << 16; scmd_printk(KERN_NOTICE, cmd, "eata_pio_queue pid %ld, HBA busy, " - "returning DID_BUS_BUSY, done.\n", cmd->pid); + "returning DID_BUS_BUSY, done.\n", cmd->serial_number); done(cmd); cp->status = FREE; - return (0); + return 0; } /* FIXME: timeout */ while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) @@ -450,9 +435,9 @@ static int eata_pio_queue(struct scsi_cmnd *cmd, DBG(DBG_QUEUE, scmd_printk(KERN_DEBUG, cmd, "Queued base %#.4lx pid: %ld " - "slot %d irq %d\n", sh->base, cmd->pid, y, sh->irq)); + "slot %d irq %d\n", sh->base, cmd->serial_number, y, sh->irq)); - return (0); + return 0; } static int eata_pio_abort(struct scsi_cmnd *cmd) @@ -461,7 +446,7 @@ static int eata_pio_abort(struct scsi_cmnd *cmd) DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd, "eata_pio_abort called pid: %ld\n", - cmd->pid)); + cmd->serial_number)); while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY) if (--loop == 0) { @@ -497,7 +482,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd) DBG(DBG_ABNORM, scmd_printk(KERN_WARNING, cmd, "eata_pio_reset called pid:%ld\n", - cmd->pid)); + cmd->serial_number)); spin_lock_irq(host->host_lock); @@ -516,7 +501,7 @@ static int eata_pio_host_reset(struct scsi_cmnd *cmd) sp = HD(cmd)->ccb[x].cmd; HD(cmd)->ccb[x].status = RESET; - printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->pid); + printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->serial_number); if (sp == NULL) panic("eata_pio_reset: slot %d, sp==NULL.\n", x); @@ -589,23 +574,28 @@ static char *get_pio_board_data(unsigned long base, unsigned int irq, unsigned i cp.cp_cdb[5] = 0; if (eata_pio_send_command(base, EATA_CMD_PIO_SEND_CP)) - return (NULL); - while (!(inb(base + HA_RSTATUS) & HA_SDRQ)); + return NULL; + + while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) + cpu_relax(); + outsw(base + HA_RDATA, &cp, cplen); outb(EATA_CMD_PIO_TRUNC, base + HA_WCOMMAND); for (z = 0; z < cppadlen; z++) outw(0, base + HA_RDATA); - while (inb(base + HA_RSTATUS) & HA_SBUSY); + while (inb(base + HA_RSTATUS) & HA_SBUSY) + cpu_relax(); + if (inb(base + HA_RSTATUS) & HA_SERROR) - return (NULL); + return NULL; else if (!(inb(base + HA_RSTATUS) & HA_SDRQ)) - return (NULL); + return NULL; else { insw(base + HA_RDATA, &buff, 127); while (inb(base + HA_RSTATUS) & HA_SDRQ) inw(base + HA_RDATA); - return (buff); + return buff; } } diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c index 95cf7b6cd622..4ed3a5297066 100644 --- a/drivers/scsi/esp_scsi.c +++ b/drivers/scsi/esp_scsi.c @@ -2138,7 +2138,7 @@ irqreturn_t scsi_esp_intr(int irq, void *dev_id) } EXPORT_SYMBOL(scsi_esp_intr); -static void __devinit esp_get_revision(struct esp *esp) +static void esp_get_revision(struct esp *esp) { u8 val; @@ -2187,7 +2187,7 @@ static void __devinit esp_get_revision(struct esp *esp) } } -static void __devinit esp_init_swstate(struct esp *esp) +static void esp_init_swstate(struct esp *esp) { int i; @@ -2233,7 +2233,7 @@ static void esp_bootup_reset(struct esp *esp) esp_read8(ESP_INTRPT); } -static void __devinit esp_set_clock_params(struct esp *esp) +static void esp_set_clock_params(struct esp *esp) { int fmhz; u8 ccf; @@ -2306,7 +2306,7 @@ static const char *esp_chip_names[] = { static struct scsi_transport_template *esp_transport_template; -int __devinit scsi_esp_register(struct esp *esp, struct device *dev) +int scsi_esp_register(struct esp *esp, struct device *dev) { static int instance; int err; @@ -2346,7 +2346,7 @@ int __devinit scsi_esp_register(struct esp *esp, struct device *dev) } EXPORT_SYMBOL(scsi_esp_register); -void __devexit scsi_esp_unregister(struct esp *esp) +void scsi_esp_unregister(struct esp *esp) { scsi_remove_host(esp->host); } diff --git a/drivers/scsi/fdomain.c b/drivers/scsi/fdomain.c index 36169d597e98..5d282e6a6ae1 100644 --- a/drivers/scsi/fdomain.c +++ b/drivers/scsi/fdomain.c @@ -387,7 +387,9 @@ static void __iomem * bios_mem; static int bios_major; static int bios_minor; static int PCI_bus; +#ifdef CONFIG_PCI static struct pci_dev *PCI_dev; +#endif static int Quantum; /* Quantum board variant */ static int interrupt_level; static volatile int in_command; @@ -1764,6 +1766,7 @@ struct scsi_host_template fdomain_driver_template = { }; #ifndef PCMCIA +#ifdef CONFIG_PCI static struct pci_device_id fdomain_pci_tbl[] __devinitdata = { { PCI_VENDOR_ID_FD, PCI_DEVICE_ID_FD_36C70, @@ -1771,7 +1774,7 @@ static struct pci_device_id fdomain_pci_tbl[] __devinitdata = { { } }; MODULE_DEVICE_TABLE(pci, fdomain_pci_tbl); - +#endif #define driver_template fdomain_driver_template #include "scsi_module.c" diff --git a/drivers/scsi/g_NCR5380.c b/drivers/scsi/g_NCR5380.c index 880f70d24e65..607336f56d55 100644 --- a/drivers/scsi/g_NCR5380.c +++ b/drivers/scsi/g_NCR5380.c @@ -556,7 +556,7 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev, } #endif -#if NCR53C400_PSEUDO_DMA +#ifdef NCR53C400_PSEUDO_DMA /** * NCR5380_pread - pseudo DMA read diff --git a/drivers/scsi/gdth.c b/drivers/scsi/gdth.c index 55e4d2dc2bbe..e8010a702e73 100644 --- a/drivers/scsi/gdth.c +++ b/drivers/scsi/gdth.c @@ -27,280 +27,8 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Linux kernel 2.4.x, 2.6.x supported * + * Linux kernel 2.6.x supported * * * - * $Log: gdth.c,v $ - * Revision 1.74 2006/04/10 13:44:47 achim - * Community changes for 2.6.x - * Kernel 2.2.x no longer supported - * scsi_request interface removed, thanks to Christoph Hellwig - * - * Revision 1.73 2004/03/31 13:33:03 achim - * Special command 0xfd implemented to detect 64-bit DMA support - * - * Revision 1.72 2004/03/17 08:56:04 achim - * 64-bit DMA only enabled if FW >= x.43 - * - * Revision 1.71 2004/03/05 15:51:29 achim - * Screen service: separate message buffer, bugfixes - * - * Revision 1.70 2004/02/27 12:19:07 achim - * Bugfix: Reset bit in config (0xfe) call removed - * - * Revision 1.69 2004/02/20 09:50:24 achim - * Compatibility changes for kernels < 2.4.20 - * Bugfix screen service command size - * pci_set_dma_mask() error handling added - * - * Revision 1.68 2004/02/19 15:46:54 achim - * 64-bit DMA bugfixes - * Drive size bugfix for drives > 1TB - * - * Revision 1.67 2004/01/14 13:11:57 achim - * Tool access over /proc no longer supported - * Bugfixes IOCTLs - * - * Revision 1.66 2003/12/19 15:04:06 achim - * Bugfixes support for drives > 2TB - * - * Revision 1.65 2003/12/15 11:21:56 achim - * 64-bit DMA support added - * Support for drives > 2 TB implemented - * Kernels 2.2.x, 2.4.x, 2.6.x supported - * - * Revision 1.64 2003/09/17 08:30:26 achim - * EISA/ISA controller scan disabled - * Command line switch probe_eisa_isa added - * - * Revision 1.63 2003/07/12 14:01:00 Daniele Bellucci <bellucda@tiscali.it> - * Minor cleanups in gdth_ioctl. - * - * Revision 1.62 2003/02/27 15:01:59 achim - * Dynamic DMA mapping implemented - * New (character device) IOCTL interface added - * Other controller related changes made - * - * Revision 1.61 2002/11/08 13:09:52 boji - * Added support for XSCALE based RAID Controllers - * Fixed SCREENSERVICE initialization in SMP cases - * Added checks for gdth_polling before GDTH_HA_LOCK - * - * Revision 1.60 2002/02/05 09:35:22 achim - * MODULE_LICENSE only if kernel >= 2.4.11 - * - * Revision 1.59 2002/01/30 09:46:33 achim - * Small changes - * - * Revision 1.58 2002/01/29 15:30:02 achim - * Set default value of shared_access to Y - * New status S_CACHE_RESERV for clustering added - * - * Revision 1.57 2001/08/21 11:16:35 achim - * Bugfix free_irq() - * - * Revision 1.56 2001/08/09 11:19:39 achim - * Scsi_Host_Template changes - * - * Revision 1.55 2001/08/09 10:11:28 achim - * Command HOST_UNFREEZE_IO before cache service init. - * - * Revision 1.54 2001/07/20 13:48:12 achim - * Expand: gdth_analyse_hdrive() removed - * - * Revision 1.53 2001/07/17 09:52:49 achim - * Small OEM related change - * - * Revision 1.52 2001/06/19 15:06:20 achim - * New host command GDT_UNFREEZE_IO added - * - * Revision 1.51 2001/05/22 06:42:37 achim - * PCI: Subdevice ID added - * - * Revision 1.50 2001/05/17 13:42:16 achim - * Support for Intel Storage RAID Controllers added - * - * Revision 1.50 2001/05/17 12:12:34 achim - * Support for Intel Storage RAID Controllers added - * - * Revision 1.49 2001/03/15 15:07:17 achim - * New __setup interface for boot command line options added - * - * Revision 1.48 2001/02/06 12:36:28 achim - * Bugfix Cluster protocol - * - * Revision 1.47 2001/01/10 14:42:06 achim - * New switch shared_access added - * - * Revision 1.46 2001/01/09 08:11:35 achim - * gdth_command() removed - * meaning of Scsi_Pointer members changed - * - * Revision 1.45 2000/11/16 12:02:24 achim - * Changes for kernel 2.4 - * - * Revision 1.44 2000/10/11 08:44:10 achim - * Clustering changes: New flag media_changed added - * - * Revision 1.43 2000/09/20 12:59:01 achim - * DPMEM remap functions for all PCI controller types implemented - * Small changes for ia64 platform - * - * Revision 1.42 2000/07/20 09:04:50 achim - * Small changes for kernel 2.4 - * - * Revision 1.41 2000/07/04 14:11:11 achim - * gdth_analyse_hdrive() added to rescan drives after online expansion - * - * Revision 1.40 2000/06/27 11:24:16 achim - * Changes Clustering, Screenservice - * - * Revision 1.39 2000/06/15 13:09:04 achim - * Changes for gdth_do_cmd() - * - * Revision 1.38 2000/06/15 12:08:43 achim - * Bugfix gdth_sync_event(), service SCREENSERVICE - * Data direction for command 0xc2 changed to DOU - * - * Revision 1.37 2000/05/25 13:50:10 achim - * New driver parameter virt_ctr added - * - * Revision 1.36 2000/05/04 08:50:46 achim - * Event buffer now in gdth_ha_str - * - * Revision 1.35 2000/03/03 10:44:08 achim - * New event_string only valid for the RP controller family - * - * Revision 1.34 2000/03/02 14:55:29 achim - * New mechanism for async. event handling implemented - * - * Revision 1.33 2000/02/21 15:37:37 achim - * Bugfix Alpha platform + DPMEM above 4GB - * - * Revision 1.32 2000/02/14 16:17:37 achim - * Bugfix sense_buffer[] + raw devices - * - * Revision 1.31 2000/02/10 10:29:00 achim - * Delete sense_buffer[0], if command OK - * - * Revision 1.30 1999/11/02 13:42:39 achim - * ARRAY_DRV_LIST2 implemented - * Now 255 log. and 100 host drives supported - * - * Revision 1.29 1999/10/05 13:28:47 achim - * GDT_CLUST_RESET added - * - * Revision 1.28 1999/08/12 13:44:54 achim - * MOUNTALL removed - * Cluster drives -> removeable drives - * - * Revision 1.27 1999/06/22 07:22:38 achim - * Small changes - * - * Revision 1.26 1999/06/10 16:09:12 achim - * Cluster Host Drive support: Bugfixes - * - * Revision 1.25 1999/06/01 16:03:56 achim - * gdth_init_pci(): Manipulate config. space to start RP controller - * - * Revision 1.24 1999/05/26 11:53:06 achim - * Cluster Host Drive support added - * - * Revision 1.23 1999/03/26 09:12:31 achim - * Default value for hdr_channel set to 0 - * - * Revision 1.22 1999/03/22 16:27:16 achim - * Bugfix: gdth_store_event() must not be locked with GDTH_LOCK_HA() - * - * Revision 1.21 1999/03/16 13:40:34 achim - * Problems with reserved drives solved - * gdth_eh_bus_reset() implemented - * - * Revision 1.20 1999/03/10 09:08:13 achim - * Bugfix: Corrections in gdth_direction_tab[] made - * Bugfix: Increase command timeout (gdth_update_timeout()) NOT in gdth_putq() - * - * Revision 1.19 1999/03/05 14:38:16 achim - * Bugfix: Heads/Sectors mapping for reserved devices possibly wrong - * -> gdth_eval_mapping() implemented, changes in gdth_bios_param() - * INIT_RETRIES set to 100s to avoid DEINIT-Timeout for controllers - * with BIOS disabled and memory test set to Intensive - * Enhanced /proc support - * - * Revision 1.18 1999/02/24 09:54:33 achim - * Command line parameter hdr_channel implemented - * Bugfix for EISA controllers + Linux 2.2.x - * - * Revision 1.17 1998/12/17 15:58:11 achim - * Command line parameters implemented - * Changes for Alpha platforms - * PCI controller scan changed - * SMP support improved (spin_lock_irqsave(),...) - * New async. events, new scan/reserve commands included - * - * Revision 1.16 1998/09/28 16:08:46 achim - * GDT_PCIMPR: DPMEM remapping, if required - * mdelay() added - * - * Revision 1.15 1998/06/03 14:54:06 achim - * gdth_delay(), gdth_flush() implemented - * Bugfix: gdth_release() changed - * - * Revision 1.14 1998/05/22 10:01:17 achim - * mj: pcibios_strerror() removed - * Improved SMP support (if version >= 2.1.95) - * gdth_halt(): halt_called flag added (if version < 2.1) - * - * Revision 1.13 1998/04/16 09:14:57 achim - * Reserve drives (for raw service) implemented - * New error handling code enabled - * Get controller name from board_info() IOCTL - * Final round of PCI device driver patches by Martin Mares - * - * Revision 1.12 1998/03/03 09:32:37 achim - * Fibre channel controller support added - * - * Revision 1.11 1998/01/27 16:19:14 achim - * SA_SHIRQ added - * add_timer()/del_timer() instead of GDTH_TIMER - * scsi_add_timer()/scsi_del_timer() instead of SCSI_TIMER - * New error handling included - * - * Revision 1.10 1997/10/31 12:29:57 achim - * Read heads/sectors from host drive - * - * Revision 1.9 1997/09/04 10:07:25 achim - * IO-mapping with virt_to_bus(), gdth_readb(), gdth_writeb(), ... - * register_reboot_notifier() to get a notify on shutown used - * - * Revision 1.8 1997/04/02 12:14:30 achim - * Version 1.00 (see gdth.h), tested with kernel 2.0.29 - * - * Revision 1.7 1997/03/12 13:33:37 achim - * gdth_reset() changed, new async. events - * - * Revision 1.6 1997/03/04 14:01:11 achim - * Shutdown routine gdth_halt() implemented - * - * Revision 1.5 1997/02/21 09:08:36 achim - * New controller included (RP, RP1, RP2 series) - * IOCTL interface implemented - * - * Revision 1.4 1996/07/05 12:48:55 achim - * Function gdth_bios_param() implemented - * New constant GDTH_MAXC_P_L inserted - * GDT_WRITE_THR, GDT_EXT_INFO implemented - * Function gdth_reset() changed - * - * Revision 1.3 1996/05/10 09:04:41 achim - * Small changes for Linux 1.2.13 - * - * Revision 1.2 1996/05/09 12:45:27 achim - * Loadable module support implemented - * /proc support corrections made - * - * Revision 1.1 1996/04/11 07:35:57 achim - * Initial revision - * ************************************************************************/ /* All GDT Disk Array Controllers are fully supported by this driver. @@ -328,8 +56,6 @@ * max_ids:x x - target ID count per channel (1..MAXID) * rescan:Y rescan all channels/IDs * rescan:N use all devices found until now - * virt_ctr:Y map every channel to a virtual controller - * virt_ctr:N use multi channel support * hdr_channel:x x - number of virtual bus for host drives * shared_access:Y disable driver reserve/release protocol to * access a shared resource from several nodes, @@ -341,7 +67,7 @@ * force_dma32:N use 64 bit DMA mode, if supported * * The default values are: "gdth=disable:N,reserve_mode:1,reverse_scan:N, - * max_ids:127,rescan:N,virt_ctr:N,hdr_channel:0, + * max_ids:127,rescan:N,hdr_channel:0, * shared_access:Y,probe_eisa_isa:N,force_dma32:N". * Here is another example: "gdth=reserve_list:0,1,2,0,0,1,3,0,rescan:Y". * @@ -352,22 +78,22 @@ * '1' in place of 'Y' and '0' in place of 'N'. * * Default: "modprobe gdth disable=0 reserve_mode=1 reverse_scan=0 - * max_ids=127 rescan=0 virt_ctr=0 hdr_channel=0 shared_access=0 + * max_ids=127 rescan=0 hdr_channel=0 shared_access=0 * probe_eisa_isa=0 force_dma32=0" * The other example: "modprobe gdth reserve_list=0,1,2,0,0,1,3,0 rescan=1". */ /* The meaning of the Scsi_Pointer members in this driver is as follows: * ptr: Chaining - * this_residual: Command priority - * buffer: phys. DMA sense buffer - * dma_handle: phys. DMA buffer (kernel >= 2.4.0) - * buffers_residual: Timeout value - * Status: Command status (gdth_do_cmd()), DMA mem. mappings - * Message: Additional info (gdth_do_cmd()), DMA direction - * have_data_in: Flag for gdth_wait_completion() - * sent_command: Opcode special command - * phase: Service/parameter/return code special command + * this_residual: gdth_bufflen + * buffer: gdth_sglist + * dma_handle: unused + * buffers_residual: gdth_sg_count + * Status: unused + * Message: unused + * have_data_in: unused + * sent_command: unused + * phase: unused */ @@ -392,12 +118,8 @@ #include <linux/proc_fs.h> #include <linux/time.h> #include <linux/timer.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6) #include <linux/dma-mapping.h> -#else -#define DMA_32BIT_MASK 0x00000000ffffffffULL -#define DMA_64BIT_MASK 0xffffffffffffffffULL -#endif +#include <linux/list.h> #ifdef GDTH_RTC #include <linux/mc146818rtc.h> @@ -409,29 +131,27 @@ #include <asm/io.h> #include <asm/uaccess.h> #include <linux/spinlock.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include <linux/blkdev.h> -#else -#include <linux/blk.h> -#include "sd.h" -#endif +#include <linux/scatterlist.h> #include "scsi.h" #include <scsi/scsi_host.h> -#include "gdth_kcompat.h" #include "gdth.h" static void gdth_delay(int milliseconds); static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs); static irqreturn_t gdth_interrupt(int irq, void *dev_id); -static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp); -static int gdth_async_event(int hanum); +static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, + int gdth_from_wait, int* pIndex); +static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, + Scsi_Cmnd *scp); +static int gdth_async_event(gdth_ha_str *ha); static void gdth_log_event(gdth_evt_data *dvr, char *buffer); -static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority); -static void gdth_next(int hanum); -static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b); -static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp); +static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority); +static void gdth_next(gdth_ha_str *ha); +static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b); +static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); static gdth_evt_str *gdth_store_event(gdth_ha_str *ha, ushort source, ushort idx, gdth_evt_data *evt); static int gdth_read_event(gdth_ha_str *ha, int handle, gdth_evt_str *estr); @@ -439,42 +159,34 @@ static void gdth_readapp_event(gdth_ha_str *ha, unchar application, gdth_evt_str *estr); static void gdth_clear_events(void); -static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, - char *buffer,ushort count); -static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp); -static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive); +static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, + char *buffer, ushort count, int to_buffer); +static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp); +static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive); -static int gdth_search_eisa(ushort eisa_adr); -static int gdth_search_isa(ulong32 bios_adr); -static int gdth_search_pci(gdth_pci_str *pcistr); -static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, - ushort vendor, ushort dev); -static void gdth_sort_pci(gdth_pci_str *pcistr, int cnt); -static int gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha); -static int gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha); -static int gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha); - -static void gdth_enable_int(int hanum); -static int gdth_get_status(unchar *pIStatus,int irq); -static int gdth_test_busy(int hanum); -static int gdth_get_cmd_index(int hanum); -static void gdth_release_event(int hanum); -static int gdth_wait(int hanum,int index,ulong32 time); -static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, - ulong64 p2,ulong64 p3); -static int gdth_search_drives(int hanum); -static int gdth_analyse_hdrive(int hanum, ushort hdrive); - -static const char *gdth_ctr_name(int hanum); +static void gdth_enable_int(gdth_ha_str *ha); +static unchar gdth_get_status(gdth_ha_str *ha, int irq); +static int gdth_test_busy(gdth_ha_str *ha); +static int gdth_get_cmd_index(gdth_ha_str *ha); +static void gdth_release_event(gdth_ha_str *ha); +static int gdth_wait(gdth_ha_str *ha, int index,ulong32 time); +static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode, + ulong32 p1, ulong64 p2,ulong64 p3); +static int gdth_search_drives(gdth_ha_str *ha); +static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive); + +static const char *gdth_ctr_name(gdth_ha_str *ha); static int gdth_open(struct inode *inode, struct file *filep); static int gdth_close(struct inode *inode, struct file *filep); static int gdth_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg); -static void gdth_flush(int hanum); +static void gdth_flush(gdth_ha_str *ha); static int gdth_halt(struct notifier_block *nb, ulong event, void *buf); static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)); +static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp, + struct gdth_cmndinfo *cmndinfo); static void gdth_scsi_done(struct scsi_cmnd *scp); #ifdef DEBUG_GDTH @@ -571,29 +283,17 @@ static struct timer_list gdth_timer; #define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b) #define INDEX_OK(i,t) ((i)<ARRAY_SIZE(t)) -#define NUMDATA(a) ( (gdth_num_str *)((a)->hostdata)) -#define HADATA(a) (&((gdth_ext_str *)((a)->hostdata))->haext) -#define CMDDATA(a) (&((gdth_ext_str *)((a)->hostdata))->cmdext) - #define BUS_L2P(a,b) ((b)>(a)->virt_bus ? (b-1):(b)) -#define gdth_readb(addr) readb(addr) -#define gdth_readw(addr) readw(addr) -#define gdth_readl(addr) readl(addr) -#define gdth_writeb(b,addr) writeb((b),(addr)) -#define gdth_writew(b,addr) writew((b),(addr)) -#define gdth_writel(b,addr) writel((b),(addr)) - +#ifdef CONFIG_ISA static unchar gdth_drq_tab[4] = {5,6,7,7}; /* DRQ table */ +#endif +#if defined(CONFIG_EISA) || defined(CONFIG_ISA) static unchar gdth_irq_tab[6] = {0,10,11,12,14,0}; /* IRQ table */ +#endif static unchar gdth_polling; /* polling if TRUE */ -static unchar gdth_from_wait = FALSE; /* gdth_wait() */ -static int wait_index,wait_hanum; /* gdth_wait() */ static int gdth_ctr_count = 0; /* controller count */ -static int gdth_ctr_vcount = 0; /* virt. ctr. count */ -static int gdth_ctr_released = 0; /* gdth_release() */ -static struct Scsi_Host *gdth_ctr_tab[MAXHA]; /* controller table */ -static struct Scsi_Host *gdth_ctr_vtab[MAXHA*MAXBUS]; /* virt. ctr. table */ +static LIST_HEAD(gdth_instances); /* controller list */ static unchar gdth_write_through = FALSE; /* write through */ static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */ static int elastidx; @@ -645,8 +345,6 @@ static int hdr_channel = 0; static int max_ids = MAXID; /* rescan all IDs */ static int rescan = 0; -/* map channels to virtual controllers */ -static int virt_ctr = 0; /* shared access */ static int shared_access = 1; /* enable support for EISA and ISA controllers */ @@ -655,7 +353,6 @@ static int probe_eisa_isa = 0; static int force_dma32 = 0; /* parameters for modprobe/insmod */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) module_param_array(irq, int, NULL, 0); module_param(disable, int, 0); module_param(reserve_mode, int, 0); @@ -664,24 +361,9 @@ module_param(reverse_scan, int, 0); module_param(hdr_channel, int, 0); module_param(max_ids, int, 0); module_param(rescan, int, 0); -module_param(virt_ctr, int, 0); module_param(shared_access, int, 0); module_param(probe_eisa_isa, int, 0); module_param(force_dma32, int, 0); -#else -MODULE_PARM(irq, "i"); -MODULE_PARM(disable, "i"); -MODULE_PARM(reserve_mode, "i"); -MODULE_PARM(reserve_list, "4-" __MODULE_STRING(MAX_RES_ARGS) "i"); -MODULE_PARM(reverse_scan, "i"); -MODULE_PARM(hdr_channel, "i"); -MODULE_PARM(max_ids, "i"); -MODULE_PARM(rescan, "i"); -MODULE_PARM(virt_ctr, "i"); -MODULE_PARM(shared_access, "i"); -MODULE_PARM(probe_eisa_isa, "i"); -MODULE_PARM(force_dma32, "i"); -#endif MODULE_AUTHOR("Achim Leubner"); MODULE_LICENSE("GPL"); @@ -692,6 +374,47 @@ static const struct file_operations gdth_fops = { .release = gdth_close, }; +/* + * gdth scsi_command access wrappers. + * below 6 functions are used throughout the driver to access scsi_command's + * io parameters. The reason we do not use the regular accessors from + * scsi_cmnd.h is because of gdth_execute(). Since it is unrecommended for + * llds to directly set scsi_cmnd's IO members. This driver will use SCp + * members for IO parameters, and will copy scsi_cmnd's members to Scp + * members in queuecommand. For internal commands through gdth_execute() + * SCp's members will be set directly. + */ +static inline unsigned gdth_bufflen(struct scsi_cmnd *cmd) +{ + return (unsigned)cmd->SCp.this_residual; +} + +static inline void gdth_set_bufflen(struct scsi_cmnd *cmd, unsigned bufflen) +{ + cmd->SCp.this_residual = bufflen; +} + +static inline unsigned gdth_sg_count(struct scsi_cmnd *cmd) +{ + return (unsigned)cmd->SCp.buffers_residual; +} + +static inline void gdth_set_sg_count(struct scsi_cmnd *cmd, unsigned sg_count) +{ + cmd->SCp.buffers_residual = sg_count; +} + +static inline struct scatterlist *gdth_sglist(struct scsi_cmnd *cmd) +{ + return cmd->SCp.buffer; +} + +static inline void gdth_set_sglist(struct scsi_cmnd *cmd, + struct scatterlist *sglist) +{ + cmd->SCp.buffer = sglist; +} + #include "gdth_proc.h" #include "gdth_proc.c" @@ -701,6 +424,45 @@ static struct notifier_block gdth_notifier = { }; static int notifier_disabled = 0; +static gdth_ha_str *gdth_find_ha(int hanum) +{ + gdth_ha_str *ha; + + list_for_each_entry(ha, &gdth_instances, list) + if (hanum == ha->hanum) + return ha; + + return NULL; +} + +static struct gdth_cmndinfo *gdth_get_cmndinfo(gdth_ha_str *ha) +{ + struct gdth_cmndinfo *priv = NULL; + ulong flags; + int i; + + spin_lock_irqsave(&ha->smp_lock, flags); + + for (i=0; i<GDTH_MAXCMDS; ++i) { + if (ha->cmndinfo[i].index == 0) { + priv = &ha->cmndinfo[i]; + priv->index = i+1; + memset(priv, 0, sizeof(*priv)); + break; + } + } + + spin_unlock_irqrestore(&ha->smp_lock, flags); + + return priv; +} + +static void gdth_put_cmndinfo(struct gdth_cmndinfo *priv) +{ + BUG_ON(!priv); + priv->index = 0; +} + static void gdth_delay(int milliseconds) { if (milliseconds == 0) { @@ -710,80 +472,62 @@ static void gdth_delay(int milliseconds) } } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static void gdth_scsi_done(struct scsi_cmnd *scp) { - TRACE2(("gdth_scsi_done()\n")); + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); + int internal_command = cmndinfo->internal_command; + + TRACE2(("gdth_scsi_done()\n")); + + gdth_put_cmndinfo(cmndinfo); + scp->host_scribble = NULL; - if (scp->request) - complete((struct completion *)scp->request); + if (internal_command) + complete((struct completion *)scp->request); + else + scp->scsi_done(scp); } int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, int timeout, u32 *info) { + gdth_ha_str *ha = shost_priv(sdev->host); Scsi_Cmnd *scp; + struct gdth_cmndinfo cmndinfo; + struct scatterlist one_sg; DECLARE_COMPLETION_ONSTACK(wait); int rval; - scp = kmalloc(sizeof(*scp), GFP_KERNEL); + scp = kzalloc(sizeof(*scp), GFP_KERNEL); if (!scp) return -ENOMEM; - memset(scp, 0, sizeof(*scp)); + scp->device = sdev; + memset(&cmndinfo, 0, sizeof(cmndinfo)); + /* use request field to save the ptr. to completion struct. */ scp->request = (struct request *)&wait; scp->timeout_per_command = timeout*HZ; - scp->request_buffer = gdtcmd; + sg_init_one(&one_sg, gdtcmd, sizeof(*gdtcmd)); + gdth_set_sglist(scp, &one_sg); + gdth_set_sg_count(scp, 1); + gdth_set_bufflen(scp, sizeof(*gdtcmd)); scp->cmd_len = 12; memcpy(scp->cmnd, cmnd, 12); - scp->SCp.this_residual = IOCTL_PRI; /* priority */ - scp->done = gdth_scsi_done; /* some fn. test this */ - gdth_queuecommand(scp, gdth_scsi_done); - wait_for_completion(&wait); - - rval = scp->SCp.Status; - if (info) - *info = scp->SCp.Message; - kfree(scp); - return rval; -} -#else -static void gdth_scsi_done(Scsi_Cmnd *scp) -{ - TRACE2(("gdth_scsi_done()\n")); - - scp->request.rq_status = RQ_SCSI_DONE; - if (scp->request.waiting) - complete(scp->request.waiting); -} + cmndinfo.priority = IOCTL_PRI; + cmndinfo.internal_command = 1; -int __gdth_execute(struct scsi_device *sdev, gdth_cmd_str *gdtcmd, char *cmnd, - int timeout, u32 *info) -{ - Scsi_Cmnd *scp = scsi_allocate_device(sdev, 1, FALSE); - unsigned bufflen = gdtcmd ? sizeof(gdth_cmd_str) : 0; - DECLARE_COMPLETION_ONSTACK(wait); - int rval; + TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0])); + __gdth_queuecommand(ha, scp, &cmndinfo); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - scp->SCp.this_residual = IOCTL_PRI; /* priority */ - scp->request.rq_status = RQ_SCSI_BUSY; - scp->request.waiting = &wait; - scsi_do_cmd(scp, cmnd, gdtcmd, bufflen, gdth_scsi_done, timeout*HZ, 1); wait_for_completion(&wait); - rval = scp->SCp.Status; + rval = cmndinfo.status; if (info) - *info = scp->SCp.Message; - - scsi_release_command(scp); + *info = cmndinfo.info; + kfree(scp); return rval; } -#endif int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, int timeout, u32 *info) @@ -815,7 +559,7 @@ static void gdth_eval_mapping(ulong32 size, ulong32 *cyls, int *heads, int *secs } /* controller search and initialization functions */ - +#ifdef CONFIG_EISA static int __init gdth_search_eisa(ushort eisa_adr) { ulong32 id; @@ -832,8 +576,9 @@ static int __init gdth_search_eisa(ushort eisa_adr) return 0; } +#endif /* CONFIG_EISA */ - +#ifdef CONFIG_ISA static int __init gdth_search_isa(ulong32 bios_adr) { void __iomem *addr; @@ -841,14 +586,18 @@ static int __init gdth_search_isa(ulong32 bios_adr) TRACE(("gdth_search_isa() bios adr. %x\n",bios_adr)); if ((addr = ioremap(bios_adr+BIOS_ID_OFFS, sizeof(ulong32))) != NULL) { - id = gdth_readl(addr); + id = readl(addr); iounmap(addr); if (id == GDT2_ID) /* GDT2000 */ return 1; } return 0; } +#endif /* CONFIG_ISA */ +#ifdef CONFIG_PCI +static void gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, + ushort vendor, ushort dev); static int __init gdth_search_pci(gdth_pci_str *pcistr) { @@ -928,7 +677,6 @@ static void __init gdth_search_dev(gdth_pci_str *pcistr, ushort *cnt, } } - static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt) { gdth_pci_str temp; @@ -965,8 +713,9 @@ static void __init gdth_sort_pci(gdth_pci_str *pcistr, int cnt) } } while (changed); } +#endif /* CONFIG_PCI */ - +#ifdef CONFIG_EISA static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha) { ulong32 retries,id; @@ -1058,8 +807,9 @@ static int __init gdth_init_eisa(ushort eisa_adr,gdth_ha_str *ha) ha->dma64_support = 0; return 1; } +#endif /* CONFIG_EISA */ - +#ifdef CONFIG_ISA static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) { register gdt2_dpram_str __iomem *dp2_ptr; @@ -1075,22 +825,22 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) return 0; } dp2_ptr = ha->brd; - gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ + writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ /* reset interface area */ memset_io(&dp2_ptr->u, 0, sizeof(dp2_ptr->u)); - if (gdth_readl(&dp2_ptr->u) != 0) { + if (readl(&dp2_ptr->u) != 0) { printk("GDT-ISA: Initialization error (DPMEM write error)\n"); iounmap(ha->brd); return 0; } /* disable board interrupts, read DRQ and IRQ */ - gdth_writeb(0xff, &dp2_ptr->io.irqdel); - gdth_writeb(0x00, &dp2_ptr->io.irqen); - gdth_writeb(0x00, &dp2_ptr->u.ic.S_Status); - gdth_writeb(0x00, &dp2_ptr->u.ic.Cmd_Index); + writeb(0xff, &dp2_ptr->io.irqdel); + writeb(0x00, &dp2_ptr->io.irqen); + writeb(0x00, &dp2_ptr->u.ic.S_Status); + writeb(0x00, &dp2_ptr->u.ic.Cmd_Index); - irq_drq = gdth_readb(&dp2_ptr->io.rq); + irq_drq = readb(&dp2_ptr->io.rq); for (i=0; i<3; ++i) { if ((irq_drq & 1)==0) break; @@ -1098,7 +848,7 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) } ha->drq = gdth_drq_tab[i]; - irq_drq = gdth_readb(&dp2_ptr->io.rq) >> 3; + irq_drq = readb(&dp2_ptr->io.rq) >> 3; for (i=1; i<5; ++i) { if ((irq_drq & 1)==0) break; @@ -1107,12 +857,12 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) ha->irq = gdth_irq_tab[i]; /* deinitialize services */ - gdth_writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]); - gdth_writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx); - gdth_writeb(0, &dp2_ptr->io.event); + writel(bios_adr, &dp2_ptr->u.ic.S_Info[0]); + writeb(0xff, &dp2_ptr->u.ic.S_Cmd_Indx); + writeb(0, &dp2_ptr->io.event); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) { + while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-ISA: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1120,9 +870,9 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)gdth_readl(&dp2_ptr->u.ic.S_Info[0]); - gdth_writeb(0, &dp2_ptr->u.ic.Status); - gdth_writeb(0xff, &dp2_ptr->io.irqdel); + prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]); + writeb(0, &dp2_ptr->u.ic.Status); + writeb(0xff, &dp2_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-ISA: Illegal protocol version\n"); iounmap(ha->brd); @@ -1136,15 +886,15 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) ha->brd_phys = bios_adr >> 4; /* special request to controller BIOS */ - gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[0]); - gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[1]); - gdth_writel(0x01, &dp2_ptr->u.ic.S_Info[2]); - gdth_writel(0x00, &dp2_ptr->u.ic.S_Info[3]); - gdth_writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx); - gdth_writeb(0, &dp2_ptr->io.event); + writel(0x00, &dp2_ptr->u.ic.S_Info[0]); + writel(0x00, &dp2_ptr->u.ic.S_Info[1]); + writel(0x01, &dp2_ptr->u.ic.S_Info[2]); + writel(0x00, &dp2_ptr->u.ic.S_Info[3]); + writeb(0xfe, &dp2_ptr->u.ic.S_Cmd_Indx); + writeb(0, &dp2_ptr->io.event); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { + while (readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-ISA: Initialization error\n"); iounmap(ha->brd); @@ -1152,14 +902,15 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) } gdth_delay(1); } - gdth_writeb(0, &dp2_ptr->u.ic.Status); - gdth_writeb(0xff, &dp2_ptr->io.irqdel); + writeb(0, &dp2_ptr->u.ic.Status); + writeb(0xff, &dp2_ptr->io.irqdel); ha->dma64_support = 0; return 1; } +#endif /* CONFIG_ISA */ - +#ifdef CONFIG_PCI static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) { register gdt6_dpram_str __iomem *dp6_ptr; @@ -1190,8 +941,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } /* check and reset interface area */ dp6_ptr = ha->brd; - gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); - if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) { + writel(DPMEM_MAGIC, &dp6_ptr->u); + if (readl(&dp6_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; @@ -1202,7 +953,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - if (gdth_readw(ha->brd) != 0xffff) { + if (readw(ha->brd) != 0xffff) { TRACE2(("init_pci_old() address 0x%x busy\n", i)); continue; } @@ -1215,8 +966,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) return 0; } dp6_ptr = ha->brd; - gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); - if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) { + writel(DPMEM_MAGIC, &dp6_ptr->u); + if (readl(&dp6_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); found = TRUE; break; @@ -1229,24 +980,24 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } } memset_io(&dp6_ptr->u, 0, sizeof(dp6_ptr->u)); - if (gdth_readl(&dp6_ptr->u) != 0) { + if (readl(&dp6_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); iounmap(ha->brd); return 0; } /* disable board interrupts, deinit services */ - gdth_writeb(0xff, &dp6_ptr->io.irqdel); - gdth_writeb(0x00, &dp6_ptr->io.irqen); - gdth_writeb(0x00, &dp6_ptr->u.ic.S_Status); - gdth_writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); - - gdth_writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); - gdth_writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); - gdth_writeb(0, &dp6_ptr->io.event); + writeb(0xff, &dp6_ptr->io.irqdel); + writeb(0x00, &dp6_ptr->io.irqen); + writeb(0x00, &dp6_ptr->u.ic.S_Status); + writeb(0x00, &dp6_ptr->u.ic.Cmd_Index); + + writel(pcistr->dpmem, &dp6_ptr->u.ic.S_Info[0]); + writeb(0xff, &dp6_ptr->u.ic.S_Cmd_Indx); + writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { + while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1254,9 +1005,9 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)gdth_readl(&dp6_ptr->u.ic.S_Info[0]); - gdth_writeb(0, &dp6_ptr->u.ic.S_Status); - gdth_writeb(0xff, &dp6_ptr->io.irqdel); + prot_ver = (unchar)readl(&dp6_ptr->u.ic.S_Info[0]); + writeb(0, &dp6_ptr->u.ic.S_Status); + writeb(0xff, &dp6_ptr->io.irqdel); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); iounmap(ha->brd); @@ -1267,15 +1018,15 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) ha->ic_all_size = sizeof(dp6_ptr->u); /* special command to controller BIOS */ - gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[0]); - gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[1]); - gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[2]); - gdth_writel(0x00, &dp6_ptr->u.ic.S_Info[3]); - gdth_writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); - gdth_writeb(0, &dp6_ptr->io.event); + writel(0x00, &dp6_ptr->u.ic.S_Info[0]); + writel(0x00, &dp6_ptr->u.ic.S_Info[1]); + writel(0x00, &dp6_ptr->u.ic.S_Info[2]); + writel(0x00, &dp6_ptr->u.ic.S_Info[3]); + writeb(0xfe, &dp6_ptr->u.ic.S_Cmd_Indx); + writeb(0, &dp6_ptr->io.event); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { + while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); iounmap(ha->brd); @@ -1283,8 +1034,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - gdth_writeb(0, &dp6_ptr->u.ic.S_Status); - gdth_writeb(0xff, &dp6_ptr->io.irqdel); + writeb(0, &dp6_ptr->u.ic.S_Status); + writeb(0xff, &dp6_ptr->io.irqdel); ha->dma64_support = 0; @@ -1300,8 +1051,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } /* check and reset interface area */ dp6c_ptr = ha->brd; - gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); - if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) { + writel(DPMEM_MAGIC, &dp6c_ptr->u); + if (readl(&dp6c_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; @@ -1312,7 +1063,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - if (gdth_readw(ha->brd) != 0xffff) { + if (readw(ha->brd) != 0xffff) { TRACE2(("init_pci_plx() address 0x%x busy\n", i)); continue; } @@ -1325,8 +1076,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) return 0; } dp6c_ptr = ha->brd; - gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); - if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) { + writel(DPMEM_MAGIC, &dp6c_ptr->u); + if (readl(&dp6c_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); found = TRUE; break; @@ -1339,7 +1090,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } } memset_io(&dp6c_ptr->u, 0, sizeof(dp6c_ptr->u)); - if (gdth_readl(&dp6c_ptr->u) != 0) { + if (readl(&dp6c_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); iounmap(ha->brd); return 0; @@ -1349,17 +1100,17 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) outb(0x00,PTR2USHORT(&ha->plx->control1)); outb(0xff,PTR2USHORT(&ha->plx->edoor_reg)); - gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status); - gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); + writeb(0x00, &dp6c_ptr->u.ic.S_Status); + writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); - gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); - gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); + writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); + writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { + while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1367,8 +1118,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]); - gdth_writeb(0, &dp6c_ptr->u.ic.Status); + prot_ver = (unchar)readl(&dp6c_ptr->u.ic.S_Info[0]); + writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); iounmap(ha->brd); @@ -1379,17 +1130,17 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) ha->ic_all_size = sizeof(dp6c_ptr->u); /* special command to controller BIOS */ - gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); - gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); - gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[2]); - gdth_writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); - gdth_writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); + writel(0x00, &dp6c_ptr->u.ic.S_Info[0]); + writel(0x00, &dp6c_ptr->u.ic.S_Info[1]); + writel(0x00, &dp6c_ptr->u.ic.S_Info[2]); + writel(0x00, &dp6c_ptr->u.ic.S_Info[3]); + writeb(0xfe, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { + while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); iounmap(ha->brd); @@ -1397,7 +1148,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); + writeb(0, &dp6c_ptr->u.ic.S_Status); ha->dma64_support = 0; @@ -1425,12 +1176,12 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) /* Ensure that it is safe to access the non HW portions of DPMEM. * Aditional check needed for Xscale based RAID controllers */ - while( ((int)gdth_readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 ) + while( ((int)readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 ) gdth_delay(1); /* check and reset interface area */ - gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); - if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) { + writel(DPMEM_MAGIC, &dp6m_ptr->u); + if (readl(&dp6m_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; @@ -1441,7 +1192,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) printk("GDT-PCI: Initialization error (DPMEM remap error)\n"); return 0; } - if (gdth_readw(ha->brd) != 0xffff) { + if (readw(ha->brd) != 0xffff) { TRACE2(("init_pci_mpr() address 0x%x busy\n", i)); continue; } @@ -1454,8 +1205,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) return 0; } dp6m_ptr = ha->brd; - gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); - if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) { + writel(DPMEM_MAGIC, &dp6m_ptr->u); + if (readl(&dp6m_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); found = TRUE; break; @@ -1470,18 +1221,18 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) memset_io(&dp6m_ptr->u, 0, sizeof(dp6m_ptr->u)); /* disable board interrupts, deinit services */ - gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4, + writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4, &dp6m_ptr->i960r.edoor_en_reg); - gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - gdth_writeb(0x00, &dp6m_ptr->u.ic.S_Status); - gdth_writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index); + writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + writeb(0x00, &dp6m_ptr->u.ic.S_Status); + writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index); - gdth_writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]); - gdth_writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx); - gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); + writel(pcistr->dpmem, &dp6m_ptr->u.ic.S_Info[0]); + writeb(0xff, &dp6m_ptr->u.ic.S_Cmd_Indx); + writeb(1, &dp6m_ptr->i960r.ldoor_reg); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { + while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1489,8 +1240,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)gdth_readl(&dp6m_ptr->u.ic.S_Info[0]); - gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + prot_ver = (unchar)readl(&dp6m_ptr->u.ic.S_Info[0]); + writeb(0, &dp6m_ptr->u.ic.S_Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); iounmap(ha->brd); @@ -1501,15 +1252,15 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) ha->ic_all_size = sizeof(dp6m_ptr->u); /* special command to controller BIOS */ - gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[0]); - gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[1]); - gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[2]); - gdth_writel(0x00, &dp6m_ptr->u.ic.S_Info[3]); - gdth_writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx); - gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); + writel(0x00, &dp6m_ptr->u.ic.S_Info[0]); + writel(0x00, &dp6m_ptr->u.ic.S_Info[1]); + writel(0x00, &dp6m_ptr->u.ic.S_Info[2]); + writel(0x00, &dp6m_ptr->u.ic.S_Info[3]); + writeb(0xfe, &dp6m_ptr->u.ic.S_Cmd_Indx); + writeb(1, &dp6m_ptr->i960r.ldoor_reg); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { + while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); iounmap(ha->brd); @@ -1517,14 +1268,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + writeb(0, &dp6m_ptr->u.ic.S_Status); /* read FW version to detect 64-bit DMA support */ - gdth_writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx); - gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); + writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx); + writeb(1, &dp6m_ptr->i960r.ldoor_reg); retries = INIT_RETRIES; gdth_delay(20); - while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) { + while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1532,8 +1283,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)(gdth_readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16); - gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); + prot_ver = (unchar)(readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16); + writeb(0, &dp6m_ptr->u.ic.S_Status); if (prot_ver < 0x2b) /* FW < x.43: no 64-bit DMA support */ ha->dma64_support = 0; else @@ -1542,20 +1293,18 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) return 1; } - +#endif /* CONFIG_PCI */ /* controller protocol functions */ -static void __init gdth_enable_int(int hanum) +static void __init gdth_enable_int(gdth_ha_str *ha) { - gdth_ha_str *ha; ulong flags; gdt2_dpram_str __iomem *dp2_ptr; gdt6_dpram_str __iomem *dp6_ptr; gdt6m_dpram_str __iomem *dp6m_ptr; - TRACE(("gdth_enable_int() hanum %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE(("gdth_enable_int() hanum %d\n",ha->hanum)); spin_lock_irqsave(&ha->smp_lock, flags); if (ha->type == GDT_EISA) { @@ -1564,93 +1313,80 @@ static void __init gdth_enable_int(int hanum) outb(0x01, ha->bmic + EINTENABREG); } else if (ha->type == GDT_ISA) { dp2_ptr = ha->brd; - gdth_writeb(1, &dp2_ptr->io.irqdel); - gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); - gdth_writeb(1, &dp2_ptr->io.irqen); + writeb(1, &dp2_ptr->io.irqdel); + writeb(0, &dp2_ptr->u.ic.Cmd_Index); + writeb(1, &dp2_ptr->io.irqen); } else if (ha->type == GDT_PCI) { dp6_ptr = ha->brd; - gdth_writeb(1, &dp6_ptr->io.irqdel); - gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); - gdth_writeb(1, &dp6_ptr->io.irqen); + writeb(1, &dp6_ptr->io.irqdel); + writeb(0, &dp6_ptr->u.ic.Cmd_Index); + writeb(1, &dp6_ptr->io.irqen); } else if (ha->type == GDT_PCINEW) { outb(0xff, PTR2USHORT(&ha->plx->edoor_reg)); outb(0x03, PTR2USHORT(&ha->plx->control1)); } else if (ha->type == GDT_PCIMPR) { dp6m_ptr = ha->brd; - gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4, + writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4, &dp6m_ptr->i960r.edoor_en_reg); } spin_unlock_irqrestore(&ha->smp_lock, flags); } - -static int gdth_get_status(unchar *pIStatus,int irq) +/* return IStatus if interrupt was from this card else 0 */ +static unchar gdth_get_status(gdth_ha_str *ha, int irq) { - register gdth_ha_str *ha; - int i; + unchar IStatus = 0; + + TRACE(("gdth_get_status() irq %d ctr_count %d\n", irq, gdth_ctr_count)); - TRACE(("gdth_get_status() irq %d ctr_count %d\n", - irq,gdth_ctr_count)); - - *pIStatus = 0; - for (i=0; i<gdth_ctr_count; ++i) { - ha = HADATA(gdth_ctr_tab[i]); if (ha->irq != (unchar)irq) /* check IRQ */ - continue; + return false; if (ha->type == GDT_EISA) - *pIStatus = inb((ushort)ha->bmic + EDOORREG); + IStatus = inb((ushort)ha->bmic + EDOORREG); else if (ha->type == GDT_ISA) - *pIStatus = - gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); + IStatus = + readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCI) - *pIStatus = - gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); + IStatus = + readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCINEW) - *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg)); + IStatus = inb(PTR2USHORT(&ha->plx->edoor_reg)); else if (ha->type == GDT_PCIMPR) - *pIStatus = - gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg); - - if (*pIStatus) - return i; /* board found */ - } - return -1; + IStatus = + readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg); + + return IStatus; } - - -static int gdth_test_busy(int hanum) + +static int gdth_test_busy(gdth_ha_str *ha) { - register gdth_ha_str *ha; register int gdtsema0 = 0; - TRACE(("gdth_test_busy() hanum %d\n",hanum)); - - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE(("gdth_test_busy() hanum %d\n", ha->hanum)); + if (ha->type == GDT_EISA) gdtsema0 = (int)inb(ha->bmic + SEMA0REG); else if (ha->type == GDT_ISA) - gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCI) - gdtsema0 = (int)gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCINEW) gdtsema0 = (int)inb(PTR2USHORT(&ha->plx->sema0_reg)); else if (ha->type == GDT_PCIMPR) gdtsema0 = - (int)gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); + (int)readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); return (gdtsema0 & 1); } -static int gdth_get_cmd_index(int hanum) +static int gdth_get_cmd_index(gdth_ha_str *ha) { - register gdth_ha_str *ha; int i; - TRACE(("gdth_get_cmd_index() hanum %d\n",hanum)); + TRACE(("gdth_get_cmd_index() hanum %d\n", ha->hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); for (i=0; i<GDTH_MAXCMDS; ++i) { if (ha->cmd_tab[i].cmnd == UNUSED_CMND) { ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer; @@ -1663,30 +1399,26 @@ static int gdth_get_cmd_index(int hanum) } -static void gdth_set_sema0(int hanum) +static void gdth_set_sema0(gdth_ha_str *ha) { - register gdth_ha_str *ha; + TRACE(("gdth_set_sema0() hanum %d\n", ha->hanum)); - TRACE(("gdth_set_sema0() hanum %d\n",hanum)); - - ha = HADATA(gdth_ctr_tab[hanum]); if (ha->type == GDT_EISA) { outb(1, ha->bmic + SEMA0REG); } else if (ha->type == GDT_ISA) { - gdth_writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); + writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); } else if (ha->type == GDT_PCI) { - gdth_writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); + writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); } else if (ha->type == GDT_PCINEW) { outb(1, PTR2USHORT(&ha->plx->sema0_reg)); } else if (ha->type == GDT_PCIMPR) { - gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); + writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); } } -static void gdth_copy_command(int hanum) +static void gdth_copy_command(gdth_ha_str *ha) { - register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; register gdt6m_dpram_str __iomem *dp6m_ptr; register gdt6c_dpram_str __iomem *dp6c_ptr; @@ -1694,9 +1426,8 @@ static void gdth_copy_command(int hanum) gdt2_dpram_str __iomem *dp2_ptr; ushort cp_count,dp_offset,cmd_no; - TRACE(("gdth_copy_command() hanum %d\n",hanum)); + TRACE(("gdth_copy_command() hanum %d\n", ha->hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); cp_count = ha->cmd_len; dp_offset= ha->cmd_offs_dpmem; cmd_no = ha->cmd_cnt; @@ -1715,42 +1446,39 @@ static void gdth_copy_command(int hanum) /* set offset and service, copy command to DPMEM */ if (ha->type == GDT_ISA) { dp2_ptr = ha->brd; - gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, + writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp2_ptr->u.ic.comm_queue[cmd_no].offset); - gdth_writew((ushort)cmd_ptr->Service, + writew((ushort)cmd_ptr->Service, &dp2_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp2_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCI) { dp6_ptr = ha->brd; - gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, + writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6_ptr->u.ic.comm_queue[cmd_no].offset); - gdth_writew((ushort)cmd_ptr->Service, + writew((ushort)cmd_ptr->Service, &dp6_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCINEW) { dp6c_ptr = ha->brd; - gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, + writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6c_ptr->u.ic.comm_queue[cmd_no].offset); - gdth_writew((ushort)cmd_ptr->Service, + writew((ushort)cmd_ptr->Service, &dp6c_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6c_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } else if (ha->type == GDT_PCIMPR) { dp6m_ptr = ha->brd; - gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, + writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6m_ptr->u.ic.comm_queue[cmd_no].offset); - gdth_writew((ushort)cmd_ptr->Service, + writew((ushort)cmd_ptr->Service, &dp6m_ptr->u.ic.comm_queue[cmd_no].serv_id); memcpy_toio(&dp6m_ptr->u.ic.gdt_dpr_cmd[dp_offset],cmd_ptr,cp_count); } } -static void gdth_release_event(int hanum) +static void gdth_release_event(gdth_ha_str *ha) { - register gdth_ha_str *ha; - - TRACE(("gdth_release_event() hanum %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE(("gdth_release_event() hanum %d\n", ha->hanum)); #ifdef GDTH_STATISTICS { @@ -1774,56 +1502,50 @@ static void gdth_release_event(int hanum) outl(ha->ccb_phys, ha->bmic + MAILBOXREG); outb(ha->pccb->Service, ha->bmic + LDOORREG); } else if (ha->type == GDT_ISA) { - gdth_writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event); + writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event); } else if (ha->type == GDT_PCI) { - gdth_writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event); + writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event); } else if (ha->type == GDT_PCINEW) { outb(1, PTR2USHORT(&ha->plx->ldoor_reg)); } else if (ha->type == GDT_PCIMPR) { - gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg); + writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg); } } - -static int gdth_wait(int hanum,int index,ulong32 time) +static int gdth_wait(gdth_ha_str *ha, int index, ulong32 time) { - gdth_ha_str *ha; int answer_found = FALSE; + int wait_index = 0; - TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum,index,time)); + TRACE(("gdth_wait() hanum %d index %d time %d\n", ha->hanum, index, time)); - ha = HADATA(gdth_ctr_tab[hanum]); if (index == 0) return 1; /* no wait required */ - gdth_from_wait = TRUE; do { - gdth_interrupt((int)ha->irq,ha); - if (wait_hanum==hanum && wait_index==index) { + __gdth_interrupt(ha, (int)ha->irq, true, &wait_index); + if (wait_index == index) { answer_found = TRUE; break; } gdth_delay(1); } while (--time); - gdth_from_wait = FALSE; - - while (gdth_test_busy(hanum)) + + while (gdth_test_busy(ha)) gdth_delay(0); return (answer_found); } -static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, - ulong64 p2,ulong64 p3) +static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode, + ulong32 p1, ulong64 p2, ulong64 p3) { - register gdth_ha_str *ha; register gdth_cmd_str *cmd_ptr; int retries,index; TRACE2(("gdth_internal_cmd() service %d opcode %d\n",service,opcode)); - ha = HADATA(gdth_ctr_tab[hanum]); cmd_ptr = ha->pccb; memset((char*)cmd_ptr,0,sizeof(gdth_cmd_str)); @@ -1831,11 +1553,11 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, for (retries = INIT_RETRIES;;) { cmd_ptr->Service = service; cmd_ptr->RequestBuffer = INTERNAL_CMND; - if (!(index=gdth_get_cmd_index(hanum))) { + if (!(index=gdth_get_cmd_index(ha))) { TRACE(("GDT: No free command index found\n")); return 0; } - gdth_set_sema0(hanum); + gdth_set_sema0(ha); cmd_ptr->OpCode = opcode; cmd_ptr->BoardNode = LOCALBOARD; if (service == CACHESERVICE) { @@ -1875,10 +1597,10 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, ha->cmd_len = sizeof(gdth_cmd_str); ha->cmd_offs_dpmem = 0; ha->cmd_cnt = 0; - gdth_copy_command(hanum); - gdth_release_event(hanum); + gdth_copy_command(ha); + gdth_release_event(ha); gdth_delay(20); - if (!gdth_wait(hanum,index,INIT_TIMEOUT)) { + if (!gdth_wait(ha, index, INIT_TIMEOUT)) { printk("GDT: Initialization error (timeout service %d)\n",service); return 0; } @@ -1893,9 +1615,8 @@ static int gdth_internal_cmd(int hanum,unchar service,ushort opcode,ulong32 p1, /* search for devices */ -static int __init gdth_search_drives(int hanum) +static int __init gdth_search_drives(gdth_ha_str *ha) { - register gdth_ha_str *ha; ushort cdev_cnt, i; int ok; ulong32 bus_no, drv_cnt, drv_no, j; @@ -1915,22 +1636,21 @@ static int __init gdth_search_drives(int hanum) ulong flags; #endif - TRACE(("gdth_search_drives() hanum %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE(("gdth_search_drives() hanum %d\n", ha->hanum)); ok = 0; /* initialize controller services, at first: screen service */ ha->screen_feat = 0; if (!force_dma32) { - ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_X_INIT_SCR,0,0,0); + ok = gdth_internal_cmd(ha, SCREENSERVICE, GDT_X_INIT_SCR, 0, 0, 0); if (ok) ha->screen_feat = GDT_64BIT; } if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) - ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0); + ok = gdth_internal_cmd(ha, SCREENSERVICE, GDT_INIT, 0, 0, 0); if (!ok) { printk("GDT-HA %d: Initialization error screen service (code %d)\n", - hanum, ha->status); + ha->hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n")); @@ -1954,25 +1674,26 @@ static int __init gdth_search_drives(int hanum) TRACE2(("gdth_search_drives(): RTC: %x/%x/%x\n",*(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8])); /* 3. send to controller firmware */ - gdth_internal_cmd(hanum,SCREENSERVICE,GDT_REALTIME, *(ulong32 *)&rtc[0], + gdth_internal_cmd(ha, SCREENSERVICE, GDT_REALTIME, *(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]); #endif /* unfreeze all IOs */ - gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0); + gdth_internal_cmd(ha, CACHESERVICE, GDT_UNFREEZE_IO, 0, 0, 0); /* initialize cache service */ ha->cache_feat = 0; if (!force_dma32) { - ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INIT_HOST,LINUX_OS,0,0); + ok = gdth_internal_cmd(ha, CACHESERVICE, GDT_X_INIT_HOST, LINUX_OS, + 0, 0); if (ok) ha->cache_feat = GDT_64BIT; } if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) - ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0); + ok = gdth_internal_cmd(ha, CACHESERVICE, GDT_INIT, LINUX_OS, 0, 0); if (!ok) { printk("GDT-HA %d: Initialization error cache service (code %d)\n", - hanum, ha->status); + ha->hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n")); @@ -2001,9 +1722,9 @@ static int __init gdth_search_drives(int hanum) pmod->cmd_buff_size = 0; pmod->reserved1 = 0; pmod->reserved2 = 0; - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,SET_PERF_MODES, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, SET_PERF_MODES, INVALID_CHANNEL,sizeof(gdth_perf_modes))) { - printk("GDT-HA %d: Interrupt coalescing activated\n", hanum); + printk("GDT-HA %d: Interrupt coalescing activated\n", ha->hanum); } } #endif @@ -2015,7 +1736,7 @@ static int __init gdth_search_drives(int hanum) iocr->hdr.first_chan = 0; iocr->hdr.last_chan = MAXBUS-1; iocr->hdr.list_offset = GDTOFFSOF(gdth_raw_iochan_str, list[0]); - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_RAW_DESC, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, IOCHAN_RAW_DESC, INVALID_CHANNEL,sizeof(gdth_raw_iochan_str))) { TRACE2(("IOCHAN_RAW_DESC supported!\n")); ha->bus_cnt = iocr->hdr.chan_count; @@ -2030,13 +1751,13 @@ static int __init gdth_search_drives(int hanum) chn = (gdth_getch_str *)ha->pscratch; for (bus_no = 0; bus_no < MAXBUS; ++bus_no) { chn->channel_no = bus_no; - if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, + if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, SCSI_CHAN_CNT | L_CTRL_PATTERN, IO_CHANNEL | INVALID_CHANNEL, sizeof(gdth_getch_str))) { if (bus_no == 0) { printk("GDT-HA %d: Error detecting channel count (0x%x)\n", - hanum, ha->status); + ha->hanum, ha->status); return 0; } break; @@ -2051,10 +1772,10 @@ static int __init gdth_search_drives(int hanum) TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt)); /* read cache configuration */ - if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO, + if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_INFO, INVALID_CHANNEL,sizeof(gdth_cinfo_str))) { printk("GDT-HA %d: Initialization error cache service (code %d)\n", - hanum, ha->status); + ha->hanum, ha->status); return 0; } ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar; @@ -2064,11 +1785,11 @@ static int __init gdth_search_drives(int hanum) /* read board info and features */ ha->more_proc = FALSE; - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_INFO, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, BOARD_INFO, INVALID_CHANNEL,sizeof(gdth_binfo_str))) { memcpy(&ha->binfo, (gdth_binfo_str *)ha->pscratch, sizeof(gdth_binfo_str)); - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,BOARD_FEATURES, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, BOARD_FEATURES, INVALID_CHANNEL,sizeof(gdth_bfeat_str))) { TRACE2(("BOARD_INFO/BOARD_FEATURES supported\n")); ha->bfeat = *(gdth_bfeat_str *)ha->pscratch; @@ -2076,7 +1797,7 @@ static int __init gdth_search_drives(int hanum) } } else { TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n")); - strcpy(ha->binfo.type_string, gdth_ctr_name(hanum)); + strcpy(ha->binfo.type_string, gdth_ctr_name(ha)); } TRACE2(("Controller name: %s\n",ha->binfo.type_string)); @@ -2089,7 +1810,7 @@ static int __init gdth_search_drives(int hanum) ioc->hdr.first_chan = 0; ioc->hdr.last_chan = MAXBUS-1; ioc->hdr.list_offset = GDTOFFSOF(gdth_iochan_str, list[0]); - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,IOCHAN_DESC, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, IOCHAN_DESC, INVALID_CHANNEL,sizeof(gdth_iochan_str))) { for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) { ha->raw[bus_no].address = ioc->list[bus_no].address; @@ -2104,7 +1825,7 @@ static int __init gdth_search_drives(int hanum) for (bus_no = 0; bus_no < ha->bus_cnt; ++bus_no) { chn = (gdth_getch_str *)ha->pscratch; chn->channel_no = ha->raw[bus_no].local_no; - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, SCSI_CHAN_CNT | L_CTRL_PATTERN, ha->raw[bus_no].address | INVALID_CHANNEL, sizeof(gdth_getch_str))) { @@ -2116,7 +1837,7 @@ static int __init gdth_search_drives(int hanum) drl = (gdth_drlist_str *)ha->pscratch; drl->sc_no = ha->raw[bus_no].local_no; drl->sc_cnt = ha->raw[bus_no].pdev_cnt; - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, SCSI_DR_LIST | L_CTRL_PATTERN, ha->raw[bus_no].address | INVALID_CHANNEL, sizeof(gdth_drlist_str))) { @@ -2129,10 +1850,10 @@ static int __init gdth_search_drives(int hanum) } /* logical drives */ - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_CNT, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_DRV_CNT, INVALID_CHANNEL,sizeof(ulong32))) { drv_cnt = *(ulong32 *)ha->pscratch; - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_LIST, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_DRV_LIST, INVALID_CHANNEL,drv_cnt * sizeof(ulong32))) { for (j = 0; j < drv_cnt; ++j) { drv_no = ((ulong32 *)ha->pscratch)[j]; @@ -2146,7 +1867,7 @@ static int __init gdth_search_drives(int hanum) alst->entries_avail = MAX_LDRIVES; alst->first_entry = 0; alst->list_offset = GDTOFFSOF(gdth_arcdl_str, list[0]); - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, ARRAY_DRV_LIST2 | LA_CTRL_PATTERN, INVALID_CHANNEL, sizeof(gdth_arcdl_str) + (alst->entries_avail-1) * sizeof(gdth_alist_str))) { @@ -2157,7 +1878,7 @@ static int __init gdth_search_drives(int hanum) ha->hdr[j].is_hotfix = alst->list[j].is_hotfix; ha->hdr[j].master_no = alst->list[j].cd_handle; } - } else if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, + } else if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, ARRAY_DRV_LIST | LA_CTRL_PATTERN, 0, 35 * sizeof(gdth_alist_str))) { for (j = 0; j < 35; ++j) { @@ -2175,24 +1896,24 @@ static int __init gdth_search_drives(int hanum) /* initialize raw service */ ha->raw_feat = 0; if (!force_dma32) { - ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_X_INIT_RAW,0,0,0); + ok = gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_X_INIT_RAW, 0, 0, 0); if (ok) ha->raw_feat = GDT_64BIT; } if (force_dma32 || (!ok && ha->status == (ushort)S_NOFUNC)) - ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0); + ok = gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_INIT, 0, 0, 0); if (!ok) { printk("GDT-HA %d: Initialization error raw service (code %d)\n", - hanum, ha->status); + ha->hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n")); /* set/get features raw service (scatter/gather) */ - if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER, - 0,0)) { + if (gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_SET_FEAT, SCATTER_GATHER, + 0, 0)) { TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n")); - if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) { + if (gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_GET_FEAT, 0, 0, 0)) { TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n", ha->info)); ha->raw_feat |= (ushort)ha->info; @@ -2200,10 +1921,10 @@ static int __init gdth_search_drives(int hanum) } /* set/get features cache service (equal to raw service) */ - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_SET_FEAT,0, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_SET_FEAT, 0, SCATTER_GATHER,0)) { TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n")); - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) { + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_GET_FEAT, 0, 0, 0)) { TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n", ha->info)); ha->cache_feat |= (ushort)ha->info; @@ -2212,22 +1933,22 @@ static int __init gdth_search_drives(int hanum) /* reserve drives for raw service */ if (reserve_mode != 0) { - gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE_ALL, + gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESERVE_ALL, reserve_mode == 1 ? 1 : 3, 0, 0); TRACE2(("gdth_search_drives(): RESERVE_ALL code %d\n", ha->status)); } for (i = 0; i < MAX_RES_ARGS; i += 4) { - if (reserve_list[i] == hanum && reserve_list[i+1] < ha->bus_cnt && + if (reserve_list[i] == ha->hanum && reserve_list[i+1] < ha->bus_cnt && reserve_list[i+2] < ha->tid_cnt && reserve_list[i+3] < MAXLUN) { TRACE2(("gdth_search_drives(): reserve ha %d bus %d id %d lun %d\n", reserve_list[i], reserve_list[i+1], reserve_list[i+2], reserve_list[i+3])); - if (!gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_RESERVE,0, + if (!gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESERVE, 0, reserve_list[i+1], reserve_list[i+2] | (reserve_list[i+3] << 8))) { printk("GDT-HA %d: Error raw service (RESERVE, code %d)\n", - hanum, ha->status); + ha->hanum, ha->status); } } } @@ -2236,58 +1957,44 @@ static int __init gdth_search_drives(int hanum) oemstr = (gdth_oem_str_ioctl *)ha->pscratch; oemstr->params.ctl_version = 0x01; oemstr->params.buffer_size = sizeof(oemstr->text); - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_READ_OEM_STRING_RECORD,INVALID_CHANNEL, sizeof(gdth_oem_str_ioctl))) { TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD OK\n")); printk("GDT-HA %d: Vendor: %s Name: %s\n", - hanum,oemstr->text.oem_company_name,ha->binfo.type_string); + ha->hanum, oemstr->text.oem_company_name, ha->binfo.type_string); /* Save the Host Drive inquiry data */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) strlcpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id, sizeof(ha->oem_name)); -#else - strncpy(ha->oem_name,oemstr->text.scsi_host_drive_inquiry_vendor_id,7); - ha->oem_name[7] = '\0'; -#endif } else { /* Old method, based on PCI ID */ TRACE2(("gdth_search_drives(): CACHE_READ_OEM_STRING_RECORD failed\n")); printk("GDT-HA %d: Name: %s\n", - hanum,ha->binfo.type_string); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + ha->hanum, ha->binfo.type_string); if (ha->oem_id == OEM_ID_INTEL) strlcpy(ha->oem_name,"Intel ", sizeof(ha->oem_name)); else strlcpy(ha->oem_name,"ICP ", sizeof(ha->oem_name)); -#else - if (ha->oem_id == OEM_ID_INTEL) - strcpy(ha->oem_name,"Intel "); - else - strcpy(ha->oem_name,"ICP "); -#endif } /* scanning for host drives */ for (i = 0; i < cdev_cnt; ++i) - gdth_analyse_hdrive(hanum,i); + gdth_analyse_hdrive(ha, i); TRACE(("gdth_search_drives() OK\n")); return 1; } -static int gdth_analyse_hdrive(int hanum,ushort hdrive) +static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive) { - register gdth_ha_str *ha; ulong32 drv_cyls; int drv_hds, drv_secs; - TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive)); + TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n", ha->hanum, hdrive)); if (hdrive >= MAX_HDRIVES) return 0; - ha = HADATA(gdth_ctr_tab[hanum]); - if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,hdrive,0,0)) + if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_INFO, hdrive, 0, 0)) return 0; ha->hdr[hdrive].present = TRUE; ha->hdr[hdrive].size = ha->info; @@ -2307,7 +2014,7 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) ha->hdr[hdrive].size = drv_cyls * drv_hds * drv_secs; if (ha->cache_feat & GDT_64BIT) { - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INFO,hdrive,0,0) + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_X_INFO, hdrive, 0, 0) && ha->info2 != 0) { ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info; } @@ -2316,14 +2023,14 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs)); /* get informations about device */ - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_DEVTYPE,hdrive,0,0)) { + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_DEVTYPE, hdrive, 0, 0)) { TRACE2(("gdth_search_dr() cache drive %d devtype %d\n", hdrive,ha->info)); ha->hdr[hdrive].devtype = (ushort)ha->info; } /* cluster info */ - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_CLUST_INFO,hdrive,0,0)) { + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_CLUST_INFO, hdrive, 0, 0)) { TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n", hdrive,ha->info)); if (!shared_access) @@ -2331,7 +2038,7 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) } /* R/W attributes */ - if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_RW_ATTRIBS,hdrive,0,0)) { + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_RW_ATTRIBS, hdrive, 0, 0)) { TRACE2(("gdth_search_dr() cache drive %d r/w attrib. %d\n", hdrive,ha->info)); ha->hdr[hdrive].rw_attribs = (unchar)ha->info; @@ -2343,27 +2050,26 @@ static int gdth_analyse_hdrive(int hanum,ushort hdrive) /* command queueing/sending functions */ -static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) +static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority) { - register gdth_ha_str *ha; + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; ulong flags; unchar b, t; TRACE(("gdth_putq() priority %d\n",priority)); - ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); - if (scp->done != gdth_scsi_done) { - scp->SCp.this_residual = (int)priority; - b = virt_ctr ? NUMDATA(scp->device->host)->busnum:scp->device->channel; + if (!cmndinfo->internal_command) { + cmndinfo->priority = priority; + b = scp->device->channel; t = scp->device->id; if (priority >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || (b==ha->virt_bus && t<MAX_HDRIVES && ha->hdr[t].lock)) { TRACE2(("gdth_putq(): locked IO ->update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + cmndinfo->timeout = gdth_update_timeout(scp, 0); } } } @@ -2375,7 +2081,7 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) pscp = ha->req_first; nscp = (Scsi_Cmnd *)pscp->SCp.ptr; /* priority: 0-highest,..,0xff-lowest */ - while (nscp && (unchar)nscp->SCp.this_residual <= priority) { + while (nscp && gdth_cmnd_priv(nscp)->priority <= priority) { pscp = nscp; nscp = (Scsi_Cmnd *)pscp->SCp.ptr; } @@ -2395,9 +2101,8 @@ static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) #endif } -static void gdth_next(int hanum) +static void gdth_next(gdth_ha_str *ha) { - register gdth_ha_str *ha; register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; unchar b, t, l, firsttime; @@ -2405,8 +2110,7 @@ static void gdth_next(int hanum) ulong flags = 0; int cmd_index; - TRACE(("gdth_next() hanum %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE(("gdth_next() hanum %d\n", ha->hanum)); if (!gdth_polling) spin_lock_irqsave(&ha->smp_lock, flags); @@ -2416,14 +2120,14 @@ static void gdth_next(int hanum) cmd_index = 0; for (nscp = pscp = ha->req_first; nscp; nscp = (Scsi_Cmnd *)nscp->SCp.ptr) { + struct gdth_cmndinfo *nscp_cmndinfo = gdth_cmnd_priv(nscp); if (nscp != pscp && nscp != (Scsi_Cmnd *)pscp->SCp.ptr) pscp = (Scsi_Cmnd *)pscp->SCp.ptr; - if (nscp->done != gdth_scsi_done) { - b = virt_ctr ? - NUMDATA(nscp->device->host)->busnum : nscp->device->channel; + if (!nscp_cmndinfo->internal_command) { + b = nscp->device->channel; t = nscp->device->id; l = nscp->device->lun; - if (nscp->SCp.this_residual >= DEFAULT_PRI) { + if (nscp_cmndinfo->priority >= DEFAULT_PRI) { if ((b != ha->virt_bus && ha->raw[BUS_L2P(ha,b)].lock) || (b == ha->virt_bus && t < MAX_HDRIVES && ha->hdr[t].lock)) continue; @@ -2432,21 +2136,21 @@ static void gdth_next(int hanum) b = t = l = 0; if (firsttime) { - if (gdth_test_busy(hanum)) { /* controller busy ? */ - TRACE(("gdth_next() controller %d busy !\n",hanum)); + if (gdth_test_busy(ha)) { /* controller busy ? */ + TRACE(("gdth_next() controller %d busy !\n", ha->hanum)); if (!gdth_polling) { spin_unlock_irqrestore(&ha->smp_lock, flags); return; } - while (gdth_test_busy(hanum)) + while (gdth_test_busy(ha)) gdth_delay(1); } firsttime = FALSE; } - if (nscp->done != gdth_scsi_done) { - if (nscp->SCp.phase == -1) { - nscp->SCp.phase = CACHESERVICE; /* default: cache svc. */ + if (!nscp_cmndinfo->internal_command) { + if (nscp_cmndinfo->phase == -1) { + nscp_cmndinfo->phase = CACHESERVICE; /* default: cache svc. */ if (nscp->cmnd[0] == TEST_UNIT_READY) { TRACE2(("TEST_UNIT_READY Bus %d Id %d LUN %d\n", b, t, l)); @@ -2459,8 +2163,8 @@ static void gdth_next(int hanum) } else if ((ha->scan_mode & 0x0f) == 1) { if (b == 0 && ((t == 0 && l == 1) || (t == 1 && l == 0))) { - nscp->SCp.sent_command = GDT_SCAN_START; - nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) + nscp_cmndinfo->OpCode = GDT_SCAN_START; + nscp_cmndinfo->phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) | SCSIRAWSERVICE; ha->scan_mode = 0x12; TRACE2(("Scan mode: 0x%x (SCAN_START)\n", @@ -2471,8 +2175,8 @@ static void gdth_next(int hanum) } } else if (ha->scan_mode == 0x12) { if (b == ha->bus_cnt && t == ha->tid_cnt-1) { - nscp->SCp.phase = SCSIRAWSERVICE; - nscp->SCp.sent_command = GDT_SCAN_END; + nscp_cmndinfo->phase = SCSIRAWSERVICE; + nscp_cmndinfo->OpCode = GDT_SCAN_END; ha->scan_mode &= 0x10; TRACE2(("Scan mode: 0x%x (SCAN_END)\n", ha->scan_mode)); @@ -2483,18 +2187,18 @@ static void gdth_next(int hanum) nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE && (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) { /* always GDT_CLUST_INFO! */ - nscp->SCp.sent_command = GDT_CLUST_INFO; + nscp_cmndinfo->OpCode = GDT_CLUST_INFO; } } } - if (nscp->SCp.sent_command != -1) { - if ((nscp->SCp.phase & 0xff) == CACHESERVICE) { - if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) + if (nscp_cmndinfo->OpCode != -1) { + if ((nscp_cmndinfo->phase & 0xff) == CACHESERVICE) { + if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t))) this_cmd = FALSE; next_cmd = FALSE; - } else if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) { - if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) + } else if ((nscp_cmndinfo->phase & 0xff) == SCSIRAWSERVICE) { + if (!(cmd_index=gdth_fill_raw_cmd(ha, nscp, BUS_L2P(ha, b)))) this_cmd = FALSE; next_cmd = FALSE; } else { @@ -2502,18 +2206,18 @@ static void gdth_next(int hanum) nscp->sense_buffer[0] = 0x70; nscp->sense_buffer[2] = NOT_READY; nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - if (!nscp->SCp.have_data_in) - nscp->SCp.have_data_in++; + if (!nscp_cmndinfo->wait_for_completion) + nscp_cmndinfo->wait_for_completion++; else - nscp->scsi_done(nscp); + gdth_scsi_done(nscp); } - } else if (nscp->done == gdth_scsi_done) { - if (!(cmd_index=gdth_special_cmd(hanum,nscp))) + } else if (gdth_cmnd_priv(nscp)->internal_command) { + if (!(cmd_index=gdth_special_cmd(ha, nscp))) this_cmd = FALSE; next_cmd = FALSE; } else if (b != ha->virt_bus) { if (ha->raw[BUS_L2P(ha,b)].io_cnt[t] >= GDTH_MAX_RAW || - !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) + !(cmd_index=gdth_fill_raw_cmd(ha, nscp, BUS_L2P(ha, b)))) this_cmd = FALSE; else ha->raw[BUS_L2P(ha,b)].io_cnt[t]++; @@ -2521,10 +2225,10 @@ static void gdth_next(int hanum) TRACE2(("Command 0x%x to bus %d id %d lun %d -> IGNORE\n", nscp->cmnd[0], b, t, l)); nscp->result = DID_BAD_TARGET << 16; - if (!nscp->SCp.have_data_in) - nscp->SCp.have_data_in++; + if (!nscp_cmndinfo->wait_for_completion) + nscp_cmndinfo->wait_for_completion++; else - nscp->scsi_done(nscp); + gdth_scsi_done(nscp); } else { switch (nscp->cmnd[0]) { case TEST_UNIT_READY: @@ -2547,12 +2251,12 @@ static void gdth_next(int hanum) nscp->sense_buffer[0] = 0x70; nscp->sense_buffer[2] = UNIT_ATTENTION; nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - if (!nscp->SCp.have_data_in) - nscp->SCp.have_data_in++; + if (!nscp_cmndinfo->wait_for_completion) + nscp_cmndinfo->wait_for_completion++; else - nscp->scsi_done(nscp); - } else if (gdth_internal_cache_cmd(hanum,nscp)) - nscp->scsi_done(nscp); + gdth_scsi_done(nscp); + } else if (gdth_internal_cache_cmd(ha, nscp)) + gdth_scsi_done(nscp); break; case ALLOW_MEDIUM_REMOVAL: @@ -2563,15 +2267,15 @@ static void gdth_next(int hanum) TRACE(("Prevent r. nonremov. drive->do nothing\n")); nscp->result = DID_OK << 16; nscp->sense_buffer[0] = 0; - if (!nscp->SCp.have_data_in) - nscp->SCp.have_data_in++; + if (!nscp_cmndinfo->wait_for_completion) + nscp_cmndinfo->wait_for_completion++; else - nscp->scsi_done(nscp); + gdth_scsi_done(nscp); } else { nscp->cmnd[3] = (ha->hdr[t].devtype&1) ? 1:0; TRACE(("Prevent/allow r. %d rem. drive %d\n", nscp->cmnd[4],nscp->cmnd[3])); - if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) + if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t))) this_cmd = FALSE; } break; @@ -2580,7 +2284,7 @@ static void gdth_next(int hanum) case RELEASE: TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ? "RESERVE" : "RELEASE")); - if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) + if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t))) this_cmd = FALSE; break; @@ -2599,11 +2303,11 @@ static void gdth_next(int hanum) nscp->sense_buffer[0] = 0x70; nscp->sense_buffer[2] = UNIT_ATTENTION; nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - if (!nscp->SCp.have_data_in) - nscp->SCp.have_data_in++; + if (!nscp_cmndinfo->wait_for_completion) + nscp_cmndinfo->wait_for_completion++; else - nscp->scsi_done(nscp); - } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) + gdth_scsi_done(nscp); + } else if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t))) this_cmd = FALSE; break; @@ -2612,12 +2316,12 @@ static void gdth_next(int hanum) nscp->cmnd[1],nscp->cmnd[2],nscp->cmnd[3], nscp->cmnd[4],nscp->cmnd[5])); printk("GDT-HA %d: Unknown SCSI command 0x%x to cache service !\n", - hanum, nscp->cmnd[0]); + ha->hanum, nscp->cmnd[0]); nscp->result = DID_ABORT << 16; - if (!nscp->SCp.have_data_in) - nscp->SCp.have_data_in++; + if (!nscp_cmndinfo->wait_for_completion) + nscp_cmndinfo->wait_for_completion++; else - nscp->scsi_done(nscp); + gdth_scsi_done(nscp); break; } } @@ -2633,79 +2337,77 @@ static void gdth_next(int hanum) } if (ha->cmd_cnt > 0) { - gdth_release_event(hanum); + gdth_release_event(ha); } if (!gdth_polling) spin_unlock_irqrestore(&ha->smp_lock, flags); if (gdth_polling && ha->cmd_cnt > 0) { - if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) + if (!gdth_wait(ha, cmd_index, POLL_TIMEOUT)) printk("GDT-HA %d: Command %d timed out !\n", - hanum,cmd_index); + ha->hanum, cmd_index); } } - -static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, - char *buffer,ushort count) + +/* + * gdth_copy_internal_data() - copy to/from a buffer onto a scsi_cmnd's + * buffers, kmap_atomic() as needed. + */ +static void gdth_copy_internal_data(gdth_ha_str *ha, Scsi_Cmnd *scp, + char *buffer, ushort count, int to_buffer) { - ushort cpcount,i; + ushort cpcount,i, max_sg = gdth_sg_count(scp); ushort cpsum,cpnow; struct scatterlist *sl; - gdth_ha_str *ha; char *address; - cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen; - ha = HADATA(gdth_ctr_tab[hanum]); + cpcount = min_t(ushort, count, gdth_bufflen(scp)); - if (scp->use_sg) { - sl = (struct scatterlist *)scp->request_buffer; - for (i=0,cpsum=0; i<scp->use_sg; ++i,++sl) { + if (cpcount) { + cpsum=0; + scsi_for_each_sg(scp, sl, max_sg, i) { unsigned long flags; cpnow = (ushort)sl->length; TRACE(("copy_internal() now %d sum %d count %d %d\n", - cpnow,cpsum,cpcount,(ushort)scp->bufflen)); + cpnow, cpsum, cpcount, gdth_bufflen(scp))); if (cpsum+cpnow > cpcount) cpnow = cpcount - cpsum; cpsum += cpnow; if (!sl->page) { printk("GDT-HA %d: invalid sc/gt element in gdth_copy_internal_data()\n", - hanum); + ha->hanum); return; } local_irq_save(flags); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) address = kmap_atomic(sl->page, KM_BIO_SRC_IRQ) + sl->offset; - memcpy(address,buffer,cpnow); + if (to_buffer) + memcpy(buffer, address, cpnow); + else + memcpy(address, buffer, cpnow); flush_dcache_page(sl->page); kunmap_atomic(address, KM_BIO_SRC_IRQ); -#else - address = kmap_atomic(sl->page, KM_BH_IRQ) + sl->offset; - memcpy(address,buffer,cpnow); - flush_dcache_page(sl->page); - kunmap_atomic(address, KM_BH_IRQ); -#endif local_irq_restore(flags); if (cpsum == cpcount) break; buffer += cpnow; } - } else { - TRACE(("copy_internal() count %d\n",cpcount)); - memcpy((char*)scp->request_buffer,buffer,cpcount); + } else if (count) { + printk("GDT-HA %d: SCSI command with no buffers but data transfer expected!\n", + ha->hanum); + WARN_ON(1); } } -static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) +static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) { - register gdth_ha_str *ha; unchar t; gdth_inq_data inq; gdth_rdcap_data rdc; gdth_sense_data sd; gdth_modep_data mpd; + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); - ha = HADATA(gdth_ctr_tab[hanum]); t = scp->device->id; TRACE(("gdth_internal_cache_cmd() cmd 0x%x hdrive %d\n", scp->cmnd[0],t)); @@ -2736,7 +2438,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) strcpy(inq.vendor,ha->oem_name); sprintf(inq.product,"Host Drive #%02d",t); strcpy(inq.revision," "); - gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data)); + gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data), 0); break; case REQUEST_SENSE: @@ -2746,7 +2448,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) sd.key = NO_SENSE; sd.info = 0; sd.add_length= 0; - gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data)); + gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data), 0); break; case MODE_SENSE: @@ -2758,7 +2460,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) mpd.bd.block_length[0] = (SECTOR_SIZE & 0x00ff0000) >> 16; mpd.bd.block_length[1] = (SECTOR_SIZE & 0x0000ff00) >> 8; mpd.bd.block_length[2] = (SECTOR_SIZE & 0x000000ff); - gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data)); + gdth_copy_internal_data(ha, scp, (char*)&mpd, sizeof(gdth_modep_data), 0); break; case READ_CAPACITY: @@ -2768,7 +2470,7 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) else rdc.last_block_no = cpu_to_be32(ha->hdr[t].size-1); rdc.block_length = cpu_to_be32(SECTOR_SIZE); - gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data)); + gdth_copy_internal_data(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data), 0); break; case SERVICE_ACTION_IN: @@ -2779,7 +2481,8 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) TRACE2(("Read capacity (16) hdrive %d\n",t)); rdc16.last_block_no = cpu_to_be64(ha->hdr[t].size-1); rdc16.block_length = cpu_to_be32(SECTOR_SIZE); - gdth_copy_internal_data(hanum,scp,(char*)&rdc16,sizeof(gdth_rdcap16_data)); + gdth_copy_internal_data(ha, scp, (char*)&rdc16, + sizeof(gdth_rdcap16_data), 0); } else { scp->result = DID_ABORT << 16; } @@ -2790,27 +2493,22 @@ static int gdth_internal_cache_cmd(int hanum,Scsi_Cmnd *scp) break; } - if (!scp->SCp.have_data_in) - scp->SCp.have_data_in++; + if (!cmndinfo->wait_for_completion) + cmndinfo->wait_for_completion++; else return 1; return 0; } - -static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) + +static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) { - register gdth_ha_str *ha; register gdth_cmd_str *cmdp; - struct scatterlist *sl; + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); ulong32 cnt, blockcnt; ulong64 no, blockno; - dma_addr_t phys_addr; int i, cmd_index, read_write, sgcnt, mode64; - struct page *page; - ulong offset; - ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; TRACE(("gdth_fill_cache_cmd() cmd 0x%x cmdsize %d hdrive %d\n", scp->cmnd[0],scp->cmd_len,hdrive)); @@ -2826,18 +2524,18 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) cmdp->Service = CACHESERVICE; cmdp->RequestBuffer = scp; /* search free command index */ - if (!(cmd_index=gdth_get_cmd_index(hanum))) { + if (!(cmd_index=gdth_get_cmd_index(ha))) { TRACE(("GDT: No free command index found\n")); return 0; } /* if it's the first command, set command semaphore */ if (ha->cmd_cnt == 0) - gdth_set_sema0(hanum); + gdth_set_sema0(ha); /* fill command */ read_write = 0; - if (scp->SCp.sent_command != -1) - cmdp->OpCode = scp->SCp.sent_command; /* special cache cmd. */ + if (cmndinfo->OpCode != -1) + cmdp->OpCode = cmndinfo->OpCode; /* special cache cmd. */ else if (scp->cmnd[0] == RESERVE) cmdp->OpCode = GDT_RESERVE_DRV; else if (scp->cmnd[0] == RELEASE) @@ -2898,17 +2596,17 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) cmdp->u.cache.BlockCnt = blockcnt; } - if (scp->use_sg) { - sl = (struct scatterlist *)scp->request_buffer; - sgcnt = scp->use_sg; - scp->SCp.Status = GDTH_MAP_SG; - scp->SCp.Message = (read_write == 1 ? + if (gdth_bufflen(scp)) { + cmndinfo->dma_dir = (read_write == 1 ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); + sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), + cmndinfo->dma_dir); if (mode64) { + struct scatterlist *sl; + cmdp->u.cache64.DestAddr= (ulong64)-1; cmdp->u.cache64.sg_canz = sgcnt; - for (i=0; i<sgcnt; ++i,++sl) { + scsi_for_each_sg(scp, sl, sgcnt, i) { cmdp->u.cache64.sg_lst[i].sg_ptr = sg_dma_address(sl); #ifdef GDTH_DMA_STATISTICS if (cmdp->u.cache64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) @@ -2919,9 +2617,11 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) cmdp->u.cache64.sg_lst[i].sg_len = sg_dma_len(sl); } } else { + struct scatterlist *sl; + cmdp->u.cache.DestAddr= 0xffffffff; cmdp->u.cache.sg_canz = sgcnt; - for (i=0; i<sgcnt; ++i,++sl) { + scsi_for_each_sg(scp, sl, sgcnt, i) { cmdp->u.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); #ifdef GDTH_DMA_STATISTICS ha->dma32_cnt++; @@ -2937,38 +2637,6 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) } #endif - } else if (scp->request_bufflen) { - scp->SCp.Status = GDTH_MAP_SINGLE; - scp->SCp.Message = (read_write == 1 ? - PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - page = virt_to_page(scp->request_buffer); - offset = (ulong)scp->request_buffer & ~PAGE_MASK; - phys_addr = pci_map_page(ha->pdev,page,offset, - scp->request_bufflen,scp->SCp.Message); - scp->SCp.dma_handle = phys_addr; - if (mode64) { - if (ha->cache_feat & SCATTER_GATHER) { - cmdp->u.cache64.DestAddr = (ulong64)-1; - cmdp->u.cache64.sg_canz = 1; - cmdp->u.cache64.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.cache64.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.cache64.sg_lst[1].sg_len = 0; - } else { - cmdp->u.cache64.DestAddr = phys_addr; - cmdp->u.cache64.sg_canz= 0; - } - } else { - if (ha->cache_feat & SCATTER_GATHER) { - cmdp->u.cache.DestAddr = 0xffffffff; - cmdp->u.cache.sg_canz = 1; - cmdp->u.cache.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.cache.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.cache.sg_lst[1].sg_len = 0; - } else { - cmdp->u.cache.DestAddr = phys_addr; - cmdp->u.cache.sg_canz= 0; - } - } } } /* evaluate command size, check space */ @@ -3004,23 +2672,21 @@ static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) } /* copy command */ - gdth_copy_command(hanum); + gdth_copy_command(ha); return cmd_index; } -static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) +static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) { - register gdth_ha_str *ha; register gdth_cmd_str *cmdp; - struct scatterlist *sl; ushort i; - dma_addr_t phys_addr, sense_paddr; + dma_addr_t sense_paddr; int cmd_index, sgcnt, mode64; unchar t,l; struct page *page; ulong offset; + struct gdth_cmndinfo *cmndinfo; - ha = HADATA(gdth_ctr_tab[hanum]); t = scp->device->id; l = scp->device->lun; cmdp = ha->pccb; @@ -3035,26 +2701,27 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) cmdp->Service = SCSIRAWSERVICE; cmdp->RequestBuffer = scp; /* search free command index */ - if (!(cmd_index=gdth_get_cmd_index(hanum))) { + if (!(cmd_index=gdth_get_cmd_index(ha))) { TRACE(("GDT: No free command index found\n")); return 0; } /* if it's the first command, set command semaphore */ if (ha->cmd_cnt == 0) - gdth_set_sema0(hanum); + gdth_set_sema0(ha); + cmndinfo = gdth_cmnd_priv(scp); /* fill command */ - if (scp->SCp.sent_command != -1) { - cmdp->OpCode = scp->SCp.sent_command; /* special raw cmd. */ + if (cmndinfo->OpCode != -1) { + cmdp->OpCode = cmndinfo->OpCode; /* special raw cmd. */ cmdp->BoardNode = LOCALBOARD; if (mode64) { - cmdp->u.raw64.direction = (scp->SCp.phase >> 8); + cmdp->u.raw64.direction = (cmndinfo->phase >> 8); TRACE2(("special raw cmd 0x%x param 0x%x\n", cmdp->OpCode, cmdp->u.raw64.direction)); /* evaluate command size */ ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.raw64.sg_lst); } else { - cmdp->u.raw.direction = (scp->SCp.phase >> 8); + cmdp->u.raw.direction = (cmndinfo->phase >> 8); TRACE2(("special raw cmd 0x%x param 0x%x\n", cmdp->OpCode, cmdp->u.raw.direction)); /* evaluate command size */ @@ -3066,9 +2733,8 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) offset = (ulong)scp->sense_buffer & ~PAGE_MASK; sense_paddr = pci_map_page(ha->pdev,page,offset, 16,PCI_DMA_FROMDEVICE); - *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr; - /* high part, if 64bit */ - *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32); + + cmndinfo->sense_paddr = sense_paddr; cmdp->OpCode = GDT_WRITE; /* always */ cmdp->BoardNode = LOCALBOARD; if (mode64) { @@ -3080,7 +2746,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) cmdp->u.raw64.lun = l; cmdp->u.raw64.bus = b; cmdp->u.raw64.priority = 0; - cmdp->u.raw64.sdlen = scp->request_bufflen; + cmdp->u.raw64.sdlen = gdth_bufflen(scp); cmdp->u.raw64.sense_len = 16; cmdp->u.raw64.sense_data = sense_paddr; cmdp->u.raw64.direction = @@ -3097,7 +2763,7 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) cmdp->u.raw.bus = b; cmdp->u.raw.priority = 0; cmdp->u.raw.link_p = 0; - cmdp->u.raw.sdlen = scp->request_bufflen; + cmdp->u.raw.sdlen = gdth_bufflen(scp); cmdp->u.raw.sense_len = 16; cmdp->u.raw.sense_data = sense_paddr; cmdp->u.raw.direction = @@ -3106,16 +2772,16 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) cmdp->u.raw.sg_ranz = 0; } - if (scp->use_sg) { - sl = (struct scatterlist *)scp->request_buffer; - sgcnt = scp->use_sg; - scp->SCp.Status = GDTH_MAP_SG; - scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; - sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); + if (gdth_bufflen(scp)) { + cmndinfo->dma_dir = PCI_DMA_BIDIRECTIONAL; + sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), + cmndinfo->dma_dir); if (mode64) { + struct scatterlist *sl; + cmdp->u.raw64.sdata = (ulong64)-1; cmdp->u.raw64.sg_ranz = sgcnt; - for (i=0; i<sgcnt; ++i,++sl) { + scsi_for_each_sg(scp, sl, sgcnt, i) { cmdp->u.raw64.sg_lst[i].sg_ptr = sg_dma_address(sl); #ifdef GDTH_DMA_STATISTICS if (cmdp->u.raw64.sg_lst[i].sg_ptr > (ulong64)0xffffffff) @@ -3126,9 +2792,11 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) cmdp->u.raw64.sg_lst[i].sg_len = sg_dma_len(sl); } } else { + struct scatterlist *sl; + cmdp->u.raw.sdata = 0xffffffff; cmdp->u.raw.sg_ranz = sgcnt; - for (i=0; i<sgcnt; ++i,++sl) { + scsi_for_each_sg(scp, sl, sgcnt, i) { cmdp->u.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); #ifdef GDTH_DMA_STATISTICS ha->dma32_cnt++; @@ -3144,38 +2812,6 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) } #endif - } else if (scp->request_bufflen) { - scp->SCp.Status = GDTH_MAP_SINGLE; - scp->SCp.Message = PCI_DMA_BIDIRECTIONAL; - page = virt_to_page(scp->request_buffer); - offset = (ulong)scp->request_buffer & ~PAGE_MASK; - phys_addr = pci_map_page(ha->pdev,page,offset, - scp->request_bufflen,scp->SCp.Message); - scp->SCp.dma_handle = phys_addr; - - if (mode64) { - if (ha->raw_feat & SCATTER_GATHER) { - cmdp->u.raw64.sdata = (ulong64)-1; - cmdp->u.raw64.sg_ranz= 1; - cmdp->u.raw64.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.raw64.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.raw64.sg_lst[1].sg_len = 0; - } else { - cmdp->u.raw64.sdata = phys_addr; - cmdp->u.raw64.sg_ranz= 0; - } - } else { - if (ha->raw_feat & SCATTER_GATHER) { - cmdp->u.raw.sdata = 0xffffffff; - cmdp->u.raw.sg_ranz= 1; - cmdp->u.raw.sg_lst[0].sg_ptr = phys_addr; - cmdp->u.raw.sg_lst[0].sg_len = scp->request_bufflen; - cmdp->u.raw.sg_lst[1].sg_len = 0; - } else { - cmdp->u.raw.sdata = phys_addr; - cmdp->u.raw.sg_ranz= 0; - } - } } if (mode64) { TRACE(("raw cmd: addr. %x sganz %x sgptr0 %x sglen0 %x\n", @@ -3209,35 +2845,33 @@ static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) } /* copy command */ - gdth_copy_command(hanum); + gdth_copy_command(ha); return cmd_index; } -static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp) +static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) { - register gdth_ha_str *ha; register gdth_cmd_str *cmdp; int cmd_index; - ha = HADATA(gdth_ctr_tab[hanum]); cmdp= ha->pccb; TRACE2(("gdth_special_cmd(): ")); if (ha->type==GDT_EISA && ha->cmd_cnt>0) return 0; - memcpy( cmdp, scp->request_buffer, sizeof(gdth_cmd_str)); + gdth_copy_internal_data(ha, scp, (char *)cmdp, sizeof(gdth_cmd_str), 1); cmdp->RequestBuffer = scp; /* search free command index */ - if (!(cmd_index=gdth_get_cmd_index(hanum))) { + if (!(cmd_index=gdth_get_cmd_index(ha))) { TRACE(("GDT: No free command index found\n")); return 0; } /* if it's the first command, set command semaphore */ if (ha->cmd_cnt == 0) - gdth_set_sema0(hanum); + gdth_set_sema0(ha); /* evaluate command size, check space */ if (cmdp->OpCode == GDT_IOCTL) { @@ -3275,7 +2909,7 @@ static int gdth_special_cmd(int hanum,Scsi_Cmnd *scp) } /* copy command */ - gdth_copy_command(hanum); + gdth_copy_command(ha); return cmd_index; } @@ -3402,15 +3036,14 @@ static void gdth_clear_events(void) /* SCSI interface functions */ -static irqreturn_t gdth_interrupt(int irq,void *dev_id) +static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, + int gdth_from_wait, int* pIndex) { - gdth_ha_str *ha2 = (gdth_ha_str *)dev_id; - register gdth_ha_str *ha; gdt6m_dpram_str __iomem *dp6m_ptr = NULL; gdt6_dpram_str __iomem *dp6_ptr; gdt2_dpram_str __iomem *dp2_ptr; Scsi_Cmnd *scp; - int hanum, rval, i; + int rval, i; unchar IStatus; ushort Service; ulong flags = 0; @@ -3431,17 +3064,15 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) } if (!gdth_polling) - spin_lock_irqsave(&ha2->smp_lock, flags); - wait_index = 0; + spin_lock_irqsave(&ha->smp_lock, flags); /* search controller */ - if ((hanum = gdth_get_status(&IStatus,irq)) == -1) { + if (0 == (IStatus = gdth_get_status(ha, irq))) { /* spurious interrupt */ if (!gdth_polling) - spin_unlock_irqrestore(&ha2->smp_lock, flags); - return IRQ_HANDLED; + spin_unlock_irqrestore(&ha->smp_lock, flags); + return IRQ_HANDLED; } - ha = HADATA(gdth_ctr_tab[hanum]); #ifdef GDTH_STATISTICS ++act_ints; @@ -3482,32 +3113,32 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) dp2_ptr = ha->brd; if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; - ha->status = gdth_readw(&dp2_ptr->u.ic.Status); + ha->status = readw(&dp2_ptr->u.ic.Status); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); } else /* no error */ ha->status = S_OK; - ha->info = gdth_readl(&dp2_ptr->u.ic.Info[0]); - ha->service = gdth_readw(&dp2_ptr->u.ic.Service); - ha->info2 = gdth_readl(&dp2_ptr->u.ic.Info[1]); + ha->info = readl(&dp2_ptr->u.ic.Info[0]); + ha->service = readw(&dp2_ptr->u.ic.Service); + ha->info2 = readl(&dp2_ptr->u.ic.Info[1]); - gdth_writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ - gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */ - gdth_writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ + writeb(0xff, &dp2_ptr->io.irqdel); /* acknowledge interrupt */ + writeb(0, &dp2_ptr->u.ic.Cmd_Index);/* reset command index */ + writeb(0, &dp2_ptr->io.Sema1); /* reset status semaphore */ } else if (ha->type == GDT_PCI) { dp6_ptr = ha->brd; if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; - ha->status = gdth_readw(&dp6_ptr->u.ic.Status); + ha->status = readw(&dp6_ptr->u.ic.Status); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); } else /* no error */ ha->status = S_OK; - ha->info = gdth_readl(&dp6_ptr->u.ic.Info[0]); - ha->service = gdth_readw(&dp6_ptr->u.ic.Service); - ha->info2 = gdth_readl(&dp6_ptr->u.ic.Info[1]); + ha->info = readl(&dp6_ptr->u.ic.Info[0]); + ha->service = readw(&dp6_ptr->u.ic.Service); + ha->info2 = readl(&dp6_ptr->u.ic.Info[1]); - gdth_writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ - gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */ - gdth_writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ + writeb(0xff, &dp6_ptr->io.irqdel); /* acknowledge interrupt */ + writeb(0, &dp6_ptr->u.ic.Cmd_Index);/* reset command index */ + writeb(0, &dp6_ptr->io.Sema1); /* reset status semaphore */ } else if (ha->type == GDT_PCINEW) { if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; @@ -3530,7 +3161,7 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) ha->status = pcs->ext_status & 0xffff; else #endif - ha->status = gdth_readw(&dp6m_ptr->i960r.status); + ha->status = readw(&dp6m_ptr->i960r.status); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); } else /* no error */ ha->status = S_OK; @@ -3543,18 +3174,18 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) } else #endif { - ha->info = gdth_readl(&dp6m_ptr->i960r.info[0]); - ha->service = gdth_readw(&dp6m_ptr->i960r.service); - ha->info2 = gdth_readl(&dp6m_ptr->i960r.info[1]); + ha->info = readl(&dp6m_ptr->i960r.info[0]); + ha->service = readw(&dp6m_ptr->i960r.service); + ha->info2 = readl(&dp6m_ptr->i960r.info[1]); } /* event string */ if (IStatus == ASYNCINDEX) { if (ha->service != SCREENSERVICE && (ha->fw_vers & 0xff) >= 0x1a) { - ha->dvr.severity = gdth_readb + ha->dvr.severity = readb (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity); for (i = 0; i < 256; ++i) { - ha->dvr.event_string[i] = gdth_readb + ha->dvr.event_string[i] = readb (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]); if (ha->dvr.event_string[i] == 0) break; @@ -3567,13 +3198,13 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) if (!coalesced) #endif { - gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); + writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + writeb(0, &dp6m_ptr->i960r.sema1_reg); } } else { TRACE2(("gdth_interrupt() unknown controller type\n")); if (!gdth_polling) - spin_unlock_irqrestore(&ha2->smp_lock, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); return IRQ_HANDLED; } @@ -3581,26 +3212,25 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) IStatus,ha->status,ha->info)); if (gdth_from_wait) { - wait_hanum = hanum; - wait_index = (int)IStatus; + *pIndex = (int)IStatus; } if (IStatus == ASYNCINDEX) { TRACE2(("gdth_interrupt() async. event\n")); - gdth_async_event(hanum); + gdth_async_event(ha); if (!gdth_polling) - spin_unlock_irqrestore(&ha2->smp_lock, flags); - gdth_next(hanum); + spin_unlock_irqrestore(&ha->smp_lock, flags); + gdth_next(ha); return IRQ_HANDLED; } if (IStatus == SPEZINDEX) { TRACE2(("Service unknown or not initialized !\n")); ha->dvr.size = sizeof(ha->dvr.eu.driver); - ha->dvr.eu.driver.ionode = hanum; + ha->dvr.eu.driver.ionode = ha->hanum; gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); if (!gdth_polling) - spin_unlock_irqrestore(&ha2->smp_lock, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); return IRQ_HANDLED; } scp = ha->cmd_tab[IStatus-2].cmnd; @@ -3609,28 +3239,28 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) if (scp == UNUSED_CMND) { TRACE2(("gdth_interrupt() index to unused command (%d)\n",IStatus)); ha->dvr.size = sizeof(ha->dvr.eu.driver); - ha->dvr.eu.driver.ionode = hanum; + ha->dvr.eu.driver.ionode = ha->hanum; ha->dvr.eu.driver.index = IStatus; gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); if (!gdth_polling) - spin_unlock_irqrestore(&ha2->smp_lock, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); return IRQ_HANDLED; } if (scp == INTERNAL_CMND) { TRACE(("gdth_interrupt() answer to internal command\n")); if (!gdth_polling) - spin_unlock_irqrestore(&ha2->smp_lock, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); return IRQ_HANDLED; } TRACE(("gdth_interrupt() sync. status\n")); - rval = gdth_sync_event(hanum,Service,IStatus,scp); + rval = gdth_sync_event(ha,Service,IStatus,scp); if (!gdth_polling) - spin_unlock_irqrestore(&ha2->smp_lock, flags); + spin_unlock_irqrestore(&ha->smp_lock, flags); if (rval == 2) { - gdth_putq(hanum,scp,scp->SCp.this_residual); + gdth_putq(ha, scp, gdth_cmnd_priv(scp)->priority); } else if (rval == 1) { - scp->scsi_done(scp); + gdth_scsi_done(scp); } #ifdef INT_COAL @@ -3653,23 +3283,30 @@ static irqreturn_t gdth_interrupt(int irq,void *dev_id) /* coalescing only for new GDT_PCIMPR controllers available */ if (ha->type == GDT_PCIMPR && coalesced) { - gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); + writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + writeb(0, &dp6m_ptr->i960r.sema1_reg); } #endif - gdth_next(hanum); + gdth_next(ha); return IRQ_HANDLED; } -static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) +static irqreturn_t gdth_interrupt(int irq, void *dev_id) +{ + gdth_ha_str *ha = (gdth_ha_str *)dev_id; + + return __gdth_interrupt(ha, irq, false, NULL); +} + +static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, + Scsi_Cmnd *scp) { - register gdth_ha_str *ha; gdth_msg_str *msg; gdth_cmd_str *cmdp; unchar b, t; + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); - ha = HADATA(gdth_ctr_tab[hanum]); cmdp = ha->pccb; TRACE(("gdth_sync_event() serv %d status %d\n", service,ha->status)); @@ -3687,12 +3324,12 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) } if (msg->msg_ext && !msg->msg_answer) { - while (gdth_test_busy(hanum)) + while (gdth_test_busy(ha)) gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; - gdth_get_cmd_index(hanum); - gdth_set_sema0(hanum); + gdth_get_cmd_index(ha); + gdth_set_sema0(ha); cmdp->OpCode = GDT_READ; cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; @@ -3702,8 +3339,8 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) + sizeof(ulong64); ha->cmd_cnt = 0; - gdth_copy_command(hanum); - gdth_release_event(hanum); + gdth_copy_command(ha); + gdth_release_event(ha); return 0; } @@ -3721,12 +3358,12 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) } msg->msg_ext = 0; msg->msg_answer = 0; - while (gdth_test_busy(hanum)) + while (gdth_test_busy(ha)) gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; - gdth_get_cmd_index(hanum); - gdth_set_sema0(hanum); + gdth_get_cmd_index(ha); + gdth_set_sema0(ha); cmdp->OpCode = GDT_WRITE; cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; @@ -3736,74 +3373,67 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) + sizeof(ulong64); ha->cmd_cnt = 0; - gdth_copy_command(hanum); - gdth_release_event(hanum); + gdth_copy_command(ha); + gdth_release_event(ha); return 0; } printk("\n"); } else { - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; + b = scp->device->channel; t = scp->device->id; - if (scp->SCp.sent_command == -1 && b != ha->virt_bus) { + if (cmndinfo->OpCode == -1 && b != ha->virt_bus) { ha->raw[BUS_L2P(ha,b)].io_cnt[t]--; } /* cache or raw service */ if (ha->status == S_BSY) { TRACE2(("Controller busy -> retry !\n")); - if (scp->SCp.sent_command == GDT_MOUNT) - scp->SCp.sent_command = GDT_CLUST_INFO; + if (cmndinfo->OpCode == GDT_MOUNT) + cmndinfo->OpCode = GDT_CLUST_INFO; /* retry */ return 2; } - if (scp->SCp.Status == GDTH_MAP_SG) - pci_unmap_sg(ha->pdev,scp->request_buffer, - scp->use_sg,scp->SCp.Message); - else if (scp->SCp.Status == GDTH_MAP_SINGLE) - pci_unmap_page(ha->pdev,scp->SCp.dma_handle, - scp->request_bufflen,scp->SCp.Message); - if (scp->SCp.buffer) { - dma_addr_t addr; - addr = (dma_addr_t)*(ulong32 *)&scp->SCp.buffer; - if (scp->host_scribble) - addr += (dma_addr_t) - ((ulong64)(*(ulong32 *)&scp->host_scribble) << 32); - pci_unmap_page(ha->pdev,addr,16,PCI_DMA_FROMDEVICE); - } + if (gdth_bufflen(scp)) + pci_unmap_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), + cmndinfo->dma_dir); + + if (cmndinfo->sense_paddr) + pci_unmap_page(ha->pdev, cmndinfo->sense_paddr, 16, + PCI_DMA_FROMDEVICE); if (ha->status == S_OK) { - scp->SCp.Status = S_OK; - scp->SCp.Message = ha->info; - if (scp->SCp.sent_command != -1) { + cmndinfo->status = S_OK; + cmndinfo->info = ha->info; + if (cmndinfo->OpCode != -1) { TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n", - scp->SCp.sent_command)); + cmndinfo->OpCode)); /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */ - if (scp->SCp.sent_command == GDT_CLUST_INFO) { + if (cmndinfo->OpCode == GDT_CLUST_INFO) { ha->hdr[t].cluster_type = (unchar)ha->info; if (!(ha->hdr[t].cluster_type & CLUSTER_MOUNTED)) { /* NOT MOUNTED -> MOUNT */ - scp->SCp.sent_command = GDT_MOUNT; + cmndinfo->OpCode = GDT_MOUNT; if (ha->hdr[t].cluster_type & CLUSTER_RESERVED) { /* cluster drive RESERVED (on the other node) */ - scp->SCp.phase = -2; /* reservation conflict */ + cmndinfo->phase = -2; /* reservation conflict */ } } else { - scp->SCp.sent_command = -1; + cmndinfo->OpCode = -1; } } else { - if (scp->SCp.sent_command == GDT_MOUNT) { + if (cmndinfo->OpCode == GDT_MOUNT) { ha->hdr[t].cluster_type |= CLUSTER_MOUNTED; ha->hdr[t].media_changed = TRUE; - } else if (scp->SCp.sent_command == GDT_UNMOUNT) { + } else if (cmndinfo->OpCode == GDT_UNMOUNT) { ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED; ha->hdr[t].media_changed = TRUE; } - scp->SCp.sent_command = -1; + cmndinfo->OpCode = -1; } /* retry */ - scp->SCp.this_residual = HIGH_PRI; + cmndinfo->priority = HIGH_PRI; return 2; } else { /* RESERVE/RELEASE ? */ @@ -3816,17 +3446,17 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) scp->sense_buffer[0] = 0; } } else { - scp->SCp.Status = ha->status; - scp->SCp.Message = ha->info; + cmndinfo->status = ha->status; + cmndinfo->info = ha->info; - if (scp->SCp.sent_command != -1) { + if (cmndinfo->OpCode != -1) { TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n", - scp->SCp.sent_command, ha->status)); - if (scp->SCp.sent_command == GDT_SCAN_START || - scp->SCp.sent_command == GDT_SCAN_END) { - scp->SCp.sent_command = -1; + cmndinfo->OpCode, ha->status)); + if (cmndinfo->OpCode == GDT_SCAN_START || + cmndinfo->OpCode == GDT_SCAN_END) { + cmndinfo->OpCode = -1; /* retry */ - scp->SCp.this_residual = HIGH_PRI; + cmndinfo->priority = HIGH_PRI; return 2; } memset((char*)scp->sense_buffer,0,16); @@ -3848,9 +3478,9 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) scp->sense_buffer[2] = NOT_READY; scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } - if (scp->done != gdth_scsi_done) { + if (!cmndinfo->internal_command) { ha->dvr.size = sizeof(ha->dvr.eu.sync); - ha->dvr.eu.sync.ionode = hanum; + ha->dvr.eu.sync.ionode = ha->hanum; ha->dvr.eu.sync.service = service; ha->dvr.eu.sync.status = ha->status; ha->dvr.eu.sync.info = ha->info; @@ -3869,8 +3499,8 @@ static int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp) } } } - if (!scp->SCp.have_data_in) - scp->SCp.have_data_in++; + if (!cmndinfo->wait_for_completion) + cmndinfo->wait_for_completion++; else return 1; } @@ -4034,25 +3664,23 @@ static char *async_cache_tab[] = { }; -static int gdth_async_event(int hanum) +static int gdth_async_event(gdth_ha_str *ha) { - gdth_ha_str *ha; gdth_cmd_str *cmdp; int cmd_index; - ha = HADATA(gdth_ctr_tab[hanum]); cmdp= ha->pccb; TRACE2(("gdth_async_event() ha %d serv %d\n", - hanum,ha->service)); + ha->hanum, ha->service)); if (ha->service == SCREENSERVICE) { if (ha->status == MSG_REQUEST) { - while (gdth_test_busy(hanum)) + while (gdth_test_busy(ha)) gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; - cmd_index = gdth_get_cmd_index(hanum); - gdth_set_sema0(hanum); + cmd_index = gdth_get_cmd_index(ha); + gdth_set_sema0(ha); cmdp->OpCode = GDT_READ; cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; @@ -4062,7 +3690,7 @@ static int gdth_async_event(int hanum) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) + sizeof(ulong64); ha->cmd_cnt = 0; - gdth_copy_command(hanum); + gdth_copy_command(ha); if (ha->type == GDT_EISA) printk("[EISA slot %d] ",(ushort)ha->brd_phys); else if (ha->type == GDT_ISA) @@ -4070,19 +3698,19 @@ static int gdth_async_event(int hanum) else printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8), (ushort)((ha->brd_phys>>3)&0x1f)); - gdth_release_event(hanum); + gdth_release_event(ha); } } else { if (ha->type == GDT_PCIMPR && (ha->fw_vers & 0xff) >= 0x1a) { ha->dvr.size = 0; - ha->dvr.eu.async.ionode = hanum; + ha->dvr.eu.async.ionode = ha->hanum; ha->dvr.eu.async.status = ha->status; /* severity and event_string already set! */ } else { ha->dvr.size = sizeof(ha->dvr.eu.async); - ha->dvr.eu.async.ionode = hanum; + ha->dvr.eu.async.ionode = ha->hanum; ha->dvr.eu.async.service = ha->service; ha->dvr.eu.async.status = ha->status; ha->dvr.eu.async.info = ha->info; @@ -4164,9 +3792,8 @@ static void gdth_timeout(ulong data) Scsi_Cmnd *nscp; gdth_ha_str *ha; ulong flags; - int hanum = 0; - ha = HADATA(gdth_ctr_tab[hanum]); + ha = list_first_entry(&gdth_instances, gdth_ha_str, list); spin_lock_irqsave(&ha->smp_lock, flags); for (act_stats=0,i=0; i<GDTH_MAXCMDS; ++i) @@ -4229,8 +3856,6 @@ static void __init internal_setup(char *str,int *ints) max_ids = val; else if (!strncmp(argv, "rescan:", 7)) rescan = val; - else if (!strncmp(argv, "virt_ctr:", 9)) - virt_ctr = val; else if (!strncmp(argv, "shared_access:", 14)) shared_access = val; else if (!strncmp(argv, "probe_eisa_isa:", 15)) @@ -4277,523 +3902,10 @@ int __init option_setup(char *str) return 1; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static int __init gdth_detect(struct scsi_host_template *shtp) -#else -static int __init gdth_detect(Scsi_Host_Template *shtp) -#endif -{ - struct Scsi_Host *shp; - gdth_pci_str pcistr[MAXHA]; - gdth_ha_str *ha; - ulong32 isa_bios; - ushort eisa_slot; - int i,hanum,cnt,ctr,err; - unchar b; - - -#ifdef DEBUG_GDTH - printk("GDT: This driver contains debugging information !! Trace level = %d\n", - DebugState); - printk(" Destination of debugging information: "); -#ifdef __SERIAL__ -#ifdef __COM2__ - printk("Serial port COM2\n"); -#else - printk("Serial port COM1\n"); -#endif -#else - printk("Console\n"); -#endif - gdth_delay(3000); -#endif - - TRACE(("gdth_detect()\n")); - - if (disable) { - printk("GDT-HA: Controller driver disabled from command line !\n"); - return 0; - } - - printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n",GDTH_VERSION_STR); - /* initializations */ - gdth_polling = TRUE; b = 0; - gdth_clear_events(); - - /* As default we do not probe for EISA or ISA controllers */ - if (probe_eisa_isa) { - /* scanning for controllers, at first: ISA controller */ - for (isa_bios=0xc8000UL; isa_bios<=0xd8000UL; isa_bios+=0x8000UL) { - dma_addr_t scratch_dma_handle; - scratch_dma_handle = 0; - - if (gdth_ctr_count >= MAXHA) - break; - if (gdth_search_isa(isa_bios)) { /* controller found */ - shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if (shp == NULL) - continue; - - ha = HADATA(shp); - if (!gdth_init_isa(isa_bios,ha)) { - scsi_unregister(shp); - continue; - } -#ifdef __ia64__ - break; -#else - /* controller found and initialized */ - printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", - isa_bios,ha->irq,ha->drq); - - if (request_irq(ha->irq,gdth_interrupt,IRQF_DISABLED,"gdth",ha)) { - printk("GDT-ISA: Unable to allocate IRQ\n"); - scsi_unregister(shp); - continue; - } - if (request_dma(ha->drq,"gdth")) { - printk("GDT-ISA: Unable to allocate DMA channel\n"); - free_irq(ha->irq,ha); - scsi_unregister(shp); - continue; - } - set_dma_mode(ha->drq,DMA_MODE_CASCADE); - enable_dma(ha->drq); - shp->unchecked_isa_dma = 1; - shp->irq = ha->irq; - shp->dma_channel = ha->drq; - hanum = gdth_ctr_count; - gdth_ctr_tab[gdth_ctr_count++] = shp; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum= 0; - - ha->pccb = CMDDATA(shp); - ha->ccb_phys = 0L; - ha->pdev = NULL; - ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, - &scratch_dma_handle); - ha->scratch_phys = scratch_dma_handle; - ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), - &scratch_dma_handle); - ha->msg_phys = scratch_dma_handle; -#ifdef INT_COAL - ha->coal_stat = (gdth_coal_status *) - pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * - MAXOFFSETS, &scratch_dma_handle); - ha->coal_stat_phys = scratch_dma_handle; -#endif - - ha->scratch_busy = FALSE; - ha->req_first = NULL; - ha->tid_cnt = MAX_HDRIVES; - if (max_ids > 0 && max_ids < ha->tid_cnt) - ha->tid_cnt = max_ids; - for (i=0; i<GDTH_MAXCMDS; ++i) - ha->cmd_tab[i].cmnd = UNUSED_CMND; - ha->scan_mode = rescan ? 0x10 : 0; - - if (ha->pscratch == NULL || ha->pmsg == NULL || - !gdth_search_drives(hanum)) { - printk("GDT-ISA: Error during device scan\n"); - --gdth_ctr_count; - --gdth_ctr_vcount; - -#ifdef INT_COAL - if (ha->coal_stat) - pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * - MAXOFFSETS, ha->coal_stat, - ha->coal_stat_phys); -#endif - if (ha->pscratch) - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); - if (ha->pmsg) - pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), - ha->pmsg, ha->msg_phys); - - free_irq(ha->irq,ha); - scsi_unregister(shp); - continue; - } - if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) - hdr_channel = ha->bus_cnt; - ha->virt_bus = hdr_channel; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - shp->highmem_io = 0; -#endif - if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) - shp->max_cmd_len = 16; - - shp->max_id = ha->tid_cnt; - shp->max_lun = MAXLUN; - shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) { - virt_ctr = 1; - /* register addit. SCSI channels as virtual controllers */ - for (b = 1; b < ha->bus_cnt + 1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 1; - shp->irq = ha->irq; - shp->dma_channel = ha->drq; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; - } - } - - spin_lock_init(&ha->smp_lock); - gdth_enable_int(hanum); -#endif /* !__ia64__ */ - } - } - - /* scanning for EISA controllers */ - for (eisa_slot=0x1000; eisa_slot<=0x8000; eisa_slot+=0x1000) { - dma_addr_t scratch_dma_handle; - scratch_dma_handle = 0; - - if (gdth_ctr_count >= MAXHA) - break; - if (gdth_search_eisa(eisa_slot)) { /* controller found */ - shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if (shp == NULL) - continue; - - ha = HADATA(shp); - if (!gdth_init_eisa(eisa_slot,ha)) { - scsi_unregister(shp); - continue; - } - /* controller found and initialized */ - printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", - eisa_slot>>12,ha->irq); - - if (request_irq(ha->irq,gdth_interrupt,IRQF_DISABLED,"gdth",ha)) { - printk("GDT-EISA: Unable to allocate IRQ\n"); - scsi_unregister(shp); - continue; - } - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - hanum = gdth_ctr_count; - gdth_ctr_tab[gdth_ctr_count++] = shp; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum= 0; - TRACE2(("EISA detect Bus 0: hanum %d\n", - NUMDATA(shp)->hanum)); - - ha->pccb = CMDDATA(shp); - ha->ccb_phys = 0L; - - ha->pdev = NULL; - ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, - &scratch_dma_handle); - ha->scratch_phys = scratch_dma_handle; - ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), - &scratch_dma_handle); - ha->msg_phys = scratch_dma_handle; -#ifdef INT_COAL - ha->coal_stat = (gdth_coal_status *) - pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * - MAXOFFSETS, &scratch_dma_handle); - ha->coal_stat_phys = scratch_dma_handle; -#endif - ha->ccb_phys = - pci_map_single(ha->pdev,ha->pccb, - sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); - ha->scratch_busy = FALSE; - ha->req_first = NULL; - ha->tid_cnt = MAX_HDRIVES; - if (max_ids > 0 && max_ids < ha->tid_cnt) - ha->tid_cnt = max_ids; - for (i=0; i<GDTH_MAXCMDS; ++i) - ha->cmd_tab[i].cmnd = UNUSED_CMND; - ha->scan_mode = rescan ? 0x10 : 0; - - if (ha->pscratch == NULL || ha->pmsg == NULL || - !gdth_search_drives(hanum)) { - printk("GDT-EISA: Error during device scan\n"); - --gdth_ctr_count; - --gdth_ctr_vcount; -#ifdef INT_COAL - if (ha->coal_stat) - pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * - MAXOFFSETS, ha->coal_stat, - ha->coal_stat_phys); -#endif - if (ha->pscratch) - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); - if (ha->pmsg) - pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), - ha->pmsg, ha->msg_phys); - if (ha->ccb_phys) - pci_unmap_single(ha->pdev,ha->ccb_phys, - sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); - free_irq(ha->irq,ha); - scsi_unregister(shp); - continue; - } - if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) - hdr_channel = ha->bus_cnt; - ha->virt_bus = hdr_channel; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - shp->highmem_io = 0; -#endif - if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) - shp->max_cmd_len = 16; - - shp->max_id = ha->tid_cnt; - shp->max_lun = MAXLUN; - shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) { - virt_ctr = 1; - /* register addit. SCSI channels as virtual controllers */ - for (b = 1; b < ha->bus_cnt + 1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; - } - } - - spin_lock_init(&ha->smp_lock); - gdth_enable_int(hanum); - } - } - } - - /* scanning for PCI controllers */ - cnt = gdth_search_pci(pcistr); - printk("GDT-HA: Found %d PCI Storage RAID Controllers\n",cnt); - gdth_sort_pci(pcistr,cnt); - for (ctr = 0; ctr < cnt; ++ctr) { - dma_addr_t scratch_dma_handle; - scratch_dma_handle = 0; - - if (gdth_ctr_count >= MAXHA) - break; - shp = scsi_register(shtp,sizeof(gdth_ext_str)); - if (shp == NULL) - continue; - - ha = HADATA(shp); - if (!gdth_init_pci(&pcistr[ctr],ha)) { - scsi_unregister(shp); - continue; - } - /* controller found and initialized */ - printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", - pcistr[ctr].pdev->bus->number, - PCI_SLOT(pcistr[ctr].pdev->devfn), ha->irq); - - if (request_irq(ha->irq, gdth_interrupt, - IRQF_DISABLED|IRQF_SHARED, "gdth", ha)) - { - printk("GDT-PCI: Unable to allocate IRQ\n"); - scsi_unregister(shp); - continue; - } - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - hanum = gdth_ctr_count; - gdth_ctr_tab[gdth_ctr_count++] = shp; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum= 0; - - ha->pccb = CMDDATA(shp); - ha->ccb_phys = 0L; - - ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, - &scratch_dma_handle); - ha->scratch_phys = scratch_dma_handle; - ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), - &scratch_dma_handle); - ha->msg_phys = scratch_dma_handle; -#ifdef INT_COAL - ha->coal_stat = (gdth_coal_status *) - pci_alloc_consistent(ha->pdev, sizeof(gdth_coal_status) * - MAXOFFSETS, &scratch_dma_handle); - ha->coal_stat_phys = scratch_dma_handle; -#endif - ha->scratch_busy = FALSE; - ha->req_first = NULL; - ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES; - if (max_ids > 0 && max_ids < ha->tid_cnt) - ha->tid_cnt = max_ids; - for (i=0; i<GDTH_MAXCMDS; ++i) - ha->cmd_tab[i].cmnd = UNUSED_CMND; - ha->scan_mode = rescan ? 0x10 : 0; - - err = FALSE; - if (ha->pscratch == NULL || ha->pmsg == NULL || - !gdth_search_drives(hanum)) { - err = TRUE; - } else { - if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) - hdr_channel = ha->bus_cnt; - ha->virt_bus = hdr_channel; - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - scsi_set_pci_device(shp, pcistr[ctr].pdev); -#endif - if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat &GDT_64BIT)|| - /* 64-bit DMA only supported from FW >= x.43 */ - (!ha->dma64_support)) { - if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "GDT-PCI %d: Unable to set 32-bit DMA\n", hanum); - err = TRUE; - } - } else { - shp->max_cmd_len = 16; - if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) { - printk("GDT-PCI %d: 64-bit DMA enabled\n", hanum); - } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { - printk(KERN_WARNING "GDT-PCI %d: Unable to set 64/32-bit DMA\n", hanum); - err = TRUE; - } - } - } - - if (err) { - printk("GDT-PCI %d: Error during device scan\n", hanum); - --gdth_ctr_count; - --gdth_ctr_vcount; -#ifdef INT_COAL - if (ha->coal_stat) - pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * - MAXOFFSETS, ha->coal_stat, - ha->coal_stat_phys); -#endif - if (ha->pscratch) - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); - if (ha->pmsg) - pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), - ha->pmsg, ha->msg_phys); - free_irq(ha->irq,ha); - scsi_unregister(shp); - continue; - } - - shp->max_id = ha->tid_cnt; - shp->max_lun = MAXLUN; - shp->max_channel = virt_ctr ? 0 : ha->bus_cnt; - if (virt_ctr) { - virt_ctr = 1; - /* register addit. SCSI channels as virtual controllers */ - for (b = 1; b < ha->bus_cnt + 1; ++b) { - shp = scsi_register(shtp,sizeof(gdth_num_str)); - shp->unchecked_isa_dma = 0; - shp->irq = ha->irq; - shp->dma_channel = 0xff; - gdth_ctr_vtab[gdth_ctr_vcount++] = shp; - NUMDATA(shp)->hanum = (ushort)hanum; - NUMDATA(shp)->busnum = b; - } - } - - spin_lock_init(&ha->smp_lock); - gdth_enable_int(hanum); - } - - TRACE2(("gdth_detect() %d controller detected\n",gdth_ctr_count)); - if (gdth_ctr_count > 0) { -#ifdef GDTH_STATISTICS - TRACE2(("gdth_detect(): Initializing timer !\n")); - init_timer(&gdth_timer); - gdth_timer.expires = jiffies + HZ; - gdth_timer.data = 0L; - gdth_timer.function = gdth_timeout; - add_timer(&gdth_timer); -#endif - major = register_chrdev(0,"gdth",&gdth_fops); - notifier_disabled = 0; - register_reboot_notifier(&gdth_notifier); - } - gdth_polling = FALSE; - return gdth_ctr_vcount; -} - -static int gdth_release(struct Scsi_Host *shp) +static const char *gdth_ctr_name(gdth_ha_str *ha) { - int hanum; - gdth_ha_str *ha; - - TRACE2(("gdth_release()\n")); - if (NUMDATA(shp)->busnum == 0) { - hanum = NUMDATA(shp)->hanum; - ha = HADATA(gdth_ctr_tab[hanum]); - if (ha->sdev) { - scsi_free_host_dev(ha->sdev); - ha->sdev = NULL; - } - gdth_flush(hanum); - - if (shp->irq) { - free_irq(shp->irq,ha); - } -#ifndef __ia64__ - if (shp->dma_channel != 0xff) { - free_dma(shp->dma_channel); - } -#endif -#ifdef INT_COAL - if (ha->coal_stat) - pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * - MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys); -#endif - if (ha->pscratch) - pci_free_consistent(ha->pdev, GDTH_SCRATCH, - ha->pscratch, ha->scratch_phys); - if (ha->pmsg) - pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), - ha->pmsg, ha->msg_phys); - if (ha->ccb_phys) - pci_unmap_single(ha->pdev,ha->ccb_phys, - sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); - gdth_ctr_released++; - TRACE2(("gdth_release(): HA %d of %d\n", - gdth_ctr_released, gdth_ctr_count)); - - if (gdth_ctr_released == gdth_ctr_count) { -#ifdef GDTH_STATISTICS - del_timer(&gdth_timer); -#endif - unregister_chrdev(major,"gdth"); - unregister_reboot_notifier(&gdth_notifier); - } - } - - scsi_unregister(shp); - return 0; -} - - -static const char *gdth_ctr_name(int hanum) -{ - gdth_ha_str *ha; - TRACE2(("gdth_ctr_name()\n")); - ha = HADATA(gdth_ctr_tab[hanum]); - if (ha->type == GDT_EISA) { switch (ha->stype) { case GDT3_ID: @@ -4820,29 +3932,23 @@ static const char *gdth_ctr_name(int hanum) static const char *gdth_info(struct Scsi_Host *shp) { - int hanum; - gdth_ha_str *ha; + gdth_ha_str *ha = shost_priv(shp); TRACE2(("gdth_info()\n")); - hanum = NUMDATA(shp)->hanum; - ha = HADATA(gdth_ctr_tab[hanum]); - return ((const char *)ha->binfo.type_string); } static int gdth_eh_bus_reset(Scsi_Cmnd *scp) { - int i, hanum; - gdth_ha_str *ha; + gdth_ha_str *ha = shost_priv(scp->device->host); + int i; ulong flags; Scsi_Cmnd *cmnd; unchar b; TRACE2(("gdth_eh_bus_reset()\n")); - hanum = NUMDATA(scp->device->host)->hanum; - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; - ha = HADATA(gdth_ctr_tab[hanum]); + b = scp->device->channel; /* clear command tab */ spin_lock_irqsave(&ha->smp_lock, flags); @@ -4859,9 +3965,9 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp) if (ha->hdr[i].present) { spin_lock_irqsave(&ha->smp_lock, flags); gdth_polling = TRUE; - while (gdth_test_busy(hanum)) + while (gdth_test_busy(ha)) gdth_delay(0); - if (gdth_internal_cmd(hanum, CACHESERVICE, + if (gdth_internal_cmd(ha, CACHESERVICE, GDT_CLUST_RESET, i, 0, 0)) ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED; gdth_polling = FALSE; @@ -4874,9 +3980,9 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp) for (i = 0; i < MAXID; ++i) ha->raw[BUS_L2P(ha,b)].io_cnt[i] = 0; gdth_polling = TRUE; - while (gdth_test_busy(hanum)) + while (gdth_test_busy(ha)) gdth_delay(0); - gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS, + gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESET_BUS, BUS_L2P(ha,b), 0, 0); gdth_polling = FALSE; spin_unlock_irqrestore(&ha->smp_lock, flags); @@ -4884,30 +3990,18 @@ static int gdth_eh_bus_reset(Scsi_Cmnd *scp) return SUCCESS; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,sector_t cap,int *ip) -#else -static int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) -#endif { unchar b, t; - int hanum; - gdth_ha_str *ha; + gdth_ha_str *ha = shost_priv(sdev->host); struct scsi_device *sd; unsigned capacity; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sd = sdev; capacity = cap; -#else - sd = disk->device; - capacity = disk->capacity; -#endif - hanum = NUMDATA(sd->host)->hanum; - b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel; + b = sd->channel; t = sd->id; - TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t)); - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", ha->hanum, b, t)); if (b != ha->virt_bus || ha->hdr[t].heads == 0) { /* raw device or host drive without mapping information */ @@ -4925,33 +4019,42 @@ static int gdth_bios_param(Disk *disk,kdev_t dev,int *ip) } -static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)) +static int gdth_queuecommand(struct scsi_cmnd *scp, + void (*done)(struct scsi_cmnd *)) { - int hanum; - int priority; + gdth_ha_str *ha = shost_priv(scp->device->host); + struct gdth_cmndinfo *cmndinfo; TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0])); - - scp->scsi_done = (void *)done; - scp->SCp.have_data_in = 1; - scp->SCp.phase = -1; - scp->SCp.sent_command = -1; - scp->SCp.Status = GDTH_MAP_NONE; - scp->SCp.buffer = (struct scatterlist *)NULL; - - hanum = NUMDATA(scp->device->host)->hanum; + + cmndinfo = gdth_get_cmndinfo(ha); + BUG_ON(!cmndinfo); + + scp->scsi_done = done; + gdth_update_timeout(scp, scp->timeout_per_command * 6); + cmndinfo->priority = DEFAULT_PRI; + + gdth_set_bufflen(scp, scsi_bufflen(scp)); + gdth_set_sg_count(scp, scsi_sg_count(scp)); + gdth_set_sglist(scp, scsi_sglist(scp)); + + return __gdth_queuecommand(ha, scp, cmndinfo); +} + +static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp, + struct gdth_cmndinfo *cmndinfo) +{ + scp->host_scribble = (unsigned char *)cmndinfo; + cmndinfo->wait_for_completion = 1; + cmndinfo->phase = -1; + cmndinfo->OpCode = -1; + #ifdef GDTH_STATISTICS ++act_ios; #endif - priority = DEFAULT_PRI; - if (scp->done == gdth_scsi_done) - priority = scp->SCp.this_residual; - else - gdth_update_timeout(hanum, scp, scp->timeout_per_command * 6); - - gdth_putq( hanum, scp, priority ); - gdth_next( hanum ); + gdth_putq(ha, scp, cmndinfo->priority); + gdth_next(ha); return 0; } @@ -4959,12 +4062,10 @@ static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)) static int gdth_open(struct inode *inode, struct file *filep) { gdth_ha_str *ha; - int i; - for (i = 0; i < gdth_ctr_count; i++) { - ha = HADATA(gdth_ctr_tab[i]); + list_for_each_entry(ha, &gdth_instances, list) { if (!ha->sdev) - ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]); + ha->sdev = scsi_get_host_dev(ha->shost); } TRACE(("gdth_open()\n")); @@ -4983,10 +4084,11 @@ static int ioc_event(void __user *arg) gdth_ha_str *ha; ulong flags; - if (copy_from_user(&evt, arg, sizeof(gdth_ioctl_event)) || - evt.ionode >= gdth_ctr_count) + if (copy_from_user(&evt, arg, sizeof(gdth_ioctl_event))) + return -EFAULT; + ha = gdth_find_ha(evt.ionode); + if (!ha) return -EFAULT; - ha = HADATA(gdth_ctr_tab[evt.ionode]); if (evt.erase == 0xff) { if (evt.event.event_source == ES_TEST) @@ -5020,11 +4122,12 @@ static int ioc_lockdrv(void __user *arg) ulong flags; gdth_ha_str *ha; - if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv)) || - ldrv.ionode >= gdth_ctr_count) + if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv))) return -EFAULT; - ha = HADATA(gdth_ctr_tab[ldrv.ionode]); - + ha = gdth_find_ha(ldrv.ionode); + if (!ha) + return -EFAULT; + for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) { j = ldrv.drives[i]; if (j >= MAX_HDRIVES || !ha->hdr[j].present) @@ -5033,14 +4136,14 @@ static int ioc_lockdrv(void __user *arg) spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[j].lock = 1; spin_unlock_irqrestore(&ha->smp_lock, flags); - gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); - gdth_stop_timeout(ldrv.ionode, ha->bus_cnt, j); + gdth_wait_completion(ha, ha->bus_cnt, j); + gdth_stop_timeout(ha, ha->bus_cnt, j); } else { spin_lock_irqsave(&ha->smp_lock, flags); ha->hdr[j].lock = 0; spin_unlock_irqrestore(&ha->smp_lock, flags); - gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); - gdth_next(ldrv.ionode); + gdth_start_timeout(ha, ha->bus_cnt, j); + gdth_next(ha); } } return 0; @@ -5050,16 +4153,16 @@ static int ioc_resetdrv(void __user *arg, char *cmnd) { gdth_ioctl_reset res; gdth_cmd_str cmd; - int hanum; gdth_ha_str *ha; int rval; if (copy_from_user(&res, arg, sizeof(gdth_ioctl_reset)) || - res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) + res.number >= MAX_HDRIVES) return -EFAULT; - hanum = res.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); - + ha = gdth_find_ha(res.ionode); + if (!ha) + return -EFAULT; + if (!ha->hdr[res.number].present) return 0; memset(&cmd, 0, sizeof(gdth_cmd_str)); @@ -5085,22 +4188,21 @@ static int ioc_general(void __user *arg, char *cmnd) gdth_ioctl_general gen; char *buf = NULL; ulong64 paddr; - int hanum; gdth_ha_str *ha; int rval; - - if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) || - gen.ionode >= gdth_ctr_count) + + if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general))) + return -EFAULT; + ha = gdth_find_ha(gen.ionode); + if (!ha) return -EFAULT; - hanum = gen.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); if (gen.data_len + gen.sense_len != 0) { - if (!(buf = gdth_ioctl_alloc(hanum, gen.data_len + gen.sense_len, + if (!(buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len, FALSE, &paddr))) return -EFAULT; if (copy_from_user(buf, arg + sizeof(gdth_ioctl_general), gen.data_len + gen.sense_len)) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr); return -EFAULT; } @@ -5174,7 +4276,7 @@ static int ioc_general(void __user *arg, char *cmnd) gen.command.u.raw.sense_data = (ulong32)paddr + gen.data_len; } } else { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr); return -EFAULT; } } @@ -5186,15 +4288,15 @@ static int ioc_general(void __user *arg, char *cmnd) if (copy_to_user(arg + sizeof(gdth_ioctl_general), buf, gen.data_len + gen.sense_len)) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr); return -EFAULT; } if (copy_to_user(arg, &gen, sizeof(gdth_ioctl_general) - sizeof(gdth_cmd_str))) { - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr); return -EFAULT; } - gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr); return 0; } @@ -5204,7 +4306,7 @@ static int ioc_hdrlist(void __user *arg, char *cmnd) gdth_cmd_str *cmd; gdth_ha_str *ha; unchar i; - int hanum, rc = -ENOMEM; + int rc = -ENOMEM; u32 cluster_type = 0; rsc = kmalloc(sizeof(*rsc), GFP_KERNEL); @@ -5213,12 +4315,10 @@ static int ioc_hdrlist(void __user *arg, char *cmnd) goto free_fail; if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || - rsc->ionode >= gdth_ctr_count) { + (NULL == (ha = gdth_find_ha(rsc->ionode)))) { rc = -EFAULT; goto free_fail; } - hanum = rsc->ionode; - ha = HADATA(gdth_ctr_tab[hanum]); memset(cmd, 0, sizeof(gdth_cmd_str)); for (i = 0; i < MAX_HDRIVES; ++i) { @@ -5259,7 +4359,7 @@ static int ioc_rescan(void __user *arg, char *cmnd) gdth_cmd_str *cmd; ushort i, status, hdr_cnt; ulong32 info; - int hanum, cyls, hds, secs; + int cyls, hds, secs; int rc = -ENOMEM; ulong flags; gdth_ha_str *ha; @@ -5270,12 +4370,10 @@ static int ioc_rescan(void __user *arg, char *cmnd) goto free_fail; if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || - rsc->ionode >= gdth_ctr_count) { + (NULL == (ha = gdth_find_ha(rsc->ionode)))) { rc = -EFAULT; goto free_fail; } - hanum = rsc->ionode; - ha = HADATA(gdth_ctr_tab[hanum]); memset(cmd, 0, sizeof(gdth_cmd_str)); if (rsc->flag == 0) { @@ -5432,9 +4530,9 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, gdth_ioctl_ctrtype ctrt; if (copy_from_user(&ctrt, argp, sizeof(gdth_ioctl_ctrtype)) || - ctrt.ionode >= gdth_ctr_count) + (NULL == (ha = gdth_find_ha(ctrt.ionode)))) return -EFAULT; - ha = HADATA(gdth_ctr_tab[ctrt.ionode]); + if (ha->type == GDT_ISA || ha->type == GDT_EISA) { ctrt.type = (unchar)((ha->stype>>20) - 0x10); } else { @@ -5473,10 +4571,9 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, unchar i, j; if (copy_from_user(&lchn, argp, sizeof(gdth_ioctl_lockchn)) || - lchn.ionode >= gdth_ctr_count) + (NULL == (ha = gdth_find_ha(lchn.ionode)))) return -EFAULT; - ha = HADATA(gdth_ctr_tab[lchn.ionode]); - + i = lchn.channel; if (i < ha->bus_cnt) { if (lchn.lock) { @@ -5484,16 +4581,16 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, ha->raw[i].lock = 1; spin_unlock_irqrestore(&ha->smp_lock, flags); for (j = 0; j < ha->tid_cnt; ++j) { - gdth_wait_completion(lchn.ionode, i, j); - gdth_stop_timeout(lchn.ionode, i, j); + gdth_wait_completion(ha, i, j); + gdth_stop_timeout(ha, i, j); } } else { spin_lock_irqsave(&ha->smp_lock, flags); ha->raw[i].lock = 0; spin_unlock_irqrestore(&ha->smp_lock, flags); for (j = 0; j < ha->tid_cnt; ++j) { - gdth_start_timeout(lchn.ionode, i, j); - gdth_next(lchn.ionode); + gdth_start_timeout(ha, i, j); + gdth_next(ha); } } } @@ -5509,37 +4606,22 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, case GDTIOCTL_RESET_BUS: { gdth_ioctl_reset res; - int hanum, rval; + int rval; if (copy_from_user(&res, argp, sizeof(gdth_ioctl_reset)) || - res.ionode >= gdth_ctr_count) + (NULL == (ha = gdth_find_ha(res.ionode)))) return -EFAULT; - hanum = res.ionode; - ha = HADATA(gdth_ctr_tab[hanum]); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - scp = kmalloc(sizeof(*scp), GFP_KERNEL); + scp = kzalloc(sizeof(*scp), GFP_KERNEL); if (!scp) return -ENOMEM; - memset(scp, 0, sizeof(*scp)); scp->device = ha->sdev; scp->cmd_len = 12; - scp->use_sg = 0; - scp->device->channel = virt_ctr ? 0 : res.number; + scp->device->channel = res.number; rval = gdth_eh_bus_reset(scp); res.status = (rval == SUCCESS ? S_OK : S_GENERR); kfree(scp); -#else - scp = scsi_allocate_device(ha->sdev, 1, FALSE); - if (!scp) - return -ENOMEM; - scp->cmd_len = 12; - scp->use_sg = 0; - scp->channel = virt_ctr ? 0 : res.number; - rval = gdth_eh_bus_reset(scp); - res.status = (rval == SUCCESS ? S_OK : S_GENERR); - scsi_release_command(scp); -#endif + if (copy_to_user(argp, &res, sizeof(gdth_ioctl_reset))) return -EFAULT; break; @@ -5556,16 +4638,14 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, /* flush routine */ -static void gdth_flush(int hanum) +static void gdth_flush(gdth_ha_str *ha) { int i; - gdth_ha_str *ha; gdth_cmd_str gdtcmd; char cmnd[MAX_COMMAND_SIZE]; memset(cmnd, 0xff, MAX_COMMAND_SIZE); - TRACE2(("gdth_flush() hanum %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE2(("gdth_flush() hanum %d\n", ha->hanum)); for (i = 0; i < MAX_HDRIVES; ++i) { if (ha->hdr[i].present) { @@ -5581,9 +4661,9 @@ static void gdth_flush(int hanum) gdtcmd.u.cache.BlockNo = 1; gdtcmd.u.cache.sg_canz = 0; } - TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); + TRACE2(("gdth_flush(): flush ha %d drive %d\n", ha->hanum, i)); - gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 30, NULL); + gdth_execute(ha->shost, &gdtcmd, cmnd, 30, NULL); } } } @@ -5591,7 +4671,7 @@ static void gdth_flush(int hanum) /* shutdown routine */ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) { - int hanum; + gdth_ha_str *ha; #ifndef __alpha__ gdth_cmd_str gdtcmd; char cmnd[MAX_COMMAND_SIZE]; @@ -5606,8 +4686,8 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) notifier_disabled = 1; printk("GDT-HA: Flushing all host drives .. "); - for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { - gdth_flush(hanum); + list_for_each_entry(ha, &gdth_instances, list) { + gdth_flush(ha); #ifndef __alpha__ /* controller reset */ @@ -5615,8 +4695,8 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) gdtcmd.BoardNode = LOCALBOARD; gdtcmd.Service = CACHESERVICE; gdtcmd.OpCode = GDT_RESET; - TRACE2(("gdth_halt(): reset controller %d\n", hanum)); - gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 10, NULL); + TRACE2(("gdth_halt(): reset controller %d\n", ha->hanum)); + gdth_execute(ha->shost, &gdtcmd, cmnd, 10, NULL); #endif } printk("Done.\n"); @@ -5627,7 +4707,6 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) return NOTIFY_OK; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) /* configure lun */ static int gdth_slave_configure(struct scsi_device *sdev) { @@ -5636,40 +4715,536 @@ static int gdth_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_8 = 1; return 0; } -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -static struct scsi_host_template driver_template = { -#else -static Scsi_Host_Template driver_template = { -#endif - .proc_name = "gdth", - .proc_info = gdth_proc_info, +static struct scsi_host_template gdth_template = { .name = "GDT SCSI Disk Array Controller", - .detect = gdth_detect, - .release = gdth_release, .info = gdth_info, .queuecommand = gdth_queuecommand, .eh_bus_reset_handler = gdth_eh_bus_reset, + .slave_configure = gdth_slave_configure, .bios_param = gdth_bios_param, + .proc_info = gdth_proc_info, + .proc_name = "gdth", .can_queue = GDTH_MAXCMDS, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .slave_configure = gdth_slave_configure, -#endif .this_id = -1, .sg_tablesize = GDTH_MAXSG, .cmd_per_lun = GDTH_MAXC_P_L, .unchecked_isa_dma = 1, .use_clustering = ENABLE_CLUSTERING, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - .use_new_eh_code = 1, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,20) - .highmem_io = 1, +}; + +#ifdef CONFIG_ISA +static int gdth_isa_probe_one(ulong32 isa_bios) +{ + struct Scsi_Host *shp; + gdth_ha_str *ha; + dma_addr_t scratch_dma_handle = 0; + int error, i; + + if (!gdth_search_isa(isa_bios)) + return -ENXIO; + + shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str)); + if (!shp) + return -ENOMEM; + ha = shost_priv(shp); + + error = -ENODEV; + if (!gdth_init_isa(isa_bios,ha)) + goto out_host_put; + + /* controller found and initialized */ + printk("Configuring GDT-ISA HA at BIOS 0x%05X IRQ %u DRQ %u\n", + isa_bios, ha->irq, ha->drq); + + error = request_irq(ha->irq, gdth_interrupt, IRQF_DISABLED, "gdth", ha); + if (error) { + printk("GDT-ISA: Unable to allocate IRQ\n"); + goto out_host_put; + } + + error = request_dma(ha->drq, "gdth"); + if (error) { + printk("GDT-ISA: Unable to allocate DMA channel\n"); + goto out_free_irq; + } + + set_dma_mode(ha->drq,DMA_MODE_CASCADE); + enable_dma(ha->drq); + shp->unchecked_isa_dma = 1; + shp->irq = ha->irq; + shp->dma_channel = ha->drq; + + ha->hanum = gdth_ctr_count++; + ha->shost = shp; + + ha->pccb = &ha->cmdext; + ha->ccb_phys = 0L; + ha->pdev = NULL; + + error = -ENOMEM; + + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &scratch_dma_handle); + if (!ha->pscratch) + goto out_dec_counters; + ha->scratch_phys = scratch_dma_handle; + + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + if (!ha->pmsg) + goto out_free_pscratch; + ha->msg_phys = scratch_dma_handle; + +#ifdef INT_COAL + ha->coal_stat = pci_alloc_consistent(ha->pdev, + sizeof(gdth_coal_status) * MAXOFFSETS, + &scratch_dma_handle); + if (!ha->coal_stat) + goto out_free_pmsg; + ha->coal_stat_phys = scratch_dma_handle; +#endif + + ha->scratch_busy = FALSE; + ha->req_first = NULL; + ha->tid_cnt = MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i = 0; i < GDTH_MAXCMDS; ++i) + ha->cmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; + + error = -ENODEV; + if (!gdth_search_drives(ha)) { + printk("GDT-ISA: Error during device scan\n"); + goto out_free_coal_stat; + } + + if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) + hdr_channel = ha->bus_cnt; + ha->virt_bus = hdr_channel; + + if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) + shp->max_cmd_len = 16; + + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = ha->bus_cnt; + + spin_lock_init(&ha->smp_lock); + gdth_enable_int(ha); + + error = scsi_add_host(shp, NULL); + if (error) + goto out_free_coal_stat; + list_add_tail(&ha->list, &gdth_instances); + return 0; + + out_free_coal_stat: +#ifdef INT_COAL + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * MAXOFFSETS, + ha->coal_stat, ha->coal_stat_phys); + out_free_pmsg: +#endif + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + out_free_pscratch: + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + out_dec_counters: + gdth_ctr_count--; + out_free_irq: + free_irq(ha->irq, ha); + out_host_put: + scsi_host_put(shp); + return error; +} +#endif /* CONFIG_ISA */ + +#ifdef CONFIG_EISA +static int gdth_eisa_probe_one(ushort eisa_slot) +{ + struct Scsi_Host *shp; + gdth_ha_str *ha; + dma_addr_t scratch_dma_handle = 0; + int error, i; + + if (!gdth_search_eisa(eisa_slot)) + return -ENXIO; + + shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str)); + if (!shp) + return -ENOMEM; + ha = shost_priv(shp); + + error = -ENODEV; + if (!gdth_init_eisa(eisa_slot,ha)) + goto out_host_put; + + /* controller found and initialized */ + printk("Configuring GDT-EISA HA at Slot %d IRQ %u\n", + eisa_slot >> 12, ha->irq); + + error = request_irq(ha->irq, gdth_interrupt, IRQF_DISABLED, "gdth", ha); + if (error) { + printk("GDT-EISA: Unable to allocate IRQ\n"); + goto out_host_put; + } + + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + + ha->hanum = gdth_ctr_count++; + ha->shost = shp; + + TRACE2(("EISA detect Bus 0: hanum %d\n", ha->hanum)); + + ha->pccb = &ha->cmdext; + ha->ccb_phys = 0L; + + error = -ENOMEM; + + ha->pdev = NULL; + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &scratch_dma_handle); + if (!ha->pscratch) + goto out_free_irq; + ha->scratch_phys = scratch_dma_handle; + + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + if (!ha->pmsg) + goto out_free_pscratch; + ha->msg_phys = scratch_dma_handle; + +#ifdef INT_COAL + ha->coal_stat = pci_alloc_consistent(ha->pdev, + sizeof(gdth_coal_status) * MAXOFFSETS, + &scratch_dma_handle); + if (!ha->coal_stat) + goto out_free_pmsg; + ha->coal_stat_phys = scratch_dma_handle; #endif + + ha->ccb_phys = pci_map_single(ha->pdev,ha->pccb, + sizeof(gdth_cmd_str), PCI_DMA_BIDIRECTIONAL); + if (!ha->ccb_phys) + goto out_free_coal_stat; + + ha->scratch_busy = FALSE; + ha->req_first = NULL; + ha->tid_cnt = MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i = 0; i < GDTH_MAXCMDS; ++i) + ha->cmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; + + if (!gdth_search_drives(ha)) { + printk("GDT-EISA: Error during device scan\n"); + error = -ENODEV; + goto out_free_ccb_phys; + } + + if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) + hdr_channel = ha->bus_cnt; + ha->virt_bus = hdr_channel; + + if (ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) + shp->max_cmd_len = 16; + + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = ha->bus_cnt; + + spin_lock_init(&ha->smp_lock); + gdth_enable_int(ha); + + error = scsi_add_host(shp, NULL); + if (error) + goto out_free_coal_stat; + list_add_tail(&ha->list, &gdth_instances); + return 0; + + out_free_ccb_phys: + pci_unmap_single(ha->pdev,ha->ccb_phys, sizeof(gdth_cmd_str), + PCI_DMA_BIDIRECTIONAL); + out_free_coal_stat: +#ifdef INT_COAL + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * MAXOFFSETS, + ha->coal_stat, ha->coal_stat_phys); + out_free_pmsg: #endif -}; + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + out_free_pscratch: + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + out_free_irq: + free_irq(ha->irq, ha); + gdth_ctr_count--; + out_host_put: + scsi_host_put(shp); + return error; +} +#endif /* CONFIG_EISA */ + +#ifdef CONFIG_PCI +static int gdth_pci_probe_one(gdth_pci_str *pcistr, int ctr) +{ + struct Scsi_Host *shp; + gdth_ha_str *ha; + dma_addr_t scratch_dma_handle = 0; + int error, i; + + shp = scsi_host_alloc(&gdth_template, sizeof(gdth_ha_str)); + if (!shp) + return -ENOMEM; + ha = shost_priv(shp); + + error = -ENODEV; + if (!gdth_init_pci(&pcistr[ctr],ha)) + goto out_host_put; + + /* controller found and initialized */ + printk("Configuring GDT-PCI HA at %d/%d IRQ %u\n", + pcistr[ctr].pdev->bus->number, + PCI_SLOT(pcistr[ctr].pdev->devfn), + ha->irq); + + error = request_irq(ha->irq, gdth_interrupt, + IRQF_DISABLED|IRQF_SHARED, "gdth", ha); + if (error) { + printk("GDT-PCI: Unable to allocate IRQ\n"); + goto out_host_put; + } + + shp->unchecked_isa_dma = 0; + shp->irq = ha->irq; + shp->dma_channel = 0xff; + + ha->hanum = gdth_ctr_count++; + ha->shost = shp; + + ha->pccb = &ha->cmdext; + ha->ccb_phys = 0L; + + error = -ENOMEM; + + ha->pscratch = pci_alloc_consistent(ha->pdev, GDTH_SCRATCH, + &scratch_dma_handle); + if (!ha->pscratch) + goto out_free_irq; + ha->scratch_phys = scratch_dma_handle; + + ha->pmsg = pci_alloc_consistent(ha->pdev, sizeof(gdth_msg_str), + &scratch_dma_handle); + if (!ha->pmsg) + goto out_free_pscratch; + ha->msg_phys = scratch_dma_handle; + +#ifdef INT_COAL + ha->coal_stat = pci_alloc_consistent(ha->pdev, + sizeof(gdth_coal_status) * MAXOFFSETS, + &scratch_dma_handle); + if (!ha->coal_stat) + goto out_free_pmsg; + ha->coal_stat_phys = scratch_dma_handle; +#endif + + ha->scratch_busy = FALSE; + ha->req_first = NULL; + ha->tid_cnt = pcistr[ctr].pdev->device >= 0x200 ? MAXID : MAX_HDRIVES; + if (max_ids > 0 && max_ids < ha->tid_cnt) + ha->tid_cnt = max_ids; + for (i = 0; i < GDTH_MAXCMDS; ++i) + ha->cmd_tab[i].cmnd = UNUSED_CMND; + ha->scan_mode = rescan ? 0x10 : 0; + + error = -ENODEV; + if (!gdth_search_drives(ha)) { + printk("GDT-PCI %d: Error during device scan\n", ha->hanum); + goto out_free_coal_stat; + } + + if (hdr_channel < 0 || hdr_channel > ha->bus_cnt) + hdr_channel = ha->bus_cnt; + ha->virt_bus = hdr_channel; + + /* 64-bit DMA only supported from FW >= x.43 */ + if (!(ha->cache_feat & ha->raw_feat & ha->screen_feat & GDT_64BIT) || + !ha->dma64_support) { + if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "GDT-PCI %d: " + "Unable to set 32-bit DMA\n", ha->hanum); + goto out_free_coal_stat; + } + } else { + shp->max_cmd_len = 16; + if (!pci_set_dma_mask(pcistr[ctr].pdev, DMA_64BIT_MASK)) { + printk("GDT-PCI %d: 64-bit DMA enabled\n", ha->hanum); + } else if (pci_set_dma_mask(pcistr[ctr].pdev, DMA_32BIT_MASK)) { + printk(KERN_WARNING "GDT-PCI %d: " + "Unable to set 64/32-bit DMA\n", ha->hanum); + goto out_free_coal_stat; + } + } + + shp->max_id = ha->tid_cnt; + shp->max_lun = MAXLUN; + shp->max_channel = ha->bus_cnt; + + spin_lock_init(&ha->smp_lock); + gdth_enable_int(ha); + + error = scsi_add_host(shp, &pcistr[ctr].pdev->dev); + if (error) + goto out_free_coal_stat; + list_add_tail(&ha->list, &gdth_instances); + return 0; + + out_free_coal_stat: +#ifdef INT_COAL + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * MAXOFFSETS, + ha->coal_stat, ha->coal_stat_phys); + out_free_pmsg: +#endif + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + out_free_pscratch: + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + out_free_irq: + free_irq(ha->irq, ha); + gdth_ctr_count--; + out_host_put: + scsi_host_put(shp); + return error; +} +#endif /* CONFIG_PCI */ + +static void gdth_remove_one(gdth_ha_str *ha) +{ + struct Scsi_Host *shp = ha->shost; + + TRACE2(("gdth_remove_one()\n")); + + scsi_remove_host(shp); + + if (ha->sdev) { + scsi_free_host_dev(ha->sdev); + ha->sdev = NULL; + } + + gdth_flush(ha); + + if (shp->irq) + free_irq(shp->irq,ha); + +#ifdef CONFIG_ISA + if (shp->dma_channel != 0xff) + free_dma(shp->dma_channel); +#endif +#ifdef INT_COAL + if (ha->coal_stat) + pci_free_consistent(ha->pdev, sizeof(gdth_coal_status) * + MAXOFFSETS, ha->coal_stat, ha->coal_stat_phys); +#endif + if (ha->pscratch) + pci_free_consistent(ha->pdev, GDTH_SCRATCH, + ha->pscratch, ha->scratch_phys); + if (ha->pmsg) + pci_free_consistent(ha->pdev, sizeof(gdth_msg_str), + ha->pmsg, ha->msg_phys); + if (ha->ccb_phys) + pci_unmap_single(ha->pdev,ha->ccb_phys, + sizeof(gdth_cmd_str),PCI_DMA_BIDIRECTIONAL); + + scsi_host_put(shp); +} + +static int __init gdth_init(void) +{ + if (disable) { + printk("GDT-HA: Controller driver disabled from" + " command line !\n"); + return 0; + } + + printk("GDT-HA: Storage RAID Controller Driver. Version: %s\n", + GDTH_VERSION_STR); + + /* initializations */ + gdth_polling = TRUE; + gdth_clear_events(); + + /* As default we do not probe for EISA or ISA controllers */ + if (probe_eisa_isa) { + /* scanning for controllers, at first: ISA controller */ +#ifdef CONFIG_ISA + ulong32 isa_bios; + for (isa_bios = 0xc8000UL; isa_bios <= 0xd8000UL; + isa_bios += 0x8000UL) + gdth_isa_probe_one(isa_bios); +#endif +#ifdef CONFIG_EISA + { + ushort eisa_slot; + for (eisa_slot = 0x1000; eisa_slot <= 0x8000; + eisa_slot += 0x1000) + gdth_eisa_probe_one(eisa_slot); + } +#endif + } + +#ifdef CONFIG_PCI + /* scanning for PCI controllers */ + { + gdth_pci_str pcistr[MAXHA]; + int cnt,ctr; + + cnt = gdth_search_pci(pcistr); + printk("GDT-HA: Found %d PCI Storage RAID Controllers\n", cnt); + gdth_sort_pci(pcistr,cnt); + for (ctr = 0; ctr < cnt; ++ctr) + gdth_pci_probe_one(pcistr, ctr); + } +#endif /* CONFIG_PCI */ + + TRACE2(("gdth_detect() %d controller detected\n", gdth_ctr_count)); +#ifdef GDTH_STATISTICS + TRACE2(("gdth_detect(): Initializing timer !\n")); + init_timer(&gdth_timer); + gdth_timer.expires = jiffies + HZ; + gdth_timer.data = 0L; + gdth_timer.function = gdth_timeout; + add_timer(&gdth_timer); +#endif + major = register_chrdev(0,"gdth", &gdth_fops); + notifier_disabled = 0; + register_reboot_notifier(&gdth_notifier); + gdth_polling = FALSE; + return 0; +} + +static void __exit gdth_exit(void) +{ + gdth_ha_str *ha; + + list_for_each_entry(ha, &gdth_instances, list) + gdth_remove_one(ha); + +#ifdef GDTH_STATISTICS + del_timer(&gdth_timer); +#endif + unregister_chrdev(major,"gdth"); + unregister_reboot_notifier(&gdth_notifier); +} + +module_init(gdth_init); +module_exit(gdth_exit); -#include "scsi_module.c" #ifndef MODULE __setup("gdth=", option_setup); #endif diff --git a/drivers/scsi/gdth.h b/drivers/scsi/gdth.h index 37423300592e..1434c6b0297c 100644 --- a/drivers/scsi/gdth.h +++ b/drivers/scsi/gdth.h @@ -13,7 +13,6 @@ * $Id: gdth.h,v 1.58 2006/01/11 16:14:09 achim Exp $ */ -#include <linux/version.h> #include <linux/types.h> #ifndef TRUE @@ -304,15 +303,8 @@ #define MAILBOXREG 0x0c90 /* mailbox reg. (16 bytes) */ #define EISAREG 0x0cc0 /* EISA configuration */ -/* DMA memory mappings */ -#define GDTH_MAP_NONE 0 -#define GDTH_MAP_SINGLE 1 -#define GDTH_MAP_SG 2 -#define GDTH_MAP_IOCTL 3 - /* other defines */ #define LINUX_OS 8 /* used for cache optim. */ -#define SCATTER_GATHER 1 /* s/g feature */ #define SECS32 0x1f /* round capacity */ #define BIOS_ID_OFFS 0x10 /* offset contr-ID in ISABIOS */ #define LOCALBOARD 0 /* board node always 0 */ @@ -854,6 +846,9 @@ typedef struct { /* controller information structure */ typedef struct { + struct Scsi_Host *shost; + struct list_head list; + ushort hanum; ushort oem_id; /* OEM */ ushort type; /* controller class */ ulong32 stype; /* subtype (PCI: device ID) */ @@ -865,6 +860,7 @@ typedef struct { void __iomem *brd; /* DPRAM address */ ulong32 brd_phys; /* slot number/BIOS address */ gdt6c_plx_regs *plx; /* PLX regs (new PCI contr.) */ + gdth_cmd_str cmdext; gdth_cmd_str *pccb; /* address command structure */ ulong32 ccb_phys; /* phys. address */ #ifdef INT_COAL @@ -916,6 +912,19 @@ typedef struct { Scsi_Cmnd *cmnd; /* pending request */ ushort service; /* service */ } cmd_tab[GDTH_MAXCMDS]; /* table of pend. requests */ + struct gdth_cmndinfo { /* per-command private info */ + int index; + int internal_command; /* don't call scsi_done */ + dma_addr_t sense_paddr; /* sense dma-addr */ + unchar priority; + int timeout; + volatile int wait_for_completion; + ushort status; + ulong32 info; + enum dma_data_direction dma_dir; + int phase; /* ???? */ + int OpCode; + } cmndinfo[GDTH_MAXCMDS]; /* index==0 is free */ unchar bus_cnt; /* SCSI bus count */ unchar tid_cnt; /* Target ID count */ unchar bus_id[MAXBUS]; /* IOP IDs */ @@ -938,19 +947,10 @@ typedef struct { struct scsi_device *sdev; } gdth_ha_str; -/* structure for scsi_register(), SCSI bus != 0 */ -typedef struct { - ushort hanum; - ushort busnum; -} gdth_num_str; - -/* structure for scsi_register() */ -typedef struct { - gdth_num_str numext; /* must be the first element */ - gdth_ha_str haext; - gdth_cmd_str cmdext; -} gdth_ext_str; - +static inline struct gdth_cmndinfo *gdth_cmnd_priv(struct scsi_cmnd* cmd) +{ + return (struct gdth_cmndinfo *)cmd->host_scribble; +} /* INQUIRY data format */ typedef struct { diff --git a/drivers/scsi/gdth_kcompat.h b/drivers/scsi/gdth_kcompat.h deleted file mode 100644 index 2a302eee669a..000000000000 --- a/drivers/scsi/gdth_kcompat.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef IRQ_HANDLED -typedef void irqreturn_t; -#define IRQ_NONE -#define IRQ_HANDLED -#endif - -#ifndef MODULE_LICENSE -#define MODULE_LICENSE(x) -#endif - -#ifndef __iomem -#define __iomem -#endif - -#ifndef __attribute_used__ -#define __attribute_used__ __devinitdata -#endif - -#ifndef __user -#define __user -#endif - -#ifndef SERVICE_ACTION_IN -#define SERVICE_ACTION_IN 0x9e -#endif -#ifndef READ_16 -#define READ_16 0x88 -#endif -#ifndef WRITE_16 -#define WRITE_16 0x8a -#endif diff --git a/drivers/scsi/gdth_proc.c b/drivers/scsi/gdth_proc.c index 32982eb75c84..de5773443c62 100644 --- a/drivers/scsi/gdth_proc.c +++ b/drivers/scsi/gdth_proc.c @@ -4,62 +4,32 @@ #include <linux/completion.h> -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) int gdth_proc_info(struct Scsi_Host *host, char *buffer,char **start,off_t offset,int length, int inout) { - int hanum,busnum; + gdth_ha_str *ha = shost_priv(host); TRACE2(("gdth_proc_info() length %d offs %d inout %d\n", length,(int)offset,inout)); - hanum = NUMDATA(host)->hanum; - busnum= NUMDATA(host)->busnum; - - if (inout) - return(gdth_set_info(buffer,length,host,hanum,busnum)); - else - return(gdth_get_info(buffer,start,offset,length,host,hanum,busnum)); -} -#else -int gdth_proc_info(char *buffer,char **start,off_t offset,int length,int hostno, - int inout) -{ - int hanum,busnum,i; - - TRACE2(("gdth_proc_info() length %d offs %d inout %d\n", - length,(int)offset,inout)); - - for (i = 0; i < gdth_ctr_vcount; ++i) { - if (gdth_ctr_vtab[i]->host_no == hostno) - break; - } - if (i == gdth_ctr_vcount) - return(-EINVAL); - - hanum = NUMDATA(gdth_ctr_vtab[i])->hanum; - busnum= NUMDATA(gdth_ctr_vtab[i])->busnum; - if (inout) - return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum)); + return(gdth_set_info(buffer,length,host,ha)); else - return(gdth_get_info(buffer,start,offset,length, - gdth_ctr_vtab[i],hanum,busnum)); + return(gdth_get_info(buffer,start,offset,length,host,ha)); } -#endif static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, - int hanum,int busnum) + gdth_ha_str *ha) { int ret_val = -EINVAL; - TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); + TRACE2(("gdth_set_info() ha %d\n",ha->hanum,)); if (length >= 4) { if (strncmp(buffer,"gdth",4) == 0) { buffer += 5; length -= 5; - ret_val = gdth_set_asc_info(host, buffer, length, hanum); + ret_val = gdth_set_asc_info(host, buffer, length, ha); } } @@ -67,11 +37,10 @@ static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, } static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, - int length,int hanum) + int length, gdth_ha_str *ha) { int orig_length, drive, wb_mode; int i, found; - gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; ulong64 paddr; @@ -80,8 +49,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, memset(cmnd, 0xff, 12); memset(&gdtcmd, 0, sizeof(gdth_cmd_str)); - TRACE2(("gdth_set_asc_info() ha %d\n",hanum)); - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE2(("gdth_set_asc_info() ha %d\n",ha->hanum)); orig_length = length + 5; drive = -1; wb_mode = 0; @@ -157,7 +125,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, } if (wb_mode) { - if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr)) + if (!gdth_ioctl_alloc(ha, sizeof(gdth_cpar_str), TRUE, &paddr)) return(-EBUSY); pcpar = (gdth_cpar_str *)ha->pscratch; memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) ); @@ -171,7 +139,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, gdth_execute(host, &gdtcmd, cmnd, 30, NULL); - gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr); + gdth_ioctl_free(ha, GDTH_SCRATCH, ha->pscratch, paddr); printk("Done.\n"); return(orig_length); } @@ -181,11 +149,10 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, } static int gdth_get_info(char *buffer,char **start,off_t offset,int length, - struct Scsi_Host *host,int hanum,int busnum) + struct Scsi_Host *host, gdth_ha_str *ha) { int size = 0,len = 0; off_t begin = 0,pos = 0; - gdth_ha_str *ha; int id, i, j, k, sec, flag; int no_mdrv = 0, drv_no, is_mirr; ulong32 cnt; @@ -214,8 +181,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, memset(cmnd, 0xff, 12); memset(gdtcmd, 0, sizeof(gdth_cmd_str)); - TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum)); - ha = HADATA(gdth_ctr_tab[hanum]); + TRACE2(("gdth_get_info() ha %d\n",ha->hanum)); /* request is i.e. "cat /proc/scsi/gdth/0" */ @@ -245,13 +211,10 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, /* controller information */ size = sprintf(buffer+len,"\nDisk Array Controller Information:\n"); len += size; pos = begin + len; - if (virt_ctr) - sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum); - else - strcpy(hrec, ha->binfo.type_string); + strcpy(hrec, ha->binfo.type_string); size = sprintf(buffer+len, " Number: \t%d \tName: \t%s\n", - hanum, hrec); + ha->hanum, hrec); len += size; pos = begin + len; if (ha->more_proc) @@ -301,7 +264,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, len += size; pos = begin + len; flag = FALSE; - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < ha->bus_cnt; ++i) { @@ -404,7 +367,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, goto stop_output; } } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); + gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -416,7 +379,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, len += size; pos = begin + len; flag = FALSE; - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -510,7 +473,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, if (pos > offset + length) goto stop_output; } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); + gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -522,7 +485,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, len += size; pos = begin + len; flag = FALSE; - buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); + buf = gdth_ioctl_alloc(ha, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -581,7 +544,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, goto stop_output; } } - gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); + gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -593,7 +556,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, len += size; pos = begin + len; flag = FALSE; - buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr); + buf = gdth_ioctl_alloc(ha, sizeof(gdth_hget_str), FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -626,7 +589,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, } } } - gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr); + gdth_ioctl_free(ha, sizeof(gdth_hget_str), buf, paddr); for (i = 0; i < MAX_HDRIVES; ++i) { if (!(ha->hdr[i].present)) @@ -664,7 +627,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, id = gdth_read_event(ha, id, estr); if (estr->event_source == 0) break; - if (estr->event_data.eu.driver.ionode == hanum && + if (estr->event_data.eu.driver.ionode == ha->hanum && estr->event_source == ES_ASYNC) { gdth_log_event(&estr->event_data, hrec); do_gettimeofday(&tv); @@ -699,17 +662,15 @@ free_fail: return rc; } -static char *gdth_ioctl_alloc(int hanum, int size, int scratch, +static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, ulong64 *paddr) { - gdth_ha_str *ha; ulong flags; char *ret_val; if (size == 0) return NULL; - ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); if (!ha->scratch_busy && size <= GDTH_SCRATCH) { @@ -729,12 +690,10 @@ static char *gdth_ioctl_alloc(int hanum, int size, int scratch, return ret_val; } -static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr) +static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr) { - gdth_ha_str *ha; ulong flags; - ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); if (buf == ha->pscratch) { @@ -747,13 +706,11 @@ static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr) } #ifdef GDTH_IOCTL_PROC -static int gdth_ioctl_check_bin(int hanum, ushort size) +static int gdth_ioctl_check_bin(gdth_ha_str *ha, ushort size) { - gdth_ha_str *ha; ulong flags; int ret_val; - ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); ret_val = FALSE; @@ -766,27 +723,27 @@ static int gdth_ioctl_check_bin(int hanum, ushort size) } #endif -static void gdth_wait_completion(int hanum, int busnum, int id) +static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id) { - gdth_ha_str *ha; ulong flags; int i; Scsi_Cmnd *scp; + struct gdth_cmndinfo *cmndinfo; unchar b, t; - ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); for (i = 0; i < GDTH_MAXCMDS; ++i) { scp = ha->cmd_tab[i].cmnd; + cmndinfo = gdth_cmnd_priv(scp); - b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; + b = scp->device->channel; t = scp->device->id; if (!SPECIAL_SCP(scp) && t == (unchar)id && b == (unchar)busnum) { - scp->SCp.have_data_in = 0; + cmndinfo->wait_for_completion = 0; spin_unlock_irqrestore(&ha->smp_lock, flags); - while (!scp->SCp.have_data_in) + while (!cmndinfo->wait_for_completion) barrier(); spin_lock_irqsave(&ha->smp_lock, flags); } @@ -794,55 +751,51 @@ static void gdth_wait_completion(int hanum, int busnum, int id) spin_unlock_irqrestore(&ha->smp_lock, flags); } -static void gdth_stop_timeout(int hanum, int busnum, int id) +static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id) { - gdth_ha_str *ha; ulong flags; Scsi_Cmnd *scp; unchar b, t; - ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - if (scp->done != gdth_scsi_done) { - b = virt_ctr ? - NUMDATA(scp->device->host)->busnum : scp->device->channel; + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); + if (!cmndinfo->internal_command) { + b = scp->device->channel; t = scp->device->id; if (t == (unchar)id && b == (unchar)busnum) { TRACE2(("gdth_stop_timeout(): update_timeout()\n")); - scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); + cmndinfo->timeout = gdth_update_timeout(scp, 0); } } } spin_unlock_irqrestore(&ha->smp_lock, flags); } -static void gdth_start_timeout(int hanum, int busnum, int id) +static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id) { - gdth_ha_str *ha; ulong flags; Scsi_Cmnd *scp; unchar b, t; - ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); for (scp = ha->req_first; scp; scp = (Scsi_Cmnd *)scp->SCp.ptr) { - if (scp->done != gdth_scsi_done) { - b = virt_ctr ? - NUMDATA(scp->device->host)->busnum : scp->device->channel; + struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); + if (!cmndinfo->internal_command) { + b = scp->device->channel; t = scp->device->id; if (t == (unchar)id && b == (unchar)busnum) { TRACE2(("gdth_start_timeout(): update_timeout()\n")); - gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); + gdth_update_timeout(scp, cmndinfo->timeout); } } } spin_unlock_irqrestore(&ha->smp_lock, flags); } -static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout) +static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout) { int oldto; diff --git a/drivers/scsi/gdth_proc.h b/drivers/scsi/gdth_proc.h index a679eeb6820b..45e6fdacf36e 100644 --- a/drivers/scsi/gdth_proc.h +++ b/drivers/scsi/gdth_proc.h @@ -9,20 +9,20 @@ int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, int timeout, u32 *info); static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, - int hanum,int busnum); + gdth_ha_str *ha); static int gdth_get_info(char *buffer,char **start,off_t offset,int length, - struct Scsi_Host *host,int hanum,int busnum); + struct Scsi_Host *host, gdth_ha_str *ha); static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, - int length, int hanum); + int length, gdth_ha_str *ha); -static char *gdth_ioctl_alloc(int hanum, int size, int scratch, - ulong64 *paddr); -static void gdth_ioctl_free(int hanum, int size, char *buf, ulong64 paddr); -static void gdth_wait_completion(int hanum, int busnum, int id); -static void gdth_stop_timeout(int hanum, int busnum, int id); -static void gdth_start_timeout(int hanum, int busnum, int id); -static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout); +static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, + ulong64 *paddr); +static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr); +static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id); +static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id); +static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id); +static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout); #endif diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c index 96bc31266c98..adc9559cb6f4 100644 --- a/drivers/scsi/hosts.c +++ b/drivers/scsi/hosts.c @@ -342,6 +342,7 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize) shost->unchecked_isa_dma = sht->unchecked_isa_dma; shost->use_clustering = sht->use_clustering; shost->ordered_tag = sht->ordered_tag; + shost->active_mode = sht->supported_mode; if (sht->max_host_blocked) shost->max_host_blocked = sht->max_host_blocked; diff --git a/drivers/scsi/hptiop.c b/drivers/scsi/hptiop.c index 0e579ca45814..8b384fa7f048 100644 --- a/drivers/scsi/hptiop.c +++ b/drivers/scsi/hptiop.c @@ -1,6 +1,6 @@ /* * HighPoint RR3xxx controller driver for Linux - * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -42,7 +42,7 @@ MODULE_DESCRIPTION("HighPoint RocketRAID 3xxx SATA Controller Driver"); static char driver_name[] = "hptiop"; static const char driver_name_long[] = "RocketRAID 3xxx SATA Controller driver"; -static const char driver_ver[] = "v1.0 (060426)"; +static const char driver_ver[] = "v1.2 (070830)"; static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag); static void hptiop_iop_request_callback(struct hptiop_hba *hba, u32 tag); @@ -76,7 +76,7 @@ static int iop_wait_ready(struct hpt_iopmu __iomem *iop, u32 millisec) static void hptiop_request_callback(struct hptiop_hba *hba, u32 tag) { - if ((tag & IOPMU_QUEUE_MASK_HOST_BITS) == IOPMU_QUEUE_ADDR_HOST_BIT) + if (tag & IOPMU_QUEUE_ADDR_HOST_BIT) return hptiop_host_request_callback(hba, tag & ~IOPMU_QUEUE_ADDR_HOST_BIT); else @@ -323,12 +323,22 @@ static inline void free_req(struct hptiop_hba *hba, struct hptiop_request *req) hba->req_list = req; } -static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 tag) +static void hptiop_host_request_callback(struct hptiop_hba *hba, u32 _tag) { struct hpt_iop_request_scsi_command *req; struct scsi_cmnd *scp; + u32 tag; + + if (hba->iopintf_v2) { + tag = _tag & ~ IOPMU_QUEUE_REQUEST_RESULT_BIT; + req = hba->reqs[tag].req_virt; + if (likely(_tag & IOPMU_QUEUE_REQUEST_RESULT_BIT)) + req->header.result = IOP_RESULT_SUCCESS; + } else { + tag = _tag; + req = hba->reqs[tag].req_virt; + } - req = (struct hpt_iop_request_scsi_command *)hba->reqs[tag].req_virt; dprintk("hptiop_host_request_callback: req=%p, type=%d, " "result=%d, context=0x%x tag=%d\n", req, req->header.type, req->header.result, @@ -497,7 +507,7 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, goto cmd_done; } - req = (struct hpt_iop_request_scsi_command *)_req->req_virt; + req = _req->req_virt; /* build S/G table */ sg_count = hptiop_buildsgl(scp, req->sg_list); @@ -521,8 +531,19 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, memcpy(req->cdb, scp->cmnd, sizeof(req->cdb)); - writel(IOPMU_QUEUE_ADDR_HOST_BIT | _req->req_shifted_phy, - &hba->iop->inbound_queue); + if (hba->iopintf_v2) { + u32 size_bits; + if (req->header.size < 256) + size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT; + else if (req->header.size < 512) + size_bits = IOPMU_QUEUE_ADDR_HOST_BIT; + else + size_bits = IOPMU_QUEUE_REQUEST_SIZE_BIT | + IOPMU_QUEUE_ADDR_HOST_BIT; + writel(_req->req_shifted_phy | size_bits, &hba->iop->inbound_queue); + } else + writel(_req->req_shifted_phy | IOPMU_QUEUE_ADDR_HOST_BIT, + &hba->iop->inbound_queue); return 0; @@ -688,6 +709,7 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, hba->pcidev = pcidev; hba->host = host; hba->initialized = 0; + hba->iopintf_v2 = 0; atomic_set(&hba->resetting, 0); atomic_set(&hba->reset_count, 0); @@ -722,8 +744,13 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, hba->max_request_size = le32_to_cpu(iop_config.request_size); hba->max_sg_descriptors = le32_to_cpu(iop_config.max_sg_count); hba->firmware_version = le32_to_cpu(iop_config.firmware_version); + hba->interface_version = le32_to_cpu(iop_config.interface_version); hba->sdram_size = le32_to_cpu(iop_config.sdram_size); + if (hba->firmware_version > 0x01020000 || + hba->interface_version > 0x01020000) + hba->iopintf_v2 = 1; + host->max_sectors = le32_to_cpu(iop_config.data_transfer_length) >> 9; host->max_id = le32_to_cpu(iop_config.max_devices); host->sg_tablesize = le32_to_cpu(iop_config.max_sg_count); @@ -731,8 +758,15 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, host->cmd_per_lun = le32_to_cpu(iop_config.max_requests); host->max_cmd_len = 16; - set_config.vbus_id = cpu_to_le32(host->host_no); + req_size = sizeof(struct hpt_iop_request_scsi_command) + + sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1); + if ((req_size & 0x1f) != 0) + req_size = (req_size + 0x1f) & ~0x1f; + + memset(&set_config, 0, sizeof(struct hpt_iop_request_set_config)); set_config.iop_id = cpu_to_le32(host->host_no); + set_config.vbus_id = cpu_to_le16(host->host_no); + set_config.max_host_request_size = cpu_to_le16(req_size); if (iop_set_config(hba, &set_config)) { printk(KERN_ERR "scsi%d: set config failed\n", @@ -750,10 +784,6 @@ static int __devinit hptiop_probe(struct pci_dev *pcidev, } /* Allocate request mem */ - req_size = sizeof(struct hpt_iop_request_scsi_command) - + sizeof(struct hpt_iopsg) * (hba->max_sg_descriptors - 1); - if ((req_size& 0x1f) != 0) - req_size = (req_size + 0x1f) & ~0x1f; dprintk("req_size=%d, max_requests=%d\n", req_size, hba->max_requests); @@ -879,8 +909,10 @@ static void hptiop_remove(struct pci_dev *pcidev) } static struct pci_device_id hptiop_id_table[] = { - { PCI_DEVICE(0x1103, 0x3220) }, - { PCI_DEVICE(0x1103, 0x3320) }, + { PCI_VDEVICE(TTI, 0x3220) }, + { PCI_VDEVICE(TTI, 0x3320) }, + { PCI_VDEVICE(TTI, 0x3520) }, + { PCI_VDEVICE(TTI, 0x4320) }, {}, }; @@ -910,3 +942,4 @@ module_init(hptiop_module_init); module_exit(hptiop_module_exit); MODULE_LICENSE("GPL"); + diff --git a/drivers/scsi/hptiop.h b/drivers/scsi/hptiop.h index f04f7e81d1ae..2a5e46e001cb 100644 --- a/drivers/scsi/hptiop.h +++ b/drivers/scsi/hptiop.h @@ -1,6 +1,6 @@ /* * HighPoint RR3xxx controller driver for Linux - * Copyright (C) 2006 HighPoint Technologies, Inc. All Rights Reserved. + * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,219 +18,6 @@ #ifndef _HPTIOP_H_ #define _HPTIOP_H_ -/* - * logical device type. - * Identify array (logical device) and physical device. - */ -#define LDT_ARRAY 1 -#define LDT_DEVICE 2 - -/* - * Array types - */ -#define AT_UNKNOWN 0 -#define AT_RAID0 1 -#define AT_RAID1 2 -#define AT_RAID5 3 -#define AT_RAID6 4 -#define AT_JBOD 7 - -#define MAX_NAME_LENGTH 36 -#define MAX_ARRAYNAME_LEN 16 - -#define MAX_ARRAY_MEMBERS_V1 8 -#define MAX_ARRAY_MEMBERS_V2 16 - -/* keep definition for source code compatiblity */ -#define MAX_ARRAY_MEMBERS MAX_ARRAY_MEMBERS_V1 - -/* - * array flags - */ -#define ARRAY_FLAG_DISABLED 0x00000001 /* The array is disabled */ -#define ARRAY_FLAG_NEEDBUILDING 0x00000002 /* need to be rebuilt */ -#define ARRAY_FLAG_REBUILDING 0x00000004 /* in rebuilding process */ -#define ARRAY_FLAG_BROKEN 0x00000008 /* broken but still working */ -#define ARRAY_FLAG_BOOTDISK 0x00000010 /* has a active partition */ -#define ARRAY_FLAG_BOOTMARK 0x00000040 /* array has boot mark set */ -#define ARRAY_FLAG_NEED_AUTOREBUILD 0x00000080 /* auto-rebuild should start */ -#define ARRAY_FLAG_VERIFYING 0x00000100 /* is being verified */ -#define ARRAY_FLAG_INITIALIZING 0x00000200 /* is being initialized */ -#define ARRAY_FLAG_TRANSFORMING 0x00000400 /* tranform in progress */ -#define ARRAY_FLAG_NEEDTRANSFORM 0x00000800 /* array need tranform */ -#define ARRAY_FLAG_NEEDINITIALIZING 0x00001000 /* initialization not done */ -#define ARRAY_FLAG_BROKEN_REDUNDANT 0x00002000 /* broken but redundant */ - -/* - * device flags - */ -#define DEVICE_FLAG_DISABLED 0x00000001 /* device is disabled */ -#define DEVICE_FLAG_UNINITIALIZED 0x00010000 /* device is not initialized */ -#define DEVICE_FLAG_LEGACY 0x00020000 /* lagacy drive */ -#define DEVICE_FLAG_IS_SPARE 0x80000000 /* is a spare disk */ - -/* - * ioctl codes - */ -#define HPT_CTL_CODE(x) (x+0xFF00) -#define HPT_CTL_CODE_LINUX_TO_IOP(x) ((x)-0xff00) - -#define HPT_IOCTL_GET_CONTROLLER_INFO HPT_CTL_CODE(2) -#define HPT_IOCTL_GET_CHANNEL_INFO HPT_CTL_CODE(3) -#define HPT_IOCTL_GET_LOGICAL_DEVICES HPT_CTL_CODE(4) -#define HPT_IOCTL_GET_DRIVER_CAPABILITIES HPT_CTL_CODE(19) -#define HPT_IOCTL_GET_DEVICE_INFO_V3 HPT_CTL_CODE(46) -#define HPT_IOCTL_GET_CONTROLLER_INFO_V2 HPT_CTL_CODE(47) - -/* - * Controller information. - */ -struct hpt_controller_info { - u8 chip_type; /* chip type */ - u8 interrupt_level; /* IRQ level */ - u8 num_buses; /* bus count */ - u8 chip_flags; - - u8 product_id[MAX_NAME_LENGTH];/* product name */ - u8 vendor_id[MAX_NAME_LENGTH]; /* vendor name */ -} -__attribute__((packed)); - -/* - * Channel information. - */ -struct hpt_channel_info { - __le32 io_port; /* IDE Base Port Address */ - __le32 control_port; /* IDE Control Port Address */ - __le32 devices[2]; /* device connected to this channel */ -} -__attribute__((packed)); - -/* - * Array information. - */ -struct hpt_array_info_v3 { - u8 name[MAX_ARRAYNAME_LEN]; /* array name */ - u8 description[64]; /* array description */ - u8 create_manager[16]; /* who created it */ - __le32 create_time; /* when created it */ - - u8 array_type; /* array type */ - u8 block_size_shift; /* stripe size */ - u8 ndisk; /* Number of ID in Members[] */ - u8 reserved; - - __le32 flags; /* working flags, see ARRAY_FLAG_XXX */ - __le32 members[MAX_ARRAY_MEMBERS_V2]; /* member array/disks */ - - __le32 rebuilding_progress; - __le64 rebuilt_sectors; /* rebuilding point (LBA) for single member */ - - __le32 transform_source; - __le32 transform_target; /* destination device ID */ - __le32 transforming_progress; - __le32 signature; /* persistent identification*/ - __le16 critical_members; /* bit mask of critical members */ - __le16 reserve2; - __le32 reserve; -} -__attribute__((packed)); - -/* - * physical device information. - */ -#define MAX_PARENTS_PER_DISK 8 - -struct hpt_device_info_v2 { - u8 ctlr_id; /* controller id */ - u8 path_id; /* bus */ - u8 target_id; /* id */ - u8 device_mode_setting; /* Current Data Transfer mode: 0-4 PIO0-4 */ - /* 5-7 MW DMA0-2, 8-13 UDMA0-5 */ - u8 device_type; /* device type */ - u8 usable_mode; /* highest usable mode */ - -#ifdef __BIG_ENDIAN_BITFIELD - u8 NCQ_enabled: 1; - u8 NCQ_supported: 1; - u8 TCQ_enabled: 1; - u8 TCQ_supported: 1; - u8 write_cache_enabled: 1; - u8 write_cache_supported: 1; - u8 read_ahead_enabled: 1; - u8 read_ahead_supported: 1; - u8 reserved6: 6; - u8 spin_up_mode: 2; -#else - u8 read_ahead_supported: 1; - u8 read_ahead_enabled: 1; - u8 write_cache_supported: 1; - u8 write_cache_enabled: 1; - u8 TCQ_supported: 1; - u8 TCQ_enabled: 1; - u8 NCQ_supported: 1; - u8 NCQ_enabled: 1; - u8 spin_up_mode: 2; - u8 reserved6: 6; -#endif - - __le32 flags; /* working flags, see DEVICE_FLAG_XXX */ - u8 ident[150]; /* (partitial) Identify Data of this device */ - - __le64 total_free; - __le64 max_free; - __le64 bad_sectors; - __le32 parent_arrays[MAX_PARENTS_PER_DISK]; -} -__attribute__((packed)); - -/* - * Logical device information. - */ -#define INVALID_TARGET_ID 0xFF -#define INVALID_BUS_ID 0xFF - -struct hpt_logical_device_info_v3 { - u8 type; /* LDT_ARRAY or LDT_DEVICE */ - u8 cache_policy; /* refer to CACHE_POLICY_xxx */ - u8 vbus_id; /* vbus sequence in vbus_list */ - u8 target_id; /* OS target id. 0xFF is invalid */ - /* OS name: DISK $VBusId_$TargetId */ - __le64 capacity; /* array capacity */ - __le32 parent_array; /* don't use this field for physical - device. use ParentArrays field in - hpt_device_info_v2 */ - /* reserved statistic fields */ - __le32 stat1; - __le32 stat2; - __le32 stat3; - __le32 stat4; - - union { - struct hpt_array_info_v3 array; - struct hpt_device_info_v2 device; - } __attribute__((packed)) u; - -} -__attribute__((packed)); - -/* - * ioctl structure - */ -#define HPT_IOCTL_MAGIC 0xA1B2C3D4 - -struct hpt_ioctl_u { - u32 magic; /* used to check if it's a valid ioctl packet */ - u32 ioctl_code; /* operation control code */ - void __user *inbuf; /* input data buffer */ - u32 inbuf_size; /* size of input data buffer */ - void __user *outbuf; /* output data buffer */ - u32 outbuf_size; /* size of output data buffer */ - void __user *bytes_returned; /* count of bytes returned */ -} -__attribute__((packed)); - - struct hpt_iopmu { __le32 resrved0[4]; @@ -252,6 +39,8 @@ struct hpt_iopmu #define IOPMU_QUEUE_EMPTY 0xffffffff #define IOPMU_QUEUE_MASK_HOST_BITS 0xf0000000 #define IOPMU_QUEUE_ADDR_HOST_BIT 0x80000000 +#define IOPMU_QUEUE_REQUEST_SIZE_BIT 0x40000000 +#define IOPMU_QUEUE_REQUEST_RESULT_BIT 0x40000000 #define IOPMU_OUTBOUND_INT_MSG0 1 #define IOPMU_OUTBOUND_INT_MSG1 2 @@ -336,7 +125,8 @@ struct hpt_iop_request_set_config { struct hpt_iop_request_header header; __le32 iop_id; - __le32 vbus_id; + __le16 vbus_id; + __le16 max_host_request_size; __le32 reserve[6]; }; @@ -412,9 +202,8 @@ struct hptiop_hba { struct Scsi_Host * host; struct pci_dev * pcidev; - struct list_head link; - /* IOP config info */ + u32 interface_version; u32 firmware_version; u32 sdram_size; u32 max_devices; @@ -423,8 +212,10 @@ struct hptiop_hba { u32 max_sg_descriptors; u32 req_size; /* host-allocated request buffer size */ - int initialized; - int msg_done; + + int iopintf_v2: 1; + int initialized: 1; + int msg_done: 1; struct hptiop_request * req_list; struct hptiop_request reqs[HPTIOP_MAX_REQUESTS]; diff --git a/drivers/scsi/ibmmca.c b/drivers/scsi/ibmmca.c index 4275d1b04ced..1a924e9b0271 100644 --- a/drivers/scsi/ibmmca.c +++ b/drivers/scsi/ibmmca.c @@ -460,13 +460,6 @@ module_param(boot_options, charp, 0); module_param_array(io_port, int, NULL, 0); module_param_array(scsi_id, int, NULL, 0); -#if 0 /* FIXME: No longer exist? --RR */ -MODULE_PARM(display, "1i"); -MODULE_PARM(adisplay, "1i"); -MODULE_PARM(normal, "1i"); -MODULE_PARM(ansi, "1i"); -#endif - MODULE_LICENSE("GPL"); #endif /*counter of concurrent disk read/writes, to turn on/off disk led */ @@ -1693,6 +1686,7 @@ static int __devexit ibmmca_remove(struct device *dev) scsi_remove_host(shpnt); release_region(shpnt->io_port, shpnt->n_io_port); free_irq(shpnt->irq, dev); + scsi_host_put(shpnt); return 0; } diff --git a/drivers/scsi/ibmvscsi/Makefile b/drivers/scsi/ibmvscsi/Makefile index f67d9efc7a99..6ac0633d5452 100644 --- a/drivers/scsi/ibmvscsi/Makefile +++ b/drivers/scsi/ibmvscsi/Makefile @@ -1,9 +1,7 @@ obj-$(CONFIG_SCSI_IBMVSCSI) += ibmvscsic.o ibmvscsic-y += ibmvscsi.o -ifndef CONFIG_PPC_PSERIES ibmvscsic-$(CONFIG_PPC_ISERIES) += iseries_vscsi.o -endif ibmvscsic-$(CONFIG_PPC_PSERIES) += rpa_vscsi.o obj-$(CONFIG_SCSI_IBMVSCSIS) += ibmvstgt.o diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 5ecc63d1b436..cda0cc3d182f 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -70,11 +70,13 @@ #include <linux/moduleparam.h> #include <linux/dma-mapping.h> #include <linux/delay.h> +#include <asm/firmware.h> #include <asm/vio.h> #include <scsi/scsi.h> #include <scsi/scsi_cmnd.h> #include <scsi/scsi_host.h> #include <scsi/scsi_device.h> +#include <scsi/scsi_transport_srp.h> #include "ibmvscsi.h" /* The values below are somewhat arbitrary default values, but @@ -87,8 +89,12 @@ static int max_channel = 3; static int init_timeout = 5; static int max_requests = IBMVSCSI_MAX_REQUESTS_DEFAULT; +static struct scsi_transport_template *ibmvscsi_transport_template; + #define IBMVSCSI_VERSION "1.5.8" +static struct ibmvscsi_ops *ibmvscsi_ops; + MODULE_DESCRIPTION("IBM Virtual SCSI"); MODULE_AUTHOR("Dave Boutcher"); MODULE_LICENSE("GPL"); @@ -506,8 +512,8 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata) atomic_set(&hostdata->request_limit, 0); purge_requests(hostdata, DID_ERROR); - if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) || - (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0)) || + if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata)) || + (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0)) || (vio_enable_interrupts(to_vio_dev(hostdata->dev)))) { atomic_set(&hostdata->request_limit, -1); dev_err(hostdata->dev, "error after reset\n"); @@ -612,7 +618,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, } if ((rc = - ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { + ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { list_del(&evt_struct->list); del_timer(&evt_struct->timer); @@ -1211,8 +1217,8 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, case 0x01: /* Initialization message */ dev_info(hostdata->dev, "partner initialized\n"); /* Send back a response */ - if ((rc = ibmvscsi_send_crq(hostdata, - 0xC002000000000000LL, 0)) == 0) { + if ((rc = ibmvscsi_ops->send_crq(hostdata, + 0xC002000000000000LL, 0)) == 0) { /* Now login */ send_srp_login(hostdata); } else { @@ -1237,10 +1243,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, /* We need to re-setup the interpartition connection */ dev_info(hostdata->dev, "Re-enabling adapter!\n"); purge_requests(hostdata, DID_REQUEUE); - if ((ibmvscsi_reenable_crq_queue(&hostdata->queue, - hostdata)) || - (ibmvscsi_send_crq(hostdata, - 0xC001000000000000LL, 0))) { + if ((ibmvscsi_ops->reenable_crq_queue(&hostdata->queue, + hostdata)) || + (ibmvscsi_ops->send_crq(hostdata, + 0xC001000000000000LL, 0))) { atomic_set(&hostdata->request_limit, -1); dev_err(hostdata->dev, "error after enable\n"); @@ -1250,10 +1256,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, crq->format); purge_requests(hostdata, DID_ERROR); - if ((ibmvscsi_reset_crq_queue(&hostdata->queue, - hostdata)) || - (ibmvscsi_send_crq(hostdata, - 0xC001000000000000LL, 0))) { + if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, + hostdata)) || + (ibmvscsi_ops->send_crq(hostdata, + 0xC001000000000000LL, 0))) { atomic_set(&hostdata->request_limit, -1); dev_err(hostdata->dev, "error after reset\n"); @@ -1553,6 +1559,8 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) struct ibmvscsi_host_data *hostdata; struct Scsi_Host *host; struct device *dev = &vdev->dev; + struct srp_rport_identifiers ids; + struct srp_rport *rport; unsigned long wait_switch = 0; int rc; @@ -1565,6 +1573,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) goto scsi_host_alloc_failed; } + host->transportt = ibmvscsi_transport_template; hostdata = shost_priv(host); memset(hostdata, 0x00, sizeof(*hostdata)); INIT_LIST_HEAD(&hostdata->sent); @@ -1573,7 +1582,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) atomic_set(&hostdata->request_limit, -1); hostdata->host->max_sectors = 32 * 8; /* default max I/O 32 pages */ - rc = ibmvscsi_init_crq_queue(&hostdata->queue, hostdata, max_requests); + rc = ibmvscsi_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests); if (rc != 0 && rc != H_RESOURCE) { dev_err(&vdev->dev, "couldn't initialize crq. rc=%d\n", rc); goto init_crq_failed; @@ -1590,11 +1599,19 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) if (scsi_add_host(hostdata->host, hostdata->dev)) goto add_host_failed; + /* we don't have a proper target_port_id so let's use the fake one */ + memcpy(ids.port_id, hostdata->madapter_info.partition_name, + sizeof(ids.port_id)); + ids.roles = SRP_RPORT_ROLE_TARGET; + rport = srp_rport_add(host, &ids); + if (IS_ERR(rport)) + goto add_srp_port_failed; + /* Try to send an initialization message. Note that this is allowed * to fail if the other end is not acive. In that case we don't * want to scan */ - if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0 + if (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0 || rc == H_RESOURCE) { /* * Wait around max init_timeout secs for the adapter to finish @@ -1617,10 +1634,12 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id) vdev->dev.driver_data = hostdata; return 0; + add_srp_port_failed: + scsi_remove_host(hostdata->host); add_host_failed: release_event_pool(&hostdata->pool, hostdata); init_pool_failed: - ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests); + ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests); init_crq_failed: scsi_host_put(host); scsi_host_alloc_failed: @@ -1631,9 +1650,10 @@ static int ibmvscsi_remove(struct vio_dev *vdev) { struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data; release_event_pool(&hostdata->pool, hostdata); - ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, - max_requests); - + ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, + max_requests); + + srp_remove_host(hostdata->host); scsi_remove_host(hostdata->host); scsi_host_put(hostdata->host); @@ -1660,14 +1680,35 @@ static struct vio_driver ibmvscsi_driver = { } }; +static struct srp_function_template ibmvscsi_transport_functions = { +}; + int __init ibmvscsi_module_init(void) { - return vio_register_driver(&ibmvscsi_driver); + int ret; + + if (firmware_has_feature(FW_FEATURE_ISERIES)) + ibmvscsi_ops = &iseriesvscsi_ops; + else if (firmware_has_feature(FW_FEATURE_VIO)) + ibmvscsi_ops = &rpavscsi_ops; + else + return -ENODEV; + + ibmvscsi_transport_template = + srp_attach_transport(&ibmvscsi_transport_functions); + if (!ibmvscsi_transport_template) + return -ENOMEM; + + ret = vio_register_driver(&ibmvscsi_driver); + if (ret) + srp_release_transport(ibmvscsi_transport_template); + return ret; } void __exit ibmvscsi_module_exit(void) { vio_unregister_driver(&ibmvscsi_driver); + srp_release_transport(ibmvscsi_transport_template); } module_init(ibmvscsi_module_init); diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.h b/drivers/scsi/ibmvscsi/ibmvscsi.h index b19c2e26c2a5..46e850e302c7 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/drivers/scsi/ibmvscsi/ibmvscsi.h @@ -98,21 +98,25 @@ struct ibmvscsi_host_data { }; /* routines for managing a command/response queue */ -int ibmvscsi_init_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata, - int max_requests); -void ibmvscsi_release_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata, - int max_requests); -int ibmvscsi_reset_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata); - -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata); - void ibmvscsi_handle_crq(struct viosrp_crq *crq, struct ibmvscsi_host_data *hostdata); -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, - u64 word1, u64 word2); + +struct ibmvscsi_ops { + int (*init_crq_queue)(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata, + int max_requests); + void (*release_crq_queue)(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata, + int max_requests); + int (*reset_crq_queue)(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata); + int (*reenable_crq_queue)(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata); + int (*send_crq)(struct ibmvscsi_host_data *hostdata, + u64 word1, u64 word2); +}; + +extern struct ibmvscsi_ops iseriesvscsi_ops; +extern struct ibmvscsi_ops rpavscsi_ops; #endif /* IBMVSCSI_H */ diff --git a/drivers/scsi/ibmvscsi/ibmvstgt.c b/drivers/scsi/ibmvscsi/ibmvstgt.c index 8ba7dd09d01d..82bcab688b44 100644 --- a/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -25,6 +25,7 @@ #include <linux/module.h> #include <scsi/scsi.h> #include <scsi/scsi_host.h> +#include <scsi/scsi_transport_srp.h> #include <scsi/scsi_tgt.h> #include <scsi/libsrp.h> #include <asm/hvcall.h> @@ -68,9 +69,12 @@ struct vio_port { unsigned long liobn; unsigned long riobn; struct srp_target *target; + + struct srp_rport *rport; }; static struct workqueue_struct *vtgtd; +static struct scsi_transport_template *ibmvstgt_transport_template; /* * These are fixed for the system and come from the Open Firmware device tree. @@ -188,6 +192,7 @@ static int send_rsp(struct iu_entry *iue, struct scsi_cmnd *sc, static void handle_cmd_queue(struct srp_target *target) { struct Scsi_Host *shost = target->shost; + struct srp_rport *rport = target_to_port(target)->rport; struct iu_entry *iue; struct srp_cmd *cmd; unsigned long flags; @@ -200,7 +205,8 @@ retry: if (!test_and_set_bit(V_FLYING, &iue->flags)) { spin_unlock_irqrestore(&target->lock, flags); cmd = iue->sbuf->buf; - err = srp_cmd_queue(shost, cmd, iue, 0); + err = srp_cmd_queue(shost, cmd, iue, + (unsigned long)rport, 0); if (err) { eprintk("cannot queue cmd %p %d\n", cmd, err); srp_iu_put(iue); @@ -359,6 +365,16 @@ static void process_login(struct iu_entry *iue) union viosrp_iu *iu = vio_iu(iue); struct srp_login_rsp *rsp = &iu->srp.login_rsp; uint64_t tag = iu->srp.rsp.tag; + struct Scsi_Host *shost = iue->target->shost; + struct srp_target *target = host_to_srp_target(shost); + struct vio_port *vport = target_to_port(target); + struct srp_rport_identifiers ids; + + memset(&ids, 0, sizeof(ids)); + sprintf(ids.port_id, "%x", vport->dma_dev->unit_address); + ids.roles = SRP_RPORT_ROLE_INITIATOR; + if (!vport->rport) + vport->rport = srp_rport_add(shost, &ids); /* TODO handle case that requested size is wrong and * buffer format is wrong @@ -412,7 +428,9 @@ static int process_tsk_mgmt(struct iu_entry *iue) fn = 0; } if (fn) - scsi_tgt_tsk_mgmt_request(iue->target->shost, fn, + scsi_tgt_tsk_mgmt_request(iue->target->shost, + (unsigned long)iue->target->shost, + fn, iu->srp.tsk_mgmt.task_tag, (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, iue); @@ -721,7 +739,8 @@ static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) return 0; } -static int ibmvstgt_tsk_mgmt_response(u64 mid, int result) +static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost, + u64 itn_id, u64 mid, int result) { struct iu_entry *iue = (struct iu_entry *) ((void *) mid); union viosrp_iu *iu = vio_iu(iue); @@ -747,6 +766,20 @@ static int ibmvstgt_tsk_mgmt_response(u64 mid, int result) return 0; } +static int ibmvstgt_it_nexus_response(struct Scsi_Host *shost, u64 itn_id, + int result) +{ + struct srp_target *target = host_to_srp_target(shost); + struct vio_port *vport = target_to_port(target); + + if (result) { + eprintk("%p %d\n", shost, result); + srp_rport_del(vport->rport); + vport->rport = NULL; + } + return 0; +} + static ssize_t system_id_show(struct class_device *cdev, char *buf) { return snprintf(buf, PAGE_SIZE, "%s\n", system_id); @@ -785,9 +818,9 @@ static struct scsi_host_template ibmvstgt_sht = { .max_sectors = DEFAULT_MAX_SECTORS, .transfer_response = ibmvstgt_cmd_done, .eh_abort_handler = ibmvstgt_eh_abort_handler, - .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, .shost_attrs = ibmvstgt_attrs, .proc_name = TGT_NAME, + .supported_mode = MODE_TARGET, }; static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) @@ -804,6 +837,7 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) shost = scsi_host_alloc(&ibmvstgt_sht, sizeof(struct srp_target)); if (!shost) goto free_vport; + shost->transportt = ibmvstgt_transport_template; err = scsi_tgt_alloc_queue(shost); if (err) goto put_host; @@ -837,8 +871,8 @@ static int ibmvstgt_probe(struct vio_dev *dev, const struct vio_device_id *id) err = scsi_add_host(shost, target->dev); if (err) goto destroy_queue; - return 0; + return 0; destroy_queue: crq_queue_destroy(target); free_srp_target: @@ -857,6 +891,7 @@ static int ibmvstgt_remove(struct vio_dev *dev) struct vio_port *vport = target->ldata; crq_queue_destroy(target); + srp_remove_host(shost); scsi_remove_host(shost); scsi_tgt_free_queue(shost); srp_target_free(target); @@ -909,15 +944,25 @@ static int get_system_info(void) return 0; } +static struct srp_function_template ibmvstgt_transport_functions = { + .tsk_mgmt_response = ibmvstgt_tsk_mgmt_response, + .it_nexus_response = ibmvstgt_it_nexus_response, +}; + static int ibmvstgt_init(void) { int err = -ENOMEM; printk("IBM eServer i/pSeries Virtual SCSI Target Driver\n"); + ibmvstgt_transport_template = + srp_attach_transport(&ibmvstgt_transport_functions); + if (!ibmvstgt_transport_template) + return err; + vtgtd = create_workqueue("ibmvtgtd"); if (!vtgtd) - return err; + goto release_transport; err = get_system_info(); if (err) @@ -928,9 +973,10 @@ static int ibmvstgt_init(void) goto destroy_wq; return 0; - destroy_wq: destroy_workqueue(vtgtd); +release_transport: + srp_release_transport(ibmvstgt_transport_template); return err; } @@ -940,6 +986,7 @@ static void ibmvstgt_exit(void) destroy_workqueue(vtgtd); vio_unregister_driver(&ibmvstgt_driver); + srp_release_transport(ibmvstgt_transport_template); } MODULE_DESCRIPTION("IBM Virtual SCSI Target"); diff --git a/drivers/scsi/ibmvscsi/iseries_vscsi.c b/drivers/scsi/ibmvscsi/iseries_vscsi.c index 6aeb5f003c3c..0775fdee5fa8 100644 --- a/drivers/scsi/ibmvscsi/iseries_vscsi.c +++ b/drivers/scsi/ibmvscsi/iseries_vscsi.c @@ -53,7 +53,7 @@ struct srp_lp_event { /** * standard interface for handling logical partition events. */ -static void ibmvscsi_handle_event(struct HvLpEvent *lpevt) +static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt) { struct srp_lp_event *evt = (struct srp_lp_event *)lpevt; @@ -74,9 +74,9 @@ static void ibmvscsi_handle_event(struct HvLpEvent *lpevt) /* ------------------------------------------------------------ * Routines for driver initialization */ -int ibmvscsi_init_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata, - int max_requests) +static int iseriesvscsi_init_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata, + int max_requests) { int rc; @@ -88,7 +88,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, goto viopath_open_failed; } - rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event); + rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event); if (rc < 0) { printk("vio_setHandler failed with rc %d in open_event_path\n", rc); @@ -102,9 +102,9 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, return -1; } -void ibmvscsi_release_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata, - int max_requests) +static void iseriesvscsi_release_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata, + int max_requests) { vio_clearHandler(viomajorsubtype_scsi); viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests); @@ -117,8 +117,8 @@ void ibmvscsi_release_crq_queue(struct crq_queue *queue, * * no-op for iSeries */ -int ibmvscsi_reset_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata) +static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata) { return 0; } @@ -130,19 +130,20 @@ int ibmvscsi_reset_crq_queue(struct crq_queue *queue, * * no-op for iSeries */ -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata) +static int iseriesvscsi_reenable_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata) { return 0; } /** - * ibmvscsi_send_crq: - Send a CRQ + * iseriesvscsi_send_crq: - Send a CRQ * @hostdata: the adapter * @word1: the first 64 bits of the data * @word2: the second 64 bits of the data */ -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2) +static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata, + u64 word1, u64 word2) { single_host_data = hostdata; return HvCallEvent_signalLpEventFast(viopath_hostLp, @@ -156,3 +157,11 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2) VIOVERSION << 16, word1, word2, 0, 0); } + +struct ibmvscsi_ops iseriesvscsi_ops = { + .init_crq_queue = iseriesvscsi_init_crq_queue, + .release_crq_queue = iseriesvscsi_release_crq_queue, + .reset_crq_queue = iseriesvscsi_reset_crq_queue, + .reenable_crq_queue = iseriesvscsi_reenable_crq_queue, + .send_crq = iseriesvscsi_send_crq, +}; diff --git a/drivers/scsi/ibmvscsi/rpa_vscsi.c b/drivers/scsi/ibmvscsi/rpa_vscsi.c index 9c14e789df5f..182146100dc1 100644 --- a/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -42,14 +42,14 @@ static unsigned int partition_number = -1; * Routines for managing the command/response queue */ /** - * ibmvscsi_handle_event: - Interrupt handler for crq events + * rpavscsi_handle_event: - Interrupt handler for crq events * @irq: number of irq to handle, not used * @dev_instance: ibmvscsi_host_data of host that received interrupt * * Disables interrupts and schedules srp_task * Always returns IRQ_HANDLED */ -static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance) +static irqreturn_t rpavscsi_handle_event(int irq, void *dev_instance) { struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)dev_instance; @@ -66,9 +66,9 @@ static irqreturn_t ibmvscsi_handle_event(int irq, void *dev_instance) * Frees irq, deallocates a page for messages, unmaps dma, and unregisters * the crq with the hypervisor. */ -void ibmvscsi_release_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata, - int max_requests) +static void rpavscsi_release_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata, + int max_requests) { long rc; struct vio_dev *vdev = to_vio_dev(hostdata->dev); @@ -108,12 +108,13 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue) } /** - * ibmvscsi_send_crq: - Send a CRQ + * rpavscsi_send_crq: - Send a CRQ * @hostdata: the adapter * @word1: the first 64 bits of the data * @word2: the second 64 bits of the data */ -int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2) +static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata, + u64 word1, u64 word2) { struct vio_dev *vdev = to_vio_dev(hostdata->dev); @@ -121,10 +122,10 @@ int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2) } /** - * ibmvscsi_task: - Process srps asynchronously + * rpavscsi_task: - Process srps asynchronously * @data: ibmvscsi_host_data of host */ -static void ibmvscsi_task(void *data) +static void rpavscsi_task(void *data) { struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data; struct vio_dev *vdev = to_vio_dev(hostdata->dev); @@ -190,6 +191,42 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata) } /** + * reset_crq_queue: - resets a crq after a failure + * @queue: crq_queue to initialize and register + * @hostdata: ibmvscsi_host_data of host + * + */ +static int rpavscsi_reset_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata) +{ + int rc; + struct vio_dev *vdev = to_vio_dev(hostdata->dev); + + /* Close the CRQ */ + do { + rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); + } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); + + /* Clean out the queue */ + memset(queue->msgs, 0x00, PAGE_SIZE); + queue->cur = 0; + + set_adapter_info(hostdata); + + /* And re-open it again */ + rc = plpar_hcall_norets(H_REG_CRQ, + vdev->unit_address, + queue->msg_token, PAGE_SIZE); + if (rc == 2) { + /* Adapter is good, but other end is not ready */ + dev_warn(hostdata->dev, "Partner adapter not ready\n"); + } else if (rc != 0) { + dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc); + } + return rc; +} + +/** * initialize_crq_queue: - Initializes and registers CRQ with hypervisor * @queue: crq_queue to initialize and register * @hostdata: ibmvscsi_host_data of host @@ -198,9 +235,9 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata) * the crq with the hypervisor. * Returns zero on success. */ -int ibmvscsi_init_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata, - int max_requests) +static int rpavscsi_init_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata, + int max_requests) { int rc; int retrc; @@ -227,7 +264,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, queue->msg_token, PAGE_SIZE); if (rc == H_RESOURCE) /* maybe kexecing and resource is busy. try a reset */ - rc = ibmvscsi_reset_crq_queue(queue, + rc = rpavscsi_reset_crq_queue(queue, hostdata); if (rc == 2) { @@ -240,7 +277,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, } if (request_irq(vdev->irq, - ibmvscsi_handle_event, + rpavscsi_handle_event, 0, "ibmvscsi", (void *)hostdata) != 0) { dev_err(hostdata->dev, "couldn't register irq 0x%x\n", vdev->irq); @@ -256,7 +293,7 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, queue->cur = 0; spin_lock_init(&queue->lock); - tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task, + tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task, (unsigned long)hostdata); return retrc; @@ -281,8 +318,8 @@ int ibmvscsi_init_crq_queue(struct crq_queue *queue, * @hostdata: ibmvscsi_host_data of host * */ -int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata) +static int rpavscsi_reenable_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata) { int rc; struct vio_dev *vdev = to_vio_dev(hostdata->dev); @@ -297,38 +334,10 @@ int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, return rc; } -/** - * reset_crq_queue: - resets a crq after a failure - * @queue: crq_queue to initialize and register - * @hostdata: ibmvscsi_host_data of host - * - */ -int ibmvscsi_reset_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata) -{ - int rc; - struct vio_dev *vdev = to_vio_dev(hostdata->dev); - - /* Close the CRQ */ - do { - rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); - } while ((rc == H_BUSY) || (H_IS_LONG_BUSY(rc))); - - /* Clean out the queue */ - memset(queue->msgs, 0x00, PAGE_SIZE); - queue->cur = 0; - - set_adapter_info(hostdata); - - /* And re-open it again */ - rc = plpar_hcall_norets(H_REG_CRQ, - vdev->unit_address, - queue->msg_token, PAGE_SIZE); - if (rc == 2) { - /* Adapter is good, but other end is not ready */ - dev_warn(hostdata->dev, "Partner adapter not ready\n"); - } else if (rc != 0) { - dev_warn(hostdata->dev, "couldn't register crq--rc 0x%x\n", rc); - } - return rc; -} +struct ibmvscsi_ops rpavscsi_ops = { + .init_crq_queue = rpavscsi_init_crq_queue, + .release_crq_queue = rpavscsi_release_crq_queue, + .reset_crq_queue = rpavscsi_reset_crq_queue, + .reenable_crq_queue = rpavscsi_reenable_crq_queue, + .send_crq = rpavscsi_send_crq, +}; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index 1cc01acc2808..d81bb076a15a 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -82,14 +82,12 @@ typedef struct idescsi_pc_s { */ #define PC_DMA_IN_PROGRESS 0 /* 1 while DMA in progress */ #define PC_WRITING 1 /* Data direction */ -#define PC_TRANSFORM 2 /* transform SCSI commands */ #define PC_TIMEDOUT 3 /* command timed out */ #define PC_DMA_OK 4 /* Use DMA */ /* * SCSI command transformation layer */ -#define IDESCSI_TRANSFORM 0 /* Enable/Disable transformation */ #define IDESCSI_SG_TRANSFORM 1 /* /dev/sg transformation */ /* @@ -175,7 +173,8 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne char *buf; while (bcount) { - if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) { + if (pc->sg - scsi_sglist(pc->scsi_cmd) > + scsi_sg_count(pc->scsi_cmd)) { printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); idescsi_discard_data (drive, bcount); return; @@ -210,7 +209,8 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign char *buf; while (bcount) { - if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) { + if (pc->sg - scsi_sglist(pc->scsi_cmd) > + scsi_sg_count(pc->scsi_cmd)) { printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); idescsi_output_zeros (drive, bcount); return; @@ -239,77 +239,6 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign } } -/* - * Most of the SCSI commands are supported directly by ATAPI devices. - * idescsi_transform_pc handles the few exceptions. - */ -static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc) -{ - u8 *c = pc->c, *scsi_buf = pc->buffer, *sc = pc->scsi_cmd->cmnd; - char *atapi_buf; - - if (!test_bit(PC_TRANSFORM, &pc->flags)) - return; - if (drive->media == ide_cdrom || drive->media == ide_optical) { - if (c[0] == READ_6 || c[0] == WRITE_6) { - c[8] = c[4]; c[5] = c[3]; c[4] = c[2]; - c[3] = c[1] & 0x1f; c[2] = 0; c[1] &= 0xe0; - c[0] += (READ_10 - READ_6); - } - if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) { - unsigned short new_len; - if (!scsi_buf) - return; - if ((atapi_buf = kmalloc(pc->buffer_size + 4, GFP_ATOMIC)) == NULL) - return; - memset(atapi_buf, 0, pc->buffer_size + 4); - memset (c, 0, 12); - c[0] = sc[0] | 0x40; - c[1] = sc[1]; - c[2] = sc[2]; - new_len = sc[4] + 4; - c[8] = new_len; - c[7] = new_len >> 8; - c[9] = sc[5]; - if (c[0] == MODE_SELECT_10) { - atapi_buf[1] = scsi_buf[0]; /* Mode data length */ - atapi_buf[2] = scsi_buf[1]; /* Medium type */ - atapi_buf[3] = scsi_buf[2]; /* Device specific parameter */ - atapi_buf[7] = scsi_buf[3]; /* Block descriptor length */ - memcpy(atapi_buf + 8, scsi_buf + 4, pc->buffer_size - 4); - } - pc->buffer = atapi_buf; - pc->request_transfer += 4; - pc->buffer_size += 4; - } - } -} - -static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc) -{ - u8 *atapi_buf = pc->buffer; - u8 *sc = pc->scsi_cmd->cmnd; - u8 *scsi_buf = pc->scsi_cmd->request_buffer; - - if (!test_bit(PC_TRANSFORM, &pc->flags)) - return; - if (drive->media == ide_cdrom || drive->media == ide_optical) { - if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) { - scsi_buf[0] = atapi_buf[1]; /* Mode data length */ - scsi_buf[1] = atapi_buf[2]; /* Medium type */ - scsi_buf[2] = atapi_buf[3]; /* Device specific parameter */ - scsi_buf[3] = atapi_buf[7]; /* Block descriptor length */ - memcpy(scsi_buf + 4, atapi_buf + 8, pc->request_transfer - 8); - } - if (pc->c[0] == INQUIRY) { - scsi_buf[2] |= 2; /* ansi_revision */ - scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2; /* response data format */ - } - } - if (atapi_buf && atapi_buf != scsi_buf) - kfree(atapi_buf); -} - static void hexdump(u8 *x, int len) { int i; @@ -393,7 +322,6 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) idescsi_pc_t *pc = (idescsi_pc_t *) rq->special; int log = test_bit(IDESCSI_LOG_CMD, &scsi->log); struct Scsi_Host *host; - u8 *scsi_buf; int errors = rq->errors; unsigned long flags; @@ -434,15 +362,6 @@ static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs) pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16); } else { pc->scsi_cmd->result = DID_OK << 16; - idescsi_transform_pc2 (drive, pc); - if (log) { - printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number); - if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) { - printk(", rst = "); - scsi_buf = pc->scsi_cmd->request_buffer; - hexdump(scsi_buf, min_t(unsigned, 16, pc->scsi_cmd->request_bufflen)); - } else printk("\n"); - } } host = pc->scsi_cmd->device->host; spin_lock_irqsave(host->host_lock, flags); @@ -637,19 +556,14 @@ static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc) return 1; sg = hwif->sg_table; - scsi_sg = pc->scsi_cmd->request_buffer; - segments = pc->scsi_cmd->use_sg; + scsi_sg = scsi_sglist(pc->scsi_cmd); + segments = scsi_sg_count(pc->scsi_cmd); if (segments > hwif->sg_max_nents) return 1; - if (!segments) { - hwif->sg_nents = 1; - sg_init_one(sg, pc->scsi_cmd->request_buffer, pc->request_transfer); - } else { - hwif->sg_nents = segments; - memcpy(sg, scsi_sg, sizeof(*sg) * segments); - } + hwif->sg_nents = segments; + memcpy(sg, scsi_sg, sizeof(*sg) * segments); return 0; } @@ -744,7 +658,6 @@ static void idescsi_setup (ide_drive_t *drive, idescsi_scsi_t *scsi) { if (drive->id && (drive->id->config & 0x0060) == 0x20) set_bit (IDESCSI_DRQ_INTERRUPT, &scsi->flags); - set_bit(IDESCSI_TRANSFORM, &scsi->transform); clear_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); #if IDESCSI_DEBUG_LOG set_bit(IDESCSI_LOG_CMD, &scsi->log); @@ -758,6 +671,7 @@ static void ide_scsi_remove(ide_drive_t *drive) struct ide_scsi_obj *scsi = scsihost_to_idescsi(scsihost); struct gendisk *g = scsi->disk; + scsi_remove_host(scsihost); ide_proc_unregister_driver(drive, scsi->driver); ide_unregister_region(g); @@ -766,7 +680,6 @@ static void ide_scsi_remove(ide_drive_t *drive) g->private_data = NULL; put_disk(g); - scsi_remove_host(scsihost); ide_scsi_put(scsi); } @@ -838,6 +751,8 @@ static struct block_device_operations idescsi_ops = { static int idescsi_slave_configure(struct scsi_device * sdp) { /* Configure detected device */ + sdp->use_10_for_rw = 1; + sdp->use_10_for_ms = 1; scsi_adjust_queue_depth(sdp, MSG_SIMPLE_TAG, sdp->host->cmd_per_lun); return 0; } @@ -862,24 +777,6 @@ static int idescsi_ioctl (struct scsi_device *dev, int cmd, void __user *arg) return -EINVAL; } -static inline int should_transform(ide_drive_t *drive, struct scsi_cmnd *cmd) -{ - idescsi_scsi_t *scsi = drive_to_idescsi(drive); - - /* this was a layering violation and we can't support it - anymore, sorry. */ -#if 0 - struct gendisk *disk = cmd->request->rq_disk; - - if (disk) { - struct struct scsi_device_Template **p = disk->private_data; - if (strcmp((*p)->scsi_driverfs_driver.name, "sg") == 0) - return test_bit(IDESCSI_SG_TRANSFORM, &scsi->transform); - } -#endif - return test_bit(IDESCSI_TRANSFORM, &scsi->transform); -} - static int idescsi_queue (struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { @@ -905,23 +802,14 @@ static int idescsi_queue (struct scsi_cmnd *cmd, pc->flags = 0; pc->rq = rq; memcpy (pc->c, cmd->cmnd, cmd->cmd_len); - if (cmd->use_sg) { - pc->buffer = NULL; - pc->sg = cmd->request_buffer; - } else { - pc->buffer = cmd->request_buffer; - pc->sg = NULL; - } + pc->buffer = NULL; + pc->sg = scsi_sglist(cmd); pc->b_count = 0; - pc->request_transfer = pc->buffer_size = cmd->request_bufflen; + pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd); pc->scsi_cmd = cmd; pc->done = done; pc->timeout = jiffies + cmd->timeout_per_command; - if (should_transform(drive, cmd)) - set_bit(PC_TRANSFORM, &pc->flags); - idescsi_transform_pc1 (drive, pc); - if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) { printk ("ide-scsi: %s: que %lu, cmd = ", drive->name, cmd->serial_number); hexdump(cmd->cmnd, cmd->cmd_len); diff --git a/drivers/scsi/imm.c b/drivers/scsi/imm.c index 005d2b05f32d..74cdc1f0a78f 100644 --- a/drivers/scsi/imm.c +++ b/drivers/scsi/imm.c @@ -740,10 +740,6 @@ static void imm_interrupt(struct work_struct *work) struct Scsi_Host *host = cmd->device->host; unsigned long flags; - if (!cmd) { - printk("IMM: bug in imm_interrupt\n"); - return; - } if (imm_engine(dev, cmd)) { schedule_delayed_work(&dev->imm_tq, 1); return; diff --git a/drivers/scsi/in2000.c b/drivers/scsi/in2000.c index 312190a69389..ab7cbf3449ce 100644 --- a/drivers/scsi/in2000.c +++ b/drivers/scsi/in2000.c @@ -343,7 +343,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) instance = cmd->device->host; hostdata = (struct IN2000_hostdata *) instance->hostdata; - DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->pid)) + DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->serial_number)) /* Set up a few fields in the Scsi_Cmnd structure for our own use: * - host_scribble is the pointer to the next cmd in the input queue @@ -427,7 +427,7 @@ static int in2000_queuecommand(Scsi_Cmnd * cmd, void (*done) (Scsi_Cmnd *)) in2000_execute(cmd->device->host); - DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid)) + DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number)) return 0; } @@ -703,7 +703,7 @@ static void in2000_execute(struct Scsi_Host *instance) * to search the input_Q again... */ - DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid)) + DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->serial_number)) } @@ -1147,7 +1147,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) case CSR_XFER_DONE | PHS_COMMAND: case CSR_UNEXP | PHS_COMMAND: case CSR_SRV_REQ | PHS_COMMAND: - DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid)) + DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->serial_number)) transfer_pio(cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata); hostdata->state = S_CONNECTED; break; @@ -1189,7 +1189,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) switch (msg) { case COMMAND_COMPLETE: - DB(DB_INTR, printk("CCMP-%ld", cmd->pid)) + DB(DB_INTR, printk("CCMP-%ld", cmd->serial_number)) write_3393_cmd(hostdata, WD_CMD_NEGATE_ACK); hostdata->state = S_PRE_CMP_DISC; break; @@ -1327,7 +1327,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); if (phs == 0x60) { - DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid)) + DB(DB_INTR, printk("SX-DONE-%ld", cmd->serial_number)) cmd->SCp.Message = COMMAND_COMPLETE; lun = read_3393(hostdata, WD_TARGET_LUN); DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun)) @@ -1348,7 +1348,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) in2000_execute(instance); } else { - printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->pid); + printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->serial_number); } break; @@ -1415,7 +1415,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) spin_unlock_irqrestore(instance->host_lock, flags); return IRQ_HANDLED; } - DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid)) + DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->serial_number)) hostdata->connected = NULL; hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); hostdata->state = S_UNCONNECTED; @@ -1440,7 +1440,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) */ write_3393(hostdata, WD_SOURCE_ID, SRCID_ER); - DB(DB_INTR, printk("DISC-%ld", cmd->pid)) + DB(DB_INTR, printk("DISC-%ld", cmd->serial_number)) if (cmd == NULL) { printk(" - Already disconnected! "); hostdata->state = S_UNCONNECTED; @@ -1573,7 +1573,7 @@ static irqreturn_t in2000_intr(int irqnum, void *dev_id) } else hostdata->state = S_CONNECTED; - DB(DB_INTR, printk("-%ld", cmd->pid)) + DB(DB_INTR, printk("-%ld", cmd->serial_number)) break; default: @@ -1702,7 +1702,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd) prev->host_scribble = cmd->host_scribble; cmd->host_scribble = NULL; cmd->result = DID_ABORT << 16; - printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->pid); + printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->serial_number); cmd->scsi_done(cmd); return SUCCESS; } @@ -1723,7 +1723,7 @@ static int __in2000_abort(Scsi_Cmnd * cmd) if (hostdata->connected == cmd) { - printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->pid); + printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->serial_number); printk("sending wd33c93 ABORT command - "); write_3393(hostdata, WD_CONTROL, CTRL_IDI | CTRL_EDI | CTRL_POLLED); @@ -2268,7 +2268,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, strcat(bp, "\nconnected: "); if (hd->connected) { cmd = (Scsi_Cmnd *) hd->connected; - sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); } } @@ -2276,7 +2276,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, strcat(bp, "\ninput_Q: "); cmd = (Scsi_Cmnd *) hd->input_Q; while (cmd) { - sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (Scsi_Cmnd *) cmd->host_scribble; } @@ -2285,7 +2285,7 @@ static int in2000_proc_info(struct Scsi_Host *instance, char *buf, char **start, strcat(bp, "\ndisconnected_Q:"); cmd = (Scsi_Cmnd *) hd->disconnected_Q; while (cmd) { - sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (Scsi_Cmnd *) cmd->host_scribble; } diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 492a51bd6aa8..2ed099e2c20d 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -204,8 +204,8 @@ module_param(ips, charp, 0); /* * DRIVER_VER */ -#define IPS_VERSION_HIGH "7.12" -#define IPS_VERSION_LOW ".05 " +#define IPS_VERSION_HIGH IPS_VER_MAJOR_STRING "." IPS_VER_MINOR_STRING +#define IPS_VERSION_LOW "." IPS_VER_BUILD_STRING " " #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) #warning "This driver has only been tested on the x86/ia64/x86_64 platforms" @@ -656,6 +656,8 @@ ips_release(struct Scsi_Host *sh) METHOD_TRACE("ips_release", 1); + scsi_remove_host(sh); + for (i = 0; i < IPS_MAX_ADAPTERS && ips_sh[i] != sh; i++) ; if (i == IPS_MAX_ADAPTERS) { @@ -707,7 +709,6 @@ ips_release(struct Scsi_Host *sh) /* free IRQ */ free_irq(ha->irq, ha); - scsi_remove_host(sh); scsi_host_put(sh); ips_released_controllers++; @@ -6946,7 +6947,7 @@ module_exit(ips_module_exit); static int __devinit ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent) { - int index; + int uninitialized_var(index); int rc; METHOD_TRACE("ips_insert_device", 1); diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index 24123d537c58..3bcbd9ff056b 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -1172,12 +1172,13 @@ typedef struct { *************************************************************************/ #define IPS_VER_MAJOR 7 -#define IPS_VER_MAJOR_STRING "7" +#define IPS_VER_MAJOR_STRING __stringify(IPS_VER_MAJOR) #define IPS_VER_MINOR 12 -#define IPS_VER_MINOR_STRING "12" -#define IPS_VER_BUILD 02 -#define IPS_VER_BUILD_STRING "02" -#define IPS_VER_STRING "7.12.02" +#define IPS_VER_MINOR_STRING __stringify(IPS_VER_MINOR) +#define IPS_VER_BUILD 05 +#define IPS_VER_BUILD_STRING __stringify(IPS_VER_BUILD) +#define IPS_VER_STRING IPS_VER_MAJOR_STRING "." \ + IPS_VER_MINOR_STRING "." IPS_VER_BUILD_STRING #define IPS_RELEASE_ID 0x00020000 #define IPS_BUILD_IDENT 761 #define IPS_LEGALCOPYRIGHT_STRING "(C) Copyright IBM Corp. 1994, 2002. All Rights Reserved." diff --git a/drivers/scsi/libsrp.c b/drivers/scsi/libsrp.c index 732446e63963..2ad0a27dbaab 100644 --- a/drivers/scsi/libsrp.c +++ b/drivers/scsi/libsrp.c @@ -392,7 +392,7 @@ static int vscsis_data_length(struct srp_cmd *cmd, enum dma_data_direction dir) } int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, - u64 addr) + u64 itn_id, u64 addr) { enum dma_data_direction dir; struct scsi_cmnd *sc; @@ -428,7 +428,8 @@ int srp_cmd_queue(struct Scsi_Host *shost, struct srp_cmd *cmd, void *info, sc->request_bufflen = len; sc->request_buffer = (void *) (unsigned long) addr; sc->tag = tag; - err = scsi_tgt_queue_command(sc, (struct scsi_lun *) &cmd->lun, cmd->tag); + err = scsi_tgt_queue_command(sc, itn_id, (struct scsi_lun *)&cmd->lun, + cmd->tag); if (err) scsi_host_put_command(shost, sc); diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 2e3c01bebed6..149fdd25f8e8 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -43,7 +43,6 @@ #include "lpfc_crtn.h" #include "lpfc_vport.h" #include "lpfc_version.h" -#include "lpfc_vport.h" #include "lpfc_debugfs.h" #ifdef CONFIG_LPFC_DEBUG_FS @@ -902,7 +901,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) } } - vport->disc_trc = kmalloc( + vport->disc_trc = kmzlloc( (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc), GFP_KERNEL); @@ -913,8 +912,6 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) goto debug_failed; } atomic_set(&vport->disc_trc_cnt, 0); - memset(vport->disc_trc, 0, - (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc)); snprintf(name, sizeof(name), "discovery_trace"); vport->debug_disc_trc = diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 414350ab584e..ecebdfa00470 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -43,7 +43,6 @@ #include "lpfc_crtn.h" #include "lpfc_vport.h" #include "lpfc_version.h" -#include "lpfc_vport.h" static int lpfc_parse_vpd(struct lpfc_hba *, uint8_t *, int); static void lpfc_get_hba_model_desc(struct lpfc_hba *, uint8_t *, uint8_t *); @@ -1266,11 +1265,10 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit) uint32_t *HashWorking; uint32_t *pwwnn = (uint32_t *) phba->wwnn; - HashWorking = kmalloc(80 * sizeof(uint32_t), GFP_KERNEL); + HashWorking = kcalloc(80, sizeof(uint32_t), GFP_KERNEL); if (!HashWorking) return; - memset(HashWorking, 0, (80 * sizeof(uint32_t))); HashWorking[0] = HashWorking[78] = *pwwnn++; HashWorking[1] = HashWorking[79] = *pwwnn; diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 17d7dc05149b..cd674938ccd5 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c @@ -202,10 +202,9 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport) dma_addr_t pdma_phys; uint16_t iotag; - psb = kmalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); + psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); if (!psb) return NULL; - memset(psb, 0, sizeof (struct lpfc_scsi_buf)); /* * Get memory from the pci pool to map the virt space to pci bus space diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index ce5ff2bccba6..e5337ad4121e 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -675,7 +675,7 @@ lpfc_sli_hbqbuf_find(struct lpfc_hba *phba, uint32_t tag) uint32_t hbqno; hbqno = tag >> 16; - if (hbqno > LPFC_MAX_HBQS) + if (hbqno >= LPFC_MAX_HBQS) return NULL; list_for_each_entry(d_buf, &phba->hbqs[hbqno].hbq_buffer_list, list) { diff --git a/drivers/scsi/megaraid.c b/drivers/scsi/megaraid.c index da56163c30a8..e7e11f282c8f 100644 --- a/drivers/scsi/megaraid.c +++ b/drivers/scsi/megaraid.c @@ -4416,8 +4416,7 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) scmd = &adapter->int_scmd; memset(scmd, 0, sizeof(Scsi_Cmnd)); - sdev = kmalloc(sizeof(struct scsi_device), GFP_KERNEL); - memset(sdev, 0, sizeof(struct scsi_device)); + sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); scmd->device = sdev; scmd->device->host = adapter->host; diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c index 1bdddad48571..b264b499d982 100644 --- a/drivers/scsi/mvme16x_scsi.c +++ b/drivers/scsi/mvme16x_scsi.c @@ -48,13 +48,12 @@ mvme16x_probe(struct device *dev) goto out; } - hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); if (hostdata == NULL) { printk(KERN_ERR "mvme16x-scsi: " "Failed to allocate host data\n"); goto out; } - memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); /* Fill in the required pieces of hostdata */ hostdata->base = (void __iomem *)0xfff47000UL; diff --git a/drivers/scsi/ncr53c8xx.c b/drivers/scsi/ncr53c8xx.c index 030ba49f33ff..016c462bc771 100644 --- a/drivers/scsi/ncr53c8xx.c +++ b/drivers/scsi/ncr53c8xx.c @@ -8143,12 +8143,7 @@ static int ncr53c8xx_abort(struct scsi_cmnd *cmd) unsigned long flags; struct scsi_cmnd *done_list; -#if defined SCSI_RESET_SYNCHRONOUS && defined SCSI_RESET_ASYNCHRONOUS - printk("ncr53c8xx_abort: pid=%lu serial_number=%ld\n", - cmd->pid, cmd->serial_number); -#else - printk("ncr53c8xx_abort: command pid %lu\n", cmd->pid); -#endif + printk("ncr53c8xx_abort: command pid %lu\n", cmd->serial_number); NCR_LOCK_NCB(np, flags); @@ -8528,18 +8523,15 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, } -int ncr53c8xx_release(struct Scsi_Host *host) +void ncr53c8xx_release(struct Scsi_Host *host) { - struct host_data *host_data; + struct host_data *host_data = shost_priv(host); #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx: release\n"); #endif - if (!host) - return 1; - host_data = (struct host_data *)host->hostdata; - if (host_data && host_data->ncb) + if (host_data->ncb) ncr_detach(host_data->ncb); - return 1; + scsi_host_put(host); } static void ncr53c8xx_set_period(struct scsi_target *starget, int period) diff --git a/drivers/scsi/ncr53c8xx.h b/drivers/scsi/ncr53c8xx.h index b39357d9af8d..0e008dacf679 100644 --- a/drivers/scsi/ncr53c8xx.h +++ b/drivers/scsi/ncr53c8xx.h @@ -1321,7 +1321,7 @@ struct ncr_device { }; extern struct Scsi_Host *ncr_attach(struct scsi_host_template *tpnt, int unit, struct ncr_device *device); -extern int ncr53c8xx_release(struct Scsi_Host *host); +extern void ncr53c8xx_release(struct Scsi_Host *host); irqreturn_t ncr53c8xx_intr(int irq, void *dev_id); extern int ncr53c8xx_init(void); extern void ncr53c8xx_exit(void); diff --git a/drivers/scsi/osst.c b/drivers/scsi/osst.c index 08060fb478b6..331b789937c4 100644 --- a/drivers/scsi/osst.c +++ b/drivers/scsi/osst.c @@ -3298,7 +3298,7 @@ static ssize_t osst_write(struct file * filp, const char __user * buf, size_t co char * name = tape_name(STp); - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return (-ERESTARTSYS); /* @@ -3600,7 +3600,7 @@ if (SRpnt) printk(KERN_ERR "%s:A: Not supposed to have SRpnt at line %d\n", name out: if (SRpnt != NULL) osst_release_request(SRpnt); - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -3619,7 +3619,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo char * name = tape_name(STp); - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return (-ERESTARTSYS); /* @@ -3785,7 +3785,7 @@ static ssize_t osst_read(struct file * filp, char __user * buf, size_t count, lo out: if (SRpnt != NULL) osst_release_request(SRpnt); - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -4852,7 +4852,7 @@ static int osst_ioctl(struct inode * inode,struct file * file, char * name = tape_name(STp); void __user * p = (void __user *)arg; - if (down_interruptible(&STp->lock)) + if (mutex_lock_interruptible(&STp->lock)) return -ERESTARTSYS; #if DEBUG @@ -5163,14 +5163,14 @@ static int osst_ioctl(struct inode * inode,struct file * file, } if (SRpnt) osst_release_request(SRpnt); - up(&STp->lock); + mutex_unlock(&STp->lock); return scsi_ioctl(STp->device, cmd_in, p); out: if (SRpnt) osst_release_request(SRpnt); - up(&STp->lock); + mutex_unlock(&STp->lock); return retval; } @@ -5778,13 +5778,12 @@ static int osst_probe(struct device *dev) dev_num = i; /* allocate a struct osst_tape for this device */ - tpnt = kmalloc(sizeof(struct osst_tape), GFP_ATOMIC); - if (tpnt == NULL) { + tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC); + if (!tpnt) { write_unlock(&os_scsi_tapes_lock); printk(KERN_ERR "osst :E: Can't allocate device descriptor, device not attached.\n"); goto out_put_disk; } - memset(tpnt, 0, sizeof(struct osst_tape)); /* allocate a buffer for this device */ i = SDp->host->sg_tablesize; @@ -5866,7 +5865,7 @@ static int osst_probe(struct device *dev) tpnt->modes[2].defined = 1; tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0; - init_MUTEX(&tpnt->lock); + mutex_init(&tpnt->lock); osst_nr_dev++; write_unlock(&os_scsi_tapes_lock); diff --git a/drivers/scsi/osst.h b/drivers/scsi/osst.h index 2cc7b5a1606a..5aa22740b5df 100644 --- a/drivers/scsi/osst.h +++ b/drivers/scsi/osst.h @@ -4,6 +4,7 @@ #include <asm/byteorder.h> #include <linux/completion.h> +#include <linux/mutex.h> /* FIXME - rename and use the following two types or delete them! * and the types really should go to st.h anyway... @@ -532,7 +533,7 @@ struct osst_tape { struct scsi_driver *driver; unsigned capacity; struct scsi_device *device; - struct semaphore lock; /* for serialization */ + struct mutex lock; /* for serialization */ struct completion wait; /* for SCSI commands */ struct osst_buffer * buffer; diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index 445cfbbca9b3..a45d89b14147 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -25,8 +25,6 @@ ***********************************************************************/ -/* $Id: nsp_cs.c,v 1.23 2003/08/18 11:09:19 elca Exp $ */ - #include <linux/version.h> #include <linux/module.h> #include <linux/kernel.h> @@ -59,7 +57,7 @@ #include "nsp_cs.h" MODULE_AUTHOR("YOKOTA Hiroshi <yokota@netlab.is.tsukuba.ac.jp>"); -MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module $Revision: 1.23 $"); +MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module"); MODULE_SUPPORTED_DEVICE("sd,sr,sg,st"); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); @@ -83,10 +81,6 @@ static struct scsi_host_template nsp_driver_template = { .proc_name = "nsp_cs", .proc_info = nsp_proc_info, .name = "WorkBit NinjaSCSI-3/32Bi(16bit)", -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) - .detect = nsp_detect_old, - .release = nsp_release_old, -#endif .info = nsp_info, .queuecommand = nsp_queuecommand, /* .eh_abort_handler = nsp_eh_abort,*/ @@ -97,9 +91,6 @@ static struct scsi_host_template nsp_driver_template = { .sg_tablesize = SG_ALL, .cmd_per_lun = 1, .use_clustering = DISABLE_CLUSTERING, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,2)) - .use_new_eh_code = 1, -#endif }; static nsp_hw_data nsp_data_base; /* attach <-> detect glue */ @@ -1313,11 +1304,7 @@ static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht) nsp_hw_data *data_b = &nsp_data_base, *data; nsp_dbg(NSP_DEBUG_INIT, "this_id=%d", sht->this_id); -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) host = scsi_host_alloc(&nsp_driver_template, sizeof(nsp_hw_data)); -#else - host = scsi_register(sht, sizeof(nsp_hw_data)); -#endif if (host == NULL) { nsp_dbg(NSP_DEBUG_INIT, "host failed"); return NULL; @@ -1354,37 +1341,6 @@ static struct Scsi_Host *nsp_detect(struct scsi_host_template *sht) return host; /* detect done. */ } -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) -static int nsp_detect_old(struct scsi_host_template *sht) -{ - if (nsp_detect(sht) == NULL) { - return 0; - } else { - //MOD_INC_USE_COUNT; - return 1; - } -} - - -static int nsp_release_old(struct Scsi_Host *shpnt) -{ - //nsp_hw_data *data = (nsp_hw_data *)shpnt->hostdata; - - /* PCMCIA Card Service dose same things below. */ - /* So we do nothing. */ - //if (shpnt->irq) { - // free_irq(shpnt->irq, data->ScsiInfo); - //} - //if (shpnt->io_port) { - // release_region(shpnt->io_port, shpnt->n_io_port); - //} - - //MOD_DEC_USE_COUNT; - - return 0; -} -#endif - /*----------------------------------------------------------------*/ /* return info string */ /*----------------------------------------------------------------*/ @@ -1403,19 +1359,9 @@ static const char *nsp_info(struct Scsi_Host *shpnt) nsp_dbg(NSP_DEBUG_PROC, "buffer=0x%p pos=0x%p length=%d %d\n", buffer, pos, length, length - (pos - buffer));\ } \ } while(0) -static int -nsp_proc_info( -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - struct Scsi_Host *host, -#endif - char *buffer, - char **start, - off_t offset, - int length, -#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - int hostno, -#endif - int inout) + +static int nsp_proc_info(struct Scsi_Host *host, char *buffer, char **start, + off_t offset, int length, int inout) { int id; char *pos = buffer; @@ -1423,24 +1369,13 @@ nsp_proc_info( int speed; unsigned long flags; nsp_hw_data *data; -#if !(LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) - struct Scsi_Host *host; -#else int hostno; -#endif + if (inout) { return -EINVAL; } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,73)) hostno = host->host_no; -#else - /* search this HBA host */ - host = scsi_host_hn_get(hostno); - if (host == NULL) { - return -ESRCH; - } -#endif data = (nsp_hw_data *)host->hostdata; @@ -1675,10 +1610,6 @@ static int nsp_cs_config(struct pcmcia_device *link) cistpl_cftable_entry_t dflt = { 0 }; struct Scsi_Host *host; nsp_hw_data *data = &nsp_data_base; -#if !(LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)) - struct scsi_device *dev; - dev_node_t **tail, *node; -#endif nsp_dbg(NSP_DEBUG_INIT, "in"); @@ -1811,17 +1742,7 @@ static int nsp_cs_config(struct pcmcia_device *link) goto cs_failed; } -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2)) host = nsp_detect(&nsp_driver_template); -#else - scsi_register_host(&nsp_driver_template); - for (host = scsi_host_get_next(NULL); host != NULL; - host = scsi_host_get_next(host)) { - if (host->hostt == &nsp_driver_template) { - break; - } - } -#endif if (host == NULL) { nsp_dbg(NSP_DEBUG_INIT, "detect failed"); @@ -1829,7 +1750,6 @@ static int nsp_cs_config(struct pcmcia_device *link) } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)) ret = scsi_add_host (host, NULL); if (ret) goto cs_failed; @@ -1840,52 +1760,6 @@ static int nsp_cs_config(struct pcmcia_device *link) link->dev_node = &info->node; info->host = host; -#else - nsp_dbg(NSP_DEBUG_INIT, "GET_SCSI_INFO"); - tail = &link->dev_node; - info->ndev = 0; - - nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host); - - for (dev = host->host_queue; dev != NULL; dev = dev->next) { - unsigned long id; - id = (dev->id & 0x0f) + ((dev->lun & 0x0f) << 4) + - ((dev->channel & 0x0f) << 8) + - ((dev->host->host_no & 0x0f) << 12); - node = &info->node[info->ndev]; - node->minor = 0; - switch (dev->type) { - case TYPE_TAPE: - node->major = SCSI_TAPE_MAJOR; - snprintf(node->dev_name, sizeof(node->dev_name), "st#%04lx", id); - break; - case TYPE_DISK: - case TYPE_MOD: - node->major = SCSI_DISK0_MAJOR; - snprintf(node->dev_name, sizeof(node->dev_name), "sd#%04lx", id); - break; - case TYPE_ROM: - case TYPE_WORM: - node->major = SCSI_CDROM_MAJOR; - snprintf(node->dev_name, sizeof(node->dev_name), "sr#%04lx", id); - break; - default: - node->major = SCSI_GENERIC_MAJOR; - snprintf(node->dev_name, sizeof(node->dev_name), "sg#%04lx", id); - break; - } - *tail = node; tail = &node->next; - info->ndev++; - info->host = dev->host; - } - - *tail = NULL; - if (info->ndev == 0) { - nsp_msg(KERN_INFO, "no SCSI devices found"); - } - nsp_dbg(NSP_DEBUG_INIT, "host=0x%p", host); -#endif - /* Finally, report what we've done */ printk(KERN_INFO "nsp_cs: index 0x%02x: ", link->conf.ConfigIndex); @@ -1938,13 +1812,9 @@ static void nsp_cs_release(struct pcmcia_device *link) nsp_dbg(NSP_DEBUG_INIT, "link=0x%p", link); /* Unlink the device chain */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2)) if (info->host != NULL) { scsi_remove_host(info->host); } -#else - scsi_unregister_host(&nsp_driver_template); -#endif link->dev_node = NULL; if (link->win) { @@ -1954,11 +1824,9 @@ static void nsp_cs_release(struct pcmcia_device *link) } pcmcia_disable_device(link); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,2)) if (info->host != NULL) { scsi_host_put(info->host); } -#endif } /* nsp_cs_release */ static int nsp_cs_suspend(struct pcmcia_device *link) @@ -2005,7 +1873,6 @@ static int nsp_cs_resume(struct pcmcia_device *link) /*======================================================================* * module entry point *====================================================================*/ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) static struct pcmcia_device_id nsp_cs_ids[] = { PCMCIA_DEVICE_PROD_ID123("IO DATA", "CBSC16 ", "1", 0x547e66dc, 0x0d63a3fd, 0x51de003a), PCMCIA_DEVICE_PROD_ID123("KME ", "SCSI-CARD-001", "1", 0x534c02bc, 0x52008408, 0x51de003a), @@ -2029,28 +1896,12 @@ static struct pcmcia_driver nsp_driver = { .suspend = nsp_cs_suspend, .resume = nsp_cs_resume, }; -#endif static int __init nsp_cs_init(void) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,68)) nsp_msg(KERN_INFO, "loading..."); return pcmcia_register_driver(&nsp_driver); -#else - servinfo_t serv; - - nsp_msg(KERN_INFO, "loading..."); - pcmcia_get_card_services_info(&serv); - if (serv.Revision != CS_RELEASE_CODE) { - nsp_msg(KERN_DEBUG, "Card Services release does not match!"); - return -EINVAL; - } - register_pcmcia_driver(&dev_info, &nsp_cs_attach, &nsp_cs_detach); - - nsp_dbg(NSP_DEBUG_INIT, "out"); - return 0; -#endif } static void __exit nsp_cs_exit(void) diff --git a/drivers/scsi/pcmcia/nsp_cs.h b/drivers/scsi/pcmcia/nsp_cs.h index 9102cbdf1359..b7f0fa246413 100644 --- a/drivers/scsi/pcmcia/nsp_cs.h +++ b/drivers/scsi/pcmcia/nsp_cs.h @@ -10,8 +10,6 @@ =========================================================*/ -/* $Id: nsp_cs.h,v 1.19 2003/08/18 11:09:19 elca Exp $ */ - #ifndef __nsp_cs__ #define __nsp_cs__ @@ -227,13 +225,7 @@ typedef struct scsi_info_t { struct pcmcia_device *p_dev; struct Scsi_Host *host; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,74)) dev_node_t node; -#else - int ndev; - dev_node_t node[8]; - struct bus_operations *bus; -#endif int stop; } scsi_info_t; diff --git a/drivers/scsi/pluto.c b/drivers/scsi/pluto.c index d953d43fe2e6..0363c1cd68c1 100644 --- a/drivers/scsi/pluto.c +++ b/drivers/scsi/pluto.c @@ -111,13 +111,12 @@ int __init pluto_detect(struct scsi_host_template *tpnt) #endif return 0; } - fcs = kmalloc(sizeof (struct ctrl_inquiry) * fcscount, GFP_DMA); + fcs = kcalloc(fcscount, sizeof (struct ctrl_inquiry), GFP_DMA); if (!fcs) { printk ("PLUTO: Not enough memory to probe\n"); return 0; } - memset (fcs, 0, sizeof (struct ctrl_inquiry) * fcscount); memset (&dev, 0, sizeof(dev)); atomic_set (&fcss, fcscount); @@ -161,7 +160,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt) SCpnt->request->cmd_flags &= ~REQ_STARTED; - SCpnt->done = pluto_detect_done; SCpnt->request_bufflen = 256; SCpnt->request_buffer = fcs[i].inquiry; PLD(("set up %d %08lx\n", i, (long)SCpnt)) @@ -196,7 +194,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt) SCpnt = &(fcs[i].cmd); /* Let FC mid-level free allocated resources */ - SCpnt->done (SCpnt); + pluto_detect_scsi_done(SCpnt); if (!SCpnt->result) { struct pluto_inquiry *inq; @@ -211,7 +209,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt) char *p; long *ages; - ages = kmalloc (((inq->channels + 1) * inq->targets) * sizeof(long), GFP_KERNEL); + ages = kcalloc((inq->channels + 1) * inq->targets, sizeof(long), GFP_KERNEL); if (!ages) continue; host = scsi_register (tpnt, sizeof (struct pluto)); @@ -238,7 +236,6 @@ int __init pluto_detect(struct scsi_host_template *tpnt) fc->channels = inq->channels + 1; fc->targets = inq->targets; fc->ages = ages; - memset (ages, 0, ((inq->channels + 1) * inq->targets) * sizeof(long)); pluto->fc = fc; memcpy (pluto->rev_str, inq->revision, 4); @@ -260,7 +257,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt) } else fc->fcp_register(fc, TYPE_SCSI_FCP, 1); } - kfree((char *)fcs); + kfree(fcs); if (nplutos) printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos); return nplutos; diff --git a/drivers/scsi/ps3rom.c b/drivers/scsi/ps3rom.c index b50f1e14f2a5..0f43d1d046d9 100644 --- a/drivers/scsi/ps3rom.c +++ b/drivers/scsi/ps3rom.c @@ -100,16 +100,16 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) struct scatterlist *sgpnt; unsigned int buflen; - buflen = cmd->request_bufflen; + buflen = scsi_bufflen(cmd); if (!buflen) return 0; - if (!cmd->request_buffer) + if (!scsi_sglist(cmd)) return -1; - sgpnt = cmd->request_buffer; active = 1; - for (k = 0, req_len = 0, act_len = 0; k < cmd->use_sg; ++k, ++sgpnt) { + req_len = act_len = 0; + scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { if (active) { kaddr = kmap_atomic(sgpnt->page, KM_IRQ0); len = sgpnt->length; @@ -124,7 +124,7 @@ static int fill_from_dev_buffer(struct scsi_cmnd *cmd, const void *buf) } req_len += sgpnt->length; } - cmd->resid = req_len - act_len; + scsi_set_resid(cmd, req_len - act_len); return 0; } @@ -138,15 +138,15 @@ static int fetch_to_dev_buffer(struct scsi_cmnd *cmd, void *buf) struct scatterlist *sgpnt; unsigned int buflen; - buflen = cmd->request_bufflen; + buflen = scsi_bufflen(cmd); if (!buflen) return 0; - if (!cmd->request_buffer) + if (!scsi_sglist(cmd)) return -1; - sgpnt = cmd->request_buffer; - for (k = 0, req_len = 0, fin = 0; k < cmd->use_sg; ++k, ++sgpnt) { + req_len = fin = 0; + scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { kaddr = kmap_atomic(sgpnt->page, KM_IRQ0); len = sgpnt->length; if ((req_len + len) > buflen) { @@ -177,12 +177,12 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev, memcpy(&atapi_cmnd.pkt, cmd->cmnd, 12); atapi_cmnd.pktlen = 12; atapi_cmnd.block_size = 1; /* transfer size is block_size * blocks */ - atapi_cmnd.blocks = atapi_cmnd.arglen = cmd->request_bufflen; + atapi_cmnd.blocks = atapi_cmnd.arglen = scsi_bufflen(cmd); atapi_cmnd.buffer = dev->bounce_lpar; switch (cmd->sc_data_direction) { case DMA_FROM_DEVICE: - if (cmd->request_bufflen >= CD_FRAMESIZE) + if (scsi_bufflen(cmd) >= CD_FRAMESIZE) atapi_cmnd.proto = DMA_PROTO; else atapi_cmnd.proto = PIO_DATA_IN_PROTO; @@ -190,7 +190,7 @@ static int ps3rom_atapi_request(struct ps3_storage_device *dev, break; case DMA_TO_DEVICE: - if (cmd->request_bufflen >= CD_FRAMESIZE) + if (scsi_bufflen(cmd) >= CD_FRAMESIZE) atapi_cmnd.proto = DMA_PROTO; else atapi_cmnd.proto = PIO_DATA_OUT_PROTO; diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c index 54d8bdf86852..fba8aa8a81b5 100644 --- a/drivers/scsi/qla1280.c +++ b/drivers/scsi/qla1280.c @@ -4086,7 +4086,7 @@ __qla1280_print_scsi_cmd(struct scsi_cmnd *cmd) } */ printk(" tag=%d, transfersize=0x%x \n", cmd->tag, cmd->transfersize); - printk(" Pid=%li, SP=0x%p\n", cmd->pid, CMD_SP(cmd)); + printk(" Pid=%li, SP=0x%p\n", cmd->serial_number, CMD_SP(cmd)); printk(" underflow size = 0x%x, direction=0x%x\n", cmd->underflow, cmd->sc_data_direction); } diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index 0f2a9f5d801c..05fa7796a559 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -18,7 +18,7 @@ qla2x00_sysfs_read_fw_dump(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); char *rbuf = (char *)ha->fw_dump; @@ -39,7 +39,7 @@ qla2x00_sysfs_write_fw_dump(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int reading; @@ -89,7 +89,7 @@ qla2x00_sysfs_read_nvram(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int size = ha->nvram_size; char *nvram_cache = ha->nvram; @@ -112,7 +112,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); unsigned long flags; uint16_t cnt; @@ -146,7 +146,7 @@ qla2x00_sysfs_write_nvram(struct kobject *kobj, /* Write NVRAM. */ spin_lock_irqsave(&ha->hardware_lock, flags); ha->isp_ops->write_nvram(ha, (uint8_t *)buf, ha->nvram_base, count); - ha->isp_ops->read_nvram(ha, (uint8_t *)&ha->nvram, ha->nvram_base, + ha->isp_ops->read_nvram(ha, (uint8_t *)ha->nvram, ha->nvram_base, count); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -170,15 +170,15 @@ qla2x00_sysfs_read_optrom(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); if (ha->optrom_state != QLA_SREADING) return 0; - if (off > ha->optrom_size) + if (off > ha->optrom_region_size) return 0; - if (off + count > ha->optrom_size) - count = ha->optrom_size - off; + if (off + count > ha->optrom_region_size) + count = ha->optrom_region_size - off; memcpy(buf, &ha->optrom_buffer[off], count); @@ -190,15 +190,15 @@ qla2x00_sysfs_write_optrom(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); if (ha->optrom_state != QLA_SWRITING) return -EINVAL; - if (off > ha->optrom_size) + if (off > ha->optrom_region_size) return -ERANGE; - if (off + count > ha->optrom_size) - count = ha->optrom_size - off; + if (off + count > ha->optrom_region_size) + count = ha->optrom_region_size - off; memcpy(&ha->optrom_buffer[off], buf, count); @@ -220,14 +220,18 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); - int val; + uint32_t start = 0; + uint32_t size = ha->optrom_size; + int val, valid; if (off) return 0; - if (sscanf(buf, "%d", &val) != 1) + if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) + return -EINVAL; + if (start > ha->optrom_size) return -EINVAL; switch (val) { @@ -237,6 +241,11 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, break; ha->optrom_state = QLA_SWAITING; + + DEBUG2(qla_printk(KERN_INFO, ha, + "Freeing flash region allocation -- 0x%x bytes.\n", + ha->optrom_region_size)); + vfree(ha->optrom_buffer); ha->optrom_buffer = NULL; break; @@ -244,44 +253,107 @@ 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; + ha->optrom_state = QLA_SREADING; - ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); + ha->optrom_buffer = vmalloc(ha->optrom_region_size); if (ha->optrom_buffer == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocate memory for optrom retrieval " - "(%x).\n", ha->optrom_size); + "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; return count; } - memset(ha->optrom_buffer, 0, ha->optrom_size); - ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0, - ha->optrom_size); + DEBUG2(qla_printk(KERN_INFO, ha, + "Reading flash region -- 0x%x/0x%x.\n", + ha->optrom_region_start, ha->optrom_region_size)); + + memset(ha->optrom_buffer, 0, ha->optrom_region_size); + ha->isp_ops->read_optrom(ha, ha->optrom_buffer, + ha->optrom_region_start, ha->optrom_region_size); break; case 2: if (ha->optrom_state != QLA_SWAITING) break; + /* + * We need to be more restrictive on which FLASH regions are + * allowed to be updated via user-space. Regions accessible + * via this method include: + * + * ISP21xx/ISP22xx/ISP23xx type boards: + * + * 0x000000 -> 0x020000 -- Boot code. + * + * ISP2322/ISP24xx type boards: + * + * 0x000000 -> 0x07ffff -- Boot code. + * 0x080000 -> 0x0fffff -- Firmware. + * + * ISP25xx type boards: + * + * 0x000000 -> 0x07ffff -- Boot code. + * 0x080000 -> 0x0fffff -- Firmware. + * 0x120000 -> 0x12ffff -- VPD and HBA parameters. + */ + valid = 0; + if (ha->optrom_size == OPTROM_SIZE_2300 && start == 0) + valid = 1; + else if (start == (FA_BOOT_CODE_ADDR*4) || + start == (FA_RISC_CODE_ADDR*4)) + valid = 1; + else if (IS_QLA25XX(ha) && start == (FA_VPD_NVRAM_ADDR*4)) + valid = 1; + if (!valid) { + 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; + ha->optrom_state = QLA_SWRITING; - ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); + ha->optrom_buffer = vmalloc(ha->optrom_region_size); if (ha->optrom_buffer == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocate memory for optrom update " - "(%x).\n", ha->optrom_size); + "(%x).\n", ha->optrom_region_size); ha->optrom_state = QLA_SWAITING; return count; } - memset(ha->optrom_buffer, 0, ha->optrom_size); + + DEBUG2(qla_printk(KERN_INFO, ha, + "Staging flash region write -- 0x%x/0x%x.\n", + ha->optrom_region_start, ha->optrom_region_size)); + + memset(ha->optrom_buffer, 0, ha->optrom_region_size); break; case 3: if (ha->optrom_state != QLA_SWRITING) break; - ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0, - ha->optrom_size); + DEBUG2(qla_printk(KERN_INFO, ha, + "Writing flash region -- 0x%x/0x%x.\n", + ha->optrom_region_start, ha->optrom_region_size)); + + ha->isp_ops->write_optrom(ha, ha->optrom_buffer, + ha->optrom_region_start, ha->optrom_region_size); break; + default: + count = -EINVAL; } return count; } @@ -300,7 +372,7 @@ qla2x00_sysfs_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); int size = ha->vpd_size; char *vpd_cache = ha->vpd; @@ -323,7 +395,7 @@ qla2x00_sysfs_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); unsigned long flags; @@ -354,7 +426,7 @@ qla2x00_sysfs_read_sfp(struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { - struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = shost_priv(dev_to_shost(container_of(kobj, struct device, kobj))); uint16_t iter, addr, offset; int rval; @@ -459,7 +531,7 @@ qla2x00_drvr_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_fw_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); char fw_str[30]; return snprintf(buf, PAGE_SIZE, "%s\n", @@ -469,7 +541,7 @@ qla2x00_fw_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_serial_num_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); uint32_t sn; sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; @@ -480,14 +552,14 @@ qla2x00_serial_num_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_isp_name_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "ISP%04X\n", ha->pdev->device); } static ssize_t qla2x00_isp_id_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%04x %04x %04x %04x\n", ha->product_id[0], ha->product_id[1], ha->product_id[2], ha->product_id[3]); @@ -496,14 +568,14 @@ qla2x00_isp_id_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_model_name_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_number); } static ssize_t qla2x00_model_desc_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_desc ? ha->model_desc: ""); } @@ -511,7 +583,7 @@ qla2x00_model_desc_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_pci_info_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); char pci_info[30]; return snprintf(buf, PAGE_SIZE, "%s\n", @@ -521,7 +593,7 @@ qla2x00_pci_info_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_state_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int len = 0; if (atomic_read(&ha->loop_state) == LOOP_DOWN || @@ -559,7 +631,7 @@ qla2x00_state_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_zio_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int len = 0; switch (ha->zio_mode) { @@ -576,7 +648,7 @@ qla2x00_zio_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int val = 0; uint16_t zio_mode; @@ -602,7 +674,7 @@ qla2x00_zio_store(struct class_device *cdev, const char *buf, size_t count) static ssize_t qla2x00_zio_timer_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100); } @@ -611,7 +683,7 @@ static ssize_t qla2x00_zio_timer_store(struct class_device *cdev, const char *buf, size_t count) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int val = 0; uint16_t zio_timer; @@ -629,7 +701,7 @@ qla2x00_zio_timer_store(struct class_device *cdev, const char *buf, static ssize_t qla2x00_beacon_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int len = 0; if (ha->beacon_blink_led) @@ -643,7 +715,7 @@ static ssize_t qla2x00_beacon_store(struct class_device *cdev, const char *buf, size_t count) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); int val = 0; int rval; @@ -673,7 +745,7 @@ qla2x00_beacon_store(struct class_device *cdev, const char *buf, static ssize_t qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], ha->bios_revision[0]); @@ -682,7 +754,7 @@ qla2x00_optrom_bios_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], ha->efi_revision[0]); @@ -691,7 +763,7 @@ qla2x00_optrom_efi_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], ha->fcode_revision[0]); @@ -700,7 +772,7 @@ qla2x00_optrom_fcode_version_show(struct class_device *cdev, char *buf) static ssize_t qla2x00_optrom_fw_version_show(struct class_device *cdev, char *buf) { - scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); + scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d.%02d %d\n", ha->fw_revision[0], ha->fw_revision[1], ha->fw_revision[2], @@ -757,7 +829,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = { static void qla2x00_get_host_port_id(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); fc_host_port_id(shost) = ha->d_id.b.domain << 16 | ha->d_id.b.area << 8 | ha->d_id.b.al_pa; @@ -766,7 +838,7 @@ qla2x00_get_host_port_id(struct Scsi_Host *shost) static void qla2x00_get_host_speed(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); uint32_t speed = 0; switch (ha->link_data_rate) { @@ -786,7 +858,7 @@ qla2x00_get_host_speed(struct Scsi_Host *shost) static void qla2x00_get_host_port_type(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); uint32_t port_type = FC_PORTTYPE_UNKNOWN; switch (ha->current_topology) { @@ -810,7 +882,7 @@ static void qla2x00_get_starget_node_name(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(starget->dev.parent); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); fc_port_t *fcport; u64 node_name = 0; @@ -828,7 +900,7 @@ static void qla2x00_get_starget_port_name(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(starget->dev.parent); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); fc_port_t *fcport; u64 port_name = 0; @@ -846,7 +918,7 @@ static void qla2x00_get_starget_port_id(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(starget->dev.parent); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); fc_port_t *fcport; uint32_t port_id = ~0U; @@ -865,7 +937,7 @@ static void qla2x00_get_rport_loss_tmo(struct fc_rport *rport) { struct Scsi_Host *host = rport_to_shost(rport); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); rport->dev_loss_tmo = ha->port_down_retry_count + 5; } @@ -874,7 +946,7 @@ static void qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) { struct Scsi_Host *host = rport_to_shost(rport); - scsi_qla_host_t *ha = to_qla_host(host); + scsi_qla_host_t *ha = shost_priv(host); if (timeout) ha->port_down_retry_count = timeout; @@ -887,7 +959,7 @@ qla2x00_set_rport_loss_tmo(struct fc_rport *rport, uint32_t timeout) static int qla2x00_issue_lip(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); return 0; @@ -896,7 +968,7 @@ qla2x00_issue_lip(struct Scsi_Host *shost) static struct fc_host_statistics * qla2x00_get_fc_host_stats(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); int rval; uint16_t mb_stat[1]; link_stat_t stat_buf; @@ -934,7 +1006,7 @@ done: static void qla2x00_get_host_symbolic_name(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); qla2x00_get_sym_node_name(ha, fc_host_symbolic_name(shost)); } @@ -942,7 +1014,7 @@ qla2x00_get_host_symbolic_name(struct Scsi_Host *shost) static void qla2x00_set_host_system_hostname(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); } @@ -950,7 +1022,7 @@ qla2x00_set_host_system_hostname(struct Scsi_Host *shost) static void qla2x00_get_host_fabric_name(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); u64 node_name; if (ha->device_flags & SWITCH_FOUND) @@ -964,7 +1036,7 @@ qla2x00_get_host_fabric_name(struct Scsi_Host *shost) static void qla2x00_get_host_port_state(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = to_qla_host(shost); + scsi_qla_host_t *ha = shost_priv(shost); if (!ha->flags.online) fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; @@ -978,7 +1050,7 @@ static int qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) { int ret = 0; - scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha; ret = qla24xx_vport_create_req_sanity_check(fc_vport); @@ -1047,7 +1119,7 @@ vport_create_failed_2: int qla24xx_vport_delete(struct fc_vport *fc_vport) { - scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha = fc_vport->dd_data; qla24xx_disable_vp(vha); @@ -1178,6 +1250,6 @@ qla2x00_init_host_attr(scsi_qla_host_t *ha) fc_host_node_name(ha->host) = wwn_to_u64(ha->node_name); fc_host_port_name(ha->host) = wwn_to_u64(ha->port_name); fc_host_supported_classes(ha->host) = FC_COS_CLASS3; - fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC; + fc_host_max_npiv_vports(ha->host) = ha->max_npiv_vports;; fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count; } diff --git a/drivers/scsi/qla2xxx/qla_dbg.c b/drivers/scsi/qla2xxx/qla_dbg.c index c6680348b648..eaa04dabcdf6 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.c +++ b/drivers/scsi/qla2xxx/qla_dbg.c @@ -38,7 +38,7 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr) } static int -qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, +qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, uint32_t cram_size, uint32_t *ext_mem, void **nxt) { int rval; @@ -152,6 +152,103 @@ qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, return rval; } +static uint32_t * +qla24xx_read_window(struct device_reg_24xx __iomem *reg, uint32_t iobase, + uint32_t count, uint32_t *buf) +{ + uint32_t __iomem *dmp_reg; + + WRT_REG_DWORD(®->iobase_addr, iobase); + dmp_reg = ®->iobase_window; + while (count--) + *buf++ = htonl(RD_REG_DWORD(dmp_reg++)); + + return buf; +} + +static inline int +qla24xx_pause_risc(struct device_reg_24xx __iomem *reg) +{ + int rval = QLA_SUCCESS; + uint32_t cnt; + + if (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) + return rval; + + WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); + for (cnt = 30000; (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) + udelay(100); + else + rval = QLA_FUNCTION_TIMEOUT; + } + + return rval; +} + +static int +qla24xx_soft_reset(scsi_qla_host_t *ha) +{ + int rval = QLA_SUCCESS; + uint32_t cnt; + uint16_t mb0, wd; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + /* Reset RISC. */ + WRT_REG_DWORD(®->ctrl_status, CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_DWORD(®->ctrl_status) & CSRX_DMA_ACTIVE) == 0) + break; + + udelay(10); + } + + WRT_REG_DWORD(®->ctrl_status, + CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); + pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); + + udelay(100); + /* Wait for firmware to complete NVRAM accesses. */ + mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); + for (cnt = 10000 ; cnt && mb0; cnt--) { + udelay(5); + mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); + barrier(); + } + + /* Wait for soft-reset to complete. */ + for (cnt = 0; cnt < 30000; cnt++) { + if ((RD_REG_DWORD(®->ctrl_status) & + CSRX_ISP_SOFT_RESET) == 0) + break; + + udelay(10); + } + WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); + RD_REG_DWORD(®->hccr); /* PCI Posting. */ + + for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) + udelay(100); + else + rval = QLA_FUNCTION_TIMEOUT; + } + + return rval; +} + +static inline void +qla2xxx_read_window(struct device_reg_2xxx __iomem *reg, uint32_t count, + uint16_t *buf) +{ + uint16_t __iomem *dmp_reg = ®->u.isp2300.fb_cmd; + + while (count--) + *buf++ = htons(RD_REG_WORD(dmp_reg++)); +} + /** * qla2300_fw_dump() - Dumps binary data from the 2300 firmware. * @ha: HA context @@ -214,88 +311,61 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) } if (rval == QLA_SUCCESS) { - dmp_reg = (uint16_t __iomem *)(reg + 0); + dmp_reg = ®->flash_address; for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); + dmp_reg = ®->u.isp2300.req_q_in; for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++) fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x40); + dmp_reg = ®->u.isp2300.mailbox0; for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); WRT_REG_WORD(®->ctrl_status, 0x40); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->resp_dma_reg) / 2; cnt++) - fw->resp_dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 32, fw->resp_dma_reg); WRT_REG_WORD(®->ctrl_status, 0x50); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) - fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 48, fw->dma_reg); WRT_REG_WORD(®->ctrl_status, 0x00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); + dmp_reg = ®->risc_hw; for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); WRT_REG_WORD(®->pcr, 0x2000); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++) - fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); WRT_REG_WORD(®->pcr, 0x2200); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++) - fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp1_reg); WRT_REG_WORD(®->pcr, 0x2400); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++) - fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp2_reg); WRT_REG_WORD(®->pcr, 0x2600); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++) - fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp3_reg); WRT_REG_WORD(®->pcr, 0x2800); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++) - fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp4_reg); WRT_REG_WORD(®->pcr, 0x2A00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++) - fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp5_reg); WRT_REG_WORD(®->pcr, 0x2C00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++) - fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp6_reg); WRT_REG_WORD(®->pcr, 0x2E00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++) - fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp7_reg); WRT_REG_WORD(®->ctrl_status, 0x10); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++) - fw->frame_buf_hdw_reg[cnt] = - htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg); WRT_REG_WORD(®->ctrl_status, 0x20); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++) - fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->fpm_b0_reg); WRT_REG_WORD(®->ctrl_status, 0x30); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++) - fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->fpm_b1_reg); /* Reset RISC. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); @@ -567,83 +637,59 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) rval = QLA_FUNCTION_TIMEOUT; } if (rval == QLA_SUCCESS) { - dmp_reg = (uint16_t __iomem *)(reg + 0); + dmp_reg = ®->flash_address; for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); + dmp_reg = ®->u.isp2100.mailbox0; for (cnt = 0; cnt < ha->mbx_count; cnt++) { - if (cnt == 8) { - dmp_reg = (uint16_t __iomem *) - ((uint8_t __iomem *)reg + 0xe0); - } + if (cnt == 8) + dmp_reg = ®->u_end.isp2200.mailbox8; + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); } - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x20); + dmp_reg = ®->u.isp2100.unused_2[0]; for (cnt = 0; cnt < sizeof(fw->dma_reg) / 2; cnt++) fw->dma_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); WRT_REG_WORD(®->ctrl_status, 0x00); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); + dmp_reg = ®->risc_hw; for (cnt = 0; cnt < sizeof(fw->risc_hdw_reg) / 2; cnt++) fw->risc_hdw_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); WRT_REG_WORD(®->pcr, 0x2000); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp0_reg) / 2; cnt++) - fw->risc_gp0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); WRT_REG_WORD(®->pcr, 0x2100); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp1_reg) / 2; cnt++) - fw->risc_gp1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp1_reg); WRT_REG_WORD(®->pcr, 0x2200); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp2_reg) / 2; cnt++) - fw->risc_gp2_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp2_reg); WRT_REG_WORD(®->pcr, 0x2300); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp3_reg) / 2; cnt++) - fw->risc_gp3_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp3_reg); WRT_REG_WORD(®->pcr, 0x2400); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp4_reg) / 2; cnt++) - fw->risc_gp4_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp4_reg); WRT_REG_WORD(®->pcr, 0x2500); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp5_reg) / 2; cnt++) - fw->risc_gp5_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp5_reg); WRT_REG_WORD(®->pcr, 0x2600); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp6_reg) / 2; cnt++) - fw->risc_gp6_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp6_reg); WRT_REG_WORD(®->pcr, 0x2700); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->risc_gp7_reg) / 2; cnt++) - fw->risc_gp7_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->risc_gp7_reg); WRT_REG_WORD(®->ctrl_status, 0x10); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->frame_buf_hdw_reg) / 2; cnt++) - fw->frame_buf_hdw_reg[cnt] = - htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg); WRT_REG_WORD(®->ctrl_status, 0x20); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->fpm_b0_reg) / 2; cnt++) - fw->fpm_b0_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->fpm_b0_reg); WRT_REG_WORD(®->ctrl_status, 0x30); - dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x80); - for (cnt = 0; cnt < sizeof(fw->fpm_b1_reg) / 2; cnt++) - fw->fpm_b1_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); + qla2xxx_read_window(reg, 64, fw->fpm_b1_reg); /* Reset the ISP. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); @@ -750,7 +796,6 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) int rval; uint32_t cnt; uint32_t risc_address; - uint16_t mb0, wd; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; @@ -782,547 +827,198 @@ qla24xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) fw = &ha->fw_dump->isp.isp24; qla2xxx_prep_dump(ha, ha->fw_dump); - rval = QLA_SUCCESS; fw->host_status = htonl(RD_REG_DWORD(®->host_status)); /* Pause RISC. */ - if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) { - WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | - HCCRX_CLR_HOST_INT); - RD_REG_DWORD(®->hccr); /* PCI Posting. */ - WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); - for (cnt = 30000; - (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(100); - else - rval = QLA_FUNCTION_TIMEOUT; - } - } - - if (rval == QLA_SUCCESS) { - /* Host interface registers. */ - dmp_reg = (uint32_t __iomem *)(reg + 0); - for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) - fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Disable interrupts. */ - WRT_REG_DWORD(®->ictrl, 0); - RD_REG_DWORD(®->ictrl); - - /* Shadow registers. */ - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - RD_REG_DWORD(®->iobase_addr); - WRT_REG_DWORD(®->iobase_select, 0xB0000000); - fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0100000); - fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0200000); - fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0300000); - fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0400000); - fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0500000); - fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0600000); - fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - /* Mailbox registers. */ - mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) - fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); - - /* Transfer sequence registers. */ - iter_reg = fw->xseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xBF00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFE0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xseq_0_reg) / 4; cnt++) - fw->xseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFF0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) - fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Receive sequence registers. */ - iter_reg = fw->rseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xFF00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFD0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_0_reg) / 4; cnt++) - fw->rseq_0_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFE0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) - fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFF0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) - fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Command DMA registers. */ - WRT_REG_DWORD(®->iobase_addr, 0x7100); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) - fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Queues. */ - iter_reg = fw->req0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7200); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->resp0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7300); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->req1_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7400); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Transmit DMA registers. */ - iter_reg = fw->xmt0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7600); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7610); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt1_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7620); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7630); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt2_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7640); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7650); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt3_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7660); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7670); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt4_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7680); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7690); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x76A0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) - fw->xmt_data_dma_reg[cnt] = - htonl(RD_REG_DWORD(dmp_reg++)); - - /* Receive DMA registers. */ - iter_reg = fw->rcvt0_data_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7700); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7710); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->rcvt1_data_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7720); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7730); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* RISC registers. */ - iter_reg = fw->risc_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0x0F00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Local memory controller registers. */ - iter_reg = fw->lmc_reg; - WRT_REG_DWORD(®->iobase_addr, 0x3000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Fibre Protocol Module registers. */ - iter_reg = fw->fpm_hdw_reg; - WRT_REG_DWORD(®->iobase_addr, 0x4000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4070); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4080); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4090); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x40A0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x40B0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Frame Buffer registers. */ - iter_reg = fw->fb_hdw_reg; - WRT_REG_DWORD(®->iobase_addr, 0x6000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6100); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6130); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6150); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6170); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6190); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x61B0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Reset RISC. */ - WRT_REG_DWORD(®->ctrl_status, - CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); - for (cnt = 0; cnt < 30000; cnt++) { - if ((RD_REG_DWORD(®->ctrl_status) & - CSRX_DMA_ACTIVE) == 0) - break; - - udelay(10); - } - - WRT_REG_DWORD(®->ctrl_status, - CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); - pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); - - udelay(100); - /* Wait for firmware to complete NVRAM accesses. */ - mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); - for (cnt = 10000 ; cnt && mb0; cnt--) { - udelay(5); - mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); - barrier(); - } - - /* Wait for soft-reset to complete. */ - for (cnt = 0; cnt < 30000; cnt++) { - if ((RD_REG_DWORD(®->ctrl_status) & - CSRX_ISP_SOFT_RESET) == 0) - break; - - udelay(10); - } - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); - RD_REG_DWORD(®->hccr); /* PCI Posting. */ - } - - for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(100); - else - rval = QLA_FUNCTION_TIMEOUT; - } - - if (rval == QLA_SUCCESS) - rval = qla2xxx_dump_memory(ha, fw->code_ram, - sizeof(fw->code_ram), fw->ext_mem, &nxt); - - if (rval == QLA_SUCCESS) { - nxt = qla2xxx_copy_queues(ha, nxt); - if (ha->eft) - memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); - } - + rval = qla24xx_pause_risc(reg); + if (rval != QLA_SUCCESS) + goto qla24xx_fw_dump_failed_0; + + /* Host interface registers. */ + dmp_reg = ®->flash_addr; + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Disable interrupts. */ + WRT_REG_DWORD(®->ictrl, 0); + RD_REG_DWORD(®->ictrl); + + /* Shadow registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x0F70); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_select, 0xB0000000); + fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0100000); + fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0200000); + fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0300000); + fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0400000); + fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0500000); + fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0600000); + fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + /* Mailbox registers. */ + mbx_reg = ®->mailbox0; + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); + + /* Transfer sequence registers. */ + iter_reg = fw->xseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg); + qla24xx_read_window(reg, 0xBF70, 16, iter_reg); + + qla24xx_read_window(reg, 0xBFE0, 16, fw->xseq_0_reg); + qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg); + + /* Receive sequence registers. */ + iter_reg = fw->rseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg); + qla24xx_read_window(reg, 0xFF70, 16, iter_reg); + + qla24xx_read_window(reg, 0xFFD0, 16, fw->rseq_0_reg); + qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg); + qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg); + + /* Command DMA registers. */ + qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg); + + /* Queues. */ + iter_reg = fw->req0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->resp0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->req1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Transmit DMA registers. */ + iter_reg = fw->xmt0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg); + qla24xx_read_window(reg, 0x7610, 16, iter_reg); + + iter_reg = fw->xmt1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg); + qla24xx_read_window(reg, 0x7630, 16, iter_reg); + + iter_reg = fw->xmt2_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg); + qla24xx_read_window(reg, 0x7650, 16, iter_reg); + + iter_reg = fw->xmt3_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg); + qla24xx_read_window(reg, 0x7670, 16, iter_reg); + + iter_reg = fw->xmt4_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg); + qla24xx_read_window(reg, 0x7690, 16, iter_reg); + + qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg); + + /* Receive DMA registers. */ + iter_reg = fw->rcvt0_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg); + qla24xx_read_window(reg, 0x7710, 16, iter_reg); + + iter_reg = fw->rcvt1_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg); + qla24xx_read_window(reg, 0x7730, 16, iter_reg); + + /* RISC registers. */ + iter_reg = fw->risc_gp_reg; + iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg); + qla24xx_read_window(reg, 0x0F70, 16, iter_reg); + + /* Local memory controller registers. */ + iter_reg = fw->lmc_reg; + iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg); + qla24xx_read_window(reg, 0x3060, 16, iter_reg); + + /* Fibre Protocol Module registers. */ + iter_reg = fw->fpm_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg); + qla24xx_read_window(reg, 0x40B0, 16, iter_reg); + + /* Frame Buffer registers. */ + iter_reg = fw->fb_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg); + qla24xx_read_window(reg, 0x61B0, 16, iter_reg); + + rval = qla24xx_soft_reset(ha); + if (rval != QLA_SUCCESS) + goto qla24xx_fw_dump_failed_0; + + rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram), + fw->ext_mem, &nxt); + if (rval != QLA_SUCCESS) + goto qla24xx_fw_dump_failed_0; + + nxt = qla2xxx_copy_queues(ha, nxt); + if (ha->eft) + memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); + +qla24xx_fw_dump_failed_0: if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); @@ -1346,7 +1042,6 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) int rval; uint32_t cnt; uint32_t risc_address; - uint16_t mb0, wd; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; uint32_t __iomem *dmp_reg; @@ -1377,655 +1072,260 @@ qla25xx_fw_dump(scsi_qla_host_t *ha, int hardware_locked) } fw = &ha->fw_dump->isp.isp25; qla2xxx_prep_dump(ha, ha->fw_dump); + ha->fw_dump->version = __constant_htonl(2); - rval = QLA_SUCCESS; fw->host_status = htonl(RD_REG_DWORD(®->host_status)); /* Pause RISC. */ - if ((RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0) { - WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_RESET | - HCCRX_CLR_HOST_INT); - RD_REG_DWORD(®->hccr); /* PCI Posting. */ - WRT_REG_DWORD(®->hccr, HCCRX_SET_RISC_PAUSE); - for (cnt = 30000; - (RD_REG_DWORD(®->hccr) & HCCRX_RISC_PAUSE) == 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(100); - else - rval = QLA_FUNCTION_TIMEOUT; - } - } - - if (rval == QLA_SUCCESS) { - /* Host interface registers. */ - dmp_reg = (uint32_t __iomem *)(reg + 0); - for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) - fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Disable interrupts. */ - WRT_REG_DWORD(®->ictrl, 0); - RD_REG_DWORD(®->ictrl); - - /* Shadow registers. */ - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - RD_REG_DWORD(®->iobase_addr); - WRT_REG_DWORD(®->iobase_select, 0xB0000000); - fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0100000); - fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0200000); - fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0300000); - fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0400000); - fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0500000); - fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0600000); - fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0700000); - fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0800000); - fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0900000); - fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - WRT_REG_DWORD(®->iobase_select, 0xB0A00000); - fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); - - /* RISC I/O register. */ - WRT_REG_DWORD(®->iobase_addr, 0x0010); - RD_REG_DWORD(®->iobase_addr); - fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); - - /* Mailbox registers. */ - mbx_reg = ®->mailbox0; - for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) - fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); - - /* Transfer sequence registers. */ - iter_reg = fw->xseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xBF00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBF70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xseq_0_reg; - WRT_REG_DWORD(®->iobase_addr, 0xBFC0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFD0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFE0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xBFF0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xseq_1_reg) / 4; cnt++) - fw->xseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Receive sequence registers. */ - iter_reg = fw->rseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xFF00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFF70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->rseq_0_reg; - WRT_REG_DWORD(®->iobase_addr, 0xFFC0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFD0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFE0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_1_reg) / 4; cnt++) - fw->rseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xFFF0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->rseq_2_reg) / 4; cnt++) - fw->rseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Auxiliary sequence registers. */ - iter_reg = fw->aseq_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0xB000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB070); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->aseq_0_reg; - WRT_REG_DWORD(®->iobase_addr, 0xB0C0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB0D0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB0E0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->aseq_1_reg) / 4; cnt++) - fw->aseq_1_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0xB0F0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->aseq_2_reg) / 4; cnt++) - fw->aseq_2_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Command DMA registers. */ - WRT_REG_DWORD(®->iobase_addr, 0x7100); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->cmd_dma_reg) / 4; cnt++) - fw->cmd_dma_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Queues. */ - iter_reg = fw->req0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7200); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->resp0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7300); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->req1_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7400); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 8; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - dmp_reg = ®->iobase_q; - for (cnt = 0; cnt < 7; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Transmit DMA registers. */ - iter_reg = fw->xmt0_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7600); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7610); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt1_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7620); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7630); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt2_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7640); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7650); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt3_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7660); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7670); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->xmt4_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7680); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7690); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x76A0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < sizeof(fw->xmt_data_dma_reg) / 4; cnt++) - fw->xmt_data_dma_reg[cnt] = - htonl(RD_REG_DWORD(dmp_reg++)); - - /* Receive DMA registers. */ - iter_reg = fw->rcvt0_data_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7700); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7710); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - iter_reg = fw->rcvt1_data_dma_reg; - WRT_REG_DWORD(®->iobase_addr, 0x7720); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x7730); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* RISC registers. */ - iter_reg = fw->risc_gp_reg; - WRT_REG_DWORD(®->iobase_addr, 0x0F00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F10); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F20); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F30); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F40); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F50); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F60); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x0F70); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Local memory controller registers. */ - iter_reg = fw->lmc_reg; - WRT_REG_DWORD(®->iobase_addr, 0x3000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x3070); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Fibre Protocol Module registers. */ - iter_reg = fw->fpm_hdw_reg; - WRT_REG_DWORD(®->iobase_addr, 0x4000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4050); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4060); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4070); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4080); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x4090); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x40A0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x40B0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Frame Buffer registers. */ - iter_reg = fw->fb_hdw_reg; - WRT_REG_DWORD(®->iobase_addr, 0x6000); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6010); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6020); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6030); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6040); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6100); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6130); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6150); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6170); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6190); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x61B0); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - WRT_REG_DWORD(®->iobase_addr, 0x6F00); - dmp_reg = ®->iobase_window; - for (cnt = 0; cnt < 16; cnt++) - *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); - - /* Reset RISC. */ - WRT_REG_DWORD(®->ctrl_status, - CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); - for (cnt = 0; cnt < 30000; cnt++) { - if ((RD_REG_DWORD(®->ctrl_status) & - CSRX_DMA_ACTIVE) == 0) - break; - - udelay(10); - } - - WRT_REG_DWORD(®->ctrl_status, - CSRX_ISP_SOFT_RESET|CSRX_DMA_SHUTDOWN|MWB_4096_BYTES); - pci_read_config_word(ha->pdev, PCI_COMMAND, &wd); - - udelay(100); - /* Wait for firmware to complete NVRAM accesses. */ - mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); - for (cnt = 10000 ; cnt && mb0; cnt--) { - udelay(5); - mb0 = (uint32_t) RD_REG_WORD(®->mailbox0); - barrier(); - } - - /* Wait for soft-reset to complete. */ - for (cnt = 0; cnt < 30000; cnt++) { - if ((RD_REG_DWORD(®->ctrl_status) & - CSRX_ISP_SOFT_RESET) == 0) - break; - - udelay(10); - } - WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_RESET); - RD_REG_DWORD(®->hccr); /* PCI Posting. */ - } - - for (cnt = 30000; RD_REG_WORD(®->mailbox0) != 0 && - rval == QLA_SUCCESS; cnt--) { - if (cnt) - udelay(100); - else - rval = QLA_FUNCTION_TIMEOUT; - } - - if (rval == QLA_SUCCESS) - rval = qla2xxx_dump_memory(ha, fw->code_ram, - sizeof(fw->code_ram), fw->ext_mem, &nxt); - - if (rval == QLA_SUCCESS) { - nxt = qla2xxx_copy_queues(ha, nxt); - if (ha->eft) - memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); - } - + rval = qla24xx_pause_risc(reg); + if (rval != QLA_SUCCESS) + goto qla25xx_fw_dump_failed_0; + + /* Host/Risc registers. */ + iter_reg = fw->host_risc_reg; + iter_reg = qla24xx_read_window(reg, 0x7000, 16, iter_reg); + qla24xx_read_window(reg, 0x7010, 16, iter_reg); + + /* PCIe registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x7C00); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_window, 0x01); + dmp_reg = ®->iobase_c4; + fw->pcie_regs[0] = htonl(RD_REG_DWORD(dmp_reg++)); + fw->pcie_regs[1] = htonl(RD_REG_DWORD(dmp_reg++)); + fw->pcie_regs[2] = htonl(RD_REG_DWORD(dmp_reg)); + fw->pcie_regs[3] = htonl(RD_REG_DWORD(®->iobase_window)); + WRT_REG_DWORD(®->iobase_window, 0x00); + RD_REG_DWORD(®->iobase_window); + + /* Host interface registers. */ + dmp_reg = ®->flash_addr; + for (cnt = 0; cnt < sizeof(fw->host_reg) / 4; cnt++) + fw->host_reg[cnt] = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Disable interrupts. */ + WRT_REG_DWORD(®->ictrl, 0); + RD_REG_DWORD(®->ictrl); + + /* Shadow registers. */ + WRT_REG_DWORD(®->iobase_addr, 0x0F70); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_select, 0xB0000000); + fw->shadow_reg[0] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0100000); + fw->shadow_reg[1] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0200000); + fw->shadow_reg[2] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0300000); + fw->shadow_reg[3] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0400000); + fw->shadow_reg[4] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0500000); + fw->shadow_reg[5] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0600000); + fw->shadow_reg[6] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0700000); + fw->shadow_reg[7] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0800000); + fw->shadow_reg[8] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0900000); + fw->shadow_reg[9] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + WRT_REG_DWORD(®->iobase_select, 0xB0A00000); + fw->shadow_reg[10] = htonl(RD_REG_DWORD(®->iobase_sdata)); + + /* RISC I/O register. */ + WRT_REG_DWORD(®->iobase_addr, 0x0010); + fw->risc_io_reg = htonl(RD_REG_DWORD(®->iobase_window)); + + /* Mailbox registers. */ + mbx_reg = ®->mailbox0; + for (cnt = 0; cnt < sizeof(fw->mailbox_reg) / 2; cnt++) + fw->mailbox_reg[cnt] = htons(RD_REG_WORD(mbx_reg++)); + + /* Transfer sequence registers. */ + iter_reg = fw->xseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xBF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBF60, 16, iter_reg); + qla24xx_read_window(reg, 0xBF70, 16, iter_reg); + + iter_reg = fw->xseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xBFC0, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xBFD0, 16, iter_reg); + qla24xx_read_window(reg, 0xBFE0, 16, iter_reg); + + qla24xx_read_window(reg, 0xBFF0, 16, fw->xseq_1_reg); + + /* Receive sequence registers. */ + iter_reg = fw->rseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xFF00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xFF60, 16, iter_reg); + qla24xx_read_window(reg, 0xFF70, 16, iter_reg); + + iter_reg = fw->rseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xFFC0, 16, iter_reg); + qla24xx_read_window(reg, 0xFFD0, 16, iter_reg); + + qla24xx_read_window(reg, 0xFFE0, 16, fw->rseq_1_reg); + qla24xx_read_window(reg, 0xFFF0, 16, fw->rseq_2_reg); + + /* Auxiliary sequence registers. */ + iter_reg = fw->aseq_gp_reg; + iter_reg = qla24xx_read_window(reg, 0xB000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0xB060, 16, iter_reg); + qla24xx_read_window(reg, 0xB070, 16, iter_reg); + + iter_reg = fw->aseq_0_reg; + iter_reg = qla24xx_read_window(reg, 0xB0C0, 16, iter_reg); + qla24xx_read_window(reg, 0xB0D0, 16, iter_reg); + + qla24xx_read_window(reg, 0xB0E0, 16, fw->aseq_1_reg); + qla24xx_read_window(reg, 0xB0F0, 16, fw->aseq_2_reg); + + /* Command DMA registers. */ + qla24xx_read_window(reg, 0x7100, 16, fw->cmd_dma_reg); + + /* Queues. */ + iter_reg = fw->req0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7200, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->resp0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7300, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + iter_reg = fw->req1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7400, 8, iter_reg); + dmp_reg = ®->iobase_q; + for (cnt = 0; cnt < 7; cnt++) + *iter_reg++ = htonl(RD_REG_DWORD(dmp_reg++)); + + /* Transmit DMA registers. */ + iter_reg = fw->xmt0_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7600, 16, iter_reg); + qla24xx_read_window(reg, 0x7610, 16, iter_reg); + + iter_reg = fw->xmt1_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7620, 16, iter_reg); + qla24xx_read_window(reg, 0x7630, 16, iter_reg); + + iter_reg = fw->xmt2_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7640, 16, iter_reg); + qla24xx_read_window(reg, 0x7650, 16, iter_reg); + + iter_reg = fw->xmt3_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7660, 16, iter_reg); + qla24xx_read_window(reg, 0x7670, 16, iter_reg); + + iter_reg = fw->xmt4_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7680, 16, iter_reg); + qla24xx_read_window(reg, 0x7690, 16, iter_reg); + + qla24xx_read_window(reg, 0x76A0, 16, fw->xmt_data_dma_reg); + + /* Receive DMA registers. */ + iter_reg = fw->rcvt0_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7700, 16, iter_reg); + qla24xx_read_window(reg, 0x7710, 16, iter_reg); + + iter_reg = fw->rcvt1_data_dma_reg; + iter_reg = qla24xx_read_window(reg, 0x7720, 16, iter_reg); + qla24xx_read_window(reg, 0x7730, 16, iter_reg); + + /* RISC registers. */ + iter_reg = fw->risc_gp_reg; + iter_reg = qla24xx_read_window(reg, 0x0F00, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F10, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F20, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F30, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F40, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F50, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x0F60, 16, iter_reg); + qla24xx_read_window(reg, 0x0F70, 16, iter_reg); + + /* Local memory controller registers. */ + iter_reg = fw->lmc_reg; + iter_reg = qla24xx_read_window(reg, 0x3000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x3060, 16, iter_reg); + qla24xx_read_window(reg, 0x3070, 16, iter_reg); + + /* Fibre Protocol Module registers. */ + iter_reg = fw->fpm_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x4000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4050, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4060, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4070, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4080, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x4090, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x40A0, 16, iter_reg); + qla24xx_read_window(reg, 0x40B0, 16, iter_reg); + + /* Frame Buffer registers. */ + iter_reg = fw->fb_hdw_reg; + iter_reg = qla24xx_read_window(reg, 0x6000, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6010, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6020, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6030, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6040, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6100, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6130, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6150, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6170, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x6190, 16, iter_reg); + iter_reg = qla24xx_read_window(reg, 0x61B0, 16, iter_reg); + qla24xx_read_window(reg, 0x6F00, 16, iter_reg); + + rval = qla24xx_soft_reset(ha); + if (rval != QLA_SUCCESS) + goto qla25xx_fw_dump_failed_0; + + rval = qla24xx_dump_memory(ha, fw->code_ram, sizeof(fw->code_ram), + fw->ext_mem, &nxt); + if (rval != QLA_SUCCESS) + goto qla25xx_fw_dump_failed_0; + + nxt = qla2xxx_copy_queues(ha, nxt); + if (ha->eft) + memcpy(nxt, ha->eft, ntohl(ha->fw_dump->eft_size)); + +qla25xx_fw_dump_failed_0: if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); @@ -2102,7 +1402,7 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd) struct scsi_qla_host *ha; srb_t *sp; - ha = (struct scsi_qla_host *)cmd->device->host->hostdata; + ha = shost_priv(cmd->device->host); sp = (srb_t *) cmd->SCp.ptr; printk("SCSI Command @=0x%p, Handle=0x%p\n", cmd, cmd->host_scribble); diff --git a/drivers/scsi/qla2xxx/qla_dbg.h b/drivers/scsi/qla2xxx/qla_dbg.h index cca4b0d8253e..a50ecf0b7c84 100644 --- a/drivers/scsi/qla2xxx/qla_dbg.h +++ b/drivers/scsi/qla2xxx/qla_dbg.h @@ -215,6 +215,8 @@ struct qla24xx_fw_dump { struct qla25xx_fw_dump { uint32_t host_status; + uint32_t host_risc_reg[32]; + uint32_t pcie_regs[4]; uint32_t host_reg[32]; uint32_t shadow_reg[11]; uint32_t risc_io_reg; diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index c1964866a423..1900fbf6cd74 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -23,6 +23,7 @@ #include <linux/interrupt.h> #include <linux/workqueue.h> #include <linux/firmware.h> +#include <linux/aer.h> #include <asm/semaphore.h> #include <scsi/scsi.h> @@ -184,8 +185,6 @@ * SCSI Request Block */ typedef struct srb { - struct list_head list; - struct scsi_qla_host *ha; /* HA the SP is queued on */ struct fc_port *fcport; @@ -316,7 +315,9 @@ struct device_reg_2xxx { } u; uint16_t fpm_diag_config; - uint16_t unused_5[0x6]; /* Gap */ + uint16_t unused_5[0x4]; /* Gap */ + uint16_t risc_hw; + uint16_t unused_5_1; /* Gap */ uint16_t pcr; /* Processor Control Register. */ uint16_t unused_6[0x5]; /* Gap */ uint16_t mctr; /* Memory Configuration and Timing. */ @@ -1702,7 +1703,7 @@ struct ct_fdmi_hba_attributes { /* * Port attribute types. */ -#define FDMI_PORT_ATTR_COUNT 5 +#define FDMI_PORT_ATTR_COUNT 6 #define FDMI_PORT_FC4_TYPES 1 #define FDMI_PORT_SUPPORT_SPEED 2 #define FDMI_PORT_CURRENT_SPEED 3 @@ -2476,6 +2477,8 @@ typedef struct scsi_qla_host { #define QLA_SWAITING 0 #define QLA_SREADING 1 #define QLA_SWRITING 2 + uint32_t optrom_region_start; + uint32_t optrom_region_size; /* PCI expansion ROM image information. */ #define ROM_CODE_TYPE_BIOS 0 @@ -2529,7 +2532,7 @@ typedef struct scsi_qla_host { #define VP_ERR_FAB_NORESOURCES 3 #define VP_ERR_FAB_LOGOUT 4 #define VP_ERR_ADAP_NORESOURCES 5 - int max_npiv_vports; /* 63 or 125 per topoloty */ + uint16_t max_npiv_vports; /* 63 or 125 per topoloty */ int cur_vport_count; } scsi_qla_host_t; @@ -2542,8 +2545,6 @@ typedef struct scsi_qla_host { test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags) || \ atomic_read(&ha->loop_state) == LOOP_DOWN) -#define to_qla_host(x) ((scsi_qla_host_t *) (x)->hostdata) - #define qla_printk(level, ha, format, arg...) \ dev_printk(level , &((ha)->pdev->dev) , format , ## arg) diff --git a/drivers/scsi/qla2xxx/qla_fw.h b/drivers/scsi/qla2xxx/qla_fw.h index 99fe49618d61..25364b1aaf12 100644 --- a/drivers/scsi/qla2xxx/qla_fw.h +++ b/drivers/scsi/qla2xxx/qla_fw.h @@ -779,6 +779,8 @@ struct device_reg_24xx { #define FA_NVRAM_VPD_SIZE 0x200 #define FA_NVRAM_VPD0_ADDR 0x00 #define FA_NVRAM_VPD1_ADDR 0x100 + +#define FA_BOOT_CODE_ADDR 0x00000 /* * RISC code begins at offset 512KB * within flash. Consisting of two @@ -940,7 +942,9 @@ struct device_reg_24xx { uint16_t mailbox31; uint32_t iobase_window; - uint32_t unused_4[8]; /* Gap. */ + uint32_t iobase_c4; + uint32_t iobase_c8; + uint32_t unused_4_1[6]; /* Gap. */ uint32_t iobase_q; uint32_t unused_5[2]; /* Gap. */ uint32_t iobase_select; diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h index aa1e41152283..09cb2a908059 100644 --- a/drivers/scsi/qla2xxx/qla_gbl.h +++ b/drivers/scsi/qla2xxx/qla_gbl.h @@ -134,6 +134,9 @@ extern int qla2x00_load_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t); extern int +qla2x00_dump_ram(scsi_qla_host_t *, dma_addr_t, uint32_t, uint32_t); + +extern int qla2x00_execute_fw(scsi_qla_host_t *, uint32_t); extern void @@ -212,8 +215,8 @@ extern int qla2x00_get_id_list(scsi_qla_host_t *, void *, dma_addr_t, uint16_t *); extern int -qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *, - uint16_t *); +qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, + uint16_t *, uint16_t *, uint16_t *); extern int qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); @@ -302,6 +305,8 @@ extern uint8_t *qla24xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, uint32_t, uint32_t); extern int qla24xx_write_optrom_data(struct scsi_qla_host *, uint8_t *, uint32_t, uint32_t); +extern uint8_t *qla25xx_read_optrom_data(struct scsi_qla_host *, uint8_t *, + uint32_t, uint32_t); extern int qla2x00_get_flash_version(scsi_qla_host_t *, void *); extern int qla24xx_get_flash_version(scsi_qla_host_t *, void *); diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c index a7e23583f899..eb0784c9ff83 100644 --- a/drivers/scsi/qla2xxx/qla_gs.c +++ b/drivers/scsi/qla2xxx/qla_gs.c @@ -1517,7 +1517,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) /* Attributes */ ct_req->req.rpa.attrs.count = - __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT); + __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT - 1); entries = ct_req->req.rpa.port_name; /* FC4 types. */ @@ -1600,7 +1600,7 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) /* OS device name. */ eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_OS_DEVICE_NAME); - sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no); + strcpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME); alen = strlen(eiter->a.os_dev_name); alen += (alen & 3) ? (4 - (alen & 3)) : 4; eiter->len = cpu_to_be16(4 + alen); @@ -1611,6 +1611,8 @@ qla2x00_fdmi_rpa(scsi_qla_host_t *ha) /* Hostname. */ if (strlen(fc_host_system_hostname(ha->host))) { + ct_req->req.rpa.attrs.count = + __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT); eiter = (struct ct_fdmi_port_attr *) (entries + size); eiter->type = __constant_cpu_to_be16(FDMI_PORT_HOST_NAME); snprintf(eiter->a.host_name, sizeof(eiter->a.host_name), diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 1a058ec9bd0c..191dafd89be0 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -849,7 +849,8 @@ qla2x00_resize_request_q(scsi_qla_host_t *ha) return; /* Retrieve IOCB counts available to the firmware. */ - rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); + rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt, + &ha->max_npiv_vports); if (rval) return; /* No point in continuing if current settings are sufficient. */ @@ -916,9 +917,15 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) &ha->fw_attributes, &ha->fw_memory_size); qla2x00_resize_request_q(ha); ha->flags.npiv_supported = 0; - if (IS_QLA24XX(ha) && - (ha->fw_attributes & BIT_2)) + if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) && + (ha->fw_attributes & BIT_2)) { ha->flags.npiv_supported = 1; + if ((!ha->max_npiv_vports) || + ((ha->max_npiv_vports + 1) % + MAX_MULTI_ID_FABRIC)) + ha->max_npiv_vports = + MAX_NUM_VPORT_FABRIC; + } if (ql2xallocfwdump) qla2x00_alloc_fw_dump(ha); @@ -1155,8 +1162,7 @@ qla2x00_init_rings(scsi_qla_host_t *ha) DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); - mid_init_cb->count = MAX_NUM_VPORT_FABRIC; - ha->max_npiv_vports = MAX_NUM_VPORT_FABRIC; + mid_init_cb->count = ha->max_npiv_vports; rval = qla2x00_init_firmware(ha, ha->init_cb_size); if (rval) { @@ -1786,12 +1792,11 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) { fc_port_t *fcport; - fcport = kmalloc(sizeof(fc_port_t), flags); - if (fcport == NULL) - return (fcport); + fcport = kzalloc(sizeof(fc_port_t), flags); + if (!fcport) + return NULL; /* Setup fcport template structure. */ - memset(fcport, 0, sizeof (fc_port_t)); fcport->ha = ha; fcport->vp_idx = ha->vp_idx; fcport->port_type = FCT_UNKNOWN; @@ -1801,7 +1806,7 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) fcport->supported_classes = FC_COS_UNSPECIFIED; spin_lock_init(&fcport->rport_lock); - return (fcport); + return fcport; } /* @@ -2127,15 +2132,9 @@ qla2x00_iidma_fcport(scsi_qla_host_t *ha, fc_port_t *fcport) if (!IS_IIDMA_CAPABLE(ha)) return; - if (fcport->fp_speed == PORT_SPEED_UNKNOWN) { - DEBUG2(printk("scsi(%ld): %02x%02x%02x%02x%02x%02x%02x%02x -- " - "unsupported FM port operating speed.\n", - ha->host_no, fcport->port_name[0], fcport->port_name[1], - fcport->port_name[2], fcport->port_name[3], - fcport->port_name[4], fcport->port_name[5], - fcport->port_name[6], fcport->port_name[7])); + if (fcport->fp_speed == PORT_SPEED_UNKNOWN || + fcport->fp_speed > ha->link_data_rate) return; - } rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed, mb); @@ -2473,13 +2472,12 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *ha, struct list_head *new_fcports) rval = QLA_SUCCESS; /* Try GID_PT to get device list, else GAN. */ - swl = kmalloc(sizeof(sw_info_t) * MAX_FIBRE_DEVICES, GFP_ATOMIC); - if (swl == NULL) { + swl = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_ATOMIC); + if (!swl) { /*EMPTY*/ DEBUG2(printk("scsi(%ld): GID_PT allocations failed, fallback " "on GA_NXT\n", ha->host_no)); } else { - memset(swl, 0, sizeof(sw_info_t) * MAX_FIBRE_DEVICES); if (qla2x00_gid_pt(ha, swl) != QLA_SUCCESS) { kfree(swl); swl = NULL; diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c index 3a5e78cb6b3f..7f6a89bd94f3 100644 --- a/drivers/scsi/qla2xxx/qla_iocb.c +++ b/drivers/scsi/qla2xxx/qla_iocb.c @@ -308,7 +308,7 @@ qla2x00_start_scsi(srb_t *sp) handle++; if (handle == MAX_OUTSTANDING_COMMANDS) handle = 1; - if (ha->outstanding_cmds[handle] == 0) + if (!ha->outstanding_cmds[handle]) break; } if (index == MAX_OUTSTANDING_COMMANDS) @@ -711,7 +711,7 @@ qla24xx_start_scsi(srb_t *sp) handle++; if (handle == MAX_OUTSTANDING_COMMANDS) handle = 1; - if (ha->outstanding_cmds[handle] == 0) + if (!ha->outstanding_cmds[handle]) break; } if (index == MAX_OUTSTANDING_COMMANDS) diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index eecae9905ece..c4768c4f3990 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -6,6 +6,7 @@ */ #include "qla_def.h" +#include <linux/delay.h> #include <scsi/scsi_tcq.h> static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); @@ -34,6 +35,7 @@ qla2100_intr_handler(int irq, void *dev_id) int status; unsigned long flags; unsigned long iter; + uint16_t hccr; uint16_t mb[4]; ha = (scsi_qla_host_t *) dev_id; @@ -48,7 +50,23 @@ qla2100_intr_handler(int irq, void *dev_id) spin_lock_irqsave(&ha->hardware_lock, flags); for (iter = 50; iter--; ) { - if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0) + hccr = RD_REG_WORD(®->hccr); + if (hccr & HCCR_RISC_PAUSE) { + if (pci_channel_offline(ha->pdev)) + break; + + /* + * Issue a "HARD" reset in order for the RISC interrupt + * bit to be cleared. Schedule a big hammmer to get + * out of the RISC PAUSED state. + */ + WRT_REG_WORD(®->hccr, HCCR_RESET_RISC); + RD_REG_WORD(®->hccr); + + ha->isp_ops->fw_dump(ha, 1); + set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); + break; + } else if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0) break; if (RD_REG_WORD(®->semaphore) & BIT_0) { @@ -127,6 +145,9 @@ qla2300_intr_handler(int irq, void *dev_id) for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->u.isp2300.host_status); if (stat & HSR_RISC_PAUSED) { + if (pci_channel_offline(ha->pdev)) + break; + hccr = RD_REG_WORD(®->hccr); if (hccr & (BIT_15 | BIT_13 | BIT_11 | BIT_8)) qla_printk(KERN_INFO, ha, "Parity error -- " @@ -1464,6 +1485,52 @@ qla24xx_process_response_queue(struct scsi_qla_host *ha) WRT_REG_DWORD(®->rsp_q_out, ha->rsp_ring_index); } +static void +qla2xxx_check_risc_status(scsi_qla_host_t *ha) +{ + int rval; + uint32_t cnt; + struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + + if (!IS_QLA25XX(ha)) + return; + + rval = QLA_SUCCESS; + WRT_REG_DWORD(®->iobase_addr, 0x7C00); + RD_REG_DWORD(®->iobase_addr); + WRT_REG_DWORD(®->iobase_window, 0x0001); + for (cnt = 10000; (RD_REG_DWORD(®->iobase_window) & BIT_0) == 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) { + WRT_REG_DWORD(®->iobase_window, 0x0001); + udelay(10); + } else + rval = QLA_FUNCTION_TIMEOUT; + } + if (rval == QLA_SUCCESS) + goto next_test; + + WRT_REG_DWORD(®->iobase_window, 0x0003); + for (cnt = 100; (RD_REG_DWORD(®->iobase_window) & BIT_0) == 0 && + rval == QLA_SUCCESS; cnt--) { + if (cnt) { + WRT_REG_DWORD(®->iobase_window, 0x0003); + udelay(10); + } else + rval = QLA_FUNCTION_TIMEOUT; + } + if (rval != QLA_SUCCESS) + goto done; + +next_test: + if (RD_REG_DWORD(®->iobase_c8) & BIT_3) + qla_printk(KERN_INFO, ha, "Additional code -- 0x55AA.\n"); + +done: + WRT_REG_DWORD(®->iobase_window, 0x0000); + RD_REG_DWORD(®->iobase_window); +} + /** * qla24xx_intr_handler() - Process interrupts for the ISP23xx and ISP63xx. * @irq: @@ -1499,10 +1566,16 @@ qla24xx_intr_handler(int irq, void *dev_id) for (iter = 50; iter--; ) { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { + if (pci_channel_offline(ha->pdev)) + break; + hccr = RD_REG_DWORD(®->hccr); qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " "Dumping firmware!\n", hccr); + + qla2xxx_check_risc_status(ha); + ha->isp_ops->fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; @@ -1606,7 +1679,6 @@ qla24xx_msix_rsp_q(int irq, void *dev_id) qla24xx_process_response_queue(ha); WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - RD_REG_DWORD_RELAXED(®->hccr); spin_unlock_irqrestore(&ha->hardware_lock, flags); @@ -1620,7 +1692,6 @@ qla24xx_msix_default(int irq, void *dev_id) struct device_reg_24xx __iomem *reg; int status; unsigned long flags; - unsigned long iter; uint32_t stat; uint32_t hccr; uint16_t mb[4]; @@ -1630,13 +1701,19 @@ qla24xx_msix_default(int irq, void *dev_id) status = 0; spin_lock_irqsave(&ha->hardware_lock, flags); - for (iter = 50; iter--; ) { + do { stat = RD_REG_DWORD(®->host_status); if (stat & HSRX_RISC_PAUSED) { + if (pci_channel_offline(ha->pdev)) + break; + hccr = RD_REG_DWORD(®->hccr); qla_printk(KERN_INFO, ha, "RISC paused -- HCCR=%x, " "Dumping firmware!\n", hccr); + + qla2xxx_check_risc_status(ha); + ha->isp_ops->fw_dump(ha, 1); set_bit(ISP_ABORT_NEEDED, &ha->dpc_flags); break; @@ -1669,8 +1746,7 @@ qla24xx_msix_default(int irq, void *dev_id) break; } WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - RD_REG_DWORD_RELAXED(®->hccr); - } + } while (0); spin_unlock_irqrestore(&ha->hardware_lock, flags); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index d3746ec80a85..c53ec67c47f4 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -391,7 +391,8 @@ qla2x00_execute_fw(scsi_qla_host_t *ha, uint32_t risc_addr) mcp->mb[1] = MSW(risc_addr); mcp->mb[2] = LSW(risc_addr); mcp->mb[3] = 0; - mcp->out_mb |= MBX_3|MBX_2|MBX_1; + mcp->mb[4] = 0; + mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1; mcp->in_mb |= MBX_1; } else { mcp->mb[1] = LSW(risc_addr); @@ -1919,7 +1920,8 @@ qla2x00_get_id_list(scsi_qla_host_t *ha, void *id_list, dma_addr_t id_list_dma, */ int qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, - uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, uint16_t *orig_iocb_cnt) + uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, + uint16_t *orig_iocb_cnt, uint16_t *max_npiv_vports) { int rval; mbx_cmd_t mc; @@ -1929,7 +1931,7 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, mcp->mb[0] = MBC_GET_RESOURCE_COUNTS; mcp->out_mb = MBX_0; - mcp->in_mb = MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = MBX_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; mcp->tov = 30; mcp->flags = 0; rval = qla2x00_mailbox_command(ha, mcp); @@ -1940,9 +1942,9 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, ha->host_no, mcp->mb[0])); } else { DEBUG11(printk("%s(%ld): done. mb1=%x mb2=%x mb3=%x mb6=%x " - "mb7=%x mb10=%x.\n", __func__, ha->host_no, + "mb7=%x mb10=%x mb11=%x.\n", __func__, ha->host_no, mcp->mb[1], mcp->mb[2], mcp->mb[3], mcp->mb[6], mcp->mb[7], - mcp->mb[10])); + mcp->mb[10], mcp->mb[11])); if (cur_xchg_cnt) *cur_xchg_cnt = mcp->mb[3]; @@ -1952,6 +1954,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *ha, uint16_t *cur_xchg_cnt, *cur_iocb_cnt = mcp->mb[7]; if (orig_iocb_cnt) *orig_iocb_cnt = mcp->mb[10]; + if (max_npiv_vports) + *max_npiv_vports = mcp->mb[11]; } return (rval); @@ -2980,3 +2984,51 @@ qla2x00_send_change_request(scsi_qla_host_t *ha, uint16_t format, return rval; } + +int +qla2x00_dump_ram(scsi_qla_host_t *ha, dma_addr_t req_dma, uint32_t addr, + uint32_t size) +{ + int rval; + mbx_cmd_t mc; + mbx_cmd_t *mcp = &mc; + + DEBUG11(printk("%s(%ld): entered.\n", __func__, ha->host_no)); + + if (MSW(addr) || IS_FWI2_CAPABLE(ha)) { + mcp->mb[0] = MBC_DUMP_RISC_RAM_EXTENDED; + mcp->mb[8] = MSW(addr); + mcp->out_mb = MBX_8|MBX_0; + } else { + mcp->mb[0] = MBC_DUMP_RISC_RAM; + mcp->out_mb = MBX_0; + } + mcp->mb[1] = LSW(addr); + mcp->mb[2] = MSW(req_dma); + mcp->mb[3] = LSW(req_dma); + mcp->mb[6] = MSW(MSD(req_dma)); + mcp->mb[7] = LSW(MSD(req_dma)); + mcp->out_mb |= MBX_7|MBX_6|MBX_3|MBX_2|MBX_1; + if (IS_FWI2_CAPABLE(ha)) { + mcp->mb[4] = MSW(size); + mcp->mb[5] = LSW(size); + mcp->out_mb |= MBX_5|MBX_4; + } else { + mcp->mb[4] = LSW(size); + mcp->out_mb |= MBX_4; + } + + mcp->in_mb = MBX_0; + mcp->tov = 30; + mcp->flags = 0; + rval = qla2x00_mailbox_command(ha, mcp); + + if (rval != QLA_SUCCESS) { + DEBUG2_3_11(printk("%s(%ld): failed=%x mb[0]=%x.\n", __func__, + ha->host_no, rval, mcp->mb[0])); + } else { + DEBUG11(printk("%s(%ld): done.\n", __func__, ha->host_no)); + } + + return rval; +} diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 54dc415d8b53..821ee74aadc6 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -104,7 +104,7 @@ qla24xx_find_vhost_by_name(scsi_qla_host_t *ha, uint8_t *port_name) * * Context: */ -void +static void qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) { fc_port_t *fcport; @@ -179,37 +179,7 @@ enable_failed: return 1; } -/** - * qla24xx_modify_vport() - Modifies the virtual fabric port's configuration - * @ha: HA context - * @vp: pointer to buffer of virtual port parameters. - * @ret_code: return error code: - * - * Returns the virtual port id, or MAX_VSAN_ID, if couldn't create. - */ -uint32_t -qla24xx_modify_vhba(scsi_qla_host_t *ha, vport_params_t *vp, uint32_t *vp_id) -{ - scsi_qla_host_t *vha; - - vha = qla24xx_find_vhost_by_name(ha, vp->port_name); - if (!vha) { - *vp_id = MAX_NUM_VPORT_LOOP; - return VP_RET_CODE_WWPN; - } - - if (qla24xx_enable_vp(vha)) { - scsi_host_put(vha->host); - qla2x00_mem_free(vha); - *vp_id = MAX_NUM_VPORT_LOOP; - return VP_RET_CODE_RESOURCES; - } - - *vp_id = vha->vp_idx; - return VP_RET_CODE_OK; -} - -void +static void qla24xx_configure_vp(scsi_qla_host_t *vha) { struct fc_vport *fc_vport; @@ -363,7 +333,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *ha) int qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport) { - scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha; uint8_t port_name[WWN_SIZE]; @@ -397,7 +367,7 @@ qla24xx_vport_create_req_sanity_check(struct fc_vport *fc_vport) scsi_qla_host_t * qla24xx_create_vhost(struct fc_vport *fc_vport) { - scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; + scsi_qla_host_t *ha = shost_priv(fc_vport->shost); scsi_qla_host_t *vha; struct Scsi_Host *host; @@ -409,7 +379,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) return(NULL); } - vha = (scsi_qla_host_t *)host->hostdata; + vha = shost_priv(host); /* clone the parent hba */ memcpy(vha, ha, sizeof (scsi_qla_host_t)); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index acca898ce0a2..a6bb8d0ecf13 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -379,12 +379,17 @@ qla2x00_get_new_sp(scsi_qla_host_t *ha, fc_port_t *fcport, static int qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = 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)); 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; @@ -440,13 +445,18 @@ qc_fail_command: static int qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = 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)); srb_t *sp; int rval; scsi_qla_host_t *pha = to_qla_parent(ha); + if (unlikely(pci_channel_offline(ha->pdev))) { + cmd->result = DID_REQUEUE << 16; + goto qc24_fail_command; + } + rval = fc_remote_port_chkready(rport); if (rval) { cmd->result = rval; @@ -653,7 +663,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd) static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); srb_t *sp; int ret, i; unsigned int id, lun; @@ -793,7 +803,7 @@ qla2x00_eh_wait_for_pending_target_commands(scsi_qla_host_t *ha, unsigned int t) static int qla2xxx_eh_device_reset(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; unsigned int id, lun; @@ -922,7 +932,7 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha) static int qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); scsi_qla_host_t *pha = to_qla_parent(ha); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; @@ -982,7 +992,7 @@ eh_bus_reset_done: static int qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = to_qla_host(cmd->device->host); + scsi_qla_host_t *ha = shost_priv(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; unsigned int id, lun; @@ -1132,7 +1142,7 @@ qla2xxx_slave_alloc(struct scsi_device *sdev) static int qla2xxx_slave_configure(struct scsi_device *sdev) { - scsi_qla_host_t *ha = to_qla_host(sdev->host); + scsi_qla_host_t *ha = shost_priv(sdev->host); struct fc_rport *rport = starget_to_rport(sdev->sdev_target); if (sdev->tagged_supported) @@ -1384,7 +1394,7 @@ static struct isp_operations qla25xx_isp_ops = { .beacon_on = qla24xx_beacon_on, .beacon_off = qla24xx_beacon_off, .beacon_blink = qla24xx_beacon_blink, - .read_optrom = qla24xx_read_optrom_data, + .read_optrom = qla25xx_read_optrom_data, .write_optrom = qla24xx_write_optrom_data, .get_flash_version = qla24xx_get_flash_version, }; @@ -1533,7 +1543,7 @@ iospace_error_exit: static void qla2xxx_scan_start(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; + scsi_qla_host_t *ha = shost_priv(shost); set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); @@ -1543,7 +1553,7 @@ qla2xxx_scan_start(struct Scsi_Host *shost) static int qla2xxx_scan_finished(struct Scsi_Host *shost, unsigned long time) { - scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; + scsi_qla_host_t *ha = shost_priv(shost); if (!ha->host) return 1; @@ -1571,6 +1581,10 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) if (pci_enable_device(pdev)) goto probe_out; + if (pci_find_aer_capability(pdev)) + if (pci_enable_pcie_error_reporting(pdev)) + goto probe_out; + sht = &qla2x00_driver_template; if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432 || @@ -1586,7 +1600,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) } /* Clear our data area */ - ha = (scsi_qla_host_t *)host->hostdata; + ha = shost_priv(host); memset(ha, 0, sizeof(scsi_qla_host_t)); ha->pdev = pdev; @@ -2423,7 +2437,6 @@ qla2x00_do_dpc(void *data) if (atomic_read(&fcport->state) != FCS_ONLINE && fcport->login_retry) { - fcport->login_retry--; if (fcport->flags & FCF_FABRIC_DEVICE) { if (fcport->flags & FCF_TAPE_PRESENT) @@ -2439,6 +2452,7 @@ qla2x00_do_dpc(void *data) qla2x00_local_device_login( ha, fcport); + fcport->login_retry--; if (status == QLA_SUCCESS) { fcport->old_loop_id = fcport->loop_id; @@ -2456,6 +2470,8 @@ qla2x00_do_dpc(void *data) } else { fcport->login_retry = 0; } + if (fcport->login_retry == 0) + fcport->loop_id = FC_NO_LOOP_ID; } if (test_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags)) break; @@ -2814,6 +2830,105 @@ qla2x00_release_firmware(void) up(&qla_fw_lock); } +static pci_ers_result_t +qla2xxx_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) +{ + switch (state) { + case pci_channel_io_normal: + return PCI_ERS_RESULT_CAN_RECOVER; + case pci_channel_io_frozen: + pci_disable_device(pdev); + return PCI_ERS_RESULT_NEED_RESET; + case pci_channel_io_perm_failure: + qla2x00_remove_one(pdev); + return PCI_ERS_RESULT_DISCONNECT; + } + return PCI_ERS_RESULT_NEED_RESET; +} + +static pci_ers_result_t +qla2xxx_pci_mmio_enabled(struct pci_dev *pdev) +{ + int risc_paused = 0; + uint32_t stat; + unsigned long flags; + scsi_qla_host_t *ha = pci_get_drvdata(pdev); + struct device_reg_2xxx __iomem *reg = &ha->iobase->isp; + struct device_reg_24xx __iomem *reg24 = &ha->iobase->isp24; + + spin_lock_irqsave(&ha->hardware_lock, flags); + if (IS_QLA2100(ha) || IS_QLA2200(ha)){ + stat = RD_REG_DWORD(®->hccr); + if (stat & HCCR_RISC_PAUSE) + risc_paused = 1; + } else if (IS_QLA23XX(ha)) { + stat = RD_REG_DWORD(®->u.isp2300.host_status); + if (stat & HSR_RISC_PAUSED) + risc_paused = 1; + } else if (IS_FWI2_CAPABLE(ha)) { + stat = RD_REG_DWORD(®24->host_status); + if (stat & HSRX_RISC_PAUSED) + risc_paused = 1; + } + spin_unlock_irqrestore(&ha->hardware_lock, flags); + + if (risc_paused) { + qla_printk(KERN_INFO, ha, "RISC paused -- mmio_enabled, " + "Dumping firmware!\n"); + ha->isp_ops->fw_dump(ha, 0); + + return PCI_ERS_RESULT_NEED_RESET; + } else + return PCI_ERS_RESULT_RECOVERED; +} + +static pci_ers_result_t +qla2xxx_pci_slot_reset(struct pci_dev *pdev) +{ + pci_ers_result_t ret = PCI_ERS_RESULT_DISCONNECT; + scsi_qla_host_t *ha = pci_get_drvdata(pdev); + + if (pci_enable_device(pdev)) { + qla_printk(KERN_WARNING, ha, + "Can't re-enable PCI device after reset.\n"); + + return ret; + } + pci_set_master(pdev); + + if (ha->isp_ops->pci_config(ha)) + return ret; + + set_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + if (qla2x00_abort_isp(ha)== QLA_SUCCESS) + ret = PCI_ERS_RESULT_RECOVERED; + clear_bit(ABORT_ISP_ACTIVE, &ha->dpc_flags); + + return ret; +} + +static void +qla2xxx_pci_resume(struct pci_dev *pdev) +{ + scsi_qla_host_t *ha = pci_get_drvdata(pdev); + int ret; + + ret = qla2x00_wait_for_hba_online(ha); + if (ret != QLA_SUCCESS) { + qla_printk(KERN_ERR, ha, + "the device failed to resume I/O " + "from slot/link_reset"); + } + pci_cleanup_aer_uncorrect_error_status(pdev); +} + +static struct pci_error_handlers qla2xxx_err_handler = { + .error_detected = qla2xxx_pci_error_detected, + .mmio_enabled = qla2xxx_pci_mmio_enabled, + .slot_reset = qla2xxx_pci_slot_reset, + .resume = qla2xxx_pci_resume, +}; + static struct pci_device_id qla2xxx_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100) }, { PCI_DEVICE(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200) }, @@ -2839,6 +2954,7 @@ static struct pci_driver qla2xxx_pci_driver = { .id_table = qla2xxx_pci_tbl, .probe = qla2x00_probe_one, .remove = __devexit_p(qla2x00_remove_one), + .err_handler = &qla2xxx_err_handler, }; /** diff --git a/drivers/scsi/qla2xxx/qla_sup.c b/drivers/scsi/qla2xxx/qla_sup.c index a925a3f179f9..40b059fc1981 100644 --- a/drivers/scsi/qla2xxx/qla_sup.c +++ b/drivers/scsi/qla2xxx/qla_sup.c @@ -425,6 +425,9 @@ qla2x00_set_nvram_protection(scsi_qla_host_t *ha, int stat) /* Flash Manipulation Routines */ /*****************************************************************************/ +#define OPTROM_BURST_SIZE 0x1000 +#define OPTROM_BURST_DWORDS (OPTROM_BURST_SIZE / 4) + static inline uint32_t flash_conf_to_access_addr(uint32_t faddr) { @@ -544,41 +547,59 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { int ret; - uint32_t liter; - uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask; + uint32_t liter, miter; + uint32_t sec_mask, rest_addr, conf_addr; uint32_t fdata, findex ; uint8_t man_id, flash_id; struct device_reg_24xx __iomem *reg = &ha->iobase->isp24; + dma_addr_t optrom_dma; + void *optrom = NULL; + uint32_t *s, *d; ret = QLA_SUCCESS; + /* Prepare burst-capable write on supported ISPs. */ + if (IS_QLA25XX(ha) && !(faddr & 0xfff) && + dwords > OPTROM_BURST_DWORDS) { + optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + &optrom_dma, GFP_KERNEL); + if (!optrom) { + qla_printk(KERN_DEBUG, ha, + "Unable to allocate memory for optrom burst write " + "(%x KB).\n", OPTROM_BURST_SIZE / 1024); + } + } + qla24xx_get_flash_manufacturer(ha, &man_id, &flash_id); DEBUG9(printk("%s(%ld): Flash man_id=%d flash_id=%d\n", __func__, ha->host_no, man_id, flash_id)); - sec_end_mask = 0; conf_addr = flash_conf_to_access_addr(0x03d8); switch (man_id) { case 0xbf: /* STT flash. */ - rest_addr = 0x1fff; - sec_mask = 0x3e000; + if (flash_id == 0x8e) { + rest_addr = 0x3fff; + sec_mask = 0x7c000; + } else { + rest_addr = 0x1fff; + sec_mask = 0x7e000; + } if (flash_id == 0x80) conf_addr = flash_conf_to_access_addr(0x0352); break; case 0x13: /* ST M25P80. */ rest_addr = 0x3fff; - sec_mask = 0x3c000; + sec_mask = 0x7c000; break; case 0x1f: // Atmel 26DF081A - rest_addr = 0x0fff; - sec_mask = 0xff000; - sec_end_mask = 0x003ff; + rest_addr = 0x3fff; + sec_mask = 0x7c000; conf_addr = flash_conf_to_access_addr(0x0320); break; default: /* Default to 64 kb sector size. */ rest_addr = 0x3fff; - sec_mask = 0x3c000; + sec_mask = 0x7c000; break; } @@ -592,56 +613,81 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, /* Some flash parts need an additional zero-write to clear bits.*/ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0); - do { /* Loop once to provide quick error exit. */ - for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { - if (man_id == 0x1f) { - findex = faddr << 2; - fdata = findex & sec_mask; - } else { - findex = faddr; - fdata = (findex & sec_mask) << 2; - } + for (liter = 0; liter < dwords; liter++, faddr++, dwptr++) { + if (man_id == 0x1f) { + findex = faddr << 2; + fdata = findex & sec_mask; + } else { + findex = faddr; + fdata = (findex & sec_mask) << 2; + } - /* Are we at the beginning of a sector? */ - if ((findex & rest_addr) == 0) { - /* - * Do sector unprotect at 4K boundry for Atmel - * part. - */ - if (man_id == 0x1f) - qla24xx_write_flash_dword(ha, - flash_conf_to_access_addr(0x0339), - (fdata & 0xff00) | ((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); - ret = qla24xx_write_flash_dword(ha, conf_addr, - (fdata & 0xff00) |((fdata << 16) & + /* Are we at the beginning of a sector? */ + if ((findex & rest_addr) == 0) { + /* Do sector unprotect at 4K boundry for Atmel part. */ + if (man_id == 0x1f) + qla24xx_write_flash_dword(ha, + flash_conf_to_access_addr(0x0339), + (fdata & 0xff00) | ((fdata << 16) & 0xff0000) | ((fdata >> 16) & 0xff)); - if (ret != QLA_SUCCESS) { - DEBUG9(printk("%s(%ld) Unable to flash " - "sector: address=%x.\n", __func__, - ha->host_no, faddr)); - break; - } + ret = qla24xx_write_flash_dword(ha, conf_addr, + (fdata & 0xff00) |((fdata << 16) & + 0xff0000) | ((fdata >> 16) & 0xff)); + if (ret != QLA_SUCCESS) { + DEBUG9(printk("%s(%ld) Unable to flash " + "sector: address=%x.\n", __func__, + ha->host_no, faddr)); + break; } - ret = qla24xx_write_flash_dword(ha, + } + + /* Go with burst-write. */ + if (optrom && (liter + OPTROM_BURST_DWORDS) < dwords) { + /* Copy data to DMA'ble buffer. */ + for (miter = 0, s = optrom, d = dwptr; + miter < OPTROM_BURST_DWORDS; miter++, s++, d++) + *s = cpu_to_le32(*d); + + ret = qla2x00_load_ram(ha, optrom_dma, flash_data_to_access_addr(faddr), - cpu_to_le32(*dwptr)); + OPTROM_BURST_DWORDS); if (ret != QLA_SUCCESS) { - DEBUG9(printk("%s(%ld) Unable to program flash " - "address=%x data=%x.\n", __func__, - ha->host_no, faddr, *dwptr)); - break; + qla_printk(KERN_WARNING, ha, + "Unable to burst-write optrom segment " + "(%x/%x/%llx).\n", ret, + flash_data_to_access_addr(faddr), + optrom_dma); + qla_printk(KERN_WARNING, ha, + "Reverting to slow-write.\n"); + + dma_free_coherent(&ha->pdev->dev, + OPTROM_BURST_SIZE, optrom, optrom_dma); + optrom = NULL; + } else { + liter += OPTROM_BURST_DWORDS - 1; + faddr += OPTROM_BURST_DWORDS - 1; + dwptr += OPTROM_BURST_DWORDS - 1; + continue; } + } - /* Do sector protect at 4K boundry for Atmel part. */ - if (man_id == 0x1f && - ((faddr & sec_end_mask) == 0x3ff)) - qla24xx_write_flash_dword(ha, - flash_conf_to_access_addr(0x0336), - (fdata & 0xff00) | ((fdata << 16) & - 0xff0000) | ((fdata >> 16) & 0xff)); + ret = qla24xx_write_flash_dword(ha, + flash_data_to_access_addr(faddr), cpu_to_le32(*dwptr)); + if (ret != QLA_SUCCESS) { + DEBUG9(printk("%s(%ld) Unable to program flash " + "address=%x data=%x.\n", __func__, + ha->host_no, faddr, *dwptr)); + break; } - } while (0); + + /* Do sector protect at 4K boundry for Atmel part. */ + if (man_id == 0x1f && + ((faddr & rest_addr) == rest_addr)) + qla24xx_write_flash_dword(ha, + flash_conf_to_access_addr(0x0336), + (fdata & 0xff00) | ((fdata << 16) & + 0xff0000) | ((fdata >> 16) & 0xff)); + } /* Enable flash write-protection. */ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c); @@ -651,6 +697,10 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, RD_REG_DWORD(®->ctrl_status) & ~CSRX_FLASH_ENABLE); RD_REG_DWORD(®->ctrl_status); /* PCI Posting. */ + if (optrom) + dma_free_coherent(&ha->pdev->dev, + OPTROM_BURST_SIZE, optrom, optrom_dma); + return ret; } @@ -1728,7 +1778,6 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, { /* Suspend HBA. */ scsi_block_requests(ha->host); - ha->isp_ops->disable_intrs(ha); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with read. */ @@ -1736,7 +1785,6 @@ qla24xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, /* Resume HBA. */ clear_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); - ha->isp_ops->enable_intrs(ha); scsi_unblock_requests(ha->host); return buf; @@ -1750,7 +1798,6 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, /* Suspend HBA. */ scsi_block_requests(ha->host); - ha->isp_ops->disable_intrs(ha); set_bit(MBX_UPDATE_FLASH_ACTIVE, &ha->mbx_cmd_flags); /* Go with write. */ @@ -1767,6 +1814,70 @@ qla24xx_write_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, return rval; } +uint8_t * +qla25xx_read_optrom_data(struct scsi_qla_host *ha, uint8_t *buf, + uint32_t offset, uint32_t length) +{ + int rval; + dma_addr_t optrom_dma; + void *optrom; + uint8_t *pbuf; + uint32_t faddr, left, burst; + + if (offset & 0xfff) + goto slow_read; + if (length < OPTROM_BURST_SIZE) + goto slow_read; + + optrom = dma_alloc_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + &optrom_dma, GFP_KERNEL); + if (!optrom) { + qla_printk(KERN_DEBUG, ha, + "Unable to allocate memory for optrom burst read " + "(%x KB).\n", OPTROM_BURST_SIZE / 1024); + + goto slow_read; + } + + pbuf = buf; + faddr = offset >> 2; + left = length >> 2; + burst = OPTROM_BURST_DWORDS; + while (left != 0) { + if (burst > left) + burst = left; + + rval = qla2x00_dump_ram(ha, optrom_dma, + flash_data_to_access_addr(faddr), burst); + if (rval) { + qla_printk(KERN_WARNING, ha, + "Unable to burst-read optrom segment " + "(%x/%x/%llx).\n", rval, + flash_data_to_access_addr(faddr), optrom_dma); + qla_printk(KERN_WARNING, ha, + "Reverting to slow-read.\n"); + + dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, + optrom, optrom_dma); + goto slow_read; + } + + memcpy(pbuf, optrom, burst * 4); + + left -= burst; + faddr += burst; + pbuf += burst * 4; + } + + dma_free_coherent(&ha->pdev->dev, OPTROM_BURST_SIZE, optrom, + optrom_dma); + + return buf; + +slow_read: + return qla24xx_read_optrom_data(ha, buf, offset, length); +} + /** * qla2x00_get_fcode_version() - Determine an FCODE image's version. * @ha: HA context diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 18095b9b76f4..2d551a3006f6 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.00-k3" +#define QLA2XXX_VERSION "8.02.00-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 diff --git a/drivers/scsi/qlogicfas.c b/drivers/scsi/qlogicfas.c index 94baca840efe..1e874f1fb5c6 100644 --- a/drivers/scsi/qlogicfas.c +++ b/drivers/scsi/qlogicfas.c @@ -166,6 +166,7 @@ static int qlogicfas_release(struct Scsi_Host *shost) { struct qlogicfas408_priv *priv = get_priv_by_host(shost); + scsi_remove_host(shost); if (shost->irq) { qlogicfas408_disable_ints(priv); free_irq(shost->irq, shost); @@ -174,7 +175,6 @@ static int qlogicfas_release(struct Scsi_Host *shost) free_dma(shost->dma_channel); if (shost->io_port && shost->n_io_port) release_region(shost->io_port, shost->n_io_port); - scsi_remove_host(shost); scsi_host_put(shost); return 0; diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 594887205b0f..e93f80316a19 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -310,8 +310,6 @@ static inline void qlogicpti_set_hostdev_defaults(struct qlogicpti *qpti) } qpti->dev_param[i].device_enable = 1; } - /* this is very important to set! */ - qpti->sbits = 1 << qpti->scsi_id; } static int qlogicpti_reset_hardware(struct Scsi_Host *host) @@ -951,153 +949,35 @@ static inline void update_can_queue(struct Scsi_Host *host, u_int in_ptr, u_int host->sg_tablesize = QLOGICPTI_MAX_SG(num_free); } -static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out) +static int qlogicpti_slave_configure(struct scsi_device *sdev) { - unsigned char *buf; - unsigned int buflen; - - if (cmd->use_sg) { - struct scatterlist *sg; + struct qlogicpti *qpti = shost_priv(sdev->host); + int tgt = sdev->id; + u_short param[6]; - sg = (struct scatterlist *) cmd->request_buffer; - buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; - buflen = sg->length; + /* tags handled in midlayer */ + /* enable sync mode? */ + if (sdev->sdtr) { + qpti->dev_param[tgt].device_flags |= 0x10; } else { - buf = cmd->request_buffer; - buflen = cmd->request_bufflen; + qpti->dev_param[tgt].synchronous_offset = 0; + qpti->dev_param[tgt].synchronous_period = 0; } - - *buf_out = buf; - return buflen; -} - -static void scsi_rbuf_put(struct scsi_cmnd *cmd, unsigned char *buf) -{ - if (cmd->use_sg) { - struct scatterlist *sg; - - sg = (struct scatterlist *) cmd->request_buffer; - kunmap_atomic(buf - sg->offset, KM_IRQ0); - } -} - -/* - * Until we scan the entire bus with inquiries, go throught this fella... - */ -static void ourdone(struct scsi_cmnd *Cmnd) -{ - struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata; - int tgt = Cmnd->device->id; - void (*done) (struct scsi_cmnd *); - - /* This grot added by DaveM, blame him for ugliness. - * The issue is that in the 2.3.x driver we use the - * host_scribble portion of the scsi command as a - * completion linked list at interrupt service time, - * so we have to store the done function pointer elsewhere. - */ - done = (void (*)(struct scsi_cmnd *)) - (((unsigned long) Cmnd->SCp.Message) -#ifdef __sparc_v9__ - | ((unsigned long) Cmnd->SCp.Status << 32UL) -#endif - ); - - if ((qpti->sbits & (1 << tgt)) == 0) { - int ok = host_byte(Cmnd->result) == DID_OK; - if (Cmnd->cmnd[0] == 0x12 && ok) { - unsigned char *iqd; - unsigned int iqd_len; - - iqd_len = scsi_rbuf_get(Cmnd, &iqd); - - /* tags handled in midlayer */ - /* enable sync mode? */ - if (iqd[7] & 0x10) { - qpti->dev_param[tgt].device_flags |= 0x10; - } else { - qpti->dev_param[tgt].synchronous_offset = 0; - qpti->dev_param[tgt].synchronous_period = 0; - } - /* are we wide capable? */ - if (iqd[7] & 0x20) { - qpti->dev_param[tgt].device_flags |= 0x20; - } - - scsi_rbuf_put(Cmnd, iqd); - - qpti->sbits |= (1 << tgt); - } else if (!ok) { - qpti->sbits |= (1 << tgt); - } - } - done(Cmnd); -} - -static int qlogicpti_queuecommand(struct scsi_cmnd *Cmnd, void (*done)(struct scsi_cmnd *)); - -static int qlogicpti_queuecommand_slow(struct scsi_cmnd *Cmnd, - void (*done)(struct scsi_cmnd *)) -{ - struct qlogicpti *qpti = (struct qlogicpti *) Cmnd->device->host->hostdata; - - /* - * done checking this host adapter? - * If not, then rewrite the command - * to finish through ourdone so we - * can peek at Inquiry data results. - */ - if (qpti->sbits && qpti->sbits != 0xffff) { - /* See above about in ourdone this ugliness... */ - Cmnd->SCp.Message = ((unsigned long)done) & 0xffffffff; -#ifdef CONFIG_SPARC64 - Cmnd->SCp.Status = ((unsigned long)done >> 32UL) & 0xffffffff; -#endif - return qlogicpti_queuecommand(Cmnd, ourdone); - } - - /* - * We've peeked at all targets for this bus- time - * to set parameters for devices for real now. - */ - if (qpti->sbits == 0xffff) { - int i; - for(i = 0; i < MAX_TARGETS; i++) { - u_short param[6]; - param[0] = MBOX_SET_TARGET_PARAMS; - param[1] = (i << 8); - param[2] = (qpti->dev_param[i].device_flags << 8); - if (qpti->dev_param[i].device_flags & 0x10) { - param[3] = (qpti->dev_param[i].synchronous_offset << 8) | - qpti->dev_param[i].synchronous_period; - } else { - param[3] = 0; - } - (void) qlogicpti_mbox_command(qpti, param, 0); - } - /* - * set to zero so any traverse through ourdone - * doesn't start the whole process again, - */ - qpti->sbits = 0; - } - - /* check to see if we're done with all adapters... */ - for (qpti = qptichain; qpti != NULL; qpti = qpti->next) { - if (qpti->sbits) { - break; - } + /* are we wide capable? */ + if (sdev->wdtr) + qpti->dev_param[tgt].device_flags |= 0x20; + + param[0] = MBOX_SET_TARGET_PARAMS; + param[1] = (tgt << 8); + param[2] = (qpti->dev_param[tgt].device_flags << 8); + if (qpti->dev_param[tgt].device_flags & 0x10) { + param[3] = (qpti->dev_param[tgt].synchronous_offset << 8) | + qpti->dev_param[tgt].synchronous_period; + } else { + param[3] = 0; } - - /* - * if we hit the end of the chain w/o finding adapters still - * capability-configuring, then we're done with all adapters - * and can rock on.. - */ - if (qpti == NULL) - Cmnd->device->host->hostt->queuecommand = qlogicpti_queuecommand; - - return qlogicpti_queuecommand(Cmnd, done); + qlogicpti_mbox_command(qpti, param, 0); + return 0; } /* @@ -1390,7 +1270,8 @@ static struct scsi_host_template qpti_template = { .module = THIS_MODULE, .name = "qlogicpti", .info = qlogicpti_info, - .queuecommand = qlogicpti_queuecommand_slow, + .queuecommand = qlogicpti_queuecommand, + .slave_configure = qlogicpti_slave_configure, .eh_abort_handler = qlogicpti_abort, .eh_bus_reset_handler = qlogicpti_reset, .can_queue = QLOGICPTI_REQ_QUEUE_LEN, diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index 6cd1c0771d29..ef6da2df584b 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h @@ -380,8 +380,7 @@ struct qlogicpti { unsigned char swsreg; unsigned int gotirq : 1, /* this instance got an irq */ - is_pti : 1, /* Non-zero if this is a PTI board. */ - sbits : 16; /* syncmode known bits */ + is_pti : 1; /* Non-zero if this is a PTI board. */ }; /* How to twiddle them bits... */ diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c index a5de1a829a76..192948822455 100644 --- a/drivers/scsi/scsi.c +++ b/drivers/scsi/scsi.c @@ -59,6 +59,7 @@ #include <scsi/scsi_cmnd.h> #include <scsi/scsi_dbg.h> #include <scsi/scsi_device.h> +#include <scsi/scsi_driver.h> #include <scsi/scsi_eh.h> #include <scsi/scsi_host.h> #include <scsi/scsi_tcq.h> @@ -367,9 +368,8 @@ void scsi_log_send(struct scsi_cmnd *cmd) scsi_print_command(cmd); if (level > 3) { printk(KERN_INFO "buffer = 0x%p, bufflen = %d," - " done = 0x%p, queuecommand 0x%p\n", + " queuecommand 0x%p\n", scsi_sglist(cmd), scsi_bufflen(cmd), - cmd->done, cmd->device->host->hostt->queuecommand); } @@ -442,7 +442,7 @@ void scsi_log_completion(struct scsi_cmnd *cmd, int disposition) #endif /* - * Assign a serial number and pid to the request for error recovery + * Assign a serial number to the request for error recovery * and debugging purposes. Protected by the Host_Lock of host. */ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd *cmd) @@ -450,10 +450,6 @@ static inline void scsi_cmd_get_serial(struct Scsi_Host *host, struct scsi_cmnd cmd->serial_number = host->cmd_serial_number++; if (cmd->serial_number == 0) cmd->serial_number = host->cmd_serial_number++; - - cmd->pid = host->cmd_pid++; - if (cmd->pid == 0) - cmd->pid = host->cmd_pid++; } /* @@ -658,6 +654,12 @@ void __scsi_done(struct scsi_cmnd *cmd) blk_complete_request(rq); } +/* Move this to a header if it becomes more generally useful */ +static struct scsi_driver *scsi_cmd_to_driver(struct scsi_cmnd *cmd) +{ + return *(struct scsi_driver **)cmd->request->rq_disk->private_data; +} + /* * Function: scsi_finish_command * @@ -669,6 +671,8 @@ void scsi_finish_command(struct scsi_cmnd *cmd) { struct scsi_device *sdev = cmd->device; struct Scsi_Host *shost = sdev->host; + struct scsi_driver *drv; + unsigned int good_bytes; scsi_device_unbusy(sdev); @@ -694,7 +698,13 @@ void scsi_finish_command(struct scsi_cmnd *cmd) "Notifying upper driver of completion " "(result %x)\n", cmd->result)); - cmd->done(cmd); + good_bytes = cmd->request_bufflen; + if (cmd->request->cmd_type != REQ_TYPE_BLOCK_PC) { + drv = scsi_cmd_to_driver(cmd); + if (drv->done) + good_bytes = drv->done(cmd); + } + scsi_io_completion(cmd, good_bytes); } EXPORT_SYMBOL(scsi_finish_command); diff --git a/drivers/scsi/scsi_devinfo.c b/drivers/scsi/scsi_devinfo.c index e2ea739e33df..348cc5a6e3cd 100644 --- a/drivers/scsi/scsi_devinfo.c +++ b/drivers/scsi/scsi_devinfo.c @@ -214,6 +214,7 @@ static struct { {"PIONEER", "CD-ROM DRM-604X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"PIONEER", "CD-ROM DRM-624X", NULL, BLIST_FORCELUN | BLIST_SINGLELUN}, {"Promise", "", NULL, BLIST_SPARSELUN}, + {"QUANTUM", "XP34301", "1071", BLIST_NOTQ}, {"REGAL", "CDC-4X", NULL, BLIST_MAX5LUN | BLIST_SINGLELUN}, {"SanDisk", "ImageMate CF-SD1", NULL, BLIST_FORCELUN}, {"SEAGATE", "ST34555N", "0930", BLIST_NOTQ}, /* Chokes on tagged INQUIRY */ diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 8a525abda30f..d29f8464b74f 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c @@ -37,6 +37,7 @@ #include "scsi_priv.h" #include "scsi_logging.h" +#include "scsi_transport_api.h" #define SENSE_TIMEOUT (10*HZ) @@ -589,39 +590,23 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) } /** - * scsi_send_eh_cmnd - submit a scsi command as part of error recory + * scsi_eh_prep_cmnd - Save a scsi command info as part of error recory * @scmd: SCSI command structure to hijack - * @cmnd: CDB to send + * @ses: structure to save restore information + * @cmnd: CDB to send. Can be NULL if no new cmnd is needed * @cmnd_size: size in bytes of @cmnd - * @timeout: timeout for this request - * @copy_sense: request sense data if set to 1 - * - * This function is used to send a scsi command down to a target device - * as part of the error recovery process. If @copy_sense is 0 the command - * sent must be one that does not transfer any data. If @copy_sense is 1 - * the command must be REQUEST_SENSE and this functions copies out the - * sense buffer it got into @scmd->sense_buffer. + * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) * - * Return value: - * SUCCESS or FAILED or NEEDS_RETRY + * This function is used to save a scsi command information before re-execution + * as part of the error recovery process. If @sense_bytes is 0 the command + * sent must be one that does not transfer any data. If @sense_bytes != 0 + * @cmnd is ignored and this functions sets up a REQUEST_SENSE command + * and cmnd buffers to read @sense_bytes into @scmd->sense_buffer. **/ -static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, - int cmnd_size, int timeout, int copy_sense) +void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, + unsigned char *cmnd, int cmnd_size, unsigned sense_bytes) { struct scsi_device *sdev = scmd->device; - struct Scsi_Host *shost = sdev->host; - int old_result = scmd->result; - DECLARE_COMPLETION_ONSTACK(done); - unsigned long timeleft; - unsigned long flags; - struct scatterlist sgl; - unsigned char old_cmnd[MAX_COMMAND_SIZE]; - enum dma_data_direction old_data_direction; - unsigned short old_use_sg; - unsigned char old_cmd_len; - unsigned old_bufflen; - void *old_buffer; - int rtn; /* * We need saved copies of a number of fields - this is because @@ -630,35 +615,42 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, * we will need to restore these values prior to running the actual * command. */ - old_buffer = scmd->request_buffer; - old_bufflen = scmd->request_bufflen; - memcpy(old_cmnd, scmd->cmnd, sizeof(scmd->cmnd)); - old_data_direction = scmd->sc_data_direction; - old_cmd_len = scmd->cmd_len; - old_use_sg = scmd->use_sg; - - memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); - memcpy(scmd->cmnd, cmnd, cmnd_size); - - if (copy_sense) { - sg_init_one(&sgl, scmd->sense_buffer, - sizeof(scmd->sense_buffer)); - + ses->cmd_len = scmd->cmd_len; + memcpy(ses->cmnd, scmd->cmnd, sizeof(scmd->cmnd)); + ses->data_direction = scmd->sc_data_direction; + ses->bufflen = scmd->request_bufflen; + ses->buffer = scmd->request_buffer; + ses->use_sg = scmd->use_sg; + ses->resid = scmd->resid; + ses->result = scmd->result; + + if (sense_bytes) { + scmd->request_bufflen = min_t(unsigned, + sizeof(scmd->sense_buffer), sense_bytes); + sg_init_one(&ses->sense_sgl, scmd->sense_buffer, + scmd->request_bufflen); + scmd->request_buffer = &ses->sense_sgl; scmd->sc_data_direction = DMA_FROM_DEVICE; - scmd->request_bufflen = sgl.length; - scmd->request_buffer = &sgl; scmd->use_sg = 1; + memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); + scmd->cmnd[0] = REQUEST_SENSE; + scmd->cmnd[4] = scmd->request_bufflen; + scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); } else { scmd->request_buffer = NULL; scmd->request_bufflen = 0; scmd->sc_data_direction = DMA_NONE; scmd->use_sg = 0; + if (cmnd) { + memset(scmd->cmnd, 0, sizeof(scmd->cmnd)); + memcpy(scmd->cmnd, cmnd, cmnd_size); + scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); + } } scmd->underflow = 0; - scmd->cmd_len = COMMAND_SIZE(scmd->cmnd[0]); - if (sdev->scsi_level <= SCSI_2) + if (sdev->scsi_level <= SCSI_2 && sdev->scsi_level != SCSI_UNKNOWN) scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) | (sdev->lun << 5 & 0xe0); @@ -667,7 +659,58 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, * untransferred sense data should be interpreted as being zero. */ memset(scmd->sense_buffer, 0, sizeof(scmd->sense_buffer)); +} +EXPORT_SYMBOL(scsi_eh_prep_cmnd); + +/** + * scsi_eh_restore_cmnd - Restore a scsi command info as part of error recory + * @scmd: SCSI command structure to restore + * @ses: saved information from a coresponding call to scsi_prep_eh_cmnd + * + * Undo any damage done by above scsi_prep_eh_cmnd(). + **/ +void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, struct scsi_eh_save *ses) +{ + /* + * Restore original data + */ + scmd->cmd_len = ses->cmd_len; + memcpy(scmd->cmnd, ses->cmnd, sizeof(scmd->cmnd)); + scmd->sc_data_direction = ses->data_direction; + scmd->request_bufflen = ses->bufflen; + scmd->request_buffer = ses->buffer; + scmd->use_sg = ses->use_sg; + scmd->resid = ses->resid; + scmd->result = ses->result; +} +EXPORT_SYMBOL(scsi_eh_restore_cmnd); +/** + * scsi_send_eh_cmnd - submit a scsi command as part of error recory + * @scmd: SCSI command structure to hijack + * @cmnd: CDB to send + * @cmnd_size: size in bytes of @cmnd + * @timeout: timeout for this request + * @sense_bytes: size of sense data to copy or 0 + * + * This function is used to send a scsi command down to a target device + * as part of the error recovery process. See also scsi_eh_prep_cmnd() above. + * + * Return value: + * SUCCESS or FAILED or NEEDS_RETRY + **/ +static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, + int cmnd_size, int timeout, unsigned sense_bytes) +{ + struct scsi_device *sdev = scmd->device; + struct Scsi_Host *shost = sdev->host; + DECLARE_COMPLETION_ONSTACK(done); + unsigned long timeleft; + unsigned long flags; + struct scsi_eh_save ses; + int rtn; + + scsi_eh_prep_cmnd(scmd, &ses, cmnd, cmnd_size, sense_bytes); shost->eh_action = &done; spin_lock_irqsave(shost->host_lock, flags); @@ -711,17 +754,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, rtn = FAILED; } - - /* - * Restore original data - */ - scmd->request_buffer = old_buffer; - scmd->request_bufflen = old_bufflen; - memcpy(scmd->cmnd, old_cmnd, sizeof(scmd->cmnd)); - scmd->sc_data_direction = old_data_direction; - scmd->cmd_len = old_cmd_len; - scmd->use_sg = old_use_sg; - scmd->result = old_result; + scsi_eh_restore_cmnd(scmd, &ses); return rtn; } @@ -736,10 +769,7 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, **/ static int scsi_request_sense(struct scsi_cmnd *scmd) { - static unsigned char generic_sense[6] = - {REQUEST_SENSE, 0, 0, 0, 252, 0}; - - return scsi_send_eh_cmnd(scmd, generic_sense, 6, SENSE_TIMEOUT, 1); + return scsi_send_eh_cmnd(scmd, NULL, 0, SENSE_TIMEOUT, ~0); } /** @@ -1136,9 +1166,8 @@ static void scsi_eh_offline_sdevs(struct list_head *work_q, struct scsi_cmnd *scmd, *next; list_for_each_entry_safe(scmd, next, work_q, eh_entry) { - sdev_printk(KERN_INFO, scmd->device, - "scsi: Device offlined - not" - " ready after error recovery\n"); + sdev_printk(KERN_INFO, scmd->device, "Device offlined - " + "not ready after error recovery\n"); scsi_device_set_state(scmd->device, SDEV_OFFLINE); if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) { /* @@ -1671,7 +1700,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) memset(&scmd->cmnd, '\0', sizeof(scmd->cmnd)); scmd->scsi_done = scsi_reset_provider_done_command; - scmd->done = NULL; scmd->request_buffer = NULL; scmd->request_bufflen = 0; @@ -1681,12 +1709,6 @@ scsi_reset_provider(struct scsi_device *dev, int flag) init_timer(&scmd->eh_timeout); - /* - * Sometimes the command can get back into the timer chain, - * so use the pid as an identifier. - */ - scmd->pid = 0; - spin_lock_irqsave(shost->host_lock, flags); shost->tmf_in_progress = 1; spin_unlock_irqrestore(shost->host_lock, flags); diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 604f4d717933..207f1aa08869 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c @@ -288,7 +288,7 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, { struct request_queue *q = rq->q; int nr_pages = (bufflen + sgl[0].offset + PAGE_SIZE - 1) >> PAGE_SHIFT; - unsigned int data_len = 0, len, bytes, off; + unsigned int data_len = bufflen, len, bytes, off; struct page *page; struct bio *bio = NULL; int i, err, nr_vecs = 0; @@ -297,10 +297,15 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, page = sgl[i].page; off = sgl[i].offset; len = sgl[i].length; - data_len += len; - while (len > 0) { + 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); @@ -332,12 +337,13 @@ static int scsi_req_map_sg(struct request *rq, struct scatterlist *sgl, page++; len -= bytes; + data_len -=bytes; off = 0; } } rq->buffer = rq->data = NULL; - rq->data_len = data_len; + rq->data_len = bufflen; return 0; free_bios: @@ -430,6 +436,7 @@ EXPORT_SYMBOL_GPL(scsi_execute_async); static void scsi_init_cmd_errh(struct scsi_cmnd *cmd) { cmd->serial_number = 0; + cmd->resid = 0; memset(cmd->sense_buffer, 0, sizeof cmd->sense_buffer); if (cmd->cmd_len == 0) cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); @@ -924,11 +931,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) break; } } - if (!(req->cmd_flags & REQ_QUIET)) { - scmd_printk(KERN_INFO, cmd, - "Device not ready: "); - scsi_print_sense_hdr("", &sshdr); - } + if (!(req->cmd_flags & REQ_QUIET)) + scsi_cmd_print_sense_hdr(cmd, + "Device not ready", + &sshdr); + scsi_end_request(cmd, 0, this_count, 1); return; case VOLUME_OVERFLOW: @@ -962,7 +969,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) } scsi_end_request(cmd, 0, this_count, !result); } -EXPORT_SYMBOL(scsi_io_completion); /* * Function: scsi_init_io() @@ -1019,9 +1025,6 @@ static int scsi_init_io(struct scsi_cmnd *cmd) printk(KERN_ERR "req nr_sec %lu, cur_nr_sec %u\n", req->nr_sectors, req->current_nr_sectors); - /* release the command and kill it */ - scsi_release_buffers(cmd); - scsi_put_command(cmd); return BLKPREP_KILL; } @@ -1046,21 +1049,13 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, return cmd; } -static void scsi_blk_pc_done(struct scsi_cmnd *cmd) -{ - BUG_ON(!blk_pc_request(cmd->request)); - /* - * This will complete the whole command with uptodate=1 so - * as far as the block layer is concerned the command completed - * successfully. Since this is a REQ_BLOCK_PC command the - * caller should check the request's errors value - */ - scsi_io_completion(cmd, cmd->request_bufflen); -} - -static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) +int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd; + int ret = scsi_prep_state_check(sdev, req); + + if (ret != BLKPREP_OK) + return ret; cmd = scsi_get_cmd_from_req(sdev, req); if (unlikely(!cmd)) @@ -1103,21 +1098,22 @@ static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) cmd->transfersize = req->data_len; cmd->allowed = req->retries; cmd->timeout_per_command = req->timeout; - cmd->done = scsi_blk_pc_done; return BLKPREP_OK; } +EXPORT_SYMBOL(scsi_setup_blk_pc_cmnd); /* * Setup a REQ_TYPE_FS command. These are simple read/write request * from filesystems that still need to be translated to SCSI CDBs from * the ULD. */ -static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) +int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd; - struct scsi_driver *drv; - int ret; + int ret = scsi_prep_state_check(sdev, req); + if (ret != BLKPREP_OK) + return ret; /* * Filesystem requests must transfer data. */ @@ -1127,26 +1123,12 @@ static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) if (unlikely(!cmd)) return BLKPREP_DEFER; - ret = scsi_init_io(cmd); - if (unlikely(ret)) - return ret; - - /* - * Initialize the actual SCSI command for this request. - */ - drv = *(struct scsi_driver **)req->rq_disk->private_data; - if (unlikely(!drv->init_command(cmd))) { - scsi_release_buffers(cmd); - scsi_put_command(cmd); - return BLKPREP_KILL; - } - - return BLKPREP_OK; + return scsi_init_io(cmd); } +EXPORT_SYMBOL(scsi_setup_fs_cmnd); -static int scsi_prep_fn(struct request_queue *q, struct request *req) +int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) { - struct scsi_device *sdev = q->queuedata; int ret = BLKPREP_OK; /* @@ -1192,35 +1174,25 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) ret = BLKPREP_KILL; break; } - - if (ret != BLKPREP_OK) - goto out; } + return ret; +} +EXPORT_SYMBOL(scsi_prep_state_check); - switch (req->cmd_type) { - case REQ_TYPE_BLOCK_PC: - ret = scsi_setup_blk_pc_cmnd(sdev, req); - break; - case REQ_TYPE_FS: - ret = scsi_setup_fs_cmnd(sdev, req); - break; - default: - /* - * All other command types are not supported. - * - * Note that these days the SCSI subsystem does not use - * REQ_TYPE_SPECIAL requests anymore. These are only used - * (directly or via blk_insert_request) by non-SCSI drivers. - */ - blk_dump_rq_flags(req, "SCSI bad req"); - ret = BLKPREP_KILL; - break; - } +int scsi_prep_return(struct request_queue *q, struct request *req, int ret) +{ + struct scsi_device *sdev = q->queuedata; - out: switch (ret) { case BLKPREP_KILL: req->errors = DID_NO_CONNECT << 16; + /* release the command and kill it */ + if (req->special) { + struct scsi_cmnd *cmd = req->special; + scsi_release_buffers(cmd); + scsi_put_command(cmd); + req->special = NULL; + } break; case BLKPREP_DEFER: /* @@ -1237,6 +1209,17 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req) return ret; } +EXPORT_SYMBOL(scsi_prep_return); + +static int scsi_prep_fn(struct request_queue *q, struct request *req) +{ + struct scsi_device *sdev = q->queuedata; + int ret = BLKPREP_KILL; + + if (req->cmd_type == REQ_TYPE_BLOCK_PC) + ret = scsi_setup_blk_pc_cmnd(sdev, req); + return scsi_prep_return(q, req, ret); +} /* * scsi_dev_queue_ready: if we can send requests to sdev, return 1 else diff --git a/drivers/scsi/scsi_priv.h b/drivers/scsi/scsi_priv.h index ee8efe849bf4..eff005951895 100644 --- a/drivers/scsi/scsi_priv.h +++ b/drivers/scsi/scsi_priv.h @@ -68,6 +68,7 @@ extern int scsi_maybe_unblock_host(struct scsi_device *sdev); extern void scsi_device_unbusy(struct scsi_device *sdev); extern int scsi_queue_insert(struct scsi_cmnd *cmd, int reason); extern void scsi_next_command(struct scsi_cmnd *cmd); +extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_run_host_queues(struct Scsi_Host *shost); extern struct request_queue *scsi_alloc_queue(struct scsi_device *sdev); extern void scsi_free_queue(struct request_queue *q); diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c index a86e62f4b3ba..b53c5f67e372 100644 --- a/drivers/scsi/scsi_scan.c +++ b/drivers/scsi/scsi_scan.c @@ -85,7 +85,7 @@ static unsigned int max_scsi_luns = MAX_SCSI_LUNS; static unsigned int max_scsi_luns = 1; #endif -module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR); +module_param_named(max_luns, max_scsi_luns, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_luns, "last scsi LUN (should be between 1 and 2^32-1)"); @@ -109,18 +109,19 @@ MODULE_PARM_DESC(scan, "sync, async or none"); */ static unsigned int max_scsi_report_luns = 511; -module_param_named(max_report_luns, max_scsi_report_luns, int, S_IRUGO|S_IWUSR); +module_param_named(max_report_luns, max_scsi_report_luns, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_report_luns, "REPORT LUNS maximum number of LUNS received (should be" " between 1 and 16384)"); static unsigned int scsi_inq_timeout = SCSI_TIMEOUT/HZ+3; -module_param_named(inq_timeout, scsi_inq_timeout, int, S_IRUGO|S_IWUSR); +module_param_named(inq_timeout, scsi_inq_timeout, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(inq_timeout, "Timeout (in seconds) waiting for devices to answer INQUIRY." " Default is 5. Some non-compliant devices need more."); +/* This lock protects only this list */ static DEFINE_SPINLOCK(async_scan_lock); static LIST_HEAD(scanning_hosts); @@ -1466,14 +1467,14 @@ struct scsi_device *__scsi_add_device(struct Scsi_Host *shost, uint channel, if (strncmp(scsi_scan_type, "none", 4) == 0) return ERR_PTR(-ENODEV); - if (!shost->async_scan) - scsi_complete_async_scans(); - starget = scsi_alloc_target(parent, channel, id); if (!starget) return ERR_PTR(-ENOMEM); mutex_lock(&shost->scan_mutex); + if (!shost->async_scan) + scsi_complete_async_scans(); + if (scsi_host_scan_allowed(shost)) scsi_probe_and_add_lun(starget, lun, NULL, &sdev, 1, hostdata); mutex_unlock(&shost->scan_mutex); @@ -1586,10 +1587,10 @@ void scsi_scan_target(struct device *parent, unsigned int channel, if (strncmp(scsi_scan_type, "none", 4) == 0) return; + mutex_lock(&shost->scan_mutex); if (!shost->async_scan) scsi_complete_async_scans(); - mutex_lock(&shost->scan_mutex); if (scsi_host_scan_allowed(shost)) __scsi_scan_target(parent, channel, id, lun, rescan); mutex_unlock(&shost->scan_mutex); @@ -1634,15 +1635,15 @@ int scsi_scan_host_selected(struct Scsi_Host *shost, unsigned int channel, "%s: <%u:%u:%u>\n", __FUNCTION__, channel, id, lun)); - if (!shost->async_scan) - scsi_complete_async_scans(); - if (((channel != SCAN_WILD_CARD) && (channel > shost->max_channel)) || ((id != SCAN_WILD_CARD) && (id >= shost->max_id)) || ((lun != SCAN_WILD_CARD) && (lun > shost->max_lun))) return -EINVAL; mutex_lock(&shost->scan_mutex); + if (!shost->async_scan) + scsi_complete_async_scans(); + if (scsi_host_scan_allowed(shost)) { if (channel == SCAN_WILD_CARD) for (channel = 0; channel <= shost->max_channel; @@ -1661,7 +1662,8 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) { struct scsi_device *sdev; shost_for_each_device(sdev, shost) { - if (scsi_sysfs_add_sdev(sdev) != 0) + if (!scsi_host_scan_allowed(shost) || + scsi_sysfs_add_sdev(sdev) != 0) scsi_destroy_sdev(sdev); } } @@ -1679,6 +1681,7 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) { struct async_scan_data *data; + unsigned long flags; if (strncmp(scsi_scan_type, "sync", 4) == 0) return NULL; @@ -1698,8 +1701,13 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) goto err; init_completion(&data->prev_finished); - spin_lock(&async_scan_lock); + mutex_lock(&shost->scan_mutex); + spin_lock_irqsave(shost->host_lock, flags); shost->async_scan = 1; + spin_unlock_irqrestore(shost->host_lock, flags); + mutex_unlock(&shost->scan_mutex); + + spin_lock(&async_scan_lock); if (list_empty(&scanning_hosts)) complete(&data->prev_finished); list_add_tail(&data->list, &scanning_hosts); @@ -1723,11 +1731,15 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) static void scsi_finish_async_scan(struct async_scan_data *data) { struct Scsi_Host *shost; + unsigned long flags; if (!data) return; shost = data->shost; + + mutex_lock(&shost->scan_mutex); + if (!shost->async_scan) { printk("%s called twice for host %d", __FUNCTION__, shost->host_no); @@ -1739,8 +1751,13 @@ static void scsi_finish_async_scan(struct async_scan_data *data) scsi_sysfs_add_devices(shost); - spin_lock(&async_scan_lock); + spin_lock_irqsave(shost->host_lock, flags); shost->async_scan = 0; + spin_unlock_irqrestore(shost->host_lock, flags); + + mutex_unlock(&shost->scan_mutex); + + spin_lock(&async_scan_lock); list_del(&data->list); if (!list_empty(&scanning_hosts)) { struct async_scan_data *next = list_entry(scanning_hosts.next, @@ -1782,6 +1799,7 @@ static int do_scan_async(void *_data) **/ void scsi_scan_host(struct Scsi_Host *shost) { + struct task_struct *p; struct async_scan_data *data; if (strncmp(scsi_scan_type, "none", 4) == 0) @@ -1793,7 +1811,9 @@ void scsi_scan_host(struct Scsi_Host *shost) return; } - kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); + p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); + if (unlikely(IS_ERR(p))) + do_scan_async(data); } EXPORT_SYMBOL(scsi_scan_host); diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c index ede9986d349a..daed37df00b1 100644 --- a/drivers/scsi/scsi_sysfs.c +++ b/drivers/scsi/scsi_sysfs.c @@ -190,6 +190,46 @@ show_shost_state(struct class_device *class_dev, char *buf) static CLASS_DEVICE_ATTR(state, S_IRUGO | S_IWUSR, show_shost_state, store_shost_state); +static ssize_t +show_shost_mode(unsigned int mode, char *buf) +{ + ssize_t len = 0; + + if (mode & MODE_INITIATOR) + len = sprintf(buf, "%s", "Initiator"); + + if (mode & MODE_TARGET) + len += sprintf(buf + len, "%s%s", len ? ", " : "", "Target"); + + len += sprintf(buf + len, "\n"); + + return len; +} + +static ssize_t show_shost_supported_mode(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + + if (shost->hostt->supported_mode == MODE_UNKNOWN) + return snprintf(buf, 20, "unknown\n"); + else + return show_shost_mode(shost->hostt->supported_mode, buf); +} + +static CLASS_DEVICE_ATTR(supported_mode, S_IRUGO | S_IWUSR, show_shost_supported_mode, NULL); + +static ssize_t show_shost_active_mode(struct class_device *class_dev, char *buf) +{ + struct Scsi_Host *shost = class_to_shost(class_dev); + + if (shost->active_mode == MODE_UNKNOWN) + return snprintf(buf, 20, "unknown\n"); + else + return show_shost_mode(shost->active_mode, buf); +} + +static CLASS_DEVICE_ATTR(active_mode, S_IRUGO | S_IWUSR, show_shost_active_mode, NULL); + shost_rd_attr(unique_id, "%u\n"); shost_rd_attr(host_busy, "%hu\n"); shost_rd_attr(cmd_per_lun, "%hd\n"); @@ -208,6 +248,8 @@ static struct class_device_attribute *scsi_sysfs_shost_attrs[] = { &class_device_attr_proc_name, &class_device_attr_scan, &class_device_attr_state, + &class_device_attr_supported_mode, + &class_device_attr_active_mode, NULL }; @@ -571,24 +613,31 @@ sdev_show_modalias(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(modalias, S_IRUGO, sdev_show_modalias, NULL); /* Default template for device attributes. May NOT be modified */ -static struct device_attribute *scsi_sysfs_sdev_attrs[] = { - &dev_attr_device_blocked, - &dev_attr_queue_depth, - &dev_attr_queue_type, - &dev_attr_type, - &dev_attr_scsi_level, - &dev_attr_vendor, - &dev_attr_model, - &dev_attr_rev, - &dev_attr_rescan, - &dev_attr_delete, - &dev_attr_state, - &dev_attr_timeout, - &dev_attr_iocounterbits, - &dev_attr_iorequest_cnt, - &dev_attr_iodone_cnt, - &dev_attr_ioerr_cnt, - &dev_attr_modalias, +static struct attribute *scsi_sdev_attrs[] = { + &dev_attr_device_blocked.attr, + &dev_attr_type.attr, + &dev_attr_scsi_level.attr, + &dev_attr_vendor.attr, + &dev_attr_model.attr, + &dev_attr_rev.attr, + &dev_attr_rescan.attr, + &dev_attr_delete.attr, + &dev_attr_state.attr, + &dev_attr_timeout.attr, + &dev_attr_iocounterbits.attr, + &dev_attr_iorequest_cnt.attr, + &dev_attr_iodone_cnt.attr, + &dev_attr_ioerr_cnt.attr, + &dev_attr_modalias.attr, + NULL +}; + +static struct attribute_group scsi_sdev_attr_group = { + .attrs = scsi_sdev_attrs, +}; + +static struct attribute_group *scsi_sdev_attr_groups[] = { + &scsi_sdev_attr_group, NULL }; @@ -650,56 +699,6 @@ static struct device_attribute sdev_attr_queue_type_rw = __ATTR(queue_type, S_IRUGO | S_IWUSR, show_queue_type_field, sdev_store_queue_type_rw); -static struct device_attribute *attr_changed_internally( - struct Scsi_Host *shost, - struct device_attribute * attr) -{ - if (!strcmp("queue_depth", attr->attr.name) - && shost->hostt->change_queue_depth) - return &sdev_attr_queue_depth_rw; - else if (!strcmp("queue_type", attr->attr.name) - && shost->hostt->change_queue_type) - return &sdev_attr_queue_type_rw; - return attr; -} - - -static struct device_attribute *attr_overridden( - struct device_attribute **attrs, - struct device_attribute *attr) -{ - int i; - - if (!attrs) - return NULL; - for (i = 0; attrs[i]; i++) - if (!strcmp(attrs[i]->attr.name, attr->attr.name)) - return attrs[i]; - return NULL; -} - -static int attr_add(struct device *dev, struct device_attribute *attr) -{ - struct device_attribute *base_attr; - - /* - * Spare the caller from having to copy things it's not interested in. - */ - base_attr = attr_overridden(scsi_sysfs_sdev_attrs, attr); - if (base_attr) { - /* extend permissions */ - attr->attr.mode |= base_attr->attr.mode; - - /* override null show/store with default */ - if (!attr->show) - attr->show = base_attr->show; - if (!attr->store) - attr->store = base_attr->store; - } - - return device_create_file(dev, attr); -} - /** * scsi_sysfs_add_sdev - add scsi device to sysfs * @sdev: scsi_device to add @@ -731,6 +730,24 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) * released by the sdev_class .release */ get_device(&sdev->sdev_gendev); + /* create queue files, which may be writable, depending on the host */ + if (sdev->host->hostt->change_queue_depth) + error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw); + else + error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_depth); + if (error) { + __scsi_remove_device(sdev); + goto out; + } + if (sdev->host->hostt->change_queue_type) + error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_type_rw); + else + error = device_create_file(&sdev->sdev_gendev, &dev_attr_queue_type); + if (error) { + __scsi_remove_device(sdev); + goto out; + } + error = bsg_register_queue(rq, &sdev->sdev_gendev, NULL); if (error) @@ -741,9 +758,10 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) * nothing went wrong */ error = 0; + /* add additional host specific attributes */ if (sdev->host->hostt->sdev_attrs) { for (i = 0; sdev->host->hostt->sdev_attrs[i]; i++) { - error = attr_add(&sdev->sdev_gendev, + error = device_create_file(&sdev->sdev_gendev, sdev->host->hostt->sdev_attrs[i]); if (error) { __scsi_remove_device(sdev); @@ -751,20 +769,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) } } } - - for (i = 0; scsi_sysfs_sdev_attrs[i]; i++) { - if (!attr_overridden(sdev->host->hostt->sdev_attrs, - scsi_sysfs_sdev_attrs[i])) { - struct device_attribute * attr = - attr_changed_internally(sdev->host, - scsi_sysfs_sdev_attrs[i]); - error = device_create_file(&sdev->sdev_gendev, attr); - if (error) { - __scsi_remove_device(sdev); - goto out; - } - } - } transport_add_device(&sdev->sdev_gendev); out: @@ -951,6 +955,12 @@ int scsi_sysfs_add_host(struct Scsi_Host *shost) return 0; } +static struct device_type scsi_dev_type = { + .name = "scsi_device", + .release = scsi_device_dev_release, + .groups = scsi_sdev_attr_groups, +}; + void scsi_sysfs_device_initialize(struct scsi_device *sdev) { unsigned long flags; @@ -959,7 +969,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) device_initialize(&sdev->sdev_gendev); sdev->sdev_gendev.bus = &scsi_bus_type; - sdev->sdev_gendev.release = scsi_device_dev_release; + sdev->sdev_gendev.type = &scsi_dev_type; sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); @@ -980,7 +990,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) int scsi_is_sdev_device(const struct device *dev) { - return dev->release == scsi_device_dev_release; + return dev->type == &scsi_dev_type; } EXPORT_SYMBOL(scsi_is_sdev_device); diff --git a/drivers/scsi/scsi_tgt_if.c b/drivers/scsi/scsi_tgt_if.c index ca22ddf81746..9815a1a2db24 100644 --- a/drivers/scsi/scsi_tgt_if.c +++ b/drivers/scsi/scsi_tgt_if.c @@ -102,7 +102,8 @@ static int tgt_uspace_send_event(u32 type, struct tgt_event *p) return 0; } -int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) +int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id, + struct scsi_lun *lun, u64 tag) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); struct tgt_event ev; @@ -110,6 +111,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta memset(&ev, 0, sizeof(ev)); ev.p.cmd_req.host_no = shost->host_no; + ev.p.cmd_req.itn_id = itn_id; ev.p.cmd_req.data_len = cmd->request_bufflen; memcpy(ev.p.cmd_req.scb, cmd->cmnd, sizeof(ev.p.cmd_req.scb)); memcpy(ev.p.cmd_req.lun, lun, sizeof(ev.p.cmd_req.lun)); @@ -127,7 +129,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 ta return err; } -int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) +int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); struct tgt_event ev; @@ -135,6 +137,7 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) memset(&ev, 0, sizeof(ev)); ev.p.cmd_done.host_no = shost->host_no; + ev.p.cmd_done.itn_id = itn_id; ev.p.cmd_done.tag = tag; ev.p.cmd_done.result = cmd->result; @@ -149,14 +152,15 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) return err; } -int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, - struct scsi_lun *scsilun, void *data) +int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function, + u64 tag, struct scsi_lun *scsilun, void *data) { struct tgt_event ev; int err; memset(&ev, 0, sizeof(ev)); ev.p.tsk_mgmt_req.host_no = host_no; + ev.p.tsk_mgmt_req.itn_id = itn_id; ev.p.tsk_mgmt_req.function = function; ev.p.tsk_mgmt_req.tag = tag; memcpy(ev.p.tsk_mgmt_req.lun, scsilun, sizeof(ev.p.tsk_mgmt_req.lun)); @@ -172,6 +176,29 @@ int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, return err; } +int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 itn_id, + int function, char *initiator_id) +{ + struct tgt_event ev; + int err; + + memset(&ev, 0, sizeof(ev)); + ev.p.it_nexus_req.host_no = host_no; + ev.p.it_nexus_req.function = function; + ev.p.it_nexus_req.itn_id = itn_id; + if (initiator_id) + strncpy(ev.p.it_nexus_req.initiator_id, initiator_id, + sizeof(ev.p.it_nexus_req.initiator_id)); + + dprintk("%d %x %llx\n", host_no, function, (unsigned long long)itn_id); + + err = tgt_uspace_send_event(TGT_KEVENT_IT_NEXUS_REQ, &ev); + if (err) + eprintk("tx buf is full, could not send\n"); + + return err; +} + static int event_recv_msg(struct tgt_event *ev) { int err = 0; @@ -179,6 +206,7 @@ static int event_recv_msg(struct tgt_event *ev) switch (ev->hdr.type) { case TGT_UEVENT_CMD_RSP: err = scsi_tgt_kspace_exec(ev->p.cmd_rsp.host_no, + ev->p.cmd_rsp.itn_id, ev->p.cmd_rsp.result, ev->p.cmd_rsp.tag, ev->p.cmd_rsp.uaddr, @@ -189,9 +217,15 @@ static int event_recv_msg(struct tgt_event *ev) break; case TGT_UEVENT_TSK_MGMT_RSP: err = scsi_tgt_kspace_tsk_mgmt(ev->p.tsk_mgmt_rsp.host_no, + ev->p.tsk_mgmt_rsp.itn_id, ev->p.tsk_mgmt_rsp.mid, ev->p.tsk_mgmt_rsp.result); break; + case TGT_UEVENT_IT_NEXUS_RSP: + err = scsi_tgt_kspace_it_nexus_rsp(ev->p.it_nexus_rsp.host_no, + ev->p.it_nexus_rsp.itn_id, + ev->p.it_nexus_rsp.result); + break; default: eprintk("unknown type %d\n", ev->hdr.type); err = -EINVAL; diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 371b69c110bc..66c692ffa305 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c @@ -27,6 +27,7 @@ #include <scsi/scsi_cmnd.h> #include <scsi/scsi_device.h> #include <scsi/scsi_host.h> +#include <scsi/scsi_transport.h> #include <scsi/scsi_tgt.h> #include "scsi_tgt_priv.h" @@ -46,6 +47,7 @@ struct scsi_tgt_cmd { struct list_head hash_list; struct request *rq; + u64 itn_id; u64 tag; }; @@ -185,12 +187,13 @@ static void scsi_tgt_cmd_destroy(struct work_struct *work) } static void init_scsi_tgt_cmd(struct request *rq, struct scsi_tgt_cmd *tcmd, - u64 tag) + u64 itn_id, u64 tag) { struct scsi_tgt_queuedata *qdata = rq->q->queuedata; unsigned long flags; struct list_head *head; + tcmd->itn_id = itn_id; tcmd->tag = tag; tcmd->bio = NULL; INIT_WORK(&tcmd->work, scsi_tgt_cmd_destroy); @@ -234,7 +237,7 @@ int scsi_tgt_alloc_queue(struct Scsi_Host *shost) * command as is recvd to userspace. uspace can then make * sure we do not overload the HBA */ - q->nr_requests = shost->hostt->can_queue; + q->nr_requests = shost->can_queue; /* * We currently only support software LLDs so this does * not matter for now. Do we need this for the cards we support? @@ -301,14 +304,14 @@ EXPORT_SYMBOL_GPL(scsi_tgt_cmd_to_host); * @scsilun: scsi lun * @tag: unique value to identify this command for tmf */ -int scsi_tgt_queue_command(struct scsi_cmnd *cmd, struct scsi_lun *scsilun, - u64 tag) +int scsi_tgt_queue_command(struct scsi_cmnd *cmd, u64 itn_id, + struct scsi_lun *scsilun, u64 tag) { struct scsi_tgt_cmd *tcmd = cmd->request->end_io_data; int err; - init_scsi_tgt_cmd(cmd->request, tcmd, tag); - err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); + init_scsi_tgt_cmd(cmd->request, tcmd, itn_id, tag); + err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag); if (err) cmd_hashlist_del(cmd); @@ -326,7 +329,7 @@ static void scsi_tgt_cmd_done(struct scsi_cmnd *cmd) dprintk("cmd %p %lu\n", cmd, rq_data_dir(cmd->request)); - scsi_tgt_uspace_send_status(cmd, tcmd->tag); + scsi_tgt_uspace_send_status(cmd, tcmd->itn_id, tcmd->tag); if (cmd->request_buffer) scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); @@ -459,7 +462,7 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) return rq; } -int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, +int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, unsigned long uaddr, u32 len, unsigned long sense_uaddr, u32 sense_len, u8 rw) { @@ -541,21 +544,22 @@ done: return err; } -int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, int function, u64 tag, - struct scsi_lun *scsilun, void *data) +int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id, + int function, u64 tag, struct scsi_lun *scsilun, + void *data) { int err; /* TODO: need to retry if this fails. */ - err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, function, - tag, scsilun, data); + err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, itn_id, + function, tag, scsilun, data); if (err < 0) eprintk("The task management request lost!\n"); return err; } EXPORT_SYMBOL_GPL(scsi_tgt_tsk_mgmt_request); -int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) +int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) { struct Scsi_Host *shost; int err = -EINVAL; @@ -573,7 +577,60 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) goto done; } - err = shost->hostt->tsk_mgmt_response(mid, result); + err = shost->transportt->tsk_mgmt_response(shost, itn_id, mid, result); +done: + scsi_host_put(shost); + return err; +} + +int scsi_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + int err; + + /* TODO: need to retry if this fails. */ + err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, itn_id, 0, + initiator); + if (err < 0) + eprintk("The i_t_neuxs request lost, %d %llx!\n", + shost->host_no, (unsigned long long)itn_id); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_create); + +int scsi_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + int err; + + /* TODO: need to retry if this fails. */ + err = scsi_tgt_uspace_send_it_nexus_request(shost->host_no, + itn_id, 1, NULL); + if (err < 0) + eprintk("The i_t_neuxs request lost, %d %llx!\n", + shost->host_no, (unsigned long long)itn_id); + return err; +} +EXPORT_SYMBOL_GPL(scsi_tgt_it_nexus_destroy); + +int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 itn_id, int result) +{ + struct Scsi_Host *shost; + int err = -EINVAL; + + dprintk("%d %d %llx\n", host_no, result, (unsigned long long) mid); + + shost = scsi_host_lookup(host_no); + if (IS_ERR(shost)) { + printk(KERN_ERR "Could not find host no %d\n", host_no); + return err; + } + + if (!shost->uspace_req_q) { + printk(KERN_ERR "Not target scsi host %d\n", host_no); + goto done; + } + + err = shost->transportt->it_nexus_response(shost, itn_id, result); done: scsi_host_put(shost); return err; diff --git a/drivers/scsi/scsi_tgt_priv.h b/drivers/scsi/scsi_tgt_priv.h index e9e6db1c417f..cb92888948f9 100644 --- a/drivers/scsi/scsi_tgt_priv.h +++ b/drivers/scsi/scsi_tgt_priv.h @@ -15,12 +15,18 @@ do { \ extern void scsi_tgt_if_exit(void); extern int scsi_tgt_if_init(void); -extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, - u64 tag); -extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag); -extern int scsi_tgt_kspace_exec(int host_no, int result, u64 tag, - unsigned long uaddr, u32 len, unsigned long sense_uaddr, - u32 sense_len, u8 rw); -extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, int function, u64 tag, +extern int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 it_nexus_id, + struct scsi_lun *lun, u64 tag); +extern int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 it_nexus_id, + u64 tag); +extern int scsi_tgt_kspace_exec(int host_no, u64 it_nexus_id, int result, u64 tag, + unsigned long uaddr, u32 len, + unsigned long sense_uaddr, u32 sense_len, u8 rw); +extern int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 it_nexus_id, + int function, u64 tag, struct scsi_lun *scsilun, void *data); -extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); +extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 it_nexus_id, + u64 mid, int result); +extern int scsi_tgt_uspace_send_it_nexus_request(int host_no, u64 it_nexus_id, + int function, char *initiator); +extern int scsi_tgt_kspace_it_nexus_rsp(int host_no, u64 it_nexus_id, int result); diff --git a/drivers/scsi/scsi_transport_fc.c b/drivers/scsi/scsi_transport_fc.c index 47057254850d..7a7cfe583b2a 100644 --- a/drivers/scsi/scsi_transport_fc.c +++ b/drivers/scsi/scsi_transport_fc.c @@ -36,6 +36,7 @@ #include <net/netlink.h> #include <scsi/scsi_netlink_fc.h> #include "scsi_priv.h" +#include "scsi_transport_fc_internal.h" static int fc_queue_work(struct Scsi_Host *, struct work_struct *); static void fc_vport_sched_delete(struct work_struct *work); @@ -473,7 +474,7 @@ static DECLARE_TRANSPORT_CLASS(fc_vport_class, */ static unsigned int fc_dev_loss_tmo = 60; /* seconds */ -module_param_named(dev_loss_tmo, fc_dev_loss_tmo, int, S_IRUGO|S_IWUSR); +module_param_named(dev_loss_tmo, fc_dev_loss_tmo, uint, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(dev_loss_tmo, "Maximum number of seconds that the FC transport should" " insulate the loss of a remote port. Once this value is" @@ -1956,6 +1957,19 @@ static int fc_user_scan(struct Scsi_Host *shost, uint channel, return 0; } +static int fc_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, + int result) +{ + struct fc_internal *i = to_fc_internal(shost->transportt); + return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); +} + +static int fc_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) +{ + struct fc_internal *i = to_fc_internal(shost->transportt); + return i->f->it_nexus_response(shost, nexus, result); +} + struct scsi_transport_template * fc_attach_transport(struct fc_function_template *ft) { @@ -1999,6 +2013,10 @@ fc_attach_transport(struct fc_function_template *ft) i->t.user_scan = fc_user_scan; + /* target-mode drivers' functions */ + i->t.tsk_mgmt_response = fc_tsk_mgmt_response; + i->t.it_nexus_response = fc_it_nexus_response; + /* * Setup SCSI Target Attributes. */ @@ -2756,6 +2774,10 @@ fc_remote_port_delete(struct fc_rport *rport) spin_unlock_irqrestore(shost->host_lock, flags); + if (rport->roles & FC_PORT_ROLE_FCP_INITIATOR && + shost->active_mode & MODE_TARGET) + fc_tgt_it_nexus_destroy(shost, (unsigned long)rport); + scsi_target_block(&rport->dev); /* see if we need to kill io faster than waiting for device loss */ @@ -2796,6 +2818,7 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) struct fc_host_attrs *fc_host = shost_to_fc_host(shost); unsigned long flags; int create = 0; + int ret; spin_lock_irqsave(shost->host_lock, flags); if (roles & FC_PORT_ROLE_FCP_TARGET) { @@ -2804,6 +2827,12 @@ fc_remote_port_rolechg(struct fc_rport *rport, u32 roles) create = 1; } else if (!(rport->roles & FC_PORT_ROLE_FCP_TARGET)) create = 1; + } else if (shost->active_mode & MODE_TARGET) { + ret = fc_tgt_it_nexus_create(shost, (unsigned long)rport, + (char *)&rport->node_name); + if (ret) + printk(KERN_ERR "FC Remore Port tgt nexus failed %d\n", + ret); } rport->roles = roles; @@ -2988,10 +3017,12 @@ fc_scsi_scan_rport(struct work_struct *work) struct fc_rport *rport = container_of(work, struct fc_rport, scan_work); struct Scsi_Host *shost = rport_to_shost(rport); + struct fc_internal *i = to_fc_internal(shost->transportt); unsigned long flags; if ((rport->port_state == FC_PORTSTATE_ONLINE) && - (rport->roles & FC_PORT_ROLE_FCP_TARGET)) { + (rport->roles & FC_PORT_ROLE_FCP_TARGET) && + !(i->f->disable_target_scan)) { scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id, SCAN_WILD_CARD, 1); } diff --git a/drivers/scsi/scsi_transport_fc_internal.h b/drivers/scsi/scsi_transport_fc_internal.h new file mode 100644 index 000000000000..e7bfbe751c1f --- /dev/null +++ b/drivers/scsi/scsi_transport_fc_internal.h @@ -0,0 +1,26 @@ +#include <scsi/scsi_tgt.h> + +#ifdef CONFIG_SCSI_FC_TGT_ATTRS +static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + return scsi_tgt_it_nexus_create(shost, itn_id, initiator); +} + +static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + return scsi_tgt_it_nexus_destroy(shost, itn_id); +} +#else +static inline int fc_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + return 0; +} + +static inline int fc_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + return 0; +} + +#endif diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c new file mode 100644 index 000000000000..44a340bd937b --- /dev/null +++ b/drivers/scsi/scsi_transport_srp.c @@ -0,0 +1,381 @@ +/* + * SCSI RDMA (SRP) transport class + * + * Copyright (C) 2007 FUJITA Tomonori <tomof@acm.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation, version 2 of the + * License. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ +#include <linux/init.h> +#include <linux/module.h> +#include <linux/jiffies.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/string.h> + +#include <scsi/scsi.h> +#include <scsi/scsi_device.h> +#include <scsi/scsi_host.h> +#include <scsi/scsi_transport.h> +#include <scsi/scsi_transport_srp.h> +#include "scsi_transport_srp_internal.h" + +struct srp_host_attrs { + atomic_t next_port_id; +}; +#define to_srp_host_attrs(host) ((struct srp_host_attrs *)(host)->shost_data) + +#define SRP_HOST_ATTRS 0 +#define SRP_RPORT_ATTRS 2 + +struct srp_internal { + struct scsi_transport_template t; + struct srp_function_template *f; + + struct class_device_attribute *host_attrs[SRP_HOST_ATTRS + 1]; + + struct class_device_attribute *rport_attrs[SRP_RPORT_ATTRS + 1]; + struct class_device_attribute private_rport_attrs[SRP_RPORT_ATTRS]; + struct transport_container rport_attr_cont; +}; + +#define to_srp_internal(tmpl) container_of(tmpl, struct srp_internal, t) + +#define dev_to_rport(d) container_of(d, struct srp_rport, dev) +#define transport_class_to_srp_rport(cdev) dev_to_rport((cdev)->dev) + +static int srp_host_setup(struct transport_container *tc, struct device *dev, + struct class_device *cdev) +{ + struct Scsi_Host *shost = dev_to_shost(dev); + struct srp_host_attrs *srp_host = to_srp_host_attrs(shost); + + atomic_set(&srp_host->next_port_id, 0); + return 0; +} + +static DECLARE_TRANSPORT_CLASS(srp_host_class, "srp_host", srp_host_setup, + NULL, NULL); + +static DECLARE_TRANSPORT_CLASS(srp_rport_class, "srp_remote_ports", + NULL, NULL, NULL); + +#define SETUP_TEMPLATE(attrb, field, perm, test, ro_test, ro_perm) \ + i->private_##attrb[count] = class_device_attr_##field; \ + i->private_##attrb[count].attr.mode = perm; \ + if (ro_test) { \ + i->private_##attrb[count].attr.mode = ro_perm; \ + i->private_##attrb[count].store = NULL; \ + } \ + i->attrb[count] = &i->private_##attrb[count]; \ + if (test) \ + count++ + +#define SETUP_RPORT_ATTRIBUTE_RD(field) \ + SETUP_TEMPLATE(rport_attrs, field, S_IRUGO, 1, 0, 0) + +#define SETUP_RPORT_ATTRIBUTE_RW(field) \ + SETUP_TEMPLATE(rport_attrs, field, S_IRUGO | S_IWUSR, \ + 1, 1, S_IRUGO) + +#define SRP_PID(p) \ + (p)->port_id[0], (p)->port_id[1], (p)->port_id[2], (p)->port_id[3], \ + (p)->port_id[4], (p)->port_id[5], (p)->port_id[6], (p)->port_id[7], \ + (p)->port_id[8], (p)->port_id[9], (p)->port_id[10], (p)->port_id[11], \ + (p)->port_id[12], (p)->port_id[13], (p)->port_id[14], (p)->port_id[15] + +#define SRP_PID_FMT "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x:" \ + "%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x" + +static ssize_t +show_srp_rport_id(struct class_device *cdev, char *buf) +{ + struct srp_rport *rport = transport_class_to_srp_rport(cdev); + return sprintf(buf, SRP_PID_FMT "\n", SRP_PID(rport)); +} + +static CLASS_DEVICE_ATTR(port_id, S_IRUGO, show_srp_rport_id, NULL); + +static const struct { + u32 value; + char *name; +} srp_rport_role_names[] = { + {SRP_RPORT_ROLE_INITIATOR, "SRP Initiator"}, + {SRP_RPORT_ROLE_TARGET, "SRP Target"}, +}; + +static ssize_t +show_srp_rport_roles(struct class_device *cdev, char *buf) +{ + struct srp_rport *rport = transport_class_to_srp_rport(cdev); + int i; + char *name = NULL; + + for (i = 0; i < ARRAY_SIZE(srp_rport_role_names); i++) + if (srp_rport_role_names[i].value == rport->roles) { + name = srp_rport_role_names[i].name; + break; + } + return sprintf(buf, "%s\n", name ? : "unknown"); +} + +static CLASS_DEVICE_ATTR(roles, S_IRUGO, show_srp_rport_roles, NULL); + +static void srp_rport_release(struct device *dev) +{ + struct srp_rport *rport = dev_to_rport(dev); + + put_device(dev->parent); + kfree(rport); +} + +static int scsi_is_srp_rport(const struct device *dev) +{ + return dev->release == srp_rport_release; +} + +static int srp_rport_match(struct attribute_container *cont, + struct device *dev) +{ + struct Scsi_Host *shost; + struct srp_internal *i; + + if (!scsi_is_srp_rport(dev)) + return 0; + + shost = dev_to_shost(dev->parent); + if (!shost->transportt) + return 0; + if (shost->transportt->host_attrs.ac.class != &srp_host_class.class) + return 0; + + i = to_srp_internal(shost->transportt); + return &i->rport_attr_cont.ac == cont; +} + +static int srp_host_match(struct attribute_container *cont, struct device *dev) +{ + struct Scsi_Host *shost; + struct srp_internal *i; + + if (!scsi_is_host_device(dev)) + return 0; + + shost = dev_to_shost(dev); + if (!shost->transportt) + return 0; + if (shost->transportt->host_attrs.ac.class != &srp_host_class.class) + return 0; + + i = to_srp_internal(shost->transportt); + return &i->t.host_attrs.ac == cont; +} + +/** + * srp_rport_add - add a SRP remote port to the device hierarchy + * + * @shost: scsi host the remote port is connected to. + * @ids: The port id for the remote port. + * + * publishes a port to the rest of the system + */ +struct srp_rport *srp_rport_add(struct Scsi_Host *shost, + struct srp_rport_identifiers *ids) +{ + struct srp_rport *rport; + struct device *parent = &shost->shost_gendev; + int id, ret; + + rport = kzalloc(sizeof(*rport), GFP_KERNEL); + if (!rport) + return ERR_PTR(-ENOMEM); + + device_initialize(&rport->dev); + + rport->dev.parent = get_device(parent); + rport->dev.release = srp_rport_release; + + memcpy(rport->port_id, ids->port_id, sizeof(rport->port_id)); + rport->roles = ids->roles; + + id = atomic_inc_return(&to_srp_host_attrs(shost)->next_port_id); + sprintf(rport->dev.bus_id, "port-%d:%d", shost->host_no, id); + + transport_setup_device(&rport->dev); + + ret = device_add(&rport->dev); + if (ret) { + transport_destroy_device(&rport->dev); + put_device(&rport->dev); + return ERR_PTR(ret); + } + + if (shost->active_mode & MODE_TARGET && + ids->roles == SRP_RPORT_ROLE_INITIATOR) { + ret = srp_tgt_it_nexus_create(shost, (unsigned long)rport, + rport->port_id); + if (ret) { + device_del(&rport->dev); + transport_destroy_device(&rport->dev); + put_device(&rport->dev); + return ERR_PTR(ret); + } + } + + transport_add_device(&rport->dev); + transport_configure_device(&rport->dev); + + return rport; +} +EXPORT_SYMBOL_GPL(srp_rport_add); + +/** + * srp_rport_del -- remove a SRP remote port + * @port: SRP remote port to remove + * + * Removes the specified SRP remote port. + */ +void srp_rport_del(struct srp_rport *rport) +{ + struct device *dev = &rport->dev; + struct Scsi_Host *shost = dev_to_shost(dev->parent); + + if (shost->active_mode & MODE_TARGET && + rport->roles == SRP_RPORT_ROLE_INITIATOR) + srp_tgt_it_nexus_destroy(shost, (unsigned long)rport); + + transport_remove_device(dev); + device_del(dev); + transport_destroy_device(dev); + put_device(dev); +} +EXPORT_SYMBOL_GPL(srp_rport_del); + +static int do_srp_rport_del(struct device *dev, void *data) +{ + srp_rport_del(dev_to_rport(dev)); + return 0; +} + +/** + * srp_remove_host -- tear down a Scsi_Host's SRP data structures + * @shost: Scsi Host that is torn down + * + * Removes all SRP remote ports for a given Scsi_Host. + * Must be called just before scsi_remove_host for SRP HBAs. + */ +void srp_remove_host(struct Scsi_Host *shost) +{ + device_for_each_child(&shost->shost_gendev, NULL, do_srp_rport_del); +} +EXPORT_SYMBOL_GPL(srp_remove_host); + +static int srp_tsk_mgmt_response(struct Scsi_Host *shost, u64 nexus, u64 tm_id, + int result) +{ + struct srp_internal *i = to_srp_internal(shost->transportt); + return i->f->tsk_mgmt_response(shost, nexus, tm_id, result); +} + +static int srp_it_nexus_response(struct Scsi_Host *shost, u64 nexus, int result) +{ + struct srp_internal *i = to_srp_internal(shost->transportt); + return i->f->it_nexus_response(shost, nexus, result); +} + +/** + * srp_attach_transport -- instantiate SRP transport template + * @ft: SRP transport class function template + */ +struct scsi_transport_template * +srp_attach_transport(struct srp_function_template *ft) +{ + int count; + struct srp_internal *i; + + i = kzalloc(sizeof(*i), GFP_KERNEL); + if (!i) + return NULL; + + i->t.tsk_mgmt_response = srp_tsk_mgmt_response; + i->t.it_nexus_response = srp_it_nexus_response; + + i->t.host_size = sizeof(struct srp_host_attrs); + i->t.host_attrs.ac.attrs = &i->host_attrs[0]; + i->t.host_attrs.ac.class = &srp_host_class.class; + i->t.host_attrs.ac.match = srp_host_match; + i->host_attrs[0] = NULL; + transport_container_register(&i->t.host_attrs); + + i->rport_attr_cont.ac.attrs = &i->rport_attrs[0]; + i->rport_attr_cont.ac.class = &srp_rport_class.class; + i->rport_attr_cont.ac.match = srp_rport_match; + transport_container_register(&i->rport_attr_cont); + + count = 0; + SETUP_RPORT_ATTRIBUTE_RD(port_id); + SETUP_RPORT_ATTRIBUTE_RD(roles); + i->rport_attrs[count] = NULL; + + i->f = ft; + + return &i->t; +} +EXPORT_SYMBOL_GPL(srp_attach_transport); + +/** + * srp_release_transport -- release SRP transport template instance + * @t: transport template instance + */ +void srp_release_transport(struct scsi_transport_template *t) +{ + struct srp_internal *i = to_srp_internal(t); + + transport_container_unregister(&i->t.host_attrs); + transport_container_unregister(&i->rport_attr_cont); + + kfree(i); +} +EXPORT_SYMBOL_GPL(srp_release_transport); + +static __init int srp_transport_init(void) +{ + int ret; + + ret = transport_class_register(&srp_host_class); + if (ret) + return ret; + ret = transport_class_register(&srp_rport_class); + if (ret) + goto unregister_host_class; + + return 0; +unregister_host_class: + transport_class_unregister(&srp_host_class); + return ret; +} + +static void __exit srp_transport_exit(void) +{ + transport_class_unregister(&srp_host_class); + transport_class_unregister(&srp_rport_class); +} + +MODULE_AUTHOR("FUJITA Tomonori"); +MODULE_DESCRIPTION("SRP Transport Attributes"); +MODULE_LICENSE("GPL"); + +module_init(srp_transport_init); +module_exit(srp_transport_exit); diff --git a/drivers/scsi/scsi_transport_srp_internal.h b/drivers/scsi/scsi_transport_srp_internal.h new file mode 100644 index 000000000000..8a79747f9f3d --- /dev/null +++ b/drivers/scsi/scsi_transport_srp_internal.h @@ -0,0 +1,25 @@ +#include <scsi/scsi_tgt.h> + +#ifdef CONFIG_SCSI_SRP_TGT_ATTRS +static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + return scsi_tgt_it_nexus_create(shost, itn_id, initiator); +} + +static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + return scsi_tgt_it_nexus_destroy(shost, itn_id); +} + +#else +static inline int srp_tgt_it_nexus_create(struct Scsi_Host *shost, u64 itn_id, + char *initiator) +{ + return 0; +} +static inline int srp_tgt_it_nexus_destroy(struct Scsi_Host *shost, u64 itn_id) +{ + return 0; +} +#endif diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 2c6116fd4578..0a3a528212c2 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -86,6 +86,19 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_DISK); MODULE_ALIAS_SCSI_DEVICE(TYPE_MOD); MODULE_ALIAS_SCSI_DEVICE(TYPE_RBC); +static int sd_revalidate_disk(struct gendisk *); +static int sd_probe(struct device *); +static int sd_remove(struct device *); +static void sd_shutdown(struct device *); +static int sd_suspend(struct device *, pm_message_t state); +static int sd_resume(struct device *); +static void sd_rescan(struct device *); +static int sd_done(struct scsi_cmnd *); +static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); +static void scsi_disk_release(struct class_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_IDR(sd_index_idr); static DEFINE_SPINLOCK(sd_index_lock); @@ -240,7 +253,7 @@ static struct scsi_driver sd_template = { .shutdown = sd_shutdown, }, .rescan = sd_rescan, - .init_command = sd_init_command, + .done = sd_done, }; /* @@ -331,14 +344,31 @@ static void scsi_disk_put(struct scsi_disk *sdkp) * * Returns 1 if successful and 0 if error (or cannot be done now). **/ -static int sd_init_command(struct scsi_cmnd * SCpnt) +static int sd_prep_fn(struct request_queue *q, struct request *rq) { - struct scsi_device *sdp = SCpnt->device; - struct request *rq = SCpnt->request; + struct scsi_cmnd *SCpnt; + struct scsi_device *sdp = q->queuedata; struct gendisk *disk = rq->rq_disk; sector_t block = rq->sector; - unsigned int this_count = SCpnt->request_bufflen >> 9; + unsigned int this_count = rq->nr_sectors; unsigned int timeout = sdp->timeout; + int ret; + + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_type != REQ_TYPE_FS) { + ret = BLKPREP_KILL; + goto out; + } + ret = scsi_setup_fs_cmnd(sdp, rq); + if (ret != BLKPREP_OK) + goto out; + SCpnt = rq->special; + + /* from here on until we're complete, any goto out + * is used for a killable error condition */ + ret = BLKPREP_KILL; SCSI_LOG_HLQUEUE(1, scmd_printk(KERN_INFO, SCpnt, "sd_init_command: block=%llu, " @@ -353,7 +383,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) rq->nr_sectors)); SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "Retry with 0x%p\n", SCpnt)); - return 0; + goto out; } if (sdp->changed) { @@ -362,8 +392,9 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) * the changed bit has been reset */ /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ - return 0; + goto out; } + SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", (unsigned long long)block)); @@ -382,7 +413,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) if ((block & 1) || (rq->nr_sectors & 1)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - return 0; + goto out; } else { block = block >> 1; this_count = this_count >> 1; @@ -392,7 +423,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) if ((block & 3) || (rq->nr_sectors & 3)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - return 0; + goto out; } else { block = block >> 2; this_count = this_count >> 2; @@ -402,7 +433,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) if ((block & 7) || (rq->nr_sectors & 7)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - return 0; + goto out; } else { block = block >> 3; this_count = this_count >> 3; @@ -410,7 +441,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) } if (rq_data_dir(rq) == WRITE) { if (!sdp->writeable) { - return 0; + goto out; } SCpnt->cmnd[0] = WRITE_6; SCpnt->sc_data_direction = DMA_TO_DEVICE; @@ -419,7 +450,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags); - return 0; + goto out; } SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, @@ -470,7 +501,7 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) */ scmd_printk(KERN_ERR, SCpnt, "FUA write on READ/WRITE(6) drive\n"); - return 0; + goto out; } SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); @@ -492,16 +523,12 @@ static int sd_init_command(struct scsi_cmnd * SCpnt) SCpnt->timeout_per_command = timeout; /* - * This is the completion routine we use. This is matched in terms - * of capability to this function. - */ - SCpnt->done = sd_rw_intr; - - /* * This indicates that the command is ready from our end to be * queued. */ - return 1; + ret = BLKPREP_OK; + out: + return scsi_prep_return(q, rq, ret); } /** @@ -889,13 +916,13 @@ static struct block_device_operations sd_fops = { }; /** - * sd_rw_intr - bottom half handler: called when the lower level + * sd_done - bottom half handler: called when the lower level * driver has completed (successfully or otherwise) a scsi command. * @SCpnt: mid-level's per command structure. * * Note: potentially run from within an ISR. Must not block. **/ -static void sd_rw_intr(struct scsi_cmnd * SCpnt) +static int sd_done(struct scsi_cmnd *SCpnt) { int result = SCpnt->result; unsigned int xfer_size = SCpnt->request_bufflen; @@ -916,7 +943,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) SCSI_LOG_HLCOMPLETE(1, scsi_print_result(SCpnt)); if (sense_valid) { SCSI_LOG_HLCOMPLETE(1, scmd_printk(KERN_INFO, SCpnt, - "sd_rw_intr: sb[respc,sk,asc," + "sd_done: sb[respc,sk,asc," "ascq]=%x,%x,%x,%x\n", sshdr.response_code, sshdr.sense_key, sshdr.asc, @@ -988,7 +1015,7 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt) break; } out: - scsi_io_completion(SCpnt, good_bytes); + return good_bytes; } static int media_not_present(struct scsi_disk *sdkp, @@ -1669,6 +1696,7 @@ static int sd_probe(struct device *dev) sd_revalidate_disk(gd); + blk_queue_prep_rq(sdp->request_queue, sd_prep_fn); blk_queue_issue_flush_fn(sdp->request_queue, sd_issue_flush); gd->driverfs_dev = &sdp->sdev_gendev; diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 85d38940a6c9..f6f5fc7d0cee 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -43,6 +43,7 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #include <linux/poll.h> #include <linux/moduleparam.h> #include <linux/cdev.h> +#include <linux/idr.h> #include <linux/seq_file.h> #include <linux/blkdev.h> #include <linux/delay.h> @@ -99,12 +100,11 @@ static int scatter_elem_sz_prev = SG_SCATTER_SZ; #define SG_SECTOR_SZ 512 #define SG_SECTOR_MSK (SG_SECTOR_SZ - 1) -#define SG_DEV_ARR_LUMP 32 /* amount to over allocate sg_dev_arr by */ - static int sg_add(struct class_device *, struct class_interface *); static void sg_remove(struct class_device *, struct class_interface *); -static DEFINE_RWLOCK(sg_dev_arr_lock); /* Also used to lock +static DEFINE_IDR(sg_index_idr); +static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock file descriptor list for device */ static struct class_interface sg_interface = { @@ -114,7 +114,7 @@ static struct class_interface sg_interface = { typedef struct sg_scatter_hold { /* holding area for scsi scatter gather info */ unsigned short k_use_sg; /* Count of kernel scatter-gather pieces */ - unsigned short sglist_len; /* size of malloc'd scatter-gather list ++ */ + unsigned sglist_len; /* size of malloc'd scatter-gather list ++ */ unsigned bufflen; /* Size of (aggregate) data buffer */ unsigned b_malloc_len; /* actual len malloc'ed in buffer */ struct scatterlist *buffer;/* scatter list */ @@ -162,6 +162,7 @@ typedef struct sg_device { /* holds the state of each scsi generic device */ struct scsi_device *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 */ volatile char detached; /* 0->attached, 1->detached pending removal */ volatile char exclude; /* opened for exclusive access */ @@ -209,10 +210,6 @@ static Sg_device *sg_get_dev(int dev); static int sg_last_dev(void); #endif -static Sg_device **sg_dev_arr = NULL; -static int sg_dev_max; -static int sg_nr_dev; - #define SZ_SG_HEADER sizeof(struct sg_header) #define SZ_SG_IO_HDR sizeof(sg_io_hdr_t) #define SZ_SG_IOVEC sizeof(sg_iovec_t) @@ -1331,40 +1328,35 @@ static struct class *sg_sysfs_class; static int sg_sysfs_valid = 0; -static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) +static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) { struct request_queue *q = scsidp->request_queue; Sg_device *sdp; unsigned long iflags; - void *old_sg_dev_arr = NULL; - int k, error; + int error; + u32 k; sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL); if (!sdp) { printk(KERN_WARNING "kmalloc Sg_device failure\n"); - return -ENOMEM; + return ERR_PTR(-ENOMEM); + } + error = -ENOMEM; + if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) { + printk(KERN_WARNING "idr expansion Sg_device failure\n"); + goto out; } - write_lock_irqsave(&sg_dev_arr_lock, iflags); - if (unlikely(sg_nr_dev >= sg_dev_max)) { /* try to resize */ - Sg_device **tmp_da; - int tmp_dev_max = sg_nr_dev + SG_DEV_ARR_LUMP; - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - - tmp_da = kzalloc(tmp_dev_max * sizeof(Sg_device *), GFP_KERNEL); - if (unlikely(!tmp_da)) - goto expand_failed; + write_lock_irqsave(&sg_index_lock, iflags); + error = idr_get_new(&sg_index_idr, sdp, &k); + write_unlock_irqrestore(&sg_index_lock, iflags); - write_lock_irqsave(&sg_dev_arr_lock, iflags); - memcpy(tmp_da, sg_dev_arr, sg_dev_max * sizeof(Sg_device *)); - old_sg_dev_arr = sg_dev_arr; - sg_dev_arr = tmp_da; - sg_dev_max = tmp_dev_max; + if (error) { + printk(KERN_WARNING "idr allocation Sg_device failure: %d\n", + error); + goto out; } - for (k = 0; k < sg_dev_max; k++) - if (!sg_dev_arr[k]) - break; if (unlikely(k >= SG_MAX_DEVS)) goto overflow; @@ -1375,25 +1367,17 @@ static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) sdp->device = scsidp; init_waitqueue_head(&sdp->o_excl_wait); sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments); + sdp->index = k; - sg_nr_dev++; - sg_dev_arr[k] = sdp; - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - error = k; - + error = 0; out: - if (error < 0) + if (error) { kfree(sdp); - kfree(old_sg_dev_arr); - return error; - - expand_failed: - printk(KERN_WARNING "sg_alloc: device array cannot be resized\n"); - error = -ENOMEM; - goto out; + return ERR_PTR(error); + } + return sdp; overflow: - write_unlock_irqrestore(&sg_dev_arr_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); @@ -1408,7 +1392,7 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) struct gendisk *disk; Sg_device *sdp = NULL; struct cdev * cdev = NULL; - int error, k; + int error; unsigned long iflags; disk = alloc_disk(1); @@ -1427,15 +1411,15 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) cdev->owner = THIS_MODULE; cdev->ops = &sg_fops; - error = sg_alloc(disk, scsidp); - if (error < 0) { + sdp = sg_alloc(disk, scsidp); + if (IS_ERR(sdp)) { printk(KERN_WARNING "sg_alloc failed\n"); + error = PTR_ERR(sdp); goto out; } - k = error; - sdp = sg_dev_arr[k]; - error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1); + class_set_devdata(cl_dev, sdp); + error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, sdp->index), 1); if (error) goto cdev_add_err; @@ -1444,8 +1428,8 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) struct class_device * sg_class_member; sg_class_member = class_device_create(sg_sysfs_class, NULL, - MKDEV(SCSI_GENERIC_MAJOR, k), - cl_dev->dev, "%s", + MKDEV(SCSI_GENERIC_MAJOR, sdp->index), + cl_dev->dev, "%s", disk->disk_name); if (IS_ERR(sg_class_member)) printk(KERN_WARNING "sg_add: " @@ -1455,21 +1439,21 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) &sg_class_member->kobj, "generic"); if (error) printk(KERN_ERR "sg_add: unable to make symlink " - "'generic' back to sg%d\n", k); + "'generic' back to sg%d\n", sdp->index); } else - printk(KERN_WARNING "sg_add: sg_sys INvalid\n"); + printk(KERN_WARNING "sg_add: sg_sys Invalid\n"); sdev_printk(KERN_NOTICE, scsidp, - "Attached scsi generic sg%d type %d\n", k,scsidp->type); + "Attached scsi generic sg%d type %d\n", sdp->index, + scsidp->type); return 0; cdev_add_err: - write_lock_irqsave(&sg_dev_arr_lock, iflags); - kfree(sg_dev_arr[k]); - sg_dev_arr[k] = NULL; - sg_nr_dev--; - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + write_lock_irqsave(&sg_index_lock, iflags); + idr_remove(&sg_index_idr, sdp->index); + write_unlock_irqrestore(&sg_index_lock, iflags); + kfree(sdp); out: put_disk(disk); @@ -1482,64 +1466,56 @@ static void sg_remove(struct class_device *cl_dev, struct class_interface *cl_intf) { struct scsi_device *scsidp = to_scsi_device(cl_dev->dev); - Sg_device *sdp = NULL; + Sg_device *sdp = class_get_devdata(cl_dev); unsigned long iflags; Sg_fd *sfp; Sg_fd *tsfp; Sg_request *srp; Sg_request *tsrp; - int k, delay; + int delay; - if (NULL == sg_dev_arr) + if (!sdp) return; + delay = 0; - write_lock_irqsave(&sg_dev_arr_lock, iflags); - for (k = 0; k < sg_dev_max; k++) { - sdp = sg_dev_arr[k]; - if ((NULL == sdp) || (sdp->device != scsidp)) - continue; /* dirty but lowers nesting */ - 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); - } + 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); } - SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", k)); - if (NULL == sdp->headfp) { - sg_dev_arr[k] = NULL; + 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); } - } else { /* nothing active, simple case */ - SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", k)); - sg_dev_arr[k] = NULL; } - sg_nr_dev--; - break; - } - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); - - if (sdp) { - sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); - class_device_destroy(sg_sysfs_class, MKDEV(SCSI_GENERIC_MAJOR, k)); - cdev_del(sdp->cdev); - sdp->cdev = NULL; - put_disk(sdp->disk); - sdp->disk = NULL; - if (NULL == sdp->headfp) - kfree((char *) sdp); - } + 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); + } + write_unlock_irqrestore(&sg_index_lock, iflags); + + sysfs_remove_link(&scsidp->sdev_gendev.kobj, "generic"); + class_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 */ @@ -1609,9 +1585,7 @@ exit_sg(void) sg_sysfs_valid = 0; unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS); - kfree((char *)sg_dev_arr); - sg_dev_arr = NULL; - sg_dev_max = 0; + idr_destroy(&sg_index_idr); } static int @@ -2331,10 +2305,10 @@ sg_get_nth_sfp(Sg_device * sdp, int nth) unsigned long iflags; int k; - read_lock_irqsave(&sg_dev_arr_lock, iflags); + read_lock_irqsave(&sg_index_lock, iflags); for (k = 0, resp = sdp->headfp; resp && (k < nth); ++k, resp = resp->nextfp) ; - read_unlock_irqrestore(&sg_dev_arr_lock, iflags); + read_unlock_irqrestore(&sg_index_lock, iflags); return resp; } #endif @@ -2361,7 +2335,7 @@ sg_add_sfp(Sg_device * sdp, int dev) sfp->cmd_q = SG_DEF_COMMAND_Q; sfp->keep_orphan = SG_DEF_KEEP_ORPHAN; sfp->parentdp = sdp; - write_lock_irqsave(&sg_dev_arr_lock, iflags); + write_lock_irqsave(&sg_index_lock, iflags); if (!sdp->headfp) sdp->headfp = sfp; else { /* add to tail of existing list */ @@ -2370,7 +2344,7 @@ sg_add_sfp(Sg_device * sdp, int dev) pfp = pfp->nextfp; pfp->nextfp = sfp; } - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + 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)) sg_big_buff = def_reserved_size; @@ -2431,22 +2405,14 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) if (0 == dirty) { unsigned long iflags; - write_lock_irqsave(&sg_dev_arr_lock, iflags); + write_lock_irqsave(&sg_index_lock, iflags); __sg_remove_sfp(sdp, sfp); if (sdp->detached && (NULL == sdp->headfp)) { - int k, maxd; - - maxd = sg_dev_max; - for (k = 0; k < maxd; ++k) { - if (sdp == sg_dev_arr[k]) - break; - } - if (k < maxd) - sg_dev_arr[k] = NULL; - kfree((char *) sdp); + idr_remove(&sg_index_idr, sdp->index); + kfree(sdp); res = 1; } - write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + 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 @@ -2546,16 +2512,25 @@ sg_allow_access(unsigned char opcode, char dev_type) #ifdef CONFIG_SCSI_PROC_FS static int +sg_idr_max_id(int id, void *p, void *data) +{ + int *k = data; + + if (*k < id) + *k = id; + + return 0; +} + +static int sg_last_dev(void) { - int k; + int k = 0; unsigned long iflags; - read_lock_irqsave(&sg_dev_arr_lock, iflags); - for (k = sg_dev_max - 1; k >= 0; --k) - if (sg_dev_arr[k] && sg_dev_arr[k]->device) - break; - read_unlock_irqrestore(&sg_dev_arr_lock, iflags); + read_lock_irqsave(&sg_index_lock, iflags); + idr_for_each(&sg_index_idr, sg_idr_max_id, &k); + read_unlock_irqrestore(&sg_index_lock, iflags); return k + 1; /* origin 1 */ } #endif @@ -2563,15 +2538,13 @@ sg_last_dev(void) static Sg_device * sg_get_dev(int dev) { - Sg_device *sdp = NULL; + Sg_device *sdp; unsigned long iflags; - if (sg_dev_arr && (dev >= 0)) { - read_lock_irqsave(&sg_dev_arr_lock, iflags); - if (dev < sg_dev_max) - sdp = sg_dev_arr[dev]; - read_unlock_irqrestore(&sg_dev_arr_lock, iflags); - } + read_lock_irqsave(&sg_index_lock, iflags); + sdp = idr_find(&sg_index_idr, dev); + read_unlock_irqrestore(&sg_index_lock, iflags); + return sdp; } @@ -2805,8 +2778,6 @@ static void * dev_seq_start(struct seq_file *s, loff_t *pos) if (! it) return NULL; - if (NULL == sg_dev_arr) - return NULL; it->index = *pos; it->max = sg_last_dev(); if (it->index >= it->max) @@ -2942,8 +2913,8 @@ static int sg_proc_seq_show_debug(struct seq_file *s, void *v) Sg_device *sdp; if (it && (0 == it->index)) { - seq_printf(s, "dev_max(currently)=%d max_active_device=%d " - "(origin 1)\n", sg_dev_max, (int)it->max); + 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; diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 902eb11ffe8a..c61999031141 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c @@ -78,7 +78,7 @@ MODULE_ALIAS_SCSI_DEVICE(TYPE_WORM); static int sr_probe(struct device *); static int sr_remove(struct device *); -static int sr_init_command(struct scsi_cmnd *); +static int sr_done(struct scsi_cmnd *); static struct scsi_driver sr_template = { .owner = THIS_MODULE, @@ -87,7 +87,7 @@ static struct scsi_driver sr_template = { .probe = sr_probe, .remove = sr_remove, }, - .init_command = sr_init_command, + .done = sr_done, }; static unsigned long sr_index_bits[SR_DISKS / BITS_PER_LONG]; @@ -210,12 +210,12 @@ static int sr_media_change(struct cdrom_device_info *cdi, int slot) } /* - * rw_intr is the interrupt routine for the device driver. + * sr_done is the interrupt routine for the device driver. * - * It will be notified on the end of a SCSI read / write, and will take on + * It will be notified on the end of a SCSI read / write, and will take one * of several actions based on success or failure. */ -static void rw_intr(struct scsi_cmnd * SCpnt) +static int sr_done(struct scsi_cmnd *SCpnt) { int result = SCpnt->result; int this_count = SCpnt->request_bufflen; @@ -288,27 +288,42 @@ static void rw_intr(struct scsi_cmnd * SCpnt) } } - /* - * This calls the generic completion function, now that we know - * how many actual sectors finished, and how many sectors we need - * to say have failed. - */ - scsi_io_completion(SCpnt, good_bytes); + return good_bytes; } -static int sr_init_command(struct scsi_cmnd * SCpnt) +static int sr_prep_fn(struct request_queue *q, struct request *rq) { int block=0, this_count, s_size, timeout = SR_TIMEOUT; - struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); + struct scsi_cd *cd; + struct scsi_cmnd *SCpnt; + struct scsi_device *sdp = q->queuedata; + int ret; + + if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { + ret = scsi_setup_blk_pc_cmnd(sdp, rq); + goto out; + } else if (rq->cmd_type != REQ_TYPE_FS) { + ret = BLKPREP_KILL; + goto out; + } + ret = scsi_setup_fs_cmnd(sdp, rq); + if (ret != BLKPREP_OK) + goto out; + SCpnt = rq->special; + cd = scsi_cd(rq->rq_disk); + + /* from here on until we're complete, any goto out + * is used for a killable error condition */ + ret = BLKPREP_KILL; SCSI_LOG_HLQUEUE(1, printk("Doing sr request, dev = %s, block = %d\n", cd->disk->disk_name, block)); if (!cd->device || !scsi_device_online(cd->device)) { SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", - SCpnt->request->nr_sectors)); + rq->nr_sectors)); SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); - return 0; + goto out; } if (cd->device->changed) { @@ -316,7 +331,7 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) * quietly refuse to do anything to a changed disc until the * changed bit has been reset */ - return 0; + goto out; } /* @@ -333,21 +348,21 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) if (s_size != 512 && s_size != 1024 && s_size != 2048) { scmd_printk(KERN_ERR, SCpnt, "bad sector size %d\n", s_size); - return 0; + goto out; } - if (rq_data_dir(SCpnt->request) == WRITE) { + if (rq_data_dir(rq) == WRITE) { if (!cd->device->writeable) - return 0; + goto out; SCpnt->cmnd[0] = WRITE_10; SCpnt->sc_data_direction = DMA_TO_DEVICE; cd->cdi.media_written = 1; - } else if (rq_data_dir(SCpnt->request) == READ) { + } else if (rq_data_dir(rq) == READ) { SCpnt->cmnd[0] = READ_10; SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { - blk_dump_rq_flags(SCpnt->request, "Unknown sr command"); - return 0; + blk_dump_rq_flags(rq, "Unknown sr command"); + goto out; } { @@ -368,10 +383,10 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) /* * request doesn't start on hw block boundary, add scatter pads */ - if (((unsigned int)SCpnt->request->sector % (s_size >> 9)) || + if (((unsigned int)rq->sector % (s_size >> 9)) || (SCpnt->request_bufflen % s_size)) { scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n"); - return 0; + goto out; } this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9); @@ -379,12 +394,12 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", cd->cdi.name, - (rq_data_dir(SCpnt->request) == WRITE) ? + (rq_data_dir(rq) == WRITE) ? "writing" : "reading", - this_count, SCpnt->request->nr_sectors)); + this_count, rq->nr_sectors)); SCpnt->cmnd[1] = 0; - block = (unsigned int)SCpnt->request->sector / (s_size >> 9); + block = (unsigned int)rq->sector / (s_size >> 9); if (this_count > 0xffff) { this_count = 0xffff; @@ -410,16 +425,12 @@ static int sr_init_command(struct scsi_cmnd * SCpnt) SCpnt->timeout_per_command = timeout; /* - * This is the completion routine we use. This is matched in terms - * of capability to this function. - */ - SCpnt->done = rw_intr; - - /* * This indicates that the command is ready from our end to be * queued. */ - return 1; + ret = BLKPREP_OK; + out: + return scsi_prep_return(q, rq, ret); } static int sr_block_open(struct inode *inode, struct file *file) @@ -590,6 +601,7 @@ static int sr_probe(struct device *dev) /* FIXME: need to handle a get_capabilities failure properly ?? */ get_capabilities(cd); + blk_queue_prep_rq(sdev->request_queue, sr_prep_fn); sr_vendor_init(cd); disk->driverfs_dev = &sdev->sdev_gendev; diff --git a/drivers/scsi/sun3_NCR5380.c b/drivers/scsi/sun3_NCR5380.c index 98e3fe10c1dc..dc15a22105f7 100644 --- a/drivers/scsi/sun3_NCR5380.c +++ b/drivers/scsi/sun3_NCR5380.c @@ -2055,7 +2055,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->done(cmd); + cmd->scsi_done(cmd); return; #endif case PHASE_DATAIN: @@ -2115,7 +2115,7 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->done(cmd); + cmd->scsi_done(cmd); /* XXX - need to source or sink data here, as appropriate */ } else { #ifdef REAL_DMA @@ -2254,25 +2254,21 @@ static void NCR5380_information_transfer (struct Scsi_Host *instance) cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16); #ifdef AUTOSENSE + if ((cmd->cmnd[0] == REQUEST_SENSE) && + hostdata->ses.cmd_len) { + scsi_eh_restore_cmnd(cmd, &hostdata->ses); + hostdata->ses.cmd_len = 0 ; + } + if ((cmd->cmnd[0] != REQUEST_SENSE) && (status_byte(cmd->SCp.Status) == CHECK_CONDITION)) { + scsi_eh_prep_cmnd(cmd, &hostdata->ses, NULL, 0, ~0); ASEN_PRINTK("scsi%d: performing request sense\n", HOSTNO); - cmd->cmnd[0] = REQUEST_SENSE; - cmd->cmnd[1] &= 0xe0; - cmd->cmnd[2] = 0; - cmd->cmnd[3] = 0; - cmd->cmnd[4] = sizeof(cmd->sense_buffer); - cmd->cmnd[5] = 0; - cmd->cmd_len = COMMAND_SIZE(cmd->cmnd[0]); - - cmd->use_sg = 0; /* this is initialized from initialize_SCp cmd->SCp.buffer = NULL; cmd->SCp.buffers_residual = 0; */ - cmd->request_buffer = (char *) cmd->sense_buffer; - cmd->request_bufflen = sizeof(cmd->sense_buffer); local_irq_save(flags); LIST(cmd,hostdata->issue_queue); diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 5db1520f8ba9..5c72ca31a47a 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -567,12 +567,12 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr pDCB->TagMask |= 1 << tag[1]; pSRB->TagNumber = tag[1]; DC390_write8(ScsiFifo, tag[1]); - DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for Cmd %li (SRB %p), block tag %02x\n", scmd->pid, pSRB, tag[1])); + DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for Cmd %li (SRB %p), block tag %02x\n", scmd->serial_number, pSRB, tag[1])); cmd = SEL_W_ATN3; } else { /* No TagQ */ //no_tag: - DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", disc_allowed ? "" : "o", scmd->pid, pSRB)); + DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", disc_allowed ? "" : "o", scmd->serial_number, pSRB)); } pSRB->SRBState = SRB_START_; @@ -623,7 +623,7 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr { dc390_freetag (pDCB, pSRB); DEBUG0(printk ("DC390: Interrupt during Start SCSI (pid %li, target %02i-%02i)\n", - scmd->pid, scmd->device->id, scmd->device->lun)); + scmd->serial_number, scmd->device->id, scmd->device->lun)); pSRB->SRBState = SRB_READY; //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); pACB->SelLost++; @@ -1708,7 +1708,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* status = pSRB->TargetStatus; DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\ - pSRB, pcmd->pid)); + pSRB, pcmd->serial_number)); if(pSRB->SRBFlag & AUTO_REQSENSE) { /* Last command was a Request Sense */ pSRB->SRBFlag &= ~AUTO_REQSENSE; @@ -1729,7 +1729,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* } else { SET_RES_DRV(pcmd->result, DRIVER_SENSE); //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8); - DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->serial_number, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } @@ -1749,7 +1749,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* else if (status == SAM_STAT_TASK_SET_FULL) { scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1); - DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->serial_number, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } @@ -1803,7 +1803,7 @@ cmd_done: /* Add to free list */ dc390_Free_insert (pACB, pSRB); - DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid)); + DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->serial_number)); pcmd->scsi_done (pcmd); return; @@ -1998,7 +1998,7 @@ static int DC390_abort(struct scsi_cmnd *cmd) struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata; scmd_printk(KERN_WARNING, cmd, - "DC390: Abort command (pid %li)\n", cmd->pid); + "DC390: Abort command (pid %li)\n", cmd->serial_number); /* abort() is too stupid for already sent commands at the moment. * If it's called we are in trouble anyway, so let's dump some info @@ -2006,7 +2006,7 @@ static int DC390_abort(struct scsi_cmnd *cmd) dc390_dumpinfo(pACB, pDCB, NULL); pDCB->DCBFlag |= ABORT_DEV_; - printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->pid); + printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->serial_number); return FAILED; } diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 9e8232a1f169..fc9f51818e8f 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c @@ -1254,7 +1254,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs if (SCpnt->host_scribble) panic("%s: qcomm, pid %ld, SCpnt %p already active.\n", - BN(j), SCpnt->pid, SCpnt); + BN(j), SCpnt->serial_number, SCpnt); /* i is the mailbox number, look for the first free mailbox starting from last_cp_used */ @@ -1285,7 +1285,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs if (do_trace) printk("%s: qcomm, mbox %d, target %d.%d:%d, pid %ld.\n", BN(j), i, SCpnt->device->channel, SCpnt->device->id, - SCpnt->device->lun, SCpnt->pid); + SCpnt->device->lun, SCpnt->serial_number); cpp->opcode = OP_SCSI; cpp->channel = SCpnt->device->channel; @@ -1312,7 +1312,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs unmap_dma(i, j); SCpnt->host_scribble = NULL; scmd_printk(KERN_INFO, SCpnt, - "qcomm, pid %ld, adapter busy.\n", SCpnt->pid); + "qcomm, pid %ld, adapter busy.\n", SCpnt->serial_number); return 1; } @@ -1333,13 +1333,13 @@ static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) { if (SCarg->host_scribble == NULL) { scmd_printk(KERN_INFO, SCarg, "abort, pid %ld inactive.\n", - SCarg->pid); + SCarg->serial_number); return SUCCESS; } i = *(unsigned int *)SCarg->host_scribble; scmd_printk(KERN_INFO, SCarg, "abort, mbox %d, pid %ld.\n", - i, SCarg->pid); + i, SCarg->serial_number); if (i >= sh[j]->can_queue) panic("%s: abort, invalid SCarg->host_scribble.\n", BN(j)); @@ -1383,7 +1383,7 @@ static int u14_34f_eh_abort(struct scsi_cmnd *SCarg) { SCarg->host_scribble = NULL; HD(j)->cp_stat[i] = FREE; printk("%s, abort, mbox %d ready, DID_ABORT, pid %ld done.\n", - BN(j), i, SCarg->pid); + BN(j), i, SCarg->serial_number); SCarg->scsi_done(SCarg); return SUCCESS; } @@ -1397,12 +1397,12 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { struct scsi_cmnd *SCpnt; j = ((struct hostdata *) SCarg->device->host->hostdata)->board_number; - scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->pid); + scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->serial_number); spin_lock_irq(sh[j]->host_lock); if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); + printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->serial_number); if (HD(j)->in_reset) { printk("%s: reset, exit, already in reset.\n", BN(j)); @@ -1440,13 +1440,13 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { if (HD(j)->cp_stat[i] == READY || HD(j)->cp_stat[i] == ABORTING) { HD(j)->cp_stat[i] = ABORTING; printk("%s: reset, mbox %d aborting, pid %ld.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->serial_number); } else { HD(j)->cp_stat[i] = IN_RESET; printk("%s: reset, mbox %d in reset, pid %ld.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->serial_number); } if (SCpnt->host_scribble == NULL) @@ -1495,7 +1495,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { HD(j)->cp_stat[i] = LOCKED; printk("%s, reset, mbox %d locked, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->serial_number); } else if (HD(j)->cp_stat[i] == ABORTING) { @@ -1508,7 +1508,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { HD(j)->cp_stat[i] = FREE; printk("%s, reset, mbox %d aborting, DID_RESET, pid %ld done.\n", - BN(j), i, SCpnt->pid); + BN(j), i, SCpnt->serial_number); } else @@ -1522,7 +1522,7 @@ static int u14_34f_eh_host_reset(struct scsi_cmnd *SCarg) { HD(j)->in_reset = FALSE; do_trace = FALSE; - if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid); + if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->serial_number); else printk("%s: reset, exit.\n", BN(j)); spin_unlock_irq(sh[j]->host_lock); @@ -1639,7 +1639,7 @@ static int reorder(unsigned int j, unsigned long cursec, if (!input_only) for (n = 0; n < n_ready; n++) { k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; - ll[n] = SCpnt->request->nr_sectors; pl[n] = SCpnt->pid; + ll[n] = SCpnt->request->nr_sectors; pl[n] = SCpnt->serial_number; if (!n) continue; @@ -1666,7 +1666,7 @@ static int reorder(unsigned int j, unsigned long cursec, printk("%s %d.%d:%d pid %ld mb %d fc %d nr %d sec %ld ns %ld"\ " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, - SCpnt->lun, SCpnt->pid, k, flushcount, n_ready, + SCpnt->lun, SCpnt->serial_number, k, flushcount, n_ready, SCpnt->request->sector, SCpnt->request->nr_sectors, cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), YESNO(overlap), cpp->xdir); @@ -1703,7 +1703,7 @@ static void flush_dev(struct scsi_device *dev, unsigned long cursec, unsigned in scmd_printk(KERN_INFO, SCpnt, "%s, pid %ld, mbox %d, adapter" " busy, will abort.\n", (ihdlr ? "ihdlr" : "qcomm"), - SCpnt->pid, k); + SCpnt->serial_number, k); HD(j)->cp_stat[k] = ABORTING; continue; } @@ -1787,11 +1787,11 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { if (SCpnt->host_scribble == NULL) panic("%s: ihdlr, mbox %d, pid %ld, SCpnt %p garbled.\n", BN(j), i, - SCpnt->pid, SCpnt); + SCpnt->serial_number, SCpnt); if (*(unsigned int *)SCpnt->host_scribble != i) panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n", - BN(j), i, SCpnt->pid, *(unsigned int *)SCpnt->host_scribble); + BN(j), i, SCpnt->serial_number, *(unsigned int *)SCpnt->host_scribble); sync_dma(i, j); @@ -1835,12 +1835,12 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { (SCpnt->sense_buffer[2] & 0xf) == NOT_READY))) scmd_printk(KERN_INFO, SCpnt, "ihdlr, pid %ld, target_status 0x%x, sense key 0x%x.\n", - SCpnt->pid, spp->target_status, + SCpnt->serial_number, spp->target_status, SCpnt->sense_buffer[2]); HD(j)->target_to[scmd_id(SCpnt)][scmd_channel(SCpnt)] = 0; - if (HD(j)->last_retried_pid == SCpnt->pid) HD(j)->retries = 0; + if (HD(j)->last_retried_pid == SCpnt->serial_number) HD(j)->retries = 0; break; case ASST: /* Selection Time Out */ @@ -1877,7 +1877,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { #endif HD(j)->retries++; - HD(j)->last_retried_pid = SCpnt->pid; + HD(j)->last_retried_pid = SCpnt->serial_number; } else status = DID_ERROR << 16; @@ -1907,7 +1907,7 @@ static irqreturn_t ihdlr(int irq, unsigned int j) { #endif scmd_printk(KERN_INFO, SCpnt, "ihdlr, mbox %2d, err 0x%x:%x,"\ " pid %ld, reg 0x%x, count %d.\n", - i, spp->adapter_status, spp->target_status, SCpnt->pid, + i, spp->adapter_status, spp->target_status, SCpnt->serial_number, reg, HD(j)->iocount); unmap_dma(i, j); diff --git a/drivers/scsi/wd33c93.c b/drivers/scsi/wd33c93.c index b92ff047af38..0e8e642fd3b0 100644 --- a/drivers/scsi/wd33c93.c +++ b/drivers/scsi/wd33c93.c @@ -381,7 +381,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd, hostdata = (struct WD33C93_hostdata *) cmd->device->host->hostdata; DB(DB_QUEUE_COMMAND, - printk("Q-%d-%02x-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->pid)) + printk("Q-%d-%02x-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->serial_number)) /* Set up a few fields in the scsi_cmnd structure for our own use: * - host_scribble is the pointer to the next cmd in the input queue @@ -463,7 +463,7 @@ wd33c93_queuecommand(struct scsi_cmnd *cmd, wd33c93_execute(cmd->device->host); - DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid)) + DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->serial_number)) spin_unlock_irq(&hostdata->lock); return 0; @@ -686,7 +686,7 @@ wd33c93_execute(struct Scsi_Host *instance) */ DB(DB_EXECUTE, - printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid)) + printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->serial_number)) } static void @@ -963,7 +963,7 @@ wd33c93_intr(struct Scsi_Host *instance) case CSR_XFER_DONE | PHS_COMMAND: case CSR_UNEXP | PHS_COMMAND: case CSR_SRV_REQ | PHS_COMMAND: - DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid)) + DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->serial_number)) transfer_pio(regs, cmd->cmnd, cmd->cmd_len, DATA_OUT_DIR, hostdata); hostdata->state = S_CONNECTED; @@ -1007,7 +1007,7 @@ wd33c93_intr(struct Scsi_Host *instance) switch (msg) { case COMMAND_COMPLETE: - DB(DB_INTR, printk("CCMP-%ld", cmd->pid)) + DB(DB_INTR, printk("CCMP-%ld", cmd->serial_number)) write_wd33c93_cmd(regs, WD_CMD_NEGATE_ACK); hostdata->state = S_PRE_CMP_DISC; break; @@ -1174,7 +1174,7 @@ wd33c93_intr(struct Scsi_Host *instance) write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER); if (phs == 0x60) { - DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid)) + DB(DB_INTR, printk("SX-DONE-%ld", cmd->serial_number)) cmd->SCp.Message = COMMAND_COMPLETE; lun = read_wd33c93(regs, WD_TARGET_LUN); DB(DB_INTR, printk(":%d.%d", cmd->SCp.Status, lun)) @@ -1201,7 +1201,7 @@ wd33c93_intr(struct Scsi_Host *instance) } else { printk ("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", - asr, sr, phs, cmd->pid); + asr, sr, phs, cmd->serial_number); spin_unlock_irqrestore(&hostdata->lock, flags); } break; @@ -1266,7 +1266,7 @@ wd33c93_intr(struct Scsi_Host *instance) spin_unlock_irqrestore(&hostdata->lock, flags); return; } - DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid)) + DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->serial_number)) hostdata->connected = NULL; hostdata->busy[cmd->device->id] &= ~(1 << cmd->device->lun); hostdata->state = S_UNCONNECTED; @@ -1292,7 +1292,7 @@ wd33c93_intr(struct Scsi_Host *instance) */ write_wd33c93(regs, WD_SOURCE_ID, SRCID_ER); - DB(DB_INTR, printk("DISC-%ld", cmd->pid)) + DB(DB_INTR, printk("DISC-%ld", cmd->serial_number)) if (cmd == NULL) { printk(" - Already disconnected! "); hostdata->state = S_UNCONNECTED; @@ -1491,7 +1491,7 @@ wd33c93_intr(struct Scsi_Host *instance) } else hostdata->state = S_CONNECTED; - DB(DB_INTR, printk("-%ld", cmd->pid)) + DB(DB_INTR, printk("-%ld", cmd->serial_number)) spin_unlock_irqrestore(&hostdata->lock, flags); break; @@ -1638,7 +1638,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) cmd->result = DID_ABORT << 16; printk ("scsi%d: Abort - removing command %ld from input_Q. ", - instance->host_no, cmd->pid); + instance->host_no, cmd->serial_number); enable_irq(cmd->device->host->irq); cmd->scsi_done(cmd); return SUCCESS; @@ -1663,7 +1663,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) unsigned long timeout; printk("scsi%d: Aborting connected command %ld - ", - instance->host_no, cmd->pid); + instance->host_no, cmd->serial_number); printk("stopping DMA - "); if (hostdata->dma == D_DMA_RUNNING) { @@ -1730,7 +1730,7 @@ wd33c93_abort(struct scsi_cmnd * cmd) if (tmp == cmd) { printk ("scsi%d: Abort - command %ld found on disconnected_Q - ", - instance->host_no, cmd->pid); + instance->host_no, cmd->serial_number); printk("Abort SNOOZE. "); enable_irq(cmd->device->host->irq); return FAILED; @@ -2184,7 +2184,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off if (hd->connected) { cmd = (struct scsi_cmnd *) hd->connected; sprintf(tbuf, " %ld-%d:%d(%02x)", - cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); } } @@ -2193,7 +2193,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off cmd = (struct scsi_cmnd *) hd->input_Q; while (cmd) { sprintf(tbuf, " %ld-%d:%d(%02x)", - cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (struct scsi_cmnd *) cmd->host_scribble; } @@ -2203,7 +2203,7 @@ wd33c93_proc_info(struct Scsi_Host *instance, char *buf, char **start, off_t off cmd = (struct scsi_cmnd *) hd->disconnected_Q; while (cmd) { sprintf(tbuf, " %ld-%d:%d(%02x)", - cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (struct scsi_cmnd *) cmd->host_scribble; } diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index c822debc2668..ac67394c7373 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c @@ -69,7 +69,7 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = { static int __devinit zorro7xx_init_one(struct zorro_dev *z, const struct zorro_device_id *ent) { - struct Scsi_Host * host = NULL; + struct Scsi_Host *host; struct NCR_700_Host_Parameters *hostdata; struct zorro_driver_data *zdd; unsigned long board, ioaddr; @@ -89,14 +89,12 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z, return -EBUSY; } - hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); - if (hostdata == NULL) { + hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + if (!hostdata) { printk(KERN_ERR "zorro7xx: Failed to allocate host data\n"); goto out_release; } - memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters)); - /* Fill in the required pieces of hostdata */ if (ioaddr > 0x01000000) hostdata->base = ioremap(ioaddr, zorro_resource_len(z)); diff --git a/drivers/usb/image/microtek.c b/drivers/usb/image/microtek.c index 768b2c11a231..e7d982a71548 100644 --- a/drivers/usb/image/microtek.c +++ b/drivers/usb/image/microtek.c @@ -446,7 +446,8 @@ static void mts_data_done( struct urb* transfer ) MTS_INT_INIT(); if ( context->data_length != transfer->actual_length ) { - context->srb->resid = context->data_length - transfer->actual_length; + scsi_set_resid(context->srb, context->data_length - + transfer->actual_length); } else if ( unlikely(status) ) { context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; } @@ -490,7 +491,8 @@ static void mts_command_done( struct urb *transfer ) context->data_pipe, context->data, context->data_length, - context->srb->use_sg > 1 ? mts_do_sg : mts_data_done); + scsi_sg_count(context->srb) > 1 ? + mts_do_sg : mts_data_done); } else { mts_get_status(transfer); } @@ -505,21 +507,23 @@ static void mts_do_sg (struct urb* transfer) int status = transfer->status; MTS_INT_INIT(); - MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg); + MTS_DEBUG("Processing fragment %d of %d\n", context->fragment, + scsi_sg_count(context->srb)); if (unlikely(status)) { context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; mts_transfer_cleanup(transfer); } - sg = context->srb->request_buffer; + sg = scsi_sglist(context->srb); context->fragment++; mts_int_submit_urb(transfer, context->data_pipe, page_address(sg[context->fragment].page) + sg[context->fragment].offset, sg[context->fragment].length, - context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg); + context->fragment + 1 == scsi_sg_count(context->srb) ? + mts_data_done : mts_do_sg); return; } @@ -547,20 +551,12 @@ mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc) desc->context.srb = srb; desc->context.fragment = 0; - if (!srb->use_sg) { - if ( !srb->request_bufflen ){ - desc->context.data = NULL; - desc->context.data_length = 0; - return; - } else { - desc->context.data = srb->request_buffer; - desc->context.data_length = srb->request_bufflen; - MTS_DEBUG("length = %d or %d\n", - srb->request_bufflen, srb->bufflen); - } + if (!scsi_bufflen(srb)) { + desc->context.data = NULL; + desc->context.data_length = 0; + return; } else { - MTS_DEBUG("Using scatter/gather\n"); - sg = srb->request_buffer; + sg = scsi_sglist(srb); desc->context.data = page_address(sg[0].page) + sg[0].offset; desc->context.data_length = sg[0].length; } diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index 323293a3e61f..c646750ccc30 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -50,7 +50,7 @@ #include <linux/slab.h> #include <scsi/scsi.h> -#include <scsi/scsi_cmnd.h> +#include <scsi/scsi_eh.h> #include <scsi/scsi_device.h> #include "usb.h" @@ -580,25 +580,11 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) /* Now, if we need to do the auto-sense, let's do it */ if (need_auto_sense) { int temp_result; - void* old_request_buffer; - unsigned short old_sg; - unsigned old_request_bufflen; - unsigned char old_sc_data_direction; - unsigned char old_cmd_len; - unsigned char old_cmnd[MAX_COMMAND_SIZE]; - int old_resid; + struct scsi_eh_save ses; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); - /* save the old command */ - memcpy(old_cmnd, srb->cmnd, MAX_COMMAND_SIZE); - old_cmd_len = srb->cmd_len; - - /* set the command and the LUN */ - memset(srb->cmnd, 0, MAX_COMMAND_SIZE); - srb->cmnd[0] = REQUEST_SENSE; - srb->cmnd[1] = old_cmnd[1] & 0xE0; - srb->cmnd[4] = 18; + scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE); /* FIXME: we must do the protocol translation here */ if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI) @@ -606,36 +592,12 @@ void usb_stor_invoke_transport(struct scsi_cmnd *srb, struct us_data *us) else srb->cmd_len = 12; - /* set the transfer direction */ - old_sc_data_direction = srb->sc_data_direction; - srb->sc_data_direction = DMA_FROM_DEVICE; - - /* use the new buffer we have */ - old_request_buffer = srb->request_buffer; - srb->request_buffer = us->sensebuf; - - /* set the buffer length for transfer */ - old_request_bufflen = srb->request_bufflen; - srb->request_bufflen = US_SENSE_SIZE; - - /* set up for no scatter-gather use */ - old_sg = srb->use_sg; - srb->use_sg = 0; - /* issue the auto-sense command */ - old_resid = srb->resid; srb->resid = 0; temp_result = us->transport(us->srb, us); /* let's clean up right away */ - memcpy(srb->sense_buffer, us->sensebuf, US_SENSE_SIZE); - srb->resid = old_resid; - srb->request_buffer = old_request_buffer; - srb->request_bufflen = old_request_bufflen; - srb->use_sg = old_sg; - srb->sc_data_direction = old_sc_data_direction; - srb->cmd_len = old_cmd_len; - memcpy(srb->cmnd, old_cmnd, MAX_COMMAND_SIZE); + scsi_eh_restore_cmnd(srb, &ses); if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- auto-sense aborted\n"); diff --git a/fs/nfsd/nfs3xdr.c b/fs/nfsd/nfs3xdr.c index 10f6e7dcf633..2d116d2298f8 100644 --- a/fs/nfsd/nfs3xdr.c +++ b/fs/nfsd/nfs3xdr.c @@ -174,9 +174,6 @@ static __be32 * encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, struct kstat *stat) { - struct dentry *dentry = fhp->fh_dentry; - struct timespec time; - *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]); *p++ = htonl((u32) stat->mode); *p++ = htonl((u32) stat->nlink); @@ -191,10 +188,9 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, *p++ = htonl((u32) MAJOR(stat->rdev)); *p++ = htonl((u32) MINOR(stat->rdev)); p = encode_fsid(p, fhp); - p = xdr_encode_hyper(p, (u64) stat->ino); + p = xdr_encode_hyper(p, stat->ino); p = encode_time3(p, &stat->atime); - lease_get_mtime(dentry->d_inode, &time); - p = encode_time3(p, &time); + p = encode_time3(p, &stat->mtime); p = encode_time3(p, &stat->ctime); return p; @@ -203,31 +199,9 @@ encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp, static __be32 * encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) { - struct inode *inode = fhp->fh_dentry->d_inode; - /* Attributes to follow */ *p++ = xdr_one; - - *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]); - *p++ = htonl((u32) fhp->fh_post_mode); - *p++ = htonl((u32) fhp->fh_post_nlink); - *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid)); - *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid)); - if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) { - p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN); - } else { - p = xdr_encode_hyper(p, (u64) fhp->fh_post_size); - } - p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9); - *p++ = fhp->fh_post_rdev[0]; - *p++ = fhp->fh_post_rdev[1]; - p = encode_fsid(p, fhp); - p = xdr_encode_hyper(p, (u64) inode->i_ino); - p = encode_time3(p, &fhp->fh_post_atime); - p = encode_time3(p, &fhp->fh_post_mtime); - p = encode_time3(p, &fhp->fh_post_ctime); - - return p; + return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr); } /* @@ -246,6 +220,7 @@ encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) err = vfs_getattr(fhp->fh_export->ex_mnt, dentry, &stat); if (!err) { *p++ = xdr_one; /* attributes follow */ + lease_get_mtime(dentry->d_inode, &stat.mtime); return encode_fattr3(rqstp, p, fhp, &stat); } } @@ -284,6 +259,23 @@ encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp) return encode_post_op_attr(rqstp, p, fhp); } +/* + * Fill in the post_op attr for the wcc data + */ +void fill_post_wcc(struct svc_fh *fhp) +{ + int err; + + if (fhp->fh_post_saved) + printk("nfsd: inode locked twice during operation.\n"); + + err = vfs_getattr(fhp->fh_export->ex_mnt, fhp->fh_dentry, + &fhp->fh_post_attr); + if (err) + fhp->fh_post_saved = 0; + else + fhp->fh_post_saved = 1; +} /* * XDR decode functions @@ -643,8 +635,11 @@ int nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_attrstat *resp) { - if (resp->status == 0) + if (resp->status == 0) { + lease_get_mtime(resp->fh.fh_dentry->d_inode, + &resp->stat.mtime); p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); + } return xdr_ressize_check(rqstp, p); } @@ -802,7 +797,7 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p, static __be32 * encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, - int namlen, ino_t ino) + int namlen, u64 ino) { *p++ = xdr_one; /* mark entry present */ p = xdr_encode_hyper(p, ino); /* file id */ @@ -873,7 +868,7 @@ compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp, #define NFS3_ENTRYPLUS_BAGGAGE (1 + 21 + 1 + (NFS3_FHSIZE >> 2)) static int encode_entry(struct readdir_cd *ccd, const char *name, int namlen, - loff_t offset, ino_t ino, unsigned int d_type, int plus) + loff_t offset, u64 ino, unsigned int d_type, int plus) { struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, common); diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 31d6633c7fe4..9d536a8cb379 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -39,6 +39,7 @@ #include <linux/errno.h> #include <linux/delay.h> #include <linux/sched.h> +#include <linux/kthread.h> #include <linux/sunrpc/xdr.h> #include <linux/sunrpc/svc.h> #include <linux/sunrpc/clnt.h> @@ -343,26 +344,28 @@ static struct rpc_version * nfs_cb_version[] = { &nfs_cb_version4, }; -/* - * Use the SETCLIENTID credential - */ -static struct rpc_cred * -nfsd4_lookupcred(struct nfs4_client *clp, int taskflags) +/* Reference counting, callback cleanup, etc., all look racy as heck. + * And why is cb_set an atomic? */ + +static int do_probe_callback(void *data) { - struct auth_cred acred; - struct rpc_clnt *clnt = clp->cl_callback.cb_client; - struct rpc_cred *ret; - - get_group_info(clp->cl_cred.cr_group_info); - acred.uid = clp->cl_cred.cr_uid; - acred.gid = clp->cl_cred.cr_gid; - acred.group_info = clp->cl_cred.cr_group_info; - - dprintk("NFSD: looking up %s cred\n", - clnt->cl_auth->au_ops->au_name); - ret = rpcauth_lookup_credcache(clnt->cl_auth, &acred, taskflags); - put_group_info(clp->cl_cred.cr_group_info); - return ret; + struct nfs4_client *clp = data; + struct nfs4_callback *cb = &clp->cl_callback; + struct rpc_message msg = { + .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], + .rpc_argp = clp, + }; + int status; + + status = rpc_call_sync(cb->cb_client, &msg, RPC_TASK_SOFT); + + if (status) { + rpc_shutdown_client(cb->cb_client); + cb->cb_client = NULL; + } else + atomic_set(&cb->cb_set, 1); + put_nfs4_client(clp); + return 0; } /* @@ -390,11 +393,7 @@ nfsd4_probe_callback(struct nfs4_client *clp) .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ .flags = (RPC_CLNT_CREATE_NOPING), }; - struct rpc_message msg = { - .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], - .rpc_argp = clp, - }; - int status; + struct task_struct *t; if (atomic_read(&cb->cb_set)) return; @@ -426,16 +425,11 @@ nfsd4_probe_callback(struct nfs4_client *clp) /* the task holds a reference to the nfs4_client struct */ atomic_inc(&clp->cl_count); - msg.rpc_cred = nfsd4_lookupcred(clp,0); - if (IS_ERR(msg.rpc_cred)) - goto out_release_clp; - status = rpc_call_async(cb->cb_client, &msg, RPC_TASK_ASYNC, &nfs4_cb_null_ops, NULL); - put_rpccred(msg.rpc_cred); + t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe"); - if (status != 0) { - dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n"); + if (IS_ERR(t)) goto out_release_clp; - } + return; out_release_clp: @@ -447,30 +441,6 @@ out_err: (int)clp->cl_name.len, clp->cl_name.data); } -static void -nfs4_cb_null(struct rpc_task *task, void *dummy) -{ - struct nfs4_client *clp = (struct nfs4_client *)task->tk_msg.rpc_argp; - struct nfs4_callback *cb = &clp->cl_callback; - __be32 addr = htonl(cb->cb_addr); - - dprintk("NFSD: nfs4_cb_null task->tk_status %d\n", task->tk_status); - - if (task->tk_status < 0) { - dprintk("NFSD: callback establishment to client %.*s failed\n", - (int)clp->cl_name.len, clp->cl_name.data); - goto out; - } - atomic_set(&cb->cb_set, 1); - dprintk("NFSD: callback set to client %u.%u.%u.%u\n", NIPQUAD(addr)); -out: - put_nfs4_client(clp); -} - -static const struct rpc_call_ops nfs4_cb_null_ops = { - .rpc_call_done = nfs4_cb_null, -}; - /* * called with dp->dl_count inc'ed. * nfs4_lock_state() may or may not have been called. @@ -491,10 +461,6 @@ nfsd4_cb_recall(struct nfs4_delegation *dp) if ((!atomic_read(&clp->cl_callback.cb_set)) || !clnt) return; - msg.rpc_cred = nfsd4_lookupcred(clp, 0); - if (IS_ERR(msg.rpc_cred)) - goto out; - cbr->cbr_trunc = 0; /* XXX need to implement truncate optimization */ cbr->cbr_dp = dp; @@ -515,13 +481,12 @@ nfsd4_cb_recall(struct nfs4_delegation *dp) status = rpc_call_sync(clnt, &msg, RPC_TASK_SOFT); } out_put_cred: - put_rpccred(msg.rpc_cred); -out: if (status == -EIO) atomic_set(&clp->cl_callback.cb_set, 0); /* Success or failure, now we're either waiting for lease expiration * or deleg_return. */ dprintk("NFSD: nfs4_cb_recall: dp %p dl_flock %p dl_count %d\n",dp, dp->dl_flock, atomic_read(&dp->dl_count)); + put_nfs4_client(clp); nfs4_put_delegation(dp); return; } diff --git a/fs/nfsd/nfs4idmap.c b/fs/nfsd/nfs4idmap.c index 2ccffde81b84..4c0c683ce07a 100644 --- a/fs/nfsd/nfs4idmap.c +++ b/fs/nfsd/nfs4idmap.c @@ -207,6 +207,7 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) { struct ent ent, *res; char *buf1, *bp; + int len; int error = -EINVAL; if (buf[buflen - 1] != '\n') @@ -248,10 +249,11 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) goto out; /* Name */ - error = qword_get(&buf, buf1, PAGE_SIZE); - if (error == -EINVAL) + error = -EINVAL; + len = qword_get(&buf, buf1, PAGE_SIZE); + if (len < 0) goto out; - if (error == -ENOENT) + if (len == 0) set_bit(CACHE_NEGATIVE, &ent.h.flags); else { if (error >= IDMAP_NAMESZ) { diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 29b7e63cb32c..18ead1790bb3 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -238,12 +238,12 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, break; case NFS4_OPEN_CLAIM_DELEGATE_PREV: open->op_stateowner->so_confirmed = 1; - printk("NFSD: unsupported OPEN claim type %d\n", + dprintk("NFSD: unsupported OPEN claim type %d\n", open->op_claim_type); status = nfserr_notsupp; goto out; default: - printk("NFSD: Invalid OPEN claim type %d\n", + dprintk("NFSD: Invalid OPEN claim type %d\n", open->op_claim_type); status = nfserr_inval; goto out; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 3f559700788f..6f182d25793d 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -358,9 +358,22 @@ alloc_client(struct xdr_netobj name) return clp; } +static void +shutdown_callback_client(struct nfs4_client *clp) +{ + struct rpc_clnt *clnt = clp->cl_callback.cb_client; + + /* shutdown rpc client, ending any outstanding recall rpcs */ + if (clnt) { + clp->cl_callback.cb_client = NULL; + rpc_shutdown_client(clnt); + } +} + static inline void free_client(struct nfs4_client *clp) { + shutdown_callback_client(clp); if (clp->cl_cred.cr_group_info) put_group_info(clp->cl_cred.cr_group_info); kfree(clp->cl_name.data); @@ -375,18 +388,6 @@ put_nfs4_client(struct nfs4_client *clp) } static void -shutdown_callback_client(struct nfs4_client *clp) -{ - struct rpc_clnt *clnt = clp->cl_callback.cb_client; - - /* shutdown rpc client, ending any outstanding recall rpcs */ - if (clnt) { - clp->cl_callback.cb_client = NULL; - rpc_shutdown_client(clnt); - } -} - -static void expire_client(struct nfs4_client *clp) { struct nfs4_stateowner *sop; @@ -396,8 +397,6 @@ expire_client(struct nfs4_client *clp) dprintk("NFSD: expire_client cl_count %d\n", atomic_read(&clp->cl_count)); - shutdown_callback_client(clp); - INIT_LIST_HEAD(&reaplist); spin_lock(&recall_lock); while (!list_empty(&clp->cl_delegations)) { @@ -462,26 +461,28 @@ copy_cred(struct svc_cred *target, struct svc_cred *source) { } static inline int -same_name(const char *n1, const char *n2) { +same_name(const char *n1, const char *n2) +{ return 0 == memcmp(n1, n2, HEXDIR_LEN); } static int -cmp_verf(nfs4_verifier *v1, nfs4_verifier *v2) { - return(!memcmp(v1->data,v2->data,sizeof(v1->data))); +same_verf(nfs4_verifier *v1, nfs4_verifier *v2) +{ + return 0 == memcmp(v1->data, v2->data, sizeof(v1->data)); } static int -cmp_clid(clientid_t * cl1, clientid_t * cl2) { - return((cl1->cl_boot == cl2->cl_boot) && - (cl1->cl_id == cl2->cl_id)); +same_clid(clientid_t *cl1, clientid_t *cl2) +{ + return (cl1->cl_boot == cl2->cl_boot) && (cl1->cl_id == cl2->cl_id); } /* XXX what about NGROUP */ static int -cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){ - return(cr1->cr_uid == cr2->cr_uid); - +same_creds(struct svc_cred *cr1, struct svc_cred *cr2) +{ + return cr1->cr_uid == cr2->cr_uid; } static void @@ -507,7 +508,7 @@ check_name(struct xdr_netobj name) { if (name.len == 0) return 0; if (name.len > NFS4_OPAQUE_LIMIT) { - printk("NFSD: check_name: name too long(%d)!\n", name.len); + dprintk("NFSD: check_name: name too long(%d)!\n", name.len); return 0; } return 1; @@ -546,7 +547,7 @@ find_confirmed_client(clientid_t *clid) unsigned int idhashval = clientid_hashval(clid->cl_id); list_for_each_entry(clp, &conf_id_hashtbl[idhashval], cl_idhash) { - if (cmp_clid(&clp->cl_clientid, clid)) + if (same_clid(&clp->cl_clientid, clid)) return clp; } return NULL; @@ -559,7 +560,7 @@ find_unconfirmed_client(clientid_t *clid) unsigned int idhashval = clientid_hashval(clid->cl_id); list_for_each_entry(clp, &unconf_id_hashtbl[idhashval], cl_idhash) { - if (cmp_clid(&clp->cl_clientid, clid)) + if (same_clid(&clp->cl_clientid, clid)) return clp; } return NULL; @@ -753,7 +754,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, * or different ip_address */ status = nfserr_clid_inuse; - if (!cmp_creds(&conf->cl_cred, &rqstp->rq_cred) + if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) || conf->cl_addr != sin->sin_addr.s_addr) { dprintk("NFSD: setclientid: string in use by client" "at %u.%u.%u.%u\n", NIPQUAD(conf->cl_addr)); @@ -772,14 +773,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, new = create_client(clname, dname); if (new == NULL) goto out; - copy_verf(new, &clverifier); - new->cl_addr = sin->sin_addr.s_addr; - copy_cred(&new->cl_cred,&rqstp->rq_cred); gen_clid(new); - gen_confirm(new); - gen_callback(new, setclid); - add_to_unconfirmed(new, strhashval); - } else if (cmp_verf(&conf->cl_verifier, &clverifier)) { + } else if (same_verf(&conf->cl_verifier, &clverifier)) { /* * CASE 1: * cl_name match, confirmed, principal match @@ -804,13 +799,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, new = create_client(clname, dname); if (new == NULL) goto out; - copy_verf(new,&conf->cl_verifier); - new->cl_addr = sin->sin_addr.s_addr; - copy_cred(&new->cl_cred,&rqstp->rq_cred); copy_clid(new, conf); - gen_confirm(new); - gen_callback(new, setclid); - add_to_unconfirmed(new,strhashval); } else if (!unconf) { /* * CASE 2: @@ -823,14 +812,8 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, new = create_client(clname, dname); if (new == NULL) goto out; - copy_verf(new,&clverifier); - new->cl_addr = sin->sin_addr.s_addr; - copy_cred(&new->cl_cred,&rqstp->rq_cred); gen_clid(new); - gen_confirm(new); - gen_callback(new, setclid); - add_to_unconfirmed(new, strhashval); - } else if (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm)) { + } else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) { /* * CASE3: * confirmed found (name, principal match) @@ -850,19 +833,19 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, new = create_client(clname, dname); if (new == NULL) goto out; - copy_verf(new,&clverifier); - new->cl_addr = sin->sin_addr.s_addr; - copy_cred(&new->cl_cred,&rqstp->rq_cred); gen_clid(new); - gen_confirm(new); - gen_callback(new, setclid); - add_to_unconfirmed(new, strhashval); } else { /* No cases hit !!! */ status = nfserr_inval; goto out; } + copy_verf(new, &clverifier); + new->cl_addr = sin->sin_addr.s_addr; + copy_cred(&new->cl_cred, &rqstp->rq_cred); + gen_confirm(new); + gen_callback(new, setclid); + add_to_unconfirmed(new, strhashval); setclid->se_clientid.cl_boot = new->cl_clientid.cl_boot; setclid->se_clientid.cl_id = new->cl_clientid.cl_id; memcpy(setclid->se_confirm.data, new->cl_confirm.data, sizeof(setclid->se_confirm.data)); @@ -910,16 +893,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, goto out; if ((conf && unconf) && - (cmp_verf(&unconf->cl_confirm, &confirm)) && - (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) && + (same_verf(&unconf->cl_confirm, &confirm)) && + (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) && (same_name(conf->cl_recdir,unconf->cl_recdir)) && - (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm))) { + (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) { /* CASE 1: * unconf record that matches input clientid and input confirm. * conf record that matches input clientid. * conf and unconf records match names, verifiers */ - if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) + if (!same_creds(&conf->cl_cred, &unconf->cl_cred)) status = nfserr_clid_inuse; else { /* XXX: We just turn off callbacks until we can handle @@ -933,7 +916,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, } } else if ((conf && !unconf) || ((conf && unconf) && - (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) || + (!same_verf(&conf->cl_verifier, &unconf->cl_verifier) || !same_name(conf->cl_recdir, unconf->cl_recdir)))) { /* CASE 2: * conf record that matches input clientid. @@ -941,18 +924,18 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, * unconf->cl_name or unconf->cl_verifier don't match the * conf record. */ - if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) + if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) status = nfserr_clid_inuse; else status = nfs_ok; } else if (!conf && unconf - && cmp_verf(&unconf->cl_confirm, &confirm)) { + && same_verf(&unconf->cl_confirm, &confirm)) { /* CASE 3: * conf record not found. * unconf record found. * unconf->cl_confirm matches input confirm */ - if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) { + if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { status = nfserr_clid_inuse; } else { unsigned int hash = @@ -967,8 +950,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, conf = unconf; status = nfs_ok; } - } else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) - && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, + } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) + && (!unconf || (unconf && !same_verf(&unconf->cl_confirm, &confirm)))) { /* CASE 4: * conf record not found, or if conf, conf->cl_confirm does not @@ -1019,7 +1002,7 @@ nfsd4_free_slab(struct kmem_cache **slab) *slab = NULL; } -static void +void nfsd4_free_slabs(void) { nfsd4_free_slab(&stateowner_slab); @@ -1207,10 +1190,12 @@ move_to_close_lru(struct nfs4_stateowner *sop) } static int -cmp_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, clientid_t *clid) { - return ((sop->so_owner.len == owner->len) && - !memcmp(sop->so_owner.data, owner->data, owner->len) && - (sop->so_client->cl_clientid.cl_id == clid->cl_id)); +same_owner_str(struct nfs4_stateowner *sop, struct xdr_netobj *owner, + clientid_t *clid) +{ + return (sop->so_owner.len == owner->len) && + 0 == memcmp(sop->so_owner.data, owner->data, owner->len) && + (sop->so_client->cl_clientid.cl_id == clid->cl_id); } static struct nfs4_stateowner * @@ -1219,7 +1204,7 @@ find_openstateowner_str(unsigned int hashval, struct nfsd4_open *open) struct nfs4_stateowner *so = NULL; list_for_each_entry(so, &ownerstr_hashtbl[hashval], so_strhash) { - if (cmp_owner_str(so, &open->op_owner, &open->op_clientid)) + if (same_owner_str(so, &open->op_owner, &open->op_clientid)) return so; } return NULL; @@ -1360,6 +1345,7 @@ void nfsd_break_deleg_cb(struct file_lock *fl) * lock) we know the server hasn't removed the lease yet, we know * it's safe to take a reference: */ atomic_inc(&dp->dl_count); + atomic_inc(&dp->dl_client->cl_count); spin_lock(&recall_lock); list_add_tail(&dp->dl_recall_lru, &del_recall_lru); @@ -1368,8 +1354,12 @@ void nfsd_break_deleg_cb(struct file_lock *fl) /* only place dl_time is set. protected by lock_kernel*/ dp->dl_time = get_seconds(); - /* XXX need to merge NFSD_LEASE_TIME with fs/locks.c:lease_break_time */ - fl->fl_break_time = jiffies + NFSD_LEASE_TIME * HZ; + /* + * We don't want the locks code to timeout the lease for us; + * we'll remove it ourself if the delegation isn't returned + * in time. + */ + fl->fl_break_time = 0; t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall"); if (IS_ERR(t)) { @@ -1378,6 +1368,7 @@ void nfsd_break_deleg_cb(struct file_lock *fl) printk(KERN_INFO "NFSD: Callback thread failed for " "for client (clientid %08x/%08x)\n", clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); + put_nfs4_client(dp->dl_client); nfs4_put_delegation(dp); } } @@ -1738,7 +1729,7 @@ out: if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && flag == NFS4_OPEN_DELEGATE_NONE && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) - printk("NFSD: WARNING: refusing delegation reclaim\n"); + dprintk("NFSD: WARNING: refusing delegation reclaim\n"); open->op_delegate_type = flag; } @@ -2147,7 +2138,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei *sopp = NULL; if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { - printk("NFSD: preprocess_seqid_op: magic stateid!\n"); + dprintk("NFSD: preprocess_seqid_op: magic stateid!\n"); return nfserr_bad_stateid; } @@ -2181,25 +2172,24 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei lkflg = setlkflg(lock->lk_type); if (lock->lk_is_new) { - if (!sop->so_is_open_owner) - return nfserr_bad_stateid; - if (!cmp_clid(&clp->cl_clientid, lockclid)) + if (!sop->so_is_open_owner) + return nfserr_bad_stateid; + if (!same_clid(&clp->cl_clientid, lockclid)) return nfserr_bad_stateid; - /* stp is the open stateid */ - status = nfs4_check_openmode(stp, lkflg); - if (status) - return status; - } else { - /* stp is the lock stateid */ - status = nfs4_check_openmode(stp->st_openstp, lkflg); - if (status) - return status; + /* stp is the open stateid */ + status = nfs4_check_openmode(stp, lkflg); + if (status) + return status; + } else { + /* stp is the lock stateid */ + status = nfs4_check_openmode(stp->st_openstp, lkflg); + if (status) + return status; } - } if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { - printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); + dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); return nfserr_bad_stateid; } @@ -2215,22 +2205,22 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei goto check_replay; if (sop->so_confirmed && flags & CONFIRM) { - printk("NFSD: preprocess_seqid_op: expected" + dprintk("NFSD: preprocess_seqid_op: expected" " unconfirmed stateowner!\n"); return nfserr_bad_stateid; } if (!sop->so_confirmed && !(flags & CONFIRM)) { - printk("NFSD: preprocess_seqid_op: stateowner not" + dprintk("NFSD: preprocess_seqid_op: stateowner not" " confirmed yet!\n"); return nfserr_bad_stateid; } if (stateid->si_generation > stp->st_stateid.si_generation) { - printk("NFSD: preprocess_seqid_op: future stateid?!\n"); + dprintk("NFSD: preprocess_seqid_op: future stateid?!\n"); return nfserr_bad_stateid; } if (stateid->si_generation < stp->st_stateid.si_generation) { - printk("NFSD: preprocess_seqid_op: old stateid!\n"); + dprintk("NFSD: preprocess_seqid_op: old stateid!\n"); return nfserr_old_stateid; } renew_client(sop->so_client); @@ -2242,7 +2232,7 @@ check_replay: /* indicate replay to calling function */ return nfserr_replay_me; } - printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", + dprintk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", sop->so_seqid, seqid); *sopp = NULL; return nfserr_bad_seqid; @@ -2561,7 +2551,7 @@ find_lockstateowner_str(struct inode *inode, clientid_t *clid, struct nfs4_stateowner *op; list_for_each_entry(op, &lock_ownerstr_hashtbl[hashval], so_strhash) { - if (cmp_owner_str(op, owner, clid)) + if (same_owner_str(op, owner, clid)) return op; } return NULL; @@ -2855,7 +2845,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, file_lock.fl_type = F_WRLCK; break; default: - printk("NFSD: nfs4_lockt: bad lock type!\n"); + dprintk("NFSD: nfs4_lockt: bad lock type!\n"); status = nfserr_inval; goto out; } @@ -3025,7 +3015,7 @@ nfsd4_release_lockowner(struct svc_rqst *rqstp, INIT_LIST_HEAD(&matches); for (i = 0; i < LOCK_HASH_SIZE; i++) { list_for_each_entry(sop, &lock_ownerid_hashtbl[i], so_idhash) { - if (!cmp_owner_str(sop, owner, clid)) + if (!same_owner_str(sop, owner, clid)) continue; list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) { @@ -3149,11 +3139,14 @@ nfs4_check_open_reclaim(clientid_t *clid) /* initialization to perform at module load time: */ -void +int nfs4_state_init(void) { - int i; + int i, status; + status = nfsd4_init_slabs(); + if (status) + return status; for (i = 0; i < CLIENT_HASH_SIZE; i++) { INIT_LIST_HEAD(&conf_id_hashtbl[i]); INIT_LIST_HEAD(&conf_str_hashtbl[i]); @@ -3182,6 +3175,7 @@ nfs4_state_init(void) for (i = 0; i < CLIENT_HASH_SIZE; i++) INIT_LIST_HEAD(&reclaim_str_hashtbl[i]); reclaim_str_hashtbl_size = 0; + return 0; } static void @@ -3242,20 +3236,15 @@ __nfs4_state_start(void) set_max_delegations(); } -int +void nfs4_state_start(void) { - int status; - if (nfs4_init) - return 0; - status = nfsd4_init_slabs(); - if (status) - return status; + return; nfsd4_load_reboot_recovery_data(); __nfs4_state_start(); nfs4_init = 1; - return 0; + return; } int @@ -3313,7 +3302,6 @@ nfs4_state_shutdown(void) nfs4_lock_state(); nfs4_release_reclaim(); __nfs4_state_shutdown(); - nfsd4_free_slabs(); nfs4_unlock_state(); } diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 8ef0964179bc..e15f2cf8ac15 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1475,7 +1475,8 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, err = vfs_getattr(exp->ex_mnt, dentry, &stat); if (err) goto out_nfserr; - if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || + if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL | + FATTR4_WORD0_MAXNAME)) || (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL))) { err = vfs_statfs(dentry, &statfs); @@ -1679,7 +1680,7 @@ out_acl: if (bmval0 & FATTR4_WORD0_FILEID) { if ((buflen -= 8) < 0) goto out_resource; - WRITE64((u64) stat.ino); + WRITE64(stat.ino); } if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { if ((buflen -= 8) < 0) @@ -1721,7 +1722,7 @@ out_acl: if (bmval0 & FATTR4_WORD0_MAXNAME) { if ((buflen -= 4) < 0) goto out_resource; - WRITE32(~(u32) 0); + WRITE32(statfs.f_namelen); } if (bmval0 & FATTR4_WORD0_MAXREAD) { if ((buflen -= 8) < 0) @@ -1821,16 +1822,15 @@ out_acl: WRITE32(stat.mtime.tv_nsec); } if (bmval1 & FATTR4_WORD1_MOUNTED_ON_FILEID) { - struct dentry *mnt_pnt, *mnt_root; - if ((buflen -= 8) < 0) goto out_resource; - mnt_root = exp->ex_mnt->mnt_root; - if (mnt_root->d_inode == dentry->d_inode) { - mnt_pnt = exp->ex_mnt->mnt_mountpoint; - WRITE64((u64) mnt_pnt->d_inode->i_ino); - } else - WRITE64((u64) stat.ino); + if (exp->ex_mnt->mnt_root->d_inode == dentry->d_inode) { + err = vfs_getattr(exp->ex_mnt->mnt_parent, + exp->ex_mnt->mnt_mountpoint, &stat); + if (err) + goto out_nfserr; + } + WRITE64(stat.ino); } *attrlenp = htonl((char *)p - (char *)attrlenp - 4); *countp = p - buffer; diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index baac89d917ca..77dc9893b7ba 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -298,7 +298,7 @@ static ssize_t write_filehandle(struct file *file, char *buf, size_t size) * qword quoting is used, so filehandle will be \x.... */ char *dname, *path; - int maxsize; + int uninitialized_var(maxsize); char *mesg = buf; int len; struct auth_domain *dom; @@ -679,11 +679,13 @@ static int __init init_nfsd(void) int retval; printk(KERN_INFO "Installing knfsd (copyright (C) 1996 okir@monad.swb.de).\n"); + retval = nfs4_state_init(); /* nfs4 locking state */ + if (retval) + return retval; nfsd_stat_init(); /* Statistics */ nfsd_cache_init(); /* RPC reply cache */ nfsd_export_init(); /* Exports table */ nfsd_lockd_init(); /* lockd->nfsd callbacks */ - nfs4_state_init(); /* NFSv4 locking state */ nfsd_idmap_init(); /* Name to ID mapping */ if (proc_mkdir("fs/nfs", NULL)) { struct proc_dir_entry *entry; @@ -712,6 +714,7 @@ static void __exit exit_nfsd(void) nfsd_stat_shutdown(); nfsd_lockd_shutdown(); nfsd_idmap_shutdown(); + nfsd4_free_slabs(); unregister_filesystem(&nfsd_fs_type); } diff --git a/fs/nfsd/nfssvc.c b/fs/nfsd/nfssvc.c index a8c89ae4c743..1190aeaa92be 100644 --- a/fs/nfsd/nfssvc.c +++ b/fs/nfsd/nfssvc.c @@ -349,9 +349,7 @@ nfsd_svc(unsigned short port, int nrservs) error = nfsd_racache_init(2*nrservs); if (error<0) goto out; - error = nfs4_state_start(); - if (error<0) - goto out; + nfs4_state_start(); nfsd_reset_versions(); @@ -546,10 +544,8 @@ nfsd_dispatch(struct svc_rqst *rqstp, __be32 *statp) /* Now call the procedure handler, and encode NFS status. */ nfserr = proc->pc_func(rqstp, rqstp->rq_argp, rqstp->rq_resp); nfserr = map_new_errors(rqstp->rq_vers, nfserr); - if (nfserr == nfserr_jukebox && rqstp->rq_vers == 2) - nfserr = nfserr_dropit; if (nfserr == nfserr_dropit) { - dprintk("nfsd: Dropping request due to malloc failure!\n"); + dprintk("nfsd: Dropping request; may be revisited later\n"); nfsd_cache_update(rqstp, RC_NOCACHE, NULL); return 0; } diff --git a/fs/nfsd/nfsxdr.c b/fs/nfsd/nfsxdr.c index cb3e7fadb772..986f9b32083c 100644 --- a/fs/nfsd/nfsxdr.c +++ b/fs/nfsd/nfsxdr.c @@ -523,6 +523,10 @@ nfssvc_encode_entry(void *ccdv, const char *name, cd->common.err = nfserr_toosmall; return -EINVAL; } + if (ino > ~((u32) 0)) { + cd->common.err = nfserr_fbig; + return -EINVAL; + } *p++ = xdr_one; /* mark entry present */ *p++ = htonl((u32) ino); /* file id */ p = xdr_encode_array(p, name, namlen);/* name length & name */ diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 7867151ebb83..cec78c82b1f9 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -295,7 +295,8 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, if (!iap->ia_valid) goto out; - /* NFSv2 does not differentiate between "set-[ac]time-to-now" + /* + * NFSv2 does not differentiate between "set-[ac]time-to-now" * which only requires access, and "set-[ac]time-to-X" which * requires ownership. * So if it looks like it might be "set both to the same time which @@ -308,25 +309,33 @@ nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, */ #define BOTH_TIME_SET (ATTR_ATIME_SET | ATTR_MTIME_SET) #define MAX_TOUCH_TIME_ERROR (30*60) - if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET - && iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec - ) { - /* Looks probable. Now just make sure time is in the right ballpark. - * Solaris, at least, doesn't seem to care what the time request is. - * We require it be within 30 minutes of now. - */ - time_t delta = iap->ia_atime.tv_sec - get_seconds(); - if (delta<0) delta = -delta; - if (delta < MAX_TOUCH_TIME_ERROR && - inode_change_ok(inode, iap) != 0) { - /* turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME - * this will cause notify_change to set these times to "now" + if ((iap->ia_valid & BOTH_TIME_SET) == BOTH_TIME_SET && + iap->ia_mtime.tv_sec == iap->ia_atime.tv_sec) { + /* + * Looks probable. + * + * Now just make sure time is in the right ballpark. + * Solaris, at least, doesn't seem to care what the time + * request is. We require it be within 30 minutes of now. */ - iap->ia_valid &= ~BOTH_TIME_SET; - } + time_t delta = iap->ia_atime.tv_sec - get_seconds(); + if (delta < 0) + delta = -delta; + if (delta < MAX_TOUCH_TIME_ERROR && + inode_change_ok(inode, iap) != 0) { + /* + * Turn off ATTR_[AM]TIME_SET but leave ATTR_[AM]TIME. + * This will cause notify_change to set these times + * to "now" + */ + iap->ia_valid &= ~BOTH_TIME_SET; + } } - /* The size case is special. It changes the file as well as the attributes. */ + /* + * The size case is special. + * It changes the file as well as the attributes. + */ if (iap->ia_valid & ATTR_SIZE) { if (iap->ia_size < inode->i_size) { err = nfsd_permission(rqstp, fhp->fh_export, dentry, MAY_TRUNC|MAY_OWNER_OVERRIDE); diff --git a/fs/pipe.c b/fs/pipe.c index 6b3d91a691bf..e66ec48e95d8 100644 --- a/fs/pipe.c +++ b/fs/pipe.c @@ -45,8 +45,7 @@ void pipe_wait(struct pipe_inode_info *pipe) * Pipes are system-local resources, so sleeping on them * is considered a noninteractive wait: */ - prepare_to_wait(&pipe->wait, &wait, - TASK_INTERRUPTIBLE | TASK_NONINTERACTIVE); + prepare_to_wait(&pipe->wait, &wait, TASK_INTERRUPTIBLE); if (pipe->inode) mutex_unlock(&pipe->inode->i_mutex); schedule(); @@ -383,7 +382,7 @@ redo: /* Signal writers asynchronously that there is more room. */ if (do_wakeup) { - wake_up_interruptible(&pipe->wait); + wake_up_interruptible_sync(&pipe->wait); kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); } if (ret > 0) @@ -556,7 +555,7 @@ redo2: out: mutex_unlock(&inode->i_mutex); if (do_wakeup) { - wake_up_interruptible(&pipe->wait); + wake_up_interruptible_sync(&pipe->wait); kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); } if (ret > 0) @@ -650,7 +649,7 @@ pipe_release(struct inode *inode, int decr, int decw) if (!pipe->readers && !pipe->writers) { free_pipe_info(inode); } else { - wake_up_interruptible(&pipe->wait); + wake_up_interruptible_sync(&pipe->wait); kill_fasync(&pipe->fasync_readers, SIGIO, POLL_IN); kill_fasync(&pipe->fasync_writers, SIGIO, POLL_OUT); } diff --git a/fs/proc/array.c b/fs/proc/array.c index ee4814dd98f9..27b59f5f3bd1 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c @@ -370,6 +370,11 @@ static cputime_t task_stime(struct task_struct *p) } #endif +static cputime_t task_gtime(struct task_struct *p) +{ + return p->gtime; +} + static int do_task_stat(struct task_struct *task, char *buffer, int whole) { unsigned long vsize, eip, esp, wchan = ~0UL; @@ -385,6 +390,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) unsigned long cmin_flt = 0, cmaj_flt = 0; unsigned long min_flt = 0, maj_flt = 0; cputime_t cutime, cstime, utime, stime; + cputime_t cgtime, gtime; unsigned long rsslim = 0; char tcomm[sizeof(task->comm)]; unsigned long flags; @@ -403,6 +409,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) sigemptyset(&sigign); sigemptyset(&sigcatch); cutime = cstime = utime = stime = cputime_zero; + cgtime = gtime = cputime_zero; rcu_read_lock(); if (lock_task_sighand(task, &flags)) { @@ -420,6 +427,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) cmaj_flt = sig->cmaj_flt; cutime = sig->cutime; cstime = sig->cstime; + cgtime = sig->cgtime; rsslim = sig->rlim[RLIMIT_RSS].rlim_cur; /* add up live thread stats at the group level */ @@ -430,6 +438,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) maj_flt += t->maj_flt; utime = cputime_add(utime, task_utime(t)); stime = cputime_add(stime, task_stime(t)); + gtime = cputime_add(gtime, task_gtime(t)); t = next_thread(t); } while (t != task); @@ -437,6 +446,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) maj_flt += sig->maj_flt; utime = cputime_add(utime, sig->utime); stime = cputime_add(stime, sig->stime); + gtime += cputime_add(gtime, sig->gtime); } sid = signal_session(sig); @@ -454,6 +464,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) maj_flt = task->maj_flt; utime = task_utime(task); stime = task_stime(task); + gtime = task_gtime(task); } /* scale priority and nice values from timeslices to -20..20 */ @@ -471,7 +482,7 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) res = sprintf(buffer, "%d (%s) %c %d %d %d %d %d %u %lu \ %lu %lu %lu %lu %lu %ld %ld %ld %ld %d 0 %llu %lu %ld %lu %lu %lu %lu %lu \ -%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu\n", +%lu %lu %lu %lu %lu %lu %lu %lu %d %d %u %u %llu %lu %ld\n", task->pid, tcomm, state, @@ -516,7 +527,9 @@ static int do_task_stat(struct task_struct *task, char *buffer, int whole) task_cpu(task), task->rt_priority, task->policy, - (unsigned long long)delayacct_blkio_ticks(task)); + (unsigned long long)delayacct_blkio_ticks(task), + cputime_to_clock_t(gtime), + cputime_to_clock_t(cgtime)); if (mm) mmput(mm); return res; diff --git a/fs/proc/base.c b/fs/proc/base.c index 19489b0d5554..e5d0953d4db1 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -304,7 +304,7 @@ static int proc_pid_schedstat(struct task_struct *task, char *buffer) return sprintf(buffer, "%llu %llu %lu\n", task->sched_info.cpu_time, task->sched_info.run_delay, - task->sched_info.pcnt); + task->sched_info.pcount); } #endif diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index bee251cb87c8..b872a01ad3af 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -443,6 +443,7 @@ static int show_stat(struct seq_file *p, void *v) int i; unsigned long jif; cputime64_t user, nice, system, idle, iowait, irq, softirq, steal; + cputime64_t guest; u64 sum = 0; struct timespec boottime; unsigned int *per_irq_sum; @@ -453,6 +454,7 @@ static int show_stat(struct seq_file *p, void *v) user = nice = system = idle = iowait = irq = softirq = steal = cputime64_zero; + guest = cputime64_zero; getboottime(&boottime); jif = boottime.tv_sec; @@ -467,6 +469,7 @@ static int show_stat(struct seq_file *p, void *v) irq = cputime64_add(irq, kstat_cpu(i).cpustat.irq); softirq = cputime64_add(softirq, kstat_cpu(i).cpustat.softirq); steal = cputime64_add(steal, kstat_cpu(i).cpustat.steal); + guest = cputime64_add(guest, kstat_cpu(i).cpustat.guest); for (j = 0; j < NR_IRQS; j++) { unsigned int temp = kstat_cpu(i).irqs[j]; sum += temp; @@ -474,7 +477,7 @@ static int show_stat(struct seq_file *p, void *v) } } - seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu\n", + seq_printf(p, "cpu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", (unsigned long long)cputime64_to_clock_t(user), (unsigned long long)cputime64_to_clock_t(nice), (unsigned long long)cputime64_to_clock_t(system), @@ -482,7 +485,8 @@ static int show_stat(struct seq_file *p, void *v) (unsigned long long)cputime64_to_clock_t(iowait), (unsigned long long)cputime64_to_clock_t(irq), (unsigned long long)cputime64_to_clock_t(softirq), - (unsigned long long)cputime64_to_clock_t(steal)); + (unsigned long long)cputime64_to_clock_t(steal), + (unsigned long long)cputime64_to_clock_t(guest)); for_each_online_cpu(i) { /* Copy values here to work around gcc-2.95.3, gcc-2.96 */ @@ -494,7 +498,9 @@ static int show_stat(struct seq_file *p, void *v) irq = kstat_cpu(i).cpustat.irq; softirq = kstat_cpu(i).cpustat.softirq; steal = kstat_cpu(i).cpustat.steal; - seq_printf(p, "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu\n", + guest = kstat_cpu(i).cpustat.guest; + seq_printf(p, + "cpu%d %llu %llu %llu %llu %llu %llu %llu %llu %llu\n", i, (unsigned long long)cputime64_to_clock_t(user), (unsigned long long)cputime64_to_clock_t(nice), @@ -503,7 +509,8 @@ static int show_stat(struct seq_file *p, void *v) (unsigned long long)cputime64_to_clock_t(iowait), (unsigned long long)cputime64_to_clock_t(irq), (unsigned long long)cputime64_to_clock_t(softirq), - (unsigned long long)cputime64_to_clock_t(steal)); + (unsigned long long)cputime64_to_clock_t(steal), + (unsigned long long)cputime64_to_clock_t(guest)); } seq_printf(p, "intr %llu", (unsigned long long)sum); diff --git a/include/asm-ia64/mca.h b/include/asm-ia64/mca.h index edd5d01028df..823553bf12e6 100644 --- a/include/asm-ia64/mca.h +++ b/include/asm-ia64/mca.h @@ -151,6 +151,8 @@ extern void ia64_mca_cmc_vector_setup(void); extern int ia64_reg_MCA_extension(int (*fn)(void *, struct ia64_sal_os_state *)); extern void ia64_unreg_MCA_extension(void); extern u64 ia64_get_rnat(u64 *); +extern void ia64_mca_printk(const char * fmt, ...) + __attribute__ ((format (printf, 1, 2))); struct ia64_mca_notify_die { struct ia64_sal_os_state *sos; diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h index 46cadf5aaac5..1f5412d6f9bb 100644 --- a/include/asm-ia64/sal.h +++ b/include/asm-ia64/sal.h @@ -46,25 +46,28 @@ extern spinlock_t sal_lock; /* SAL spec _requires_ eight args for each call. */ -#define __SAL_CALL(result,a0,a1,a2,a3,a4,a5,a6,a7) \ - result = (*ia64_sal)(a0,a1,a2,a3,a4,a5,a6,a7) +#define __IA64_FW_CALL(entry,result,a0,a1,a2,a3,a4,a5,a6,a7) \ + result = (*entry)(a0,a1,a2,a3,a4,a5,a6,a7) -# define SAL_CALL(result,args...) do { \ +# define IA64_FW_CALL(entry,result,args...) do { \ unsigned long __ia64_sc_flags; \ struct ia64_fpreg __ia64_sc_fr[6]; \ ia64_save_scratch_fpregs(__ia64_sc_fr); \ spin_lock_irqsave(&sal_lock, __ia64_sc_flags); \ - __SAL_CALL(result, args); \ + __IA64_FW_CALL(entry, result, args); \ spin_unlock_irqrestore(&sal_lock, __ia64_sc_flags); \ ia64_load_scratch_fpregs(__ia64_sc_fr); \ } while (0) +# define SAL_CALL(result,args...) \ + IA64_FW_CALL(ia64_sal, result, args); + # define SAL_CALL_NOLOCK(result,args...) do { \ unsigned long __ia64_scn_flags; \ struct ia64_fpreg __ia64_scn_fr[6]; \ ia64_save_scratch_fpregs(__ia64_scn_fr); \ local_irq_save(__ia64_scn_flags); \ - __SAL_CALL(result, args); \ + __IA64_FW_CALL(ia64_sal, result, args); \ local_irq_restore(__ia64_scn_flags); \ ia64_load_scratch_fpregs(__ia64_scn_fr); \ } while (0) @@ -73,7 +76,7 @@ extern spinlock_t sal_lock; struct ia64_fpreg __ia64_scs_fr[6]; \ ia64_save_scratch_fpregs(__ia64_scs_fr); \ preempt_disable(); \ - __SAL_CALL(result, args); \ + __IA64_FW_CALL(ia64_sal, result, args); \ preempt_enable(); \ ia64_load_scratch_fpregs(__ia64_scs_fr); \ } while (0) diff --git a/include/linux/hid.h b/include/linux/hid.h index 55e51f9f76cb..edb8024d744b 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -29,13 +29,6 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ -#include <linux/types.h> -#include <linux/slab.h> -#include <linux/list.h> -#include <linux/timer.h> -#include <linux/workqueue.h> -#include <linux/input.h> - /* * USB HID (Human Interface Device) interface class code */ @@ -69,6 +62,17 @@ #define HID_DT_REPORT (USB_TYPE_CLASS | 0x02) #define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03) +#define HID_MAX_DESCRIPTOR_SIZE 4096 + +#ifdef __KERNEL__ + +#include <linux/types.h> +#include <linux/slab.h> +#include <linux/list.h> +#include <linux/timer.h> +#include <linux/workqueue.h> +#include <linux/input.h> + /* * We parse each description item into this structure. Short items data * values are expanded to 32-bit signed int, long items contain a pointer @@ -311,7 +315,6 @@ struct hid_global { * This is the local environment. It is persistent up the next main-item. */ -#define HID_MAX_DESCRIPTOR_SIZE 4096 #define HID_MAX_USAGES 8192 #define HID_DEFAULT_NUM_COLLECTIONS 16 @@ -560,4 +563,5 @@ static inline int hid_ff_init(struct hid_device *hid) { return -1; } #define err_hid(format, arg...) printk(KERN_ERR "%s: " format "\n" , \ __FILE__ , ## arg) #endif +#endif diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h index 6676cd5e9954..0536f299f7ff 100644 --- a/include/linux/hidraw.h +++ b/include/linux/hidraw.h @@ -15,9 +15,11 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ +#include <linux/hid.h> + struct hidraw_report_descriptor { __u32 size; - __u8 *value; + __u8 value[HID_MAX_DESCRIPTOR_SIZE]; }; struct hidraw_devinfo { @@ -40,8 +42,6 @@ struct hidraw_devinfo { /* kernel-only API declarations */ #ifdef __KERNEL__ -#include <linux/hid.h> - struct hidraw { unsigned int minor; int exist; diff --git a/include/linux/kernel_stat.h b/include/linux/kernel_stat.h index 43e895f1cabe..12bf44f083f5 100644 --- a/include/linux/kernel_stat.h +++ b/include/linux/kernel_stat.h @@ -23,6 +23,7 @@ struct cpu_usage_stat { cputime64_t idle; cputime64_t iowait; cputime64_t steal; + cputime64_t guest; }; struct kernel_stat { diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index e452256d3f72..604a0d786bc6 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -153,19 +153,21 @@ extern int nfsd_max_blksize; */ #ifdef CONFIG_NFSD_V4 extern unsigned int max_delegations; -void nfs4_state_init(void); -int nfs4_state_start(void); +int nfs4_state_init(void); +void nfsd4_free_slabs(void); +void nfs4_state_start(void); void nfs4_state_shutdown(void); time_t nfs4_lease_time(void); void nfs4_reset_lease(time_t leasetime); int nfs4_reset_recoverydir(char *recdir); #else -static inline void nfs4_state_init(void){}; -static inline int nfs4_state_start(void){return 0;} -static inline void nfs4_state_shutdown(void){} -static inline time_t nfs4_lease_time(void){return 0;} -static inline void nfs4_reset_lease(time_t leasetime){} -static inline int nfs4_reset_recoverydir(char *recdir) {return 0;} +static inline int nfs4_state_init(void) { return 0; } +static inline void nfsd4_free_slabs(void) { } +static inline void nfs4_state_start(void) { } +static inline void nfs4_state_shutdown(void) { } +static inline time_t nfs4_lease_time(void) { return 0; } +static inline void nfs4_reset_lease(time_t leasetime) { } +static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } #endif /* diff --git a/include/linux/nfsd/nfsfh.h b/include/linux/nfsd/nfsfh.h index 11e568ee0eeb..d1941cb965e9 100644 --- a/include/linux/nfsd/nfsfh.h +++ b/include/linux/nfsd/nfsfh.h @@ -150,17 +150,7 @@ typedef struct svc_fh { struct timespec fh_pre_ctime; /* ctime before oper */ /* Post-op attributes saved in fh_unlock */ - umode_t fh_post_mode; /* i_mode */ - nlink_t fh_post_nlink; /* i_nlink */ - uid_t fh_post_uid; /* i_uid */ - gid_t fh_post_gid; /* i_gid */ - __u64 fh_post_size; /* i_size */ - unsigned long fh_post_blocks; /* i_blocks */ - unsigned long fh_post_blksize;/* i_blksize */ - __be32 fh_post_rdev[2];/* i_rdev */ - struct timespec fh_post_atime; /* i_atime */ - struct timespec fh_post_mtime; /* i_mtime */ - struct timespec fh_post_ctime; /* i_ctime */ + struct kstat fh_post_attr; /* full attrs after operation */ #endif /* CONFIG_NFSD_V3 */ } svc_fh; @@ -297,36 +287,12 @@ fill_pre_wcc(struct svc_fh *fhp) if (!fhp->fh_pre_saved) { fhp->fh_pre_mtime = inode->i_mtime; fhp->fh_pre_ctime = inode->i_ctime; - fhp->fh_pre_size = inode->i_size; - fhp->fh_pre_saved = 1; + fhp->fh_pre_size = inode->i_size; + fhp->fh_pre_saved = 1; } } -/* - * Fill in the post_op attr for the wcc data - */ -static inline void -fill_post_wcc(struct svc_fh *fhp) -{ - struct inode *inode = fhp->fh_dentry->d_inode; - - if (fhp->fh_post_saved) - printk("nfsd: inode locked twice during operation.\n"); - - fhp->fh_post_mode = inode->i_mode; - fhp->fh_post_nlink = inode->i_nlink; - fhp->fh_post_uid = inode->i_uid; - fhp->fh_post_gid = inode->i_gid; - fhp->fh_post_size = inode->i_size; - fhp->fh_post_blksize = BLOCK_SIZE; - fhp->fh_post_blocks = inode->i_blocks; - fhp->fh_post_rdev[0] = htonl((u32)imajor(inode)); - fhp->fh_post_rdev[1] = htonl((u32)iminor(inode)); - fhp->fh_post_atime = inode->i_atime; - fhp->fh_post_mtime = inode->i_mtime; - fhp->fh_post_ctime = inode->i_ctime; - fhp->fh_post_saved = 1; -} +extern void fill_post_wcc(struct svc_fh *); #else #define fill_pre_wcc(ignored) #define fill_post_wcc(notused) diff --git a/include/linux/nfsd/xdr4.h b/include/linux/nfsd/xdr4.h index 1b653267133a..b0ddfb41c790 100644 --- a/include/linux/nfsd/xdr4.h +++ b/include/linux/nfsd/xdr4.h @@ -428,8 +428,8 @@ set_change_info(struct nfsd4_change_info *cinfo, struct svc_fh *fhp) cinfo->atomic = 1; cinfo->before_ctime_sec = fhp->fh_pre_ctime.tv_sec; cinfo->before_ctime_nsec = fhp->fh_pre_ctime.tv_nsec; - cinfo->after_ctime_sec = fhp->fh_post_ctime.tv_sec; - cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec; + cinfo->after_ctime_sec = fhp->fh_post_attr.ctime.tv_sec; + cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; } int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 87439ad94685..2aaf1c16ce98 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -1467,6 +1467,8 @@ #define PCI_DEVICE_ID_TOSHIBA_TC86C001_MISC 0x0108 #define PCI_DEVICE_ID_TOSHIBA_SPIDER_NET 0x01b3 +#define PCI_VENDOR_ID_ATTO 0x117c + #define PCI_VENDOR_ID_RICOH 0x1180 #define PCI_DEVICE_ID_RICOH_RL5C465 0x0465 #define PCI_DEVICE_ID_RICOH_RL5C466 0x0466 @@ -2075,6 +2077,9 @@ #define PCI_DEVICE_ID_ARECA_1130 0x1130 #define PCI_DEVICE_ID_ARECA_1160 0x1160 #define PCI_DEVICE_ID_ARECA_1170 0x1170 +#define PCI_DEVICE_ID_ARECA_1200 0x1200 +#define PCI_DEVICE_ID_ARECA_1201 0x1201 +#define PCI_DEVICE_ID_ARECA_1202 0x1202 #define PCI_DEVICE_ID_ARECA_1210 0x1210 #define PCI_DEVICE_ID_ARECA_1220 0x1220 #define PCI_DEVICE_ID_ARECA_1230 0x1230 diff --git a/include/linux/sched.h b/include/linux/sched.h index 833f7dc2b8de..228e0a8ce248 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -87,6 +87,7 @@ struct sched_param { #include <linux/timer.h> #include <linux/hrtimer.h> #include <linux/task_io_accounting.h> +#include <linux/kobject.h> #include <asm/processor.h> @@ -136,6 +137,7 @@ extern unsigned long weighted_cpuload(const int cpu); struct seq_file; struct cfs_rq; +struct task_group; #ifdef CONFIG_SCHED_DEBUG extern void proc_sched_show_task(struct task_struct *p, struct seq_file *m); extern void proc_sched_set_task(struct task_struct *p); @@ -174,8 +176,7 @@ print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) #define EXIT_ZOMBIE 16 #define EXIT_DEAD 32 /* in tsk->state again */ -#define TASK_NONINTERACTIVE 64 -#define TASK_DEAD 128 +#define TASK_DEAD 64 #define __set_task_state(tsk, state_value) \ do { (tsk)->state = (state_value); } while (0) @@ -516,6 +517,8 @@ struct signal_struct { * in __exit_signal, except for the group leader. */ cputime_t utime, stime, cutime, cstime; + cputime_t gtime; + cputime_t cgtime; unsigned long nvcsw, nivcsw, cnvcsw, cnivcsw; unsigned long min_flt, maj_flt, cmin_flt, cmaj_flt; unsigned long inblock, oublock, cinblock, coublock; @@ -596,8 +599,21 @@ struct user_struct { /* Hash table maintenance information */ struct hlist_node uidhash_node; uid_t uid; + +#ifdef CONFIG_FAIR_USER_SCHED + struct task_group *tg; + struct kset kset; + struct subsys_attribute user_attr; + struct work_struct work; +#endif }; +#ifdef CONFIG_FAIR_USER_SCHED +extern int uids_kobject_init(void); +#else +static inline int uids_kobject_init(void) { return 0; } +#endif + extern struct user_struct *find_user(uid_t); extern struct user_struct root_user; @@ -609,13 +625,17 @@ struct reclaim_state; #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) struct sched_info { /* cumulative counters */ - unsigned long pcnt; /* # of times run on this cpu */ + unsigned long pcount; /* # of times run on this cpu */ unsigned long long cpu_time, /* time spent on the cpu */ run_delay; /* time spent waiting on a runqueue */ /* timestamps */ unsigned long long last_arrival,/* when we last ran on a cpu */ last_queued; /* when we were last queued to run */ +#ifdef CONFIG_SCHEDSTATS + /* BKL stats */ + unsigned long bkl_count; +#endif }; #endif /* defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) */ @@ -750,7 +770,7 @@ struct sched_domain { #ifdef CONFIG_SCHEDSTATS /* load_balance() stats */ - unsigned long lb_cnt[CPU_MAX_IDLE_TYPES]; + unsigned long lb_count[CPU_MAX_IDLE_TYPES]; unsigned long lb_failed[CPU_MAX_IDLE_TYPES]; unsigned long lb_balanced[CPU_MAX_IDLE_TYPES]; unsigned long lb_imbalance[CPU_MAX_IDLE_TYPES]; @@ -760,17 +780,17 @@ struct sched_domain { unsigned long lb_nobusyq[CPU_MAX_IDLE_TYPES]; /* Active load balancing */ - unsigned long alb_cnt; + unsigned long alb_count; unsigned long alb_failed; unsigned long alb_pushed; /* SD_BALANCE_EXEC stats */ - unsigned long sbe_cnt; + unsigned long sbe_count; unsigned long sbe_balanced; unsigned long sbe_pushed; /* SD_BALANCE_FORK stats */ - unsigned long sbf_cnt; + unsigned long sbf_count; unsigned long sbf_balanced; unsigned long sbf_pushed; @@ -854,11 +874,11 @@ struct rq; struct sched_domain; struct sched_class { - struct sched_class *next; + const struct sched_class *next; void (*enqueue_task) (struct rq *rq, struct task_struct *p, int wakeup); void (*dequeue_task) (struct rq *rq, struct task_struct *p, int sleep); - void (*yield_task) (struct rq *rq, struct task_struct *p); + void (*yield_task) (struct rq *rq); void (*check_preempt_curr) (struct rq *rq, struct task_struct *p); @@ -888,31 +908,22 @@ struct load_weight { * 4 se->block_start * 4 se->run_node * 4 se->sleep_start - * 4 se->sleep_start_fair * 6 se->load.weight - * 7 se->delta_fair - * 15 se->wait_runtime */ struct sched_entity { - long wait_runtime; - unsigned long delta_fair_run; - unsigned long delta_fair_sleep; - unsigned long delta_exec; - s64 fair_key; struct load_weight load; /* for load-balancing */ struct rb_node run_node; unsigned int on_rq; + int peer_preempt; u64 exec_start; u64 sum_exec_runtime; + u64 vruntime; u64 prev_sum_exec_runtime; - u64 wait_start_fair; - u64 sleep_start_fair; #ifdef CONFIG_SCHEDSTATS u64 wait_start; u64 wait_max; - s64 sum_wait_runtime; u64 sleep_start; u64 sleep_max; @@ -921,9 +932,25 @@ struct sched_entity { u64 block_start; u64 block_max; u64 exec_max; - - unsigned long wait_runtime_overruns; - unsigned long wait_runtime_underruns; + u64 slice_max; + + u64 nr_migrations; + u64 nr_migrations_cold; + u64 nr_failed_migrations_affine; + u64 nr_failed_migrations_running; + u64 nr_failed_migrations_hot; + u64 nr_forced_migrations; + u64 nr_forced2_migrations; + + u64 nr_wakeups; + u64 nr_wakeups_sync; + u64 nr_wakeups_migrate; + u64 nr_wakeups_local; + u64 nr_wakeups_remote; + u64 nr_wakeups_affine; + u64 nr_wakeups_affine_attempts; + u64 nr_wakeups_passive; + u64 nr_wakeups_idle; #endif #ifdef CONFIG_FAIR_GROUP_SCHED @@ -952,7 +979,7 @@ struct task_struct { int prio, static_prio, normal_prio; struct list_head run_list; - struct sched_class *sched_class; + const struct sched_class *sched_class; struct sched_entity se; #ifdef CONFIG_PREEMPT_NOTIFIERS @@ -1023,6 +1050,7 @@ struct task_struct { unsigned int rt_priority; cputime_t utime, stime; + cputime_t gtime; unsigned long nvcsw, nivcsw; /* context switch counts */ struct timespec start_time; /* monotonic time */ struct timespec real_start_time; /* boot based time */ @@ -1314,6 +1342,7 @@ static inline void put_task_struct(struct task_struct *t) #define PF_STARTING 0x00000002 /* being created */ #define PF_EXITING 0x00000004 /* getting shut down */ #define PF_EXITPIDONE 0x00000008 /* pi exit done on shut down */ +#define PF_VCPU 0x00000010 /* I'm a virtual CPU */ #define PF_FORKNOEXEC 0x00000040 /* forked but didn't exec */ #define PF_SUPERPRIV 0x00000100 /* used super-user privileges */ #define PF_DUMPCORE 0x00000200 /* dumped core */ @@ -1401,15 +1430,17 @@ static inline void idle_task_exit(void) {} extern void sched_idle_next(void); +#ifdef CONFIG_SCHED_DEBUG extern unsigned int sysctl_sched_latency; -extern unsigned int sysctl_sched_min_granularity; +extern unsigned int sysctl_sched_nr_latency; extern unsigned int sysctl_sched_wakeup_granularity; extern unsigned int sysctl_sched_batch_wakeup_granularity; -extern unsigned int sysctl_sched_stat_granularity; -extern unsigned int sysctl_sched_runtime_limit; -extern unsigned int sysctl_sched_compat_yield; extern unsigned int sysctl_sched_child_runs_first; extern unsigned int sysctl_sched_features; +extern unsigned int sysctl_sched_migration_cost; +#endif + +extern unsigned int sysctl_sched_compat_yield; #ifdef CONFIG_RT_MUTEXES extern int rt_mutex_getprio(struct task_struct *p); @@ -1843,6 +1874,18 @@ extern int sched_mc_power_savings, sched_smt_power_savings; extern void normalize_rt_tasks(void); +#ifdef CONFIG_FAIR_GROUP_SCHED + +extern struct task_group init_task_group; + +extern struct task_group *sched_create_group(void); +extern void sched_destroy_group(struct task_group *tg); +extern void sched_move_task(struct task_struct *tsk); +extern int sched_group_set_shares(struct task_group *tg, unsigned long shares); +extern unsigned long sched_group_shares(struct task_group *tg); + +#endif + #ifdef CONFIG_TASK_XACCT static inline void add_rchar(struct task_struct *tsk, ssize_t amt) { diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index 3699dff7db8f..bd7a6b0a87af 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -136,16 +136,6 @@ sunrpc_cache_update(struct cache_detail *detail, struct cache_head *new, struct cache_head *old, int hash); -#define cache_for_each(pos, detail, index, member) \ - for (({read_lock(&(detail)->hash_lock); index = (detail)->hash_size;}) ; \ - ({if (index==0)read_unlock(&(detail)->hash_lock); index--;}); \ - ) \ - for (pos = container_of((detail)->hash_table[index], typeof(*pos), member); \ - &pos->member; \ - pos = container_of(pos->member.next, typeof(*pos), member)) - - - extern void cache_clean_deferred(void *owner); static inline struct cache_head *cache_get(struct cache_head *h) diff --git a/include/linux/topology.h b/include/linux/topology.h index 525d437b1253..47729f18bfdf 100644 --- a/include/linux/topology.h +++ b/include/linux/topology.h @@ -159,15 +159,14 @@ .imbalance_pct = 125, \ .cache_nice_tries = 1, \ .busy_idx = 2, \ - .idle_idx = 0, \ - .newidle_idx = 0, \ + .idle_idx = 1, \ + .newidle_idx = 2, \ .wake_idx = 1, \ .forkexec_idx = 1, \ .flags = SD_LOAD_BALANCE \ | SD_BALANCE_NEWIDLE \ | SD_BALANCE_EXEC \ | SD_WAKE_AFFINE \ - | SD_WAKE_IDLE \ | BALANCE_FOR_PKG_POWER,\ .last_balance = jiffies, \ .balance_interval = 1, \ diff --git a/include/scsi/libsrp.h b/include/scsi/libsrp.h index d143171896ae..ba615e4c1d7c 100644 --- a/include/scsi/libsrp.h +++ b/include/scsi/libsrp.h @@ -59,7 +59,7 @@ extern void srp_target_free(struct srp_target *); extern struct iu_entry *srp_iu_get(struct srp_target *); extern void srp_iu_put(struct iu_entry *); -extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64); +extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64, u64); extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *, srp_rdma_t, int, int); diff --git a/include/scsi/scsi_cmnd.h b/include/scsi/scsi_cmnd.h index 53e170586c26..65ab5145a09b 100644 --- a/include/scsi/scsi_cmnd.h +++ b/include/scsi/scsi_cmnd.h @@ -33,20 +33,17 @@ struct scsi_cmnd { struct list_head list; /* scsi_cmnd participates in queue lists */ struct list_head eh_entry; /* entry for the host eh_cmd_q */ int eh_eflags; /* Used by error handlr */ - void (*done) (struct scsi_cmnd *); /* Mid-level done function */ /* * A SCSI Command is assigned a nonzero serial_number before passed * to the driver's queue command function. The serial_number is * cleared when scsi_done is entered indicating that the command - * has been completed. It currently doesn't have much use other - * than printk's. Some lldd's use this number for other purposes. - * It's almost certain that such usages are either incorrect or - * meaningless. Please kill all usages other than printk's. Also, - * as this number is always identical to ->pid, please convert - * printk's to use ->pid, so that we can kill this field. + * has been completed. It is a bug for LLDDs to use this number + * for purposes other than printk (and even that is only useful + * for debugging). */ unsigned long serial_number; + /* * This is set to jiffies as it was when the command was first * allocated. It is used to time how long the command has @@ -116,7 +113,6 @@ struct scsi_cmnd { int result; /* Status code from lower level driver */ unsigned char tag; /* SCSI-II queued command tag */ - unsigned long pid; /* Process ID, starts at 0. Unique per host. */ }; extern struct scsi_cmnd *scsi_get_command(struct scsi_device *, gfp_t); @@ -124,7 +120,6 @@ extern struct scsi_cmnd *__scsi_get_command(struct Scsi_Host *, gfp_t); extern void scsi_put_command(struct scsi_cmnd *); extern void __scsi_put_command(struct Scsi_Host *, struct scsi_cmnd *, struct device *); -extern void scsi_io_completion(struct scsi_cmnd *, unsigned int); extern void scsi_finish_command(struct scsi_cmnd *cmd); extern void scsi_req_abort_cmd(struct scsi_cmnd *cmd); diff --git a/include/scsi/scsi_dbg.h b/include/scsi/scsi_dbg.h index 5a43a4cd96c6..e89844cc2cd3 100644 --- a/include/scsi/scsi_dbg.h +++ b/include/scsi/scsi_dbg.h @@ -9,6 +9,8 @@ extern void __scsi_print_command(unsigned char *); extern void scsi_show_extd_sense(unsigned char, unsigned char); extern void scsi_show_sense_hdr(struct scsi_sense_hdr *); extern void scsi_print_sense_hdr(const char *, struct scsi_sense_hdr *); +extern void scsi_cmd_print_sense_hdr(struct scsi_cmnd *, const char *, + struct scsi_sense_hdr *); extern void scsi_print_sense(char *, struct scsi_cmnd *); extern void __scsi_print_sense(const char *name, const unsigned char *sense_buffer, diff --git a/include/scsi/scsi_driver.h b/include/scsi/scsi_driver.h index 3465f31a21c4..1f5ca7f62116 100644 --- a/include/scsi/scsi_driver.h +++ b/include/scsi/scsi_driver.h @@ -5,14 +5,17 @@ struct module; struct scsi_cmnd; +struct scsi_device; +struct request; +struct request_queue; struct scsi_driver { struct module *owner; struct device_driver gendrv; - int (*init_command)(struct scsi_cmnd *); void (*rescan)(struct device *); + int (*done)(struct scsi_cmnd *); }; #define to_scsi_driver(drv) \ container_of((drv), struct scsi_driver, gendrv) @@ -25,4 +28,9 @@ extern int scsi_register_interface(struct class_interface *); #define scsi_unregister_interface(intf) \ class_interface_unregister(intf) +int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req); +int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req); +int scsi_prep_state_check(struct scsi_device *sdev, struct request *req); +int scsi_prep_return(struct request_queue *q, struct request *req, int ret); + #endif /* _SCSI_SCSI_DRIVER_H */ diff --git a/include/scsi/scsi_eh.h b/include/scsi/scsi_eh.h index c5c0f6762a01..44224ba4dd90 100644 --- a/include/scsi/scsi_eh.h +++ b/include/scsi/scsi_eh.h @@ -1,7 +1,7 @@ #ifndef _SCSI_SCSI_EH_H #define _SCSI_SCSI_EH_H -struct scsi_cmnd; +#include <scsi/scsi_cmnd.h> struct scsi_device; struct Scsi_Host; @@ -65,4 +65,25 @@ extern int scsi_get_sense_info_fld(const u8 * sense_buffer, int sb_len, extern int scsi_reset_provider(struct scsi_device *, int); +struct scsi_eh_save { + int result; + enum dma_data_direction data_direction; + unsigned char cmd_len; + unsigned char cmnd[MAX_COMMAND_SIZE]; + + void *buffer; + unsigned bufflen; + unsigned short use_sg; + int resid; + + struct scatterlist sense_sgl; +}; + +extern void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, + struct scsi_eh_save *ses, unsigned char *cmnd, + int cmnd_size, unsigned sense_bytes); + +extern void scsi_eh_restore_cmnd(struct scsi_cmnd* scmd, + struct scsi_eh_save *ses); + #endif /* _SCSI_SCSI_EH_H */ diff --git a/include/scsi/scsi_host.h b/include/scsi/scsi_host.h index 3b8a6a85c2f8..7d210cd6c38d 100644 --- a/include/scsi/scsi_host.h +++ b/include/scsi/scsi_host.h @@ -32,6 +32,9 @@ struct blk_queue_tags; #define SG_NONE 0 #define SG_ALL 0xff +#define MODE_UNKNOWN 0x00 +#define MODE_INITIATOR 0x01 +#define MODE_TARGET 0x02 #define DISABLE_CLUSTERING 0 #define ENABLE_CLUSTERING 1 @@ -145,9 +148,6 @@ struct scsi_host_template { int (* transfer_response)(struct scsi_cmnd *, void (*done)(struct scsi_cmnd *)); - /* Used as callback for the completion of task management request. */ - int (* tsk_mgmt_response)(u64 mid, int result); - /* * This is an error handling strategy routine. You don't need to * define one of these if you don't want to - there is a default @@ -408,6 +408,11 @@ struct scsi_host_template { unsigned char present; /* + * This specifies the mode that a LLD supports. + */ + unsigned supported_mode:2; + + /* * true if this host adapter uses unchecked DMA onto an ISA bus. */ unsigned unchecked_isa_dma:1; @@ -575,8 +580,9 @@ struct Scsi_Host { * Used to assign serial numbers to the cmds. * Protected by the host lock. */ - unsigned long cmd_serial_number, cmd_pid; + unsigned long cmd_serial_number; + unsigned active_mode:2; unsigned unchecked_isa_dma:1; unsigned use_clustering:1; unsigned use_blk_tcq:1; diff --git a/include/scsi/scsi_tgt.h b/include/scsi/scsi_tgt.h index 4f4427937af2..d0fefb96158f 100644 --- a/include/scsi/scsi_tgt.h +++ b/include/scsi/scsi_tgt.h @@ -11,9 +11,11 @@ struct scsi_lun; extern struct Scsi_Host *scsi_tgt_cmd_to_host(struct scsi_cmnd *); extern int scsi_tgt_alloc_queue(struct Scsi_Host *); extern void scsi_tgt_free_queue(struct Scsi_Host *); -extern int scsi_tgt_queue_command(struct scsi_cmnd *, struct scsi_lun *, u64); -extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, int, u64, struct scsi_lun *, - void *); +extern int scsi_tgt_queue_command(struct scsi_cmnd *, u64, struct scsi_lun *, u64); +extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, u64, int, u64, + struct scsi_lun *, void *); extern struct scsi_cmnd *scsi_host_get_command(struct Scsi_Host *, enum dma_data_direction, gfp_t); extern void scsi_host_put_command(struct Scsi_Host *, struct scsi_cmnd *); +extern int scsi_tgt_it_nexus_create(struct Scsi_Host *, u64, char *); +extern int scsi_tgt_it_nexus_destroy(struct Scsi_Host *, u64); diff --git a/include/scsi/scsi_tgt_if.h b/include/scsi/scsi_tgt_if.h index 4cf9dff29a2f..f2ee7c238a45 100644 --- a/include/scsi/scsi_tgt_if.h +++ b/include/scsi/scsi_tgt_if.h @@ -23,13 +23,15 @@ #define __SCSI_TARGET_IF_H /* user -> kernel */ -#define TGT_UEVENT_CMD_RSP 0x0001 -#define TGT_UEVENT_TSK_MGMT_RSP 0x0002 +#define TGT_UEVENT_CMD_RSP 0x0001 +#define TGT_UEVENT_IT_NEXUS_RSP 0x0002 +#define TGT_UEVENT_TSK_MGMT_RSP 0x0003 /* kernel -> user */ -#define TGT_KEVENT_CMD_REQ 0x1001 -#define TGT_KEVENT_CMD_DONE 0x1002 -#define TGT_KEVENT_TSK_MGMT_REQ 0x1003 +#define TGT_KEVENT_CMD_REQ 0x1001 +#define TGT_KEVENT_CMD_DONE 0x1002 +#define TGT_KEVENT_IT_NEXUS_REQ 0x1003 +#define TGT_KEVENT_TSK_MGMT_REQ 0x1004 struct tgt_event_hdr { uint16_t version; @@ -46,6 +48,7 @@ struct tgt_event { struct { int host_no; int result; + aligned_u64 itn_id; aligned_u64 tag; aligned_u64 uaddr; aligned_u64 sense_uaddr; @@ -55,15 +58,22 @@ struct tgt_event { } cmd_rsp; struct { int host_no; - aligned_u64 mid; int result; + aligned_u64 itn_id; + aligned_u64 mid; } tsk_mgmt_rsp; - + struct { + __s32 host_no; + __s32 result; + aligned_u64 itn_id; + __u32 function; + } it_nexus_rsp; /* kernel -> user */ struct { int host_no; uint32_t data_len; + aligned_u64 itn_id; uint8_t scb[16]; uint8_t lun[8]; int attribute; @@ -71,16 +81,25 @@ struct tgt_event { } cmd_req; struct { int host_no; - aligned_u64 tag; int result; + aligned_u64 itn_id; + aligned_u64 tag; } cmd_done; struct { int host_no; int function; + aligned_u64 itn_id; aligned_u64 tag; uint8_t lun[8]; aligned_u64 mid; } tsk_mgmt_req; + struct { + __s32 host_no; + __u32 function; + aligned_u64 itn_id; + __u32 max_cmds; + __u8 initiator_id[16]; + } it_nexus_req; } p; } __attribute__ ((aligned (sizeof(uint64_t)))); diff --git a/include/scsi/scsi_transport.h b/include/scsi/scsi_transport.h index 3c18baa65a72..0dfef752f0e2 100644 --- a/include/scsi/scsi_transport.h +++ b/include/scsi/scsi_transport.h @@ -65,6 +65,18 @@ struct scsi_transport_template { * EH_NOT_HANDLED Begin normal error recovery */ enum scsi_eh_timer_return (* eh_timed_out)(struct scsi_cmnd *); + + /* + * Used as callback for the completion of i_t_nexus request + * for target drivers. + */ + int (* it_nexus_response)(struct Scsi_Host *, u64, int); + + /* + * Used as callback for the completion of task management + * request for target drivers. + */ + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); }; #define transport_class_to_shost(tc) \ diff --git a/include/scsi/scsi_transport_fc.h b/include/scsi/scsi_transport_fc.h index a0d80bcaa93d..e466d886e192 100644 --- a/include/scsi/scsi_transport_fc.h +++ b/include/scsi/scsi_transport_fc.h @@ -589,6 +589,10 @@ struct fc_function_template { int (*vport_disable)(struct fc_vport *, bool); int (*vport_delete)(struct fc_vport *); + /* target-mode drivers' functions */ + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); + int (* it_nexus_response)(struct Scsi_Host *, u64, int); + /* allocation lengths for host-specific data */ u32 dd_fcrport_size; u32 dd_fcvport_size; @@ -632,6 +636,8 @@ struct fc_function_template { unsigned long show_host_fabric_name:1; unsigned long show_host_symbolic_name:1; unsigned long show_host_system_hostname:1; + + unsigned long disable_target_scan:1; }; diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 706c0cd36c14..7ff6199cbd55 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -24,6 +24,8 @@ #define SCSI_TRANSPORT_ISCSI_H #include <linux/device.h> +#include <linux/list.h> +#include <linux/mutex.h> #include <scsi/iscsi_if.h> struct scsi_transport_template; diff --git a/include/scsi/scsi_transport_srp.h b/include/scsi/scsi_transport_srp.h new file mode 100644 index 000000000000..9c60ca1c08c5 --- /dev/null +++ b/include/scsi/scsi_transport_srp.h @@ -0,0 +1,39 @@ +#ifndef SCSI_TRANSPORT_SRP_H +#define SCSI_TRANSPORT_SRP_H + +#include <linux/transport_class.h> +#include <linux/types.h> +#include <linux/mutex.h> + +#define SRP_RPORT_ROLE_INITIATOR 0 +#define SRP_RPORT_ROLE_TARGET 1 + +struct srp_rport_identifiers { + u8 port_id[16]; + u8 roles; +}; + +struct srp_rport { + struct device dev; + + u8 port_id[16]; + u8 roles; +}; + +struct srp_function_template { + /* for target drivers */ + int (* tsk_mgmt_response)(struct Scsi_Host *, u64, u64, int); + int (* it_nexus_response)(struct Scsi_Host *, u64, int); +}; + +extern struct scsi_transport_template * +srp_attach_transport(struct srp_function_template *); +extern void srp_release_transport(struct scsi_transport_template *); + +extern struct srp_rport *srp_rport_add(struct Scsi_Host *, + struct srp_rport_identifiers *); +extern void srp_rport_del(struct srp_rport *); + +extern void srp_remove_host(struct Scsi_Host *); + +#endif diff --git a/include/scsi/sd.h b/include/scsi/sd.h index ce02ad1f5185..f7513313ef0d 100644 --- a/include/scsi/sd.h +++ b/include/scsi/sd.h @@ -47,20 +47,6 @@ struct scsi_disk { }; #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,cdev) -static int sd_revalidate_disk(struct gendisk *disk); -static void sd_rw_intr(struct scsi_cmnd * SCpnt); -static int sd_probe(struct device *); -static int sd_remove(struct device *); -static void sd_shutdown(struct device *dev); -static int sd_suspend(struct device *dev, pm_message_t state); -static int sd_resume(struct device *dev); -static void sd_rescan(struct device *); -static int sd_init_command(struct scsi_cmnd *); -static void sd_read_capacity(struct scsi_disk *sdkp, unsigned char *buffer); -static void scsi_disk_release(struct class_device *cdev); -static void sd_print_sense_hdr(struct scsi_disk *, struct scsi_sense_hdr *); -static void sd_print_result(struct scsi_disk *, int); - #define sd_printk(prefix, sdsk, fmt, a...) \ (sdsk)->disk ? \ sdev_printk(prefix, (sdsk)->device, "[%s] " fmt, \ diff --git a/init/Kconfig b/init/Kconfig index d54d0cadcc06..54f31a191b88 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -281,6 +281,27 @@ config CPUSETS Say N if unsure. +config FAIR_GROUP_SCHED + bool "Fair group CPU scheduler" + default y + depends on EXPERIMENTAL + help + This feature lets CPU scheduler recognize task groups and control CPU + bandwidth allocation to such task groups. + +choice + depends on FAIR_GROUP_SCHED + prompt "Basis for grouping tasks" + default FAIR_USER_SCHED + +config FAIR_USER_SCHED + bool "user id" + help + This option will choose userid as the basis for grouping + tasks, thus providing equal CPU bandwidth to each user. + +endchoice + config SYSFS_DEPRECATED bool "Create deprecated sysfs files" default y diff --git a/kernel/delayacct.c b/kernel/delayacct.c index 81e697829633..09e9574eeb26 100644 --- a/kernel/delayacct.c +++ b/kernel/delayacct.c @@ -119,7 +119,7 @@ int __delayacct_add_tsk(struct taskstats *d, struct task_struct *tsk) * No locking available for sched_info (and too expensive to add one) * Mitigate by taking snapshot of values */ - t1 = tsk->sched_info.pcnt; + t1 = tsk->sched_info.pcount; t2 = tsk->sched_info.run_delay; t3 = tsk->sched_info.cpu_time; diff --git a/kernel/exit.c b/kernel/exit.c index 993369ee94d1..7f7959de4a87 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -111,6 +111,7 @@ static void __exit_signal(struct task_struct *tsk) */ sig->utime = cputime_add(sig->utime, tsk->utime); sig->stime = cputime_add(sig->stime, tsk->stime); + sig->gtime = cputime_add(sig->gtime, tsk->gtime); sig->min_flt += tsk->min_flt; sig->maj_flt += tsk->maj_flt; sig->nvcsw += tsk->nvcsw; @@ -1242,6 +1243,11 @@ static int wait_task_zombie(struct task_struct *p, int noreap, cputime_add(p->stime, cputime_add(sig->stime, sig->cstime))); + psig->cgtime = + cputime_add(psig->cgtime, + cputime_add(p->gtime, + cputime_add(sig->gtime, + sig->cgtime))); psig->cmin_flt += p->min_flt + sig->min_flt + sig->cmin_flt; psig->cmaj_flt += diff --git a/kernel/fork.c b/kernel/fork.c index 5e67f90a1694..3fc3c1383912 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -877,6 +877,8 @@ static inline int copy_signal(unsigned long clone_flags, struct task_struct * ts sig->tty_old_pgrp = NULL; sig->utime = sig->stime = sig->cutime = sig->cstime = cputime_zero; + sig->gtime = cputime_zero; + sig->cgtime = cputime_zero; sig->nvcsw = sig->nivcsw = sig->cnvcsw = sig->cnivcsw = 0; sig->min_flt = sig->maj_flt = sig->cmin_flt = sig->cmaj_flt = 0; sig->inblock = sig->oublock = sig->cinblock = sig->coublock = 0; @@ -1045,6 +1047,7 @@ static struct task_struct *copy_process(unsigned long clone_flags, p->utime = cputime_zero; p->stime = cputime_zero; + p->gtime = cputime_zero; #ifdef CONFIG_TASK_XACCT p->rchar = 0; /* I/O counter: bytes read */ diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c index d0e5c48e18c7..6046939d0804 100644 --- a/kernel/ksysfs.c +++ b/kernel/ksysfs.c @@ -14,6 +14,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/kexec.h> +#include <linux/sched.h> #define KERNEL_ATTR_RO(_name) \ static struct subsys_attribute _name##_attr = __ATTR_RO(_name) @@ -116,6 +117,13 @@ static int __init ksysfs_init(void) ¬es_attr); } + /* + * Create "/sys/kernel/uids" directory and corresponding root user's + * directory under it. + */ + if (!error) + error = uids_kobject_init(); + return error; } diff --git a/kernel/sched.c b/kernel/sched.c index 6c10fa796ca0..bba57adb9504 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -96,7 +96,7 @@ unsigned long long __attribute__((weak)) sched_clock(void) /* * Some helpers for converting nanosecond timing to jiffy resolution */ -#define NS_TO_JIFFIES(TIME) ((TIME) / (1000000000 / HZ)) +#define NS_TO_JIFFIES(TIME) ((unsigned long)(TIME) / (1000000000 / HZ)) #define JIFFIES_TO_NS(TIME) ((TIME) * (1000000000 / HZ)) #define NICE_0_LOAD SCHED_LOAD_SCALE @@ -105,11 +105,9 @@ unsigned long long __attribute__((weak)) sched_clock(void) /* * These are the 'tuning knobs' of the scheduler: * - * Minimum timeslice is 5 msecs (or 1 jiffy, whichever is larger), - * default timeslice is 100 msecs, maximum timeslice is 800 msecs. + * default timeslice is 100 msecs (used only for SCHED_RR tasks). * Timeslices get refilled after they expire. */ -#define MIN_TIMESLICE max(5 * HZ / 1000, 1) #define DEF_TIMESLICE (100 * HZ / 1000) #ifdef CONFIG_SMP @@ -133,24 +131,6 @@ static inline void sg_inc_cpu_power(struct sched_group *sg, u32 val) } #endif -#define SCALE_PRIO(x, prio) \ - max(x * (MAX_PRIO - prio) / (MAX_USER_PRIO / 2), MIN_TIMESLICE) - -/* - * static_prio_timeslice() scales user-nice values [ -20 ... 0 ... 19 ] - * to time slice values: [800ms ... 100ms ... 5ms] - */ -static unsigned int static_prio_timeslice(int static_prio) -{ - if (static_prio == NICE_TO_PRIO(19)) - return 1; - - if (static_prio < NICE_TO_PRIO(0)) - return SCALE_PRIO(DEF_TIMESLICE * 4, static_prio); - else - return SCALE_PRIO(DEF_TIMESLICE, static_prio); -} - static inline int rt_policy(int policy) { if (unlikely(policy == SCHED_FIFO) || unlikely(policy == SCHED_RR)) @@ -171,31 +151,91 @@ struct rt_prio_array { struct list_head queue[MAX_RT_PRIO]; }; -struct load_stat { - struct load_weight load; - u64 load_update_start, load_update_last; - unsigned long delta_fair, delta_exec, delta_stat; +#ifdef CONFIG_FAIR_GROUP_SCHED + +struct cfs_rq; + +/* task group related information */ +struct task_group { + /* schedulable entities of this group on each cpu */ + struct sched_entity **se; + /* runqueue "owned" by this group on each cpu */ + struct cfs_rq **cfs_rq; + unsigned long shares; + /* spinlock to serialize modification to shares */ + spinlock_t lock; +}; + +/* Default task group's sched entity on each cpu */ +static DEFINE_PER_CPU(struct sched_entity, init_sched_entity); +/* Default task group's cfs_rq on each cpu */ +static DEFINE_PER_CPU(struct cfs_rq, init_cfs_rq) ____cacheline_aligned_in_smp; + +static struct sched_entity *init_sched_entity_p[NR_CPUS]; +static struct cfs_rq *init_cfs_rq_p[NR_CPUS]; + +/* Default task group. + * Every task in system belong to this group at bootup. + */ +struct task_group init_task_group = { + .se = init_sched_entity_p, + .cfs_rq = init_cfs_rq_p, }; +#ifdef CONFIG_FAIR_USER_SCHED +# define INIT_TASK_GRP_LOAD 2*NICE_0_LOAD +#else +# define INIT_TASK_GRP_LOAD NICE_0_LOAD +#endif + +static int init_task_group_load = INIT_TASK_GRP_LOAD; + +/* return group to which a task belongs */ +static inline struct task_group *task_group(struct task_struct *p) +{ + struct task_group *tg; + +#ifdef CONFIG_FAIR_USER_SCHED + tg = p->user->tg; +#else + tg = &init_task_group; +#endif + + return tg; +} + +/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */ +static inline void set_task_cfs_rq(struct task_struct *p) +{ + p->se.cfs_rq = task_group(p)->cfs_rq[task_cpu(p)]; + p->se.parent = task_group(p)->se[task_cpu(p)]; +} + +#else + +static inline void set_task_cfs_rq(struct task_struct *p) { } + +#endif /* CONFIG_FAIR_GROUP_SCHED */ + /* CFS-related fields in a runqueue */ struct cfs_rq { struct load_weight load; unsigned long nr_running; - s64 fair_clock; u64 exec_clock; - s64 wait_runtime; - u64 sleeper_bonus; - unsigned long wait_runtime_overruns, wait_runtime_underruns; + u64 min_vruntime; struct rb_root tasks_timeline; struct rb_node *rb_leftmost; struct rb_node *rb_load_balance_curr; -#ifdef CONFIG_FAIR_GROUP_SCHED /* 'curr' points to currently running entity on this cfs_rq. * It is set to NULL otherwise (i.e when none are currently running). */ struct sched_entity *curr; + + unsigned long nr_spread_over; + +#ifdef CONFIG_FAIR_GROUP_SCHED struct rq *rq; /* cpu runqueue to which this cfs_rq is attached */ /* leaf cfs_rqs are those that hold tasks (lowest schedulable entity in @@ -206,6 +246,8 @@ struct cfs_rq { * list is used during load balance. */ struct list_head leaf_cfs_rq_list; /* Better name : task_cfs_rq_list? */ + struct task_group *tg; /* group that "owns" this runqueue */ + struct rcu_head rcu; #endif }; @@ -237,7 +279,7 @@ struct rq { #ifdef CONFIG_NO_HZ unsigned char in_nohz_recently; #endif - struct load_stat ls; /* capture load from *all* tasks on this cpu */ + struct load_weight load; /* capture load from *all* tasks on this cpu */ unsigned long nr_load_updates; u64 nr_switches; @@ -289,16 +331,19 @@ struct rq { unsigned long yld_exp_empty; unsigned long yld_act_empty; unsigned long yld_both_empty; - unsigned long yld_cnt; + unsigned long yld_count; /* schedule() stats */ unsigned long sched_switch; - unsigned long sched_cnt; + unsigned long sched_count; unsigned long sched_goidle; /* try_to_wake_up() stats */ - unsigned long ttwu_cnt; + unsigned long ttwu_count; unsigned long ttwu_local; + + /* BKL stats */ + unsigned long bkl_count; #endif struct lock_class_key rq_lock_key; }; @@ -383,6 +428,37 @@ static void update_rq_clock(struct rq *rq) #define cpu_curr(cpu) (cpu_rq(cpu)->curr) /* + * Tunables that become constants when CONFIG_SCHED_DEBUG is off: + */ +#ifdef CONFIG_SCHED_DEBUG +# define const_debug __read_mostly +#else +# define const_debug static const +#endif + +/* + * Debugging: various feature bits + */ +enum { + SCHED_FEAT_NEW_FAIR_SLEEPERS = 1, + SCHED_FEAT_START_DEBIT = 2, + SCHED_FEAT_TREE_AVG = 4, + SCHED_FEAT_APPROX_AVG = 8, + SCHED_FEAT_WAKEUP_PREEMPT = 16, + SCHED_FEAT_PREEMPT_RESTRICT = 32, +}; + +const_debug unsigned int sysctl_sched_features = + SCHED_FEAT_NEW_FAIR_SLEEPERS *1 | + SCHED_FEAT_START_DEBIT *1 | + SCHED_FEAT_TREE_AVG *0 | + SCHED_FEAT_APPROX_AVG *0 | + SCHED_FEAT_WAKEUP_PREEMPT *1 | + SCHED_FEAT_PREEMPT_RESTRICT *1; + +#define sched_feat(x) (sysctl_sched_features & SCHED_FEAT_##x) + +/* * For kernel-internal use: high-speed (but slightly incorrect) per-cpu * clock constructed from sched_clock(): */ @@ -400,18 +476,7 @@ unsigned long long cpu_clock(int cpu) return now; } - -#ifdef CONFIG_FAIR_GROUP_SCHED -/* Change a task's ->cfs_rq if it moves across CPUs */ -static inline void set_task_cfs_rq(struct task_struct *p) -{ - p->se.cfs_rq = &task_rq(p)->cfs; -} -#else -static inline void set_task_cfs_rq(struct task_struct *p) -{ -} -#endif +EXPORT_SYMBOL_GPL(cpu_clock); #ifndef prepare_arch_switch # define prepare_arch_switch(next) do { } while (0) @@ -497,16 +562,13 @@ static inline void finish_lock_switch(struct rq *rq, struct task_struct *prev) static inline struct rq *__task_rq_lock(struct task_struct *p) __acquires(rq->lock) { - struct rq *rq; - -repeat_lock_task: - rq = task_rq(p); - spin_lock(&rq->lock); - if (unlikely(rq != task_rq(p))) { + for (;;) { + struct rq *rq = task_rq(p); + spin_lock(&rq->lock); + if (likely(rq == task_rq(p))) + return rq; spin_unlock(&rq->lock); - goto repeat_lock_task; } - return rq; } /* @@ -519,18 +581,17 @@ static struct rq *task_rq_lock(struct task_struct *p, unsigned long *flags) { struct rq *rq; -repeat_lock_task: - local_irq_save(*flags); - rq = task_rq(p); - spin_lock(&rq->lock); - if (unlikely(rq != task_rq(p))) { + for (;;) { + local_irq_save(*flags); + rq = task_rq(p); + spin_lock(&rq->lock); + if (likely(rq == task_rq(p))) + return rq; spin_unlock_irqrestore(&rq->lock, *flags); - goto repeat_lock_task; } - return rq; } -static inline void __task_rq_unlock(struct rq *rq) +static void __task_rq_unlock(struct rq *rq) __releases(rq->lock) { spin_unlock(&rq->lock); @@ -545,7 +606,7 @@ static inline void task_rq_unlock(struct rq *rq, unsigned long *flags) /* * this_rq_lock - lock this runqueue and disable interrupts. */ -static inline struct rq *this_rq_lock(void) +static struct rq *this_rq_lock(void) __acquires(rq->lock) { struct rq *rq; @@ -645,19 +706,6 @@ static inline void resched_task(struct task_struct *p) } #endif -static u64 div64_likely32(u64 divident, unsigned long divisor) -{ -#if BITS_PER_LONG == 32 - if (likely(divident <= 0xffffffffULL)) - return (u32)divident / divisor; - do_div(divident, divisor); - - return divident; -#else - return divident / divisor; -#endif -} - #if BITS_PER_LONG == 32 # define WMULT_CONST (~0UL) #else @@ -699,16 +747,14 @@ calc_delta_fair(unsigned long delta_exec, struct load_weight *lw) return calc_delta_mine(delta_exec, NICE_0_LOAD, lw); } -static void update_load_add(struct load_weight *lw, unsigned long inc) +static inline void update_load_add(struct load_weight *lw, unsigned long inc) { lw->weight += inc; - lw->inv_weight = 0; } -static void update_load_sub(struct load_weight *lw, unsigned long dec) +static inline void update_load_sub(struct load_weight *lw, unsigned long dec) { lw->weight -= dec; - lw->inv_weight = 0; } /* @@ -784,29 +830,20 @@ static int balance_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest, int *this_best_prio, struct rq_iterator *iterator); #include "sched_stats.h" -#include "sched_rt.c" -#include "sched_fair.c" #include "sched_idletask.c" +#include "sched_fair.c" +#include "sched_rt.c" #ifdef CONFIG_SCHED_DEBUG # include "sched_debug.c" #endif #define sched_class_highest (&rt_sched_class) -static void __update_curr_load(struct rq *rq, struct load_stat *ls) -{ - if (rq->curr != rq->idle && ls->load.weight) { - ls->delta_exec += ls->delta_stat; - ls->delta_fair += calc_delta_fair(ls->delta_stat, &ls->load); - ls->delta_stat = 0; - } -} - /* * Update delta_exec, delta_fair fields for rq. * * delta_fair clock advances at a rate inversely proportional to - * total load (rq->ls.load.weight) on the runqueue, while + * total load (rq->load.weight) on the runqueue, while * delta_exec advances at the same rate as wall-clock (provided * cpu is not idle). * @@ -814,35 +851,17 @@ static void __update_curr_load(struct rq *rq, struct load_stat *ls) * runqueue over any given interval. This (smoothened) load is used * during load balance. * - * This function is called /before/ updating rq->ls.load + * This function is called /before/ updating rq->load * and when switching tasks. */ -static void update_curr_load(struct rq *rq) -{ - struct load_stat *ls = &rq->ls; - u64 start; - - start = ls->load_update_start; - ls->load_update_start = rq->clock; - ls->delta_stat += rq->clock - start; - /* - * Stagger updates to ls->delta_fair. Very frequent updates - * can be expensive. - */ - if (ls->delta_stat >= sysctl_sched_stat_granularity) - __update_curr_load(rq, ls); -} - static inline void inc_load(struct rq *rq, const struct task_struct *p) { - update_curr_load(rq); - update_load_add(&rq->ls.load, p->se.load.weight); + update_load_add(&rq->load, p->se.load.weight); } static inline void dec_load(struct rq *rq, const struct task_struct *p) { - update_curr_load(rq); - update_load_sub(&rq->ls.load, p->se.load.weight); + update_load_sub(&rq->load, p->se.load.weight); } static void inc_nr_running(struct task_struct *p, struct rq *rq) @@ -859,8 +878,6 @@ static void dec_nr_running(struct task_struct *p, struct rq *rq) static void set_load_weight(struct task_struct *p) { - p->se.wait_runtime = 0; - if (task_has_rt_policy(p)) { p->se.load.weight = prio_to_weight[0] * 2; p->se.load.inv_weight = prio_to_wmult[0] >> 1; @@ -952,20 +969,6 @@ static void activate_task(struct rq *rq, struct task_struct *p, int wakeup) } /* - * activate_idle_task - move idle task to the _front_ of runqueue. - */ -static inline void activate_idle_task(struct task_struct *p, struct rq *rq) -{ - update_rq_clock(rq); - - if (p->state == TASK_UNINTERRUPTIBLE) - rq->nr_uninterruptible--; - - enqueue_task(rq, p, 0); - inc_nr_running(p, rq); -} - -/* * deactivate_task - remove a task from the runqueue. */ static void deactivate_task(struct rq *rq, struct task_struct *p, int sleep) @@ -989,32 +992,50 @@ inline int task_curr(const struct task_struct *p) /* Used instead of source_load when we know the type == 0 */ unsigned long weighted_cpuload(const int cpu) { - return cpu_rq(cpu)->ls.load.weight; + return cpu_rq(cpu)->load.weight; } static inline void __set_task_cpu(struct task_struct *p, unsigned int cpu) { #ifdef CONFIG_SMP task_thread_info(p)->cpu = cpu; - set_task_cfs_rq(p); #endif + set_task_cfs_rq(p); } #ifdef CONFIG_SMP +/* + * Is this task likely cache-hot: + */ +static inline int +task_hot(struct task_struct *p, u64 now, struct sched_domain *sd) +{ + s64 delta; + + if (p->sched_class != &fair_sched_class) + return 0; + + if (sysctl_sched_migration_cost == -1) + return 1; + if (sysctl_sched_migration_cost == 0) + return 0; + + delta = now - p->se.exec_start; + + return delta < (s64)sysctl_sched_migration_cost; +} + + void set_task_cpu(struct task_struct *p, unsigned int new_cpu) { int old_cpu = task_cpu(p); struct rq *old_rq = cpu_rq(old_cpu), *new_rq = cpu_rq(new_cpu); - u64 clock_offset, fair_clock_offset; + struct cfs_rq *old_cfsrq = task_cfs_rq(p), + *new_cfsrq = cpu_cfs_rq(old_cfsrq, new_cpu); + u64 clock_offset; clock_offset = old_rq->clock - new_rq->clock; - fair_clock_offset = old_rq->cfs.fair_clock - new_rq->cfs.fair_clock; - - if (p->se.wait_start_fair) - p->se.wait_start_fair -= fair_clock_offset; - if (p->se.sleep_start_fair) - p->se.sleep_start_fair -= fair_clock_offset; #ifdef CONFIG_SCHEDSTATS if (p->se.wait_start) @@ -1023,7 +1044,14 @@ void set_task_cpu(struct task_struct *p, unsigned int new_cpu) p->se.sleep_start -= clock_offset; if (p->se.block_start) p->se.block_start -= clock_offset; + if (old_cpu != new_cpu) { + schedstat_inc(p, se.nr_migrations); + if (task_hot(p, old_rq->clock, NULL)) + schedstat_inc(p, se.nr_forced2_migrations); + } #endif + p->se.vruntime -= old_cfsrq->min_vruntime - + new_cfsrq->min_vruntime; __set_task_cpu(p, new_cpu); } @@ -1078,69 +1106,71 @@ void wait_task_inactive(struct task_struct *p) int running, on_rq; struct rq *rq; -repeat: - /* - * We do the initial early heuristics without holding - * any task-queue locks at all. We'll only try to get - * the runqueue lock when things look like they will - * work out! - */ - rq = task_rq(p); + for (;;) { + /* + * We do the initial early heuristics without holding + * any task-queue locks at all. We'll only try to get + * the runqueue lock when things look like they will + * work out! + */ + rq = task_rq(p); - /* - * If the task is actively running on another CPU - * still, just relax and busy-wait without holding - * any locks. - * - * NOTE! Since we don't hold any locks, it's not - * even sure that "rq" stays as the right runqueue! - * But we don't care, since "task_running()" will - * return false if the runqueue has changed and p - * is actually now running somewhere else! - */ - while (task_running(rq, p)) - cpu_relax(); + /* + * If the task is actively running on another CPU + * still, just relax and busy-wait without holding + * any locks. + * + * NOTE! Since we don't hold any locks, it's not + * even sure that "rq" stays as the right runqueue! + * But we don't care, since "task_running()" will + * return false if the runqueue has changed and p + * is actually now running somewhere else! + */ + while (task_running(rq, p)) + cpu_relax(); - /* - * Ok, time to look more closely! We need the rq - * lock now, to be *sure*. If we're wrong, we'll - * just go back and repeat. - */ - rq = task_rq_lock(p, &flags); - running = task_running(rq, p); - on_rq = p->se.on_rq; - task_rq_unlock(rq, &flags); + /* + * Ok, time to look more closely! We need the rq + * lock now, to be *sure*. If we're wrong, we'll + * just go back and repeat. + */ + rq = task_rq_lock(p, &flags); + running = task_running(rq, p); + on_rq = p->se.on_rq; + task_rq_unlock(rq, &flags); - /* - * Was it really running after all now that we - * checked with the proper locks actually held? - * - * Oops. Go back and try again.. - */ - if (unlikely(running)) { - cpu_relax(); - goto repeat; - } + /* + * Was it really running after all now that we + * checked with the proper locks actually held? + * + * Oops. Go back and try again.. + */ + if (unlikely(running)) { + cpu_relax(); + continue; + } - /* - * It's not enough that it's not actively running, - * it must be off the runqueue _entirely_, and not - * preempted! - * - * So if it wa still runnable (but just not actively - * running right now), it's preempted, and we should - * yield - it could be a while. - */ - if (unlikely(on_rq)) { - yield(); - goto repeat; - } + /* + * It's not enough that it's not actively running, + * it must be off the runqueue _entirely_, and not + * preempted! + * + * So if it wa still runnable (but just not actively + * running right now), it's preempted, and we should + * yield - it could be a while. + */ + if (unlikely(on_rq)) { + schedule_timeout_uninterruptible(1); + continue; + } - /* - * Ahh, all good. It wasn't running, and it wasn't - * runnable, which means that it will never become - * running in the future either. We're all done! - */ + /* + * Ahh, all good. It wasn't running, and it wasn't + * runnable, which means that it will never become + * running in the future either. We're all done! + */ + break; + } } /*** @@ -1174,7 +1204,7 @@ void kick_process(struct task_struct *p) * We want to under-estimate the load of migration sources, to * balance conservatively. */ -static inline unsigned long source_load(int cpu, int type) +static unsigned long source_load(int cpu, int type) { struct rq *rq = cpu_rq(cpu); unsigned long total = weighted_cpuload(cpu); @@ -1189,7 +1219,7 @@ static inline unsigned long source_load(int cpu, int type) * Return a high guess at the load of a migration-target cpu weighted * according to the scheduling class and "nice" value. */ -static inline unsigned long target_load(int cpu, int type) +static unsigned long target_load(int cpu, int type) { struct rq *rq = cpu_rq(cpu); unsigned long total = weighted_cpuload(cpu); @@ -1231,7 +1261,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu) /* Skip over this group if it has no CPUs allowed */ if (!cpus_intersects(group->cpumask, p->cpus_allowed)) - goto nextgroup; + continue; local_group = cpu_isset(this_cpu, group->cpumask); @@ -1259,9 +1289,7 @@ find_idlest_group(struct sched_domain *sd, struct task_struct *p, int this_cpu) min_load = avg_load; idlest = group; } -nextgroup: - group = group->next; - } while (group != sd->groups); + } while (group = group->next, group != sd->groups); if (!idlest || 100*this_load < imbalance*min_load) return NULL; @@ -1393,8 +1421,13 @@ static int wake_idle(int cpu, struct task_struct *p) if (sd->flags & SD_WAKE_IDLE) { cpus_and(tmp, sd->span, p->cpus_allowed); for_each_cpu_mask(i, tmp) { - if (idle_cpu(i)) + if (idle_cpu(i)) { + if (i != task_cpu(p)) { + schedstat_inc(p, + se.nr_wakeups_idle); + } return i; + } } } else { break; @@ -1425,7 +1458,7 @@ static inline int wake_idle(int cpu, struct task_struct *p) */ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) { - int cpu, this_cpu, success = 0; + int cpu, orig_cpu, this_cpu, success = 0; unsigned long flags; long old_state; struct rq *rq; @@ -1444,6 +1477,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) goto out_running; cpu = task_cpu(p); + orig_cpu = cpu; this_cpu = smp_processor_id(); #ifdef CONFIG_SMP @@ -1452,7 +1486,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) new_cpu = cpu; - schedstat_inc(rq, ttwu_cnt); + schedstat_inc(rq, ttwu_count); if (cpu == this_cpu) { schedstat_inc(rq, ttwu_local); goto out_set_cpu; @@ -1487,6 +1521,13 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) unsigned long tl = this_load; unsigned long tl_per_task; + /* + * Attract cache-cold tasks on sync wakeups: + */ + if (sync && !task_hot(p, rq->clock, this_sd)) + goto out_set_cpu; + + schedstat_inc(p, se.nr_wakeups_affine_attempts); tl_per_task = cpu_avg_load_per_task(this_cpu); /* @@ -1506,6 +1547,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) * there is no bad imbalance. */ schedstat_inc(this_sd, ttwu_move_affine); + schedstat_inc(p, se.nr_wakeups_affine); goto out_set_cpu; } } @@ -1517,6 +1559,7 @@ static int try_to_wake_up(struct task_struct *p, unsigned int state, int sync) if (this_sd->flags & SD_WAKE_BALANCE) { if (imbalance*this_load <= 100*load) { schedstat_inc(this_sd, ttwu_move_balance); + schedstat_inc(p, se.nr_wakeups_passive); goto out_set_cpu; } } @@ -1542,18 +1585,18 @@ out_set_cpu: out_activate: #endif /* CONFIG_SMP */ + schedstat_inc(p, se.nr_wakeups); + if (sync) + schedstat_inc(p, se.nr_wakeups_sync); + if (orig_cpu != cpu) + schedstat_inc(p, se.nr_wakeups_migrate); + if (cpu == this_cpu) + schedstat_inc(p, se.nr_wakeups_local); + else + schedstat_inc(p, se.nr_wakeups_remote); update_rq_clock(rq); activate_task(rq, p, 1); - /* - * Sync wakeups (i.e. those types of wakeups where the waker - * has indicated that it will leave the CPU in short order) - * don't trigger a preemption, if the woken up task will run on - * this cpu. (in this case the 'I will reschedule' promise of - * the waker guarantees that the freshly woken up task is going - * to be considered on this CPU.) - */ - if (!sync || cpu != this_cpu) - check_preempt_curr(rq, p); + check_preempt_curr(rq, p); success = 1; out_running: @@ -1584,28 +1627,20 @@ int fastcall wake_up_state(struct task_struct *p, unsigned int state) */ static void __sched_fork(struct task_struct *p) { - p->se.wait_start_fair = 0; p->se.exec_start = 0; p->se.sum_exec_runtime = 0; p->se.prev_sum_exec_runtime = 0; - p->se.delta_exec = 0; - p->se.delta_fair_run = 0; - p->se.delta_fair_sleep = 0; - p->se.wait_runtime = 0; - p->se.sleep_start_fair = 0; #ifdef CONFIG_SCHEDSTATS p->se.wait_start = 0; - p->se.sum_wait_runtime = 0; p->se.sum_sleep_runtime = 0; p->se.sleep_start = 0; p->se.block_start = 0; p->se.sleep_max = 0; p->se.block_max = 0; p->se.exec_max = 0; + p->se.slice_max = 0; p->se.wait_max = 0; - p->se.wait_runtime_overruns = 0; - p->se.wait_runtime_underruns = 0; #endif INIT_LIST_HEAD(&p->run_list); @@ -1636,12 +1671,14 @@ void sched_fork(struct task_struct *p, int clone_flags) #ifdef CONFIG_SMP cpu = sched_balance_self(cpu, SD_BALANCE_FORK); #endif - __set_task_cpu(p, cpu); + set_task_cpu(p, cpu); /* * Make sure we do not leak PI boosting priority to the child: */ p->prio = current->normal_prio; + if (!rt_prio(p->prio)) + p->sched_class = &fair_sched_class; #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) if (likely(sched_info_on())) @@ -1658,12 +1695,6 @@ void sched_fork(struct task_struct *p, int clone_flags) } /* - * After fork, child runs first. (default) If set to 0 then - * parent will (try to) run first. - */ -unsigned int __read_mostly sysctl_sched_child_runs_first = 1; - -/* * wake_up_new_task - wake up a newly created task for the first time. * * This function will do some initial scheduler statistics housekeeping @@ -1674,24 +1705,14 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags) { unsigned long flags; struct rq *rq; - int this_cpu; rq = task_rq_lock(p, &flags); BUG_ON(p->state != TASK_RUNNING); - this_cpu = smp_processor_id(); /* parent's CPU */ update_rq_clock(rq); p->prio = effective_prio(p); - if (rt_prio(p->prio)) - p->sched_class = &rt_sched_class; - else - p->sched_class = &fair_sched_class; - - if (!p->sched_class->task_new || !sysctl_sched_child_runs_first || - (clone_flags & CLONE_VM) || task_cpu(p) != this_cpu || - !current->se.on_rq) { - + if (!p->sched_class->task_new || !current->se.on_rq || !rq->cfs.curr) { activate_task(rq, p, 0); } else { /* @@ -1800,7 +1821,7 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev, * with the lock held can cause deadlocks; see schedule() for * details.) */ -static inline void finish_task_switch(struct rq *rq, struct task_struct *prev) +static void finish_task_switch(struct rq *rq, struct task_struct *prev) __releases(rq->lock) { struct mm_struct *mm = rq->prev_mm; @@ -1982,42 +2003,10 @@ unsigned long nr_active(void) */ static void update_cpu_load(struct rq *this_rq) { - u64 fair_delta64, exec_delta64, idle_delta64, sample_interval64, tmp64; - unsigned long total_load = this_rq->ls.load.weight; - unsigned long this_load = total_load; - struct load_stat *ls = &this_rq->ls; + unsigned long this_load = this_rq->load.weight; int i, scale; this_rq->nr_load_updates++; - if (unlikely(!(sysctl_sched_features & SCHED_FEAT_PRECISE_CPU_LOAD))) - goto do_avg; - - /* Update delta_fair/delta_exec fields first */ - update_curr_load(this_rq); - - fair_delta64 = ls->delta_fair + 1; - ls->delta_fair = 0; - - exec_delta64 = ls->delta_exec + 1; - ls->delta_exec = 0; - - sample_interval64 = this_rq->clock - ls->load_update_last; - ls->load_update_last = this_rq->clock; - - if ((s64)sample_interval64 < (s64)TICK_NSEC) - sample_interval64 = TICK_NSEC; - - if (exec_delta64 > sample_interval64) - exec_delta64 = sample_interval64; - - idle_delta64 = sample_interval64 - exec_delta64; - - tmp64 = div64_64(SCHED_LOAD_SCALE * exec_delta64, fair_delta64); - tmp64 = div64_64(tmp64 * exec_delta64, sample_interval64); - - this_load = (unsigned long)tmp64; - -do_avg: /* Update our load: */ for (i = 0, scale = 1; i < CPU_LOAD_IDX_MAX; i++, scale += scale) { @@ -2027,7 +2016,13 @@ do_avg: old_load = this_rq->cpu_load[i]; new_load = this_load; - + /* + * Round up the averaging division if load is increasing. This + * prevents us from getting stuck on 9 if the load is 10, for + * example. + */ + if (new_load > old_load) + new_load += scale-1; this_rq->cpu_load[i] = (old_load*(scale-1) + new_load) >> i; } } @@ -2179,13 +2174,38 @@ int can_migrate_task(struct task_struct *p, struct rq *rq, int this_cpu, * 2) cannot be migrated to this CPU due to cpus_allowed, or * 3) are cache-hot on their current CPU. */ - if (!cpu_isset(this_cpu, p->cpus_allowed)) + if (!cpu_isset(this_cpu, p->cpus_allowed)) { + schedstat_inc(p, se.nr_failed_migrations_affine); return 0; + } *all_pinned = 0; - if (task_running(rq, p)) + if (task_running(rq, p)) { + schedstat_inc(p, se.nr_failed_migrations_running); return 0; + } + + /* + * Aggressive migration if: + * 1) task is cache cold, or + * 2) too many balance attempts have failed. + */ + + if (!task_hot(p, rq->clock, sd) || + sd->nr_balance_failed > sd->cache_nice_tries) { +#ifdef CONFIG_SCHEDSTATS + if (task_hot(p, rq->clock, sd)) { + schedstat_inc(sd, lb_hot_gained[idle]); + schedstat_inc(p, se.nr_forced_migrations); + } +#endif + return 1; + } + if (task_hot(p, rq->clock, sd)) { + schedstat_inc(p, se.nr_failed_migrations_hot); + return 0; + } return 1; } @@ -2264,7 +2284,7 @@ static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest, struct sched_domain *sd, enum cpu_idle_type idle, int *all_pinned) { - struct sched_class *class = sched_class_highest; + const struct sched_class *class = sched_class_highest; unsigned long total_load_moved = 0; int this_best_prio = this_rq->curr->prio; @@ -2289,7 +2309,7 @@ static int move_tasks(struct rq *this_rq, int this_cpu, struct rq *busiest, static int move_one_task(struct rq *this_rq, int this_cpu, struct rq *busiest, struct sched_domain *sd, enum cpu_idle_type idle) { - struct sched_class *class; + const struct sched_class *class; int this_best_prio = MAX_PRIO; for (class = sched_class_highest; class; class = class->next) @@ -2653,7 +2673,7 @@ static int load_balance(int this_cpu, struct rq *this_rq, !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE)) sd_idle = 1; - schedstat_inc(sd, lb_cnt[idle]); + schedstat_inc(sd, lb_count[idle]); redo: group = find_busiest_group(sd, this_cpu, &imbalance, idle, &sd_idle, @@ -2806,7 +2826,7 @@ load_balance_newidle(int this_cpu, struct rq *this_rq, struct sched_domain *sd) !test_sd_parent(sd, SD_POWERSAVINGS_BALANCE)) sd_idle = 1; - schedstat_inc(sd, lb_cnt[CPU_NEWLY_IDLE]); + schedstat_inc(sd, lb_count[CPU_NEWLY_IDLE]); redo: group = find_busiest_group(sd, this_cpu, &imbalance, CPU_NEWLY_IDLE, &sd_idle, &cpus, NULL); @@ -2940,7 +2960,7 @@ static void active_load_balance(struct rq *busiest_rq, int busiest_cpu) } if (likely(sd)) { - schedstat_inc(sd, alb_cnt); + schedstat_inc(sd, alb_count); if (move_one_task(target_rq, target_cpu, busiest_rq, sd, CPU_IDLE)) @@ -3033,7 +3053,7 @@ static DEFINE_SPINLOCK(balancing); * * Balancing parameters are set up in arch_init_sched_domains. */ -static inline void rebalance_domains(int cpu, enum cpu_idle_type idle) +static void rebalance_domains(int cpu, enum cpu_idle_type idle) { int balance = 1; struct rq *rq = cpu_rq(cpu); @@ -3280,6 +3300,25 @@ void account_user_time(struct task_struct *p, cputime_t cputime) } /* + * Account guest cpu time to a process. + * @p: the process that the cpu time gets accounted to + * @cputime: the cpu time spent in virtual machine since the last update + */ +void account_guest_time(struct task_struct *p, cputime_t cputime) +{ + cputime64_t tmp; + struct cpu_usage_stat *cpustat = &kstat_this_cpu.cpustat; + + tmp = cputime_to_cputime64(cputime); + + p->utime = cputime_add(p->utime, cputime); + p->gtime = cputime_add(p->gtime, cputime); + + cpustat->user = cputime64_add(cpustat->user, tmp); + cpustat->guest = cputime64_add(cpustat->guest, tmp); +} + +/* * Account system cpu time to a process. * @p: the process that the cpu time gets accounted to * @hardirq_offset: the offset to subtract from hardirq_count() @@ -3292,6 +3331,12 @@ void account_system_time(struct task_struct *p, int hardirq_offset, struct rq *rq = this_rq(); cputime64_t tmp; + if (p->flags & PF_VCPU) { + account_guest_time(p, cputime); + p->flags &= ~PF_VCPU; + return; + } + p->stime = cputime_add(p->stime, cputime); /* Add system time to cpustat. */ @@ -3430,7 +3475,13 @@ static inline void schedule_debug(struct task_struct *prev) profile_hit(SCHED_PROFILING, __builtin_return_address(0)); - schedstat_inc(this_rq(), sched_cnt); + schedstat_inc(this_rq(), sched_count); +#ifdef CONFIG_SCHEDSTATS + if (unlikely(prev->lock_depth >= 0)) { + schedstat_inc(this_rq(), bkl_count); + schedstat_inc(prev, sched_info.bkl_count); + } +#endif } /* @@ -3439,7 +3490,7 @@ static inline void schedule_debug(struct task_struct *prev) static inline struct task_struct * pick_next_task(struct rq *rq, struct task_struct *prev) { - struct sched_class *class; + const struct sched_class *class; struct task_struct *p; /* @@ -3488,9 +3539,13 @@ need_resched_nonpreemptible: schedule_debug(prev); - spin_lock_irq(&rq->lock); - clear_tsk_need_resched(prev); + /* + * Do the rq-clock update outside the rq lock: + */ + local_irq_disable(); __update_rq_clock(rq); + spin_lock(&rq->lock); + clear_tsk_need_resched(prev); if (prev->state && !(preempt_count() & PREEMPT_ACTIVE)) { if (unlikely((prev->state & TASK_INTERRUPTIBLE) && @@ -3550,27 +3605,30 @@ asmlinkage void __sched preempt_schedule(void) if (likely(ti->preempt_count || irqs_disabled())) return; -need_resched: - add_preempt_count(PREEMPT_ACTIVE); - /* - * We keep the big kernel semaphore locked, but we - * clear ->lock_depth so that schedule() doesnt - * auto-release the semaphore: - */ + do { + add_preempt_count(PREEMPT_ACTIVE); + + /* + * We keep the big kernel semaphore locked, but we + * clear ->lock_depth so that schedule() doesnt + * auto-release the semaphore: + */ #ifdef CONFIG_PREEMPT_BKL - saved_lock_depth = task->lock_depth; - task->lock_depth = -1; + saved_lock_depth = task->lock_depth; + task->lock_depth = -1; #endif - schedule(); + schedule(); #ifdef CONFIG_PREEMPT_BKL - task->lock_depth = saved_lock_depth; + task->lock_depth = saved_lock_depth; #endif - sub_preempt_count(PREEMPT_ACTIVE); + sub_preempt_count(PREEMPT_ACTIVE); - /* we could miss a preemption opportunity between schedule and now */ - barrier(); - if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) - goto need_resched; + /* + * Check again in case we missed a preemption opportunity + * between schedule and now. + */ + barrier(); + } while (unlikely(test_thread_flag(TIF_NEED_RESCHED))); } EXPORT_SYMBOL(preempt_schedule); @@ -3590,29 +3648,32 @@ asmlinkage void __sched preempt_schedule_irq(void) /* Catch callers which need to be fixed */ BUG_ON(ti->preempt_count || !irqs_disabled()); -need_resched: - add_preempt_count(PREEMPT_ACTIVE); - /* - * We keep the big kernel semaphore locked, but we - * clear ->lock_depth so that schedule() doesnt - * auto-release the semaphore: - */ + do { + add_preempt_count(PREEMPT_ACTIVE); + + /* + * We keep the big kernel semaphore locked, but we + * clear ->lock_depth so that schedule() doesnt + * auto-release the semaphore: + */ #ifdef CONFIG_PREEMPT_BKL - saved_lock_depth = task->lock_depth; - task->lock_depth = -1; + saved_lock_depth = task->lock_depth; + task->lock_depth = -1; #endif - local_irq_enable(); - schedule(); - local_irq_disable(); + local_irq_enable(); + schedule(); + local_irq_disable(); #ifdef CONFIG_PREEMPT_BKL - task->lock_depth = saved_lock_depth; + task->lock_depth = saved_lock_depth; #endif - sub_preempt_count(PREEMPT_ACTIVE); + sub_preempt_count(PREEMPT_ACTIVE); - /* we could miss a preemption opportunity between schedule and now */ - barrier(); - if (unlikely(test_thread_flag(TIF_NEED_RESCHED))) - goto need_resched; + /* + * Check again in case we missed a preemption opportunity + * between schedule and now. + */ + barrier(); + } while (unlikely(test_thread_flag(TIF_NEED_RESCHED))); } #endif /* CONFIG_PREEMPT */ @@ -3636,10 +3697,9 @@ EXPORT_SYMBOL(default_wake_function); static void __wake_up_common(wait_queue_head_t *q, unsigned int mode, int nr_exclusive, int sync, void *key) { - struct list_head *tmp, *next; + wait_queue_t *curr, *next; - list_for_each_safe(tmp, next, &q->task_list) { - wait_queue_t *curr = list_entry(tmp, wait_queue_t, task_list); + list_for_each_entry_safe(curr, next, &q->task_list, task_list) { unsigned flags = curr->flags; if (curr->func(curr, mode, sync, key) && @@ -3729,206 +3789,116 @@ void fastcall complete_all(struct completion *x) } EXPORT_SYMBOL(complete_all); -void fastcall __sched wait_for_completion(struct completion *x) -{ - might_sleep(); - - spin_lock_irq(&x->wait.lock); - if (!x->done) { - DECLARE_WAITQUEUE(wait, current); - - wait.flags |= WQ_FLAG_EXCLUSIVE; - __add_wait_queue_tail(&x->wait, &wait); - do { - __set_current_state(TASK_UNINTERRUPTIBLE); - spin_unlock_irq(&x->wait.lock); - schedule(); - spin_lock_irq(&x->wait.lock); - } while (!x->done); - __remove_wait_queue(&x->wait, &wait); - } - x->done--; - spin_unlock_irq(&x->wait.lock); -} -EXPORT_SYMBOL(wait_for_completion); - -unsigned long fastcall __sched -wait_for_completion_timeout(struct completion *x, unsigned long timeout) +static inline long __sched +do_wait_for_common(struct completion *x, long timeout, int state) { - might_sleep(); - - spin_lock_irq(&x->wait.lock); if (!x->done) { DECLARE_WAITQUEUE(wait, current); wait.flags |= WQ_FLAG_EXCLUSIVE; __add_wait_queue_tail(&x->wait, &wait); do { - __set_current_state(TASK_UNINTERRUPTIBLE); + if (state == TASK_INTERRUPTIBLE && + signal_pending(current)) { + __remove_wait_queue(&x->wait, &wait); + return -ERESTARTSYS; + } + __set_current_state(state); spin_unlock_irq(&x->wait.lock); timeout = schedule_timeout(timeout); spin_lock_irq(&x->wait.lock); if (!timeout) { __remove_wait_queue(&x->wait, &wait); - goto out; + return timeout; } } while (!x->done); __remove_wait_queue(&x->wait, &wait); } x->done--; -out: - spin_unlock_irq(&x->wait.lock); return timeout; } -EXPORT_SYMBOL(wait_for_completion_timeout); -int fastcall __sched wait_for_completion_interruptible(struct completion *x) +static long __sched +wait_for_common(struct completion *x, long timeout, int state) { - int ret = 0; - might_sleep(); spin_lock_irq(&x->wait.lock); - if (!x->done) { - DECLARE_WAITQUEUE(wait, current); - - wait.flags |= WQ_FLAG_EXCLUSIVE; - __add_wait_queue_tail(&x->wait, &wait); - do { - if (signal_pending(current)) { - ret = -ERESTARTSYS; - __remove_wait_queue(&x->wait, &wait); - goto out; - } - __set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(&x->wait.lock); - schedule(); - spin_lock_irq(&x->wait.lock); - } while (!x->done); - __remove_wait_queue(&x->wait, &wait); - } - x->done--; -out: + timeout = do_wait_for_common(x, timeout, state); spin_unlock_irq(&x->wait.lock); + return timeout; +} - return ret; +void fastcall __sched wait_for_completion(struct completion *x) +{ + wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_UNINTERRUPTIBLE); } -EXPORT_SYMBOL(wait_for_completion_interruptible); +EXPORT_SYMBOL(wait_for_completion); unsigned long fastcall __sched -wait_for_completion_interruptible_timeout(struct completion *x, - unsigned long timeout) +wait_for_completion_timeout(struct completion *x, unsigned long timeout) { - might_sleep(); - - spin_lock_irq(&x->wait.lock); - if (!x->done) { - DECLARE_WAITQUEUE(wait, current); - - wait.flags |= WQ_FLAG_EXCLUSIVE; - __add_wait_queue_tail(&x->wait, &wait); - do { - if (signal_pending(current)) { - timeout = -ERESTARTSYS; - __remove_wait_queue(&x->wait, &wait); - goto out; - } - __set_current_state(TASK_INTERRUPTIBLE); - spin_unlock_irq(&x->wait.lock); - timeout = schedule_timeout(timeout); - spin_lock_irq(&x->wait.lock); - if (!timeout) { - __remove_wait_queue(&x->wait, &wait); - goto out; - } - } while (!x->done); - __remove_wait_queue(&x->wait, &wait); - } - x->done--; -out: - spin_unlock_irq(&x->wait.lock); - return timeout; + return wait_for_common(x, timeout, TASK_UNINTERRUPTIBLE); } -EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); +EXPORT_SYMBOL(wait_for_completion_timeout); -static inline void -sleep_on_head(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags) +int __sched wait_for_completion_interruptible(struct completion *x) { - spin_lock_irqsave(&q->lock, *flags); - __add_wait_queue(q, wait); - spin_unlock(&q->lock); + return wait_for_common(x, MAX_SCHEDULE_TIMEOUT, TASK_INTERRUPTIBLE); } +EXPORT_SYMBOL(wait_for_completion_interruptible); -static inline void -sleep_on_tail(wait_queue_head_t *q, wait_queue_t *wait, unsigned long *flags) +unsigned long fastcall __sched +wait_for_completion_interruptible_timeout(struct completion *x, + unsigned long timeout) { - spin_lock_irq(&q->lock); - __remove_wait_queue(q, wait); - spin_unlock_irqrestore(&q->lock, *flags); + return wait_for_common(x, timeout, TASK_INTERRUPTIBLE); } +EXPORT_SYMBOL(wait_for_completion_interruptible_timeout); -void __sched interruptible_sleep_on(wait_queue_head_t *q) +static long __sched +sleep_on_common(wait_queue_head_t *q, int state, long timeout) { unsigned long flags; wait_queue_t wait; init_waitqueue_entry(&wait, current); - current->state = TASK_INTERRUPTIBLE; + __set_current_state(state); - sleep_on_head(q, &wait, &flags); - schedule(); - sleep_on_tail(q, &wait, &flags); + spin_lock_irqsave(&q->lock, flags); + __add_wait_queue(q, &wait); + spin_unlock(&q->lock); + timeout = schedule_timeout(timeout); + spin_lock_irq(&q->lock); + __remove_wait_queue(q, &wait); + spin_unlock_irqrestore(&q->lock, flags); + + return timeout; +} + +void __sched interruptible_sleep_on(wait_queue_head_t *q) +{ + sleep_on_common(q, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } EXPORT_SYMBOL(interruptible_sleep_on); long __sched interruptible_sleep_on_timeout(wait_queue_head_t *q, long timeout) { - unsigned long flags; - wait_queue_t wait; - - init_waitqueue_entry(&wait, current); - - current->state = TASK_INTERRUPTIBLE; - - sleep_on_head(q, &wait, &flags); - timeout = schedule_timeout(timeout); - sleep_on_tail(q, &wait, &flags); - - return timeout; + return sleep_on_common(q, TASK_INTERRUPTIBLE, timeout); } EXPORT_SYMBOL(interruptible_sleep_on_timeout); void __sched sleep_on(wait_queue_head_t *q) { - unsigned long flags; - wait_queue_t wait; - - init_waitqueue_entry(&wait, current); - - current->state = TASK_UNINTERRUPTIBLE; - - sleep_on_head(q, &wait, &flags); - schedule(); - sleep_on_tail(q, &wait, &flags); + sleep_on_common(q, TASK_UNINTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } EXPORT_SYMBOL(sleep_on); long __sched sleep_on_timeout(wait_queue_head_t *q, long timeout) { - unsigned long flags; - wait_queue_t wait; - - init_waitqueue_entry(&wait, current); - - current->state = TASK_UNINTERRUPTIBLE; - - sleep_on_head(q, &wait, &flags); - timeout = schedule_timeout(timeout); - sleep_on_tail(q, &wait, &flags); - - return timeout; + return sleep_on_common(q, TASK_UNINTERRUPTIBLE, timeout); } EXPORT_SYMBOL(sleep_on_timeout); @@ -3947,7 +3917,7 @@ EXPORT_SYMBOL(sleep_on_timeout); void rt_mutex_setprio(struct task_struct *p, int prio) { unsigned long flags; - int oldprio, on_rq; + int oldprio, on_rq, running; struct rq *rq; BUG_ON(prio < 0 || prio > MAX_PRIO); @@ -3957,8 +3927,12 @@ void rt_mutex_setprio(struct task_struct *p, int prio) oldprio = p->prio; on_rq = p->se.on_rq; - if (on_rq) + running = task_running(rq, p); + if (on_rq) { dequeue_task(rq, p, 0); + if (running) + p->sched_class->put_prev_task(rq, p); + } if (rt_prio(prio)) p->sched_class = &rt_sched_class; @@ -3968,13 +3942,15 @@ void rt_mutex_setprio(struct task_struct *p, int prio) p->prio = prio; if (on_rq) { + if (running) + p->sched_class->set_curr_task(rq); enqueue_task(rq, p, 0); /* * Reschedule if we are currently running on this runqueue and * our priority decreased, or if we are not currently running on * this runqueue and our priority is higher than the current's */ - if (task_running(rq, p)) { + if (running) { if (p->prio > oldprio) resched_task(rq->curr); } else { @@ -4138,7 +4114,7 @@ struct task_struct *idle_task(int cpu) * find_process_by_pid - find a process with a matching PID value. * @pid: the pid in question. */ -static inline struct task_struct *find_process_by_pid(pid_t pid) +static struct task_struct *find_process_by_pid(pid_t pid) { return pid ? find_task_by_pid(pid) : current; } @@ -4180,7 +4156,7 @@ __setscheduler(struct rq *rq, struct task_struct *p, int policy, int prio) int sched_setscheduler(struct task_struct *p, int policy, struct sched_param *param) { - int retval, oldprio, oldpolicy = -1, on_rq; + int retval, oldprio, oldpolicy = -1, on_rq, running; unsigned long flags; struct rq *rq; @@ -4262,18 +4238,26 @@ recheck: } update_rq_clock(rq); on_rq = p->se.on_rq; - if (on_rq) + running = task_running(rq, p); + if (on_rq) { deactivate_task(rq, p, 0); + if (running) + p->sched_class->put_prev_task(rq, p); + } + oldprio = p->prio; __setscheduler(rq, p, policy, param->sched_priority); + if (on_rq) { + if (running) + p->sched_class->set_curr_task(rq); activate_task(rq, p, 0); /* * Reschedule if we are currently running on this runqueue and * our priority decreased, or if we are not currently running on * this runqueue and our priority is higher than the current's */ - if (task_running(rq, p)) { + if (running) { if (p->prio > oldprio) resched_task(rq->curr); } else { @@ -4344,10 +4328,10 @@ asmlinkage long sys_sched_setparam(pid_t pid, struct sched_param __user *param) asmlinkage long sys_sched_getscheduler(pid_t pid) { struct task_struct *p; - int retval = -EINVAL; + int retval; if (pid < 0) - goto out_nounlock; + return -EINVAL; retval = -ESRCH; read_lock(&tasklist_lock); @@ -4358,8 +4342,6 @@ asmlinkage long sys_sched_getscheduler(pid_t pid) retval = p->policy; } read_unlock(&tasklist_lock); - -out_nounlock: return retval; } @@ -4372,10 +4354,10 @@ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param __user *param) { struct sched_param lp; struct task_struct *p; - int retval = -EINVAL; + int retval; if (!param || pid < 0) - goto out_nounlock; + return -EINVAL; read_lock(&tasklist_lock); p = find_process_by_pid(pid); @@ -4395,7 +4377,6 @@ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param __user *param) */ retval = copy_to_user(param, &lp, sizeof(*param)) ? -EFAULT : 0; -out_nounlock: return retval; out_unlock: @@ -4555,8 +4536,8 @@ asmlinkage long sys_sched_yield(void) { struct rq *rq = this_rq_lock(); - schedstat_inc(rq, yld_cnt); - current->sched_class->yield_task(rq, current); + schedstat_inc(rq, yld_count); + current->sched_class->yield_task(rq); /* * Since we are going to call schedule() anyway, there's @@ -4750,11 +4731,12 @@ asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec __user *interval) { struct task_struct *p; - int retval = -EINVAL; + unsigned int time_slice; + int retval; struct timespec t; if (pid < 0) - goto out_nounlock; + return -EINVAL; retval = -ESRCH; read_lock(&tasklist_lock); @@ -4766,12 +4748,24 @@ long sys_sched_rr_get_interval(pid_t pid, struct timespec __user *interval) if (retval) goto out_unlock; - jiffies_to_timespec(p->policy == SCHED_FIFO ? - 0 : static_prio_timeslice(p->static_prio), &t); + if (p->policy == SCHED_FIFO) + time_slice = 0; + else if (p->policy == SCHED_RR) + time_slice = DEF_TIMESLICE; + else { + struct sched_entity *se = &p->se; + unsigned long flags; + struct rq *rq; + + rq = task_rq_lock(p, &flags); + time_slice = NS_TO_JIFFIES(sched_slice(cfs_rq_of(se), se)); + task_rq_unlock(rq, &flags); + } read_unlock(&tasklist_lock); + jiffies_to_timespec(time_slice, &t); retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0; -out_nounlock: return retval; + out_unlock: read_unlock(&tasklist_lock); return retval; @@ -4900,32 +4894,6 @@ void __cpuinit init_idle(struct task_struct *idle, int cpu) */ cpumask_t nohz_cpu_mask = CPU_MASK_NONE; -/* - * Increase the granularity value when there are more CPUs, - * because with more CPUs the 'effective latency' as visible - * to users decreases. But the relationship is not linear, - * so pick a second-best guess by going with the log2 of the - * number of CPUs. - * - * This idea comes from the SD scheduler of Con Kolivas: - */ -static inline void sched_init_granularity(void) -{ - unsigned int factor = 1 + ilog2(num_online_cpus()); - const unsigned long limit = 100000000; - - sysctl_sched_min_granularity *= factor; - if (sysctl_sched_min_granularity > limit) - sysctl_sched_min_granularity = limit; - - sysctl_sched_latency *= factor; - if (sysctl_sched_latency > limit) - sysctl_sched_latency = limit; - - sysctl_sched_runtime_limit = sysctl_sched_latency; - sysctl_sched_wakeup_granularity = sysctl_sched_min_granularity / 2; -} - #ifdef CONFIG_SMP /* * This is how migration works: @@ -5103,35 +5071,34 @@ static void move_task_off_dead_cpu(int dead_cpu, struct task_struct *p) struct rq *rq; int dest_cpu; -restart: - /* On same node? */ - mask = node_to_cpumask(cpu_to_node(dead_cpu)); - cpus_and(mask, mask, p->cpus_allowed); - dest_cpu = any_online_cpu(mask); - - /* On any allowed CPU? */ - if (dest_cpu == NR_CPUS) - dest_cpu = any_online_cpu(p->cpus_allowed); - - /* No more Mr. Nice Guy. */ - if (dest_cpu == NR_CPUS) { - rq = task_rq_lock(p, &flags); - cpus_setall(p->cpus_allowed); - dest_cpu = any_online_cpu(p->cpus_allowed); - task_rq_unlock(rq, &flags); + do { + /* On same node? */ + mask = node_to_cpumask(cpu_to_node(dead_cpu)); + cpus_and(mask, mask, p->cpus_allowed); + dest_cpu = any_online_cpu(mask); + + /* On any allowed CPU? */ + if (dest_cpu == NR_CPUS) + dest_cpu = any_online_cpu(p->cpus_allowed); + + /* No more Mr. Nice Guy. */ + if (dest_cpu == NR_CPUS) { + rq = task_rq_lock(p, &flags); + cpus_setall(p->cpus_allowed); + dest_cpu = any_online_cpu(p->cpus_allowed); + task_rq_unlock(rq, &flags); - /* - * Don't tell them about moving exiting tasks or - * kernel threads (both mm NULL), since they never - * leave kernel. - */ - if (p->mm && printk_ratelimit()) - printk(KERN_INFO "process %d (%s) no " - "longer affine to cpu%d\n", - p->pid, p->comm, dead_cpu); - } - if (!__migrate_task(p, dead_cpu, dest_cpu)) - goto restart; + /* + * Don't tell them about moving exiting tasks or + * kernel threads (both mm NULL), since they never + * leave kernel. + */ + if (p->mm && printk_ratelimit()) + printk(KERN_INFO "process %d (%s) no " + "longer affine to cpu%d\n", + p->pid, p->comm, dead_cpu); + } + } while (!__migrate_task(p, dead_cpu, dest_cpu)); } /* @@ -5173,6 +5140,20 @@ static void migrate_live_tasks(int src_cpu) } /* + * activate_idle_task - move idle task to the _front_ of runqueue. + */ +static void activate_idle_task(struct task_struct *p, struct rq *rq) +{ + update_rq_clock(rq); + + if (p->state == TASK_UNINTERRUPTIBLE) + rq->nr_uninterruptible--; + + enqueue_task(rq, p, 0); + inc_nr_running(p, rq); +} + +/* * Schedules idle task to be the next runnable task on current CPU. * It does so by boosting its priority to highest possible and adding it to * the _front_ of the runqueue. Used by CPU offline code. @@ -5284,14 +5265,23 @@ static struct ctl_table sd_ctl_root[] = { static struct ctl_table *sd_alloc_ctl_entry(int n) { struct ctl_table *entry = - kmalloc(n * sizeof(struct ctl_table), GFP_KERNEL); - - BUG_ON(!entry); - memset(entry, 0, n * sizeof(struct ctl_table)); + kcalloc(n, sizeof(struct ctl_table), GFP_KERNEL); return entry; } +static void sd_free_ctl_entry(struct ctl_table **tablep) +{ + struct ctl_table *entry = *tablep; + + for (entry = *tablep; entry->procname; entry++) + if (entry->child) + sd_free_ctl_entry(&entry->child); + + kfree(*tablep); + *tablep = NULL; +} + static void set_table_entry(struct ctl_table *entry, const char *procname, void *data, int maxlen, @@ -5307,7 +5297,10 @@ set_table_entry(struct ctl_table *entry, static struct ctl_table * sd_alloc_ctl_domain_table(struct sched_domain *sd) { - struct ctl_table *table = sd_alloc_ctl_entry(14); + struct ctl_table *table = sd_alloc_ctl_entry(12); + + if (table == NULL) + return NULL; set_table_entry(&table[0], "min_interval", &sd->min_interval, sizeof(long), 0644, proc_doulongvec_minmax); @@ -5327,11 +5320,12 @@ sd_alloc_ctl_domain_table(struct sched_domain *sd) sizeof(int), 0644, proc_dointvec_minmax); set_table_entry(&table[8], "imbalance_pct", &sd->imbalance_pct, sizeof(int), 0644, proc_dointvec_minmax); - set_table_entry(&table[10], "cache_nice_tries", + set_table_entry(&table[9], "cache_nice_tries", &sd->cache_nice_tries, sizeof(int), 0644, proc_dointvec_minmax); - set_table_entry(&table[12], "flags", &sd->flags, + set_table_entry(&table[10], "flags", &sd->flags, sizeof(int), 0644, proc_dointvec_minmax); + /* &table[11] is terminator */ return table; } @@ -5346,6 +5340,8 @@ static ctl_table *sd_alloc_ctl_cpu_table(int cpu) for_each_domain(cpu, sd) domain_num++; entry = table = sd_alloc_ctl_entry(domain_num + 1); + if (table == NULL) + return NULL; i = 0; for_each_domain(cpu, sd) { @@ -5360,24 +5356,38 @@ static ctl_table *sd_alloc_ctl_cpu_table(int cpu) } static struct ctl_table_header *sd_sysctl_header; -static void init_sched_domain_sysctl(void) +static void register_sched_domain_sysctl(void) { int i, cpu_num = num_online_cpus(); struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1); char buf[32]; + if (entry == NULL) + return; + sd_ctl_dir[0].child = entry; - for (i = 0; i < cpu_num; i++, entry++) { + for_each_online_cpu(i) { snprintf(buf, 32, "cpu%d", i); entry->procname = kstrdup(buf, GFP_KERNEL); entry->mode = 0555; entry->child = sd_alloc_ctl_cpu_table(i); + entry++; } sd_sysctl_header = register_sysctl_table(sd_ctl_root); } + +static void unregister_sched_domain_sysctl(void) +{ + unregister_sysctl_table(sd_sysctl_header); + sd_sysctl_header = NULL; + sd_free_ctl_entry(&sd_ctl_dir[0].child); +} #else -static void init_sched_domain_sysctl(void) +static void register_sched_domain_sysctl(void) +{ +} +static void unregister_sched_domain_sysctl(void) { } #endif @@ -5499,8 +5509,7 @@ int __init migration_init(void) int nr_cpu_ids __read_mostly = NR_CPUS; EXPORT_SYMBOL(nr_cpu_ids); -#undef SCHED_DOMAIN_DEBUG -#ifdef SCHED_DOMAIN_DEBUG +#ifdef CONFIG_SCHED_DEBUG static void sched_domain_debug(struct sched_domain *sd, int cpu) { int level = 0; @@ -5558,16 +5567,19 @@ static void sched_domain_debug(struct sched_domain *sd, int cpu) printk("\n"); printk(KERN_ERR "ERROR: domain->cpu_power not " "set\n"); + break; } if (!cpus_weight(group->cpumask)) { printk("\n"); printk(KERN_ERR "ERROR: empty group\n"); + break; } if (cpus_intersects(groupmask, group->cpumask)) { printk("\n"); printk(KERN_ERR "ERROR: repeated CPUs\n"); + break; } cpus_or(groupmask, groupmask, group->cpumask); @@ -5701,7 +5713,7 @@ static int __init isolated_cpu_setup(char *str) return 1; } -__setup ("isolcpus=", isolated_cpu_setup); +__setup("isolcpus=", isolated_cpu_setup); /* * init_sched_build_groups takes the cpumask we wish to span, and a pointer @@ -5930,24 +5942,23 @@ static void init_numa_sched_groups_power(struct sched_group *group_head) if (!sg) return; -next_sg: - for_each_cpu_mask(j, sg->cpumask) { - struct sched_domain *sd; + do { + for_each_cpu_mask(j, sg->cpumask) { + struct sched_domain *sd; - sd = &per_cpu(phys_domains, j); - if (j != first_cpu(sd->groups->cpumask)) { - /* - * Only add "power" once for each - * physical package. - */ - continue; - } + sd = &per_cpu(phys_domains, j); + if (j != first_cpu(sd->groups->cpumask)) { + /* + * Only add "power" once for each + * physical package. + */ + continue; + } - sg_inc_cpu_power(sg, sd->groups->__cpu_power); - } - sg = sg->next; - if (sg != group_head) - goto next_sg; + sg_inc_cpu_power(sg, sd->groups->__cpu_power); + } + sg = sg->next; + } while (sg != group_head); } #endif @@ -6058,7 +6069,7 @@ static int build_sched_domains(const cpumask_t *cpu_map) /* * Allocate the per-node list of sched groups */ - sched_group_nodes = kzalloc(sizeof(struct sched_group *)*MAX_NUMNODES, + sched_group_nodes = kcalloc(MAX_NUMNODES, sizeof(struct sched_group *), GFP_KERNEL); if (!sched_group_nodes) { printk(KERN_WARNING "Can not alloc sched group node list\n"); @@ -6311,6 +6322,8 @@ static int arch_init_sched_domains(const cpumask_t *cpu_map) err = build_sched_domains(&cpu_default_map); + register_sched_domain_sysctl(); + return err; } @@ -6327,6 +6340,8 @@ static void detach_destroy_domains(const cpumask_t *cpu_map) { int i; + unregister_sched_domain_sysctl(); + for_each_cpu_mask(i, *cpu_map) cpu_attach_domain(NULL, i); synchronize_sched(); @@ -6357,6 +6372,8 @@ int partition_sched_domains(cpumask_t *partition1, cpumask_t *partition2) if (!err && !cpus_empty(*partition2)) err = build_sched_domains(partition2); + register_sched_domain_sysctl(); + return err; } @@ -6488,17 +6505,13 @@ void __init sched_init_smp(void) /* XXX: Theoretical race here - CPU may be hotplugged now */ hotcpu_notifier(update_sched_domains, 0); - init_sched_domain_sysctl(); - /* Move init over to a non-isolated CPU */ if (set_cpus_allowed(current, non_isolated_cpus) < 0) BUG(); - sched_init_granularity(); } #else void __init sched_init_smp(void) { - sched_init_granularity(); } #endif /* CONFIG_SMP */ @@ -6512,28 +6525,20 @@ int in_sched_functions(unsigned long addr) && addr < (unsigned long)__sched_text_end); } -static inline void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq) +static void init_cfs_rq(struct cfs_rq *cfs_rq, struct rq *rq) { cfs_rq->tasks_timeline = RB_ROOT; - cfs_rq->fair_clock = 1; #ifdef CONFIG_FAIR_GROUP_SCHED cfs_rq->rq = rq; #endif + cfs_rq->min_vruntime = (u64)(-(1LL << 20)); } void __init sched_init(void) { - u64 now = sched_clock(); int highest_cpu = 0; int i, j; - /* - * Link up the scheduling class hierarchy: - */ - rt_sched_class.next = &fair_sched_class; - fair_sched_class.next = &idle_sched_class; - idle_sched_class.next = NULL; - for_each_possible_cpu(i) { struct rt_prio_array *array; struct rq *rq; @@ -6546,10 +6551,28 @@ void __init sched_init(void) init_cfs_rq(&rq->cfs, rq); #ifdef CONFIG_FAIR_GROUP_SCHED INIT_LIST_HEAD(&rq->leaf_cfs_rq_list); - list_add(&rq->cfs.leaf_cfs_rq_list, &rq->leaf_cfs_rq_list); + { + struct cfs_rq *cfs_rq = &per_cpu(init_cfs_rq, i); + struct sched_entity *se = + &per_cpu(init_sched_entity, i); + + init_cfs_rq_p[i] = cfs_rq; + init_cfs_rq(cfs_rq, rq); + cfs_rq->tg = &init_task_group; + list_add(&cfs_rq->leaf_cfs_rq_list, + &rq->leaf_cfs_rq_list); + + init_sched_entity_p[i] = se; + se->cfs_rq = &rq->cfs; + se->my_q = cfs_rq; + se->load.weight = init_task_group_load; + se->load.inv_weight = + div64_64(1ULL<<32, init_task_group_load); + se->parent = NULL; + } + init_task_group.shares = init_task_group_load; + spin_lock_init(&init_task_group.lock); #endif - rq->ls.load_update_last = now; - rq->ls.load_update_start = now; for (j = 0; j < CPU_LOAD_IDX_MAX; j++) rq->cpu_load[j] = 0; @@ -6634,26 +6657,40 @@ EXPORT_SYMBOL(__might_sleep); #endif #ifdef CONFIG_MAGIC_SYSRQ +static void normalize_task(struct rq *rq, struct task_struct *p) +{ + int on_rq; + update_rq_clock(rq); + on_rq = p->se.on_rq; + if (on_rq) + deactivate_task(rq, p, 0); + __setscheduler(rq, p, SCHED_NORMAL, 0); + if (on_rq) { + activate_task(rq, p, 0); + resched_task(rq->curr); + } +} + void normalize_rt_tasks(void) { struct task_struct *g, *p; unsigned long flags; struct rq *rq; - int on_rq; read_lock_irq(&tasklist_lock); do_each_thread(g, p) { - p->se.fair_key = 0; - p->se.wait_runtime = 0; + /* + * Only normalize user tasks: + */ + if (!p->mm) + continue; + p->se.exec_start = 0; - p->se.wait_start_fair = 0; - p->se.sleep_start_fair = 0; #ifdef CONFIG_SCHEDSTATS p->se.wait_start = 0; p->se.sleep_start = 0; p->se.block_start = 0; #endif - task_rq(p)->cfs.fair_clock = 0; task_rq(p)->clock = 0; if (!rt_task(p)) { @@ -6668,26 +6705,9 @@ void normalize_rt_tasks(void) spin_lock_irqsave(&p->pi_lock, flags); rq = __task_rq_lock(p); -#ifdef CONFIG_SMP - /* - * Do not touch the migration thread: - */ - if (p == rq->migration_thread) - goto out_unlock; -#endif - update_rq_clock(rq); - on_rq = p->se.on_rq; - if (on_rq) - deactivate_task(rq, p, 0); - __setscheduler(rq, p, SCHED_NORMAL, 0); - if (on_rq) { - activate_task(rq, p, 0); - resched_task(rq->curr); - } -#ifdef CONFIG_SMP - out_unlock: -#endif + normalize_task(rq, p); + __task_rq_unlock(rq); spin_unlock_irqrestore(&p->pi_lock, flags); } while_each_thread(g, p); @@ -6740,3 +6760,201 @@ void set_curr_task(int cpu, struct task_struct *p) } #endif + +#ifdef CONFIG_FAIR_GROUP_SCHED + +/* allocate runqueue etc for a new task group */ +struct task_group *sched_create_group(void) +{ + struct task_group *tg; + struct cfs_rq *cfs_rq; + struct sched_entity *se; + struct rq *rq; + int i; + + tg = kzalloc(sizeof(*tg), GFP_KERNEL); + if (!tg) + return ERR_PTR(-ENOMEM); + + tg->cfs_rq = kzalloc(sizeof(cfs_rq) * NR_CPUS, GFP_KERNEL); + if (!tg->cfs_rq) + goto err; + tg->se = kzalloc(sizeof(se) * NR_CPUS, GFP_KERNEL); + if (!tg->se) + goto err; + + for_each_possible_cpu(i) { + rq = cpu_rq(i); + + cfs_rq = kmalloc_node(sizeof(struct cfs_rq), GFP_KERNEL, + cpu_to_node(i)); + if (!cfs_rq) + goto err; + + se = kmalloc_node(sizeof(struct sched_entity), GFP_KERNEL, + cpu_to_node(i)); + if (!se) + goto err; + + memset(cfs_rq, 0, sizeof(struct cfs_rq)); + memset(se, 0, sizeof(struct sched_entity)); + + tg->cfs_rq[i] = cfs_rq; + init_cfs_rq(cfs_rq, rq); + cfs_rq->tg = tg; + + tg->se[i] = se; + se->cfs_rq = &rq->cfs; + se->my_q = cfs_rq; + se->load.weight = NICE_0_LOAD; + se->load.inv_weight = div64_64(1ULL<<32, NICE_0_LOAD); + se->parent = NULL; + } + + for_each_possible_cpu(i) { + rq = cpu_rq(i); + cfs_rq = tg->cfs_rq[i]; + list_add_rcu(&cfs_rq->leaf_cfs_rq_list, &rq->leaf_cfs_rq_list); + } + + tg->shares = NICE_0_LOAD; + spin_lock_init(&tg->lock); + + return tg; + +err: + for_each_possible_cpu(i) { + if (tg->cfs_rq) + kfree(tg->cfs_rq[i]); + if (tg->se) + kfree(tg->se[i]); + } + kfree(tg->cfs_rq); + kfree(tg->se); + kfree(tg); + + return ERR_PTR(-ENOMEM); +} + +/* rcu callback to free various structures associated with a task group */ +static void free_sched_group(struct rcu_head *rhp) +{ + struct cfs_rq *cfs_rq = container_of(rhp, struct cfs_rq, rcu); + struct task_group *tg = cfs_rq->tg; + struct sched_entity *se; + int i; + + /* now it should be safe to free those cfs_rqs */ + for_each_possible_cpu(i) { + cfs_rq = tg->cfs_rq[i]; + kfree(cfs_rq); + + se = tg->se[i]; + kfree(se); + } + + kfree(tg->cfs_rq); + kfree(tg->se); + kfree(tg); +} + +/* Destroy runqueue etc associated with a task group */ +void sched_destroy_group(struct task_group *tg) +{ + struct cfs_rq *cfs_rq; + int i; + + for_each_possible_cpu(i) { + cfs_rq = tg->cfs_rq[i]; + list_del_rcu(&cfs_rq->leaf_cfs_rq_list); + } + + cfs_rq = tg->cfs_rq[0]; + + /* wait for possible concurrent references to cfs_rqs complete */ + call_rcu(&cfs_rq->rcu, free_sched_group); +} + +/* change task's runqueue when it moves between groups. + * The caller of this function should have put the task in its new group + * by now. This function just updates tsk->se.cfs_rq and tsk->se.parent to + * reflect its new group. + */ +void sched_move_task(struct task_struct *tsk) +{ + int on_rq, running; + unsigned long flags; + struct rq *rq; + + rq = task_rq_lock(tsk, &flags); + + if (tsk->sched_class != &fair_sched_class) + goto done; + + update_rq_clock(rq); + + running = task_running(rq, tsk); + on_rq = tsk->se.on_rq; + + if (on_rq) { + dequeue_task(rq, tsk, 0); + if (unlikely(running)) + tsk->sched_class->put_prev_task(rq, tsk); + } + + set_task_cfs_rq(tsk); + + if (on_rq) { + if (unlikely(running)) + tsk->sched_class->set_curr_task(rq); + enqueue_task(rq, tsk, 0); + } + +done: + task_rq_unlock(rq, &flags); +} + +static void set_se_shares(struct sched_entity *se, unsigned long shares) +{ + struct cfs_rq *cfs_rq = se->cfs_rq; + struct rq *rq = cfs_rq->rq; + int on_rq; + + spin_lock_irq(&rq->lock); + + on_rq = se->on_rq; + if (on_rq) + dequeue_entity(cfs_rq, se, 0); + + se->load.weight = shares; + se->load.inv_weight = div64_64((1ULL<<32), shares); + + if (on_rq) + enqueue_entity(cfs_rq, se, 0); + + spin_unlock_irq(&rq->lock); +} + +int sched_group_set_shares(struct task_group *tg, unsigned long shares) +{ + int i; + + spin_lock(&tg->lock); + if (tg->shares == shares) + goto done; + + tg->shares = shares; + for_each_possible_cpu(i) + set_se_shares(tg->se[i], shares); + +done: + spin_unlock(&tg->lock); + return 0; +} + +unsigned long sched_group_shares(struct task_group *tg) +{ + return tg->shares; +} + +#endif /* CONFIG_FAIR_GROUP_SCHED */ diff --git a/kernel/sched_debug.c b/kernel/sched_debug.c index c3ee38bd3426..a5e517ec07c3 100644 --- a/kernel/sched_debug.c +++ b/kernel/sched_debug.c @@ -28,6 +28,31 @@ printk(x); \ } while (0) +/* + * Ease the printing of nsec fields: + */ +static long long nsec_high(long long nsec) +{ + if (nsec < 0) { + nsec = -nsec; + do_div(nsec, 1000000); + return -nsec; + } + do_div(nsec, 1000000); + + return nsec; +} + +static unsigned long nsec_low(long long nsec) +{ + if (nsec < 0) + nsec = -nsec; + + return do_div(nsec, 1000000); +} + +#define SPLIT_NS(x) nsec_high(x), nsec_low(x) + static void print_task(struct seq_file *m, struct rq *rq, struct task_struct *p) { @@ -36,23 +61,19 @@ print_task(struct seq_file *m, struct rq *rq, struct task_struct *p) else SEQ_printf(m, " "); - SEQ_printf(m, "%15s %5d %15Ld %13Ld %13Ld %9Ld %5d ", + SEQ_printf(m, "%15s %5d %9Ld.%06ld %9Ld %5d ", p->comm, p->pid, - (long long)p->se.fair_key, - (long long)(p->se.fair_key - rq->cfs.fair_clock), - (long long)p->se.wait_runtime, + SPLIT_NS(p->se.vruntime), (long long)(p->nvcsw + p->nivcsw), p->prio); #ifdef CONFIG_SCHEDSTATS - SEQ_printf(m, "%15Ld %15Ld %15Ld %15Ld %15Ld\n", - (long long)p->se.sum_exec_runtime, - (long long)p->se.sum_wait_runtime, - (long long)p->se.sum_sleep_runtime, - (long long)p->se.wait_runtime_overruns, - (long long)p->se.wait_runtime_underruns); + SEQ_printf(m, "%9Ld.%06ld %9Ld.%06ld %9Ld.%06ld\n", + SPLIT_NS(p->se.vruntime), + SPLIT_NS(p->se.sum_exec_runtime), + SPLIT_NS(p->se.sum_sleep_runtime)); #else - SEQ_printf(m, "%15Ld %15Ld %15Ld %15Ld %15Ld\n", - 0LL, 0LL, 0LL, 0LL, 0LL); + SEQ_printf(m, "%15Ld %15Ld %15Ld.%06ld %15Ld.%06ld %15Ld.%06ld\n", + 0LL, 0LL, 0LL, 0L, 0LL, 0L, 0LL, 0L); #endif } @@ -62,14 +83,10 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu) SEQ_printf(m, "\nrunnable tasks:\n" - " task PID tree-key delta waiting" - " switches prio" - " sum-exec sum-wait sum-sleep" - " wait-overrun wait-underrun\n" - "------------------------------------------------------------------" - "----------------" - "------------------------------------------------" - "--------------------------------\n"); + " task PID tree-key switches prio" + " exec-runtime sum-exec sum-sleep\n" + "------------------------------------------------------" + "----------------------------------------------------\n"); read_lock_irq(&tasklist_lock); @@ -83,45 +100,48 @@ static void print_rq(struct seq_file *m, struct rq *rq, int rq_cpu) read_unlock_irq(&tasklist_lock); } -static void -print_cfs_rq_runtime_sum(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) +void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) { - s64 wait_runtime_rq_sum = 0; - struct task_struct *p; - struct rb_node *curr; - unsigned long flags; + s64 MIN_vruntime = -1, min_vruntime, max_vruntime = -1, + spread, rq0_min_vruntime, spread0; struct rq *rq = &per_cpu(runqueues, cpu); + struct sched_entity *last; + unsigned long flags; - spin_lock_irqsave(&rq->lock, flags); - curr = first_fair(cfs_rq); - while (curr) { - p = rb_entry(curr, struct task_struct, se.run_node); - wait_runtime_rq_sum += p->se.wait_runtime; - - curr = rb_next(curr); - } - spin_unlock_irqrestore(&rq->lock, flags); - - SEQ_printf(m, " .%-30s: %Ld\n", "wait_runtime_rq_sum", - (long long)wait_runtime_rq_sum); -} - -void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq) -{ SEQ_printf(m, "\ncfs_rq\n"); -#define P(x) \ - SEQ_printf(m, " .%-30s: %Ld\n", #x, (long long)(cfs_rq->x)) - - P(fair_clock); - P(exec_clock); - P(wait_runtime); - P(wait_runtime_overruns); - P(wait_runtime_underruns); - P(sleeper_bonus); -#undef P + SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "exec_clock", + SPLIT_NS(cfs_rq->exec_clock)); - print_cfs_rq_runtime_sum(m, cpu, cfs_rq); + spin_lock_irqsave(&rq->lock, flags); + if (cfs_rq->rb_leftmost) + MIN_vruntime = (__pick_next_entity(cfs_rq))->vruntime; + last = __pick_last_entity(cfs_rq); + if (last) + max_vruntime = last->vruntime; + min_vruntime = rq->cfs.min_vruntime; + rq0_min_vruntime = per_cpu(runqueues, 0).cfs.min_vruntime; + spin_unlock_irqrestore(&rq->lock, flags); + SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "MIN_vruntime", + SPLIT_NS(MIN_vruntime)); + SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "min_vruntime", + SPLIT_NS(min_vruntime)); + SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "max_vruntime", + SPLIT_NS(max_vruntime)); + spread = max_vruntime - MIN_vruntime; + SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "spread", + SPLIT_NS(spread)); + spread0 = min_vruntime - rq0_min_vruntime; + SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "spread0", + SPLIT_NS(spread0)); + SEQ_printf(m, " .%-30s: %ld\n", "nr_running", cfs_rq->nr_running); + SEQ_printf(m, " .%-30s: %ld\n", "load", cfs_rq->load.weight); +#ifdef CONFIG_SCHEDSTATS + SEQ_printf(m, " .%-30s: %ld\n", "bkl_count", + rq->bkl_count); +#endif + SEQ_printf(m, " .%-30s: %ld\n", "nr_spread_over", + cfs_rq->nr_spread_over); } static void print_cpu(struct seq_file *m, int cpu) @@ -141,31 +161,32 @@ static void print_cpu(struct seq_file *m, int cpu) #define P(x) \ SEQ_printf(m, " .%-30s: %Ld\n", #x, (long long)(rq->x)) +#define PN(x) \ + SEQ_printf(m, " .%-30s: %Ld.%06ld\n", #x, SPLIT_NS(rq->x)) P(nr_running); SEQ_printf(m, " .%-30s: %lu\n", "load", - rq->ls.load.weight); - P(ls.delta_fair); - P(ls.delta_exec); + rq->load.weight); P(nr_switches); P(nr_load_updates); P(nr_uninterruptible); SEQ_printf(m, " .%-30s: %lu\n", "jiffies", jiffies); - P(next_balance); + PN(next_balance); P(curr->pid); - P(clock); - P(idle_clock); - P(prev_clock_raw); + PN(clock); + PN(idle_clock); + PN(prev_clock_raw); P(clock_warps); P(clock_overflows); P(clock_deep_idle_events); - P(clock_max_delta); + PN(clock_max_delta); P(cpu_load[0]); P(cpu_load[1]); P(cpu_load[2]); P(cpu_load[3]); P(cpu_load[4]); #undef P +#undef PN print_cfs_stats(m, cpu); @@ -177,12 +198,25 @@ static int sched_debug_show(struct seq_file *m, void *v) u64 now = ktime_to_ns(ktime_get()); int cpu; - SEQ_printf(m, "Sched Debug Version: v0.05-v20, %s %.*s\n", + SEQ_printf(m, "Sched Debug Version: v0.06-v22, %s %.*s\n", init_utsname()->release, (int)strcspn(init_utsname()->version, " "), init_utsname()->version); - SEQ_printf(m, "now at %Lu nsecs\n", (unsigned long long)now); + SEQ_printf(m, "now at %Lu.%06ld msecs\n", SPLIT_NS(now)); + +#define P(x) \ + SEQ_printf(m, " .%-40s: %Ld\n", #x, (long long)(x)) +#define PN(x) \ + SEQ_printf(m, " .%-40s: %Ld.%06ld\n", #x, SPLIT_NS(x)) + PN(sysctl_sched_latency); + PN(sysctl_sched_nr_latency); + PN(sysctl_sched_wakeup_granularity); + PN(sysctl_sched_batch_wakeup_granularity); + PN(sysctl_sched_child_runs_first); + P(sysctl_sched_features); +#undef PN +#undef P for_each_online_cpu(cpu) print_cpu(m, cpu); @@ -202,7 +236,7 @@ static int sched_debug_open(struct inode *inode, struct file *filp) return single_open(filp, sched_debug_show, NULL); } -static struct file_operations sched_debug_fops = { +static const struct file_operations sched_debug_fops = { .open = sched_debug_open, .read = seq_read, .llseek = seq_lseek, @@ -226,6 +260,7 @@ __initcall(init_sched_debug_procfs); void proc_sched_show_task(struct task_struct *p, struct seq_file *m) { + unsigned long nr_switches; unsigned long flags; int num_threads = 1; @@ -237,41 +272,89 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) rcu_read_unlock(); SEQ_printf(m, "%s (%d, #threads: %d)\n", p->comm, p->pid, num_threads); - SEQ_printf(m, "----------------------------------------------\n"); + SEQ_printf(m, + "---------------------------------------------------------\n"); +#define __P(F) \ + SEQ_printf(m, "%-35s:%21Ld\n", #F, (long long)F) #define P(F) \ - SEQ_printf(m, "%-25s:%20Ld\n", #F, (long long)p->F) + SEQ_printf(m, "%-35s:%21Ld\n", #F, (long long)p->F) +#define __PN(F) \ + SEQ_printf(m, "%-35s:%14Ld.%06ld\n", #F, SPLIT_NS((long long)F)) +#define PN(F) \ + SEQ_printf(m, "%-35s:%14Ld.%06ld\n", #F, SPLIT_NS((long long)p->F)) - P(se.wait_runtime); - P(se.wait_start_fair); - P(se.exec_start); - P(se.sleep_start_fair); - P(se.sum_exec_runtime); + PN(se.exec_start); + PN(se.vruntime); + PN(se.sum_exec_runtime); + + nr_switches = p->nvcsw + p->nivcsw; #ifdef CONFIG_SCHEDSTATS - P(se.wait_start); - P(se.sleep_start); - P(se.block_start); - P(se.sleep_max); - P(se.block_max); - P(se.exec_max); - P(se.wait_max); - P(se.wait_runtime_overruns); - P(se.wait_runtime_underruns); - P(se.sum_wait_runtime); + PN(se.wait_start); + PN(se.sleep_start); + PN(se.block_start); + PN(se.sleep_max); + PN(se.block_max); + PN(se.exec_max); + PN(se.slice_max); + PN(se.wait_max); + P(sched_info.bkl_count); + P(se.nr_migrations); + P(se.nr_migrations_cold); + P(se.nr_failed_migrations_affine); + P(se.nr_failed_migrations_running); + P(se.nr_failed_migrations_hot); + P(se.nr_forced_migrations); + P(se.nr_forced2_migrations); + P(se.nr_wakeups); + P(se.nr_wakeups_sync); + P(se.nr_wakeups_migrate); + P(se.nr_wakeups_local); + P(se.nr_wakeups_remote); + P(se.nr_wakeups_affine); + P(se.nr_wakeups_affine_attempts); + P(se.nr_wakeups_passive); + P(se.nr_wakeups_idle); + + { + u64 avg_atom, avg_per_cpu; + + avg_atom = p->se.sum_exec_runtime; + if (nr_switches) + do_div(avg_atom, nr_switches); + else + avg_atom = -1LL; + + avg_per_cpu = p->se.sum_exec_runtime; + if (p->se.nr_migrations) + avg_per_cpu = div64_64(avg_per_cpu, p->se.nr_migrations); + else + avg_per_cpu = -1LL; + + __PN(avg_atom); + __PN(avg_per_cpu); + } #endif - SEQ_printf(m, "%-25s:%20Ld\n", - "nr_switches", (long long)(p->nvcsw + p->nivcsw)); + __P(nr_switches); + SEQ_printf(m, "%-35s:%21Ld\n", + "nr_voluntary_switches", (long long)p->nvcsw); + SEQ_printf(m, "%-35s:%21Ld\n", + "nr_involuntary_switches", (long long)p->nivcsw); + P(se.load.weight); P(policy); P(prio); +#undef PN +#undef __PN #undef P +#undef __P { u64 t0, t1; t0 = sched_clock(); t1 = sched_clock(); - SEQ_printf(m, "%-25s:%20Ld\n", + SEQ_printf(m, "%-35s:%21Ld\n", "clock-delta", (long long)(t1-t0)); } } @@ -279,9 +362,32 @@ void proc_sched_show_task(struct task_struct *p, struct seq_file *m) void proc_sched_set_task(struct task_struct *p) { #ifdef CONFIG_SCHEDSTATS - p->se.sleep_max = p->se.block_max = p->se.exec_max = p->se.wait_max = 0; - p->se.wait_runtime_overruns = p->se.wait_runtime_underruns = 0; + p->se.wait_max = 0; + p->se.sleep_max = 0; + p->se.sum_sleep_runtime = 0; + p->se.block_max = 0; + p->se.exec_max = 0; + p->se.slice_max = 0; + p->se.nr_migrations = 0; + p->se.nr_migrations_cold = 0; + p->se.nr_failed_migrations_affine = 0; + p->se.nr_failed_migrations_running = 0; + p->se.nr_failed_migrations_hot = 0; + p->se.nr_forced_migrations = 0; + p->se.nr_forced2_migrations = 0; + p->se.nr_wakeups = 0; + p->se.nr_wakeups_sync = 0; + p->se.nr_wakeups_migrate = 0; + p->se.nr_wakeups_local = 0; + p->se.nr_wakeups_remote = 0; + p->se.nr_wakeups_affine = 0; + p->se.nr_wakeups_affine_attempts = 0; + p->se.nr_wakeups_passive = 0; + p->se.nr_wakeups_idle = 0; + p->sched_info.bkl_count = 0; #endif - p->se.sum_exec_runtime = 0; - p->se.prev_sum_exec_runtime = 0; + p->se.sum_exec_runtime = 0; + p->se.prev_sum_exec_runtime = 0; + p->nvcsw = 0; + p->nivcsw = 0; } diff --git a/kernel/sched_fair.c b/kernel/sched_fair.c index 67c67a87146e..a17b785d7000 100644 --- a/kernel/sched_fair.c +++ b/kernel/sched_fair.c @@ -25,22 +25,26 @@ * (default: 20ms, units: nanoseconds) * * NOTE: this latency value is not the same as the concept of - * 'timeslice length' - timeslices in CFS are of variable length. - * (to see the precise effective timeslice length of your workload, - * run vmstat and monitor the context-switches field) + * 'timeslice length' - timeslices in CFS are of variable length + * and have no persistent notion like in traditional, time-slice + * based scheduling concepts. * - * On SMP systems the value of this is multiplied by the log2 of the - * number of CPUs. (i.e. factor 2x on 2-way systems, 3x on 4-way - * systems, 4x on 8-way systems, 5x on 16-way systems, etc.) - * Targeted preemption latency for CPU-bound tasks: + * (to see the precise effective timeslice length of your workload, + * run vmstat and monitor the context-switches (cs) field) */ -unsigned int sysctl_sched_latency __read_mostly = 20000000ULL; +const_debug unsigned int sysctl_sched_latency = 20000000ULL; + +/* + * After fork, child runs first. (default) If set to 0 then + * parent will (try to) run first. + */ +const_debug unsigned int sysctl_sched_child_runs_first = 1; /* * Minimal preemption granularity for CPU-bound tasks: * (default: 2 msec, units: nanoseconds) */ -unsigned int sysctl_sched_min_granularity __read_mostly = 2000000ULL; +const_debug unsigned int sysctl_sched_nr_latency = 20; /* * sys_sched_yield() compat mode @@ -52,52 +56,25 @@ unsigned int __read_mostly sysctl_sched_compat_yield; /* * SCHED_BATCH wake-up granularity. - * (default: 25 msec, units: nanoseconds) + * (default: 10 msec, units: nanoseconds) * * This option delays the preemption effects of decoupled workloads * and reduces their over-scheduling. Synchronous workloads will still * have immediate wakeup/sleep latencies. */ -unsigned int sysctl_sched_batch_wakeup_granularity __read_mostly = 25000000UL; +const_debug unsigned int sysctl_sched_batch_wakeup_granularity = 10000000UL; /* * SCHED_OTHER wake-up granularity. - * (default: 1 msec, units: nanoseconds) + * (default: 10 msec, units: nanoseconds) * * This option delays the preemption effects of decoupled workloads * and reduces their over-scheduling. Synchronous workloads will still * have immediate wakeup/sleep latencies. */ -unsigned int sysctl_sched_wakeup_granularity __read_mostly = 1000000UL; - -unsigned int sysctl_sched_stat_granularity __read_mostly; - -/* - * Initialized in sched_init_granularity() [to 5 times the base granularity]: - */ -unsigned int sysctl_sched_runtime_limit __read_mostly; - -/* - * Debugging: various feature bits - */ -enum { - SCHED_FEAT_FAIR_SLEEPERS = 1, - SCHED_FEAT_SLEEPER_AVG = 2, - SCHED_FEAT_SLEEPER_LOAD_AVG = 4, - SCHED_FEAT_PRECISE_CPU_LOAD = 8, - SCHED_FEAT_START_DEBIT = 16, - SCHED_FEAT_SKIP_INITIAL = 32, -}; +const_debug unsigned int sysctl_sched_wakeup_granularity = 10000000UL; -unsigned int sysctl_sched_features __read_mostly = - SCHED_FEAT_FAIR_SLEEPERS *1 | - SCHED_FEAT_SLEEPER_AVG *0 | - SCHED_FEAT_SLEEPER_LOAD_AVG *1 | - SCHED_FEAT_PRECISE_CPU_LOAD *1 | - SCHED_FEAT_START_DEBIT *1 | - SCHED_FEAT_SKIP_INITIAL *0; - -extern struct sched_class fair_sched_class; +const_debug unsigned int sysctl_sched_migration_cost = 500000UL; /************************************************************** * CFS operations on generic schedulable entities: @@ -111,21 +88,9 @@ static inline struct rq *rq_of(struct cfs_rq *cfs_rq) return cfs_rq->rq; } -/* currently running entity (if any) on this cfs_rq */ -static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq) -{ - return cfs_rq->curr; -} - /* An entity is a task if it doesn't "own" a runqueue */ #define entity_is_task(se) (!se->my_q) -static inline void -set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se) -{ - cfs_rq->curr = se; -} - #else /* CONFIG_FAIR_GROUP_SCHED */ static inline struct rq *rq_of(struct cfs_rq *cfs_rq) @@ -133,21 +98,8 @@ static inline struct rq *rq_of(struct cfs_rq *cfs_rq) return container_of(cfs_rq, struct rq, cfs); } -static inline struct sched_entity *cfs_rq_curr(struct cfs_rq *cfs_rq) -{ - struct rq *rq = rq_of(cfs_rq); - - if (unlikely(rq->curr->sched_class != &fair_sched_class)) - return NULL; - - return &rq->curr->se; -} - #define entity_is_task(se) 1 -static inline void -set_cfs_rq_curr(struct cfs_rq *cfs_rq, struct sched_entity *se) { } - #endif /* CONFIG_FAIR_GROUP_SCHED */ static inline struct task_struct *task_of(struct sched_entity *se) @@ -160,16 +112,38 @@ static inline struct task_struct *task_of(struct sched_entity *se) * Scheduling class tree data structure manipulation methods: */ +static inline u64 max_vruntime(u64 min_vruntime, u64 vruntime) +{ + s64 delta = (s64)(vruntime - min_vruntime); + if (delta > 0) + min_vruntime = vruntime; + + return min_vruntime; +} + +static inline u64 min_vruntime(u64 min_vruntime, u64 vruntime) +{ + s64 delta = (s64)(vruntime - min_vruntime); + if (delta < 0) + min_vruntime = vruntime; + + return min_vruntime; +} + +static inline s64 entity_key(struct cfs_rq *cfs_rq, struct sched_entity *se) +{ + return se->vruntime - cfs_rq->min_vruntime; +} + /* * Enqueue an entity into the rb-tree: */ -static inline void -__enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) +static void __enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) { struct rb_node **link = &cfs_rq->tasks_timeline.rb_node; struct rb_node *parent = NULL; struct sched_entity *entry; - s64 key = se->fair_key; + s64 key = entity_key(cfs_rq, se); int leftmost = 1; /* @@ -182,7 +156,7 @@ __enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) * We dont care about collisions. Nodes with * the same key stay together. */ - if (key - entry->fair_key < 0) { + if (key < entity_key(cfs_rq, entry)) { link = &parent->rb_left; } else { link = &parent->rb_right; @@ -199,24 +173,14 @@ __enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) rb_link_node(&se->run_node, parent, link); rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline); - update_load_add(&cfs_rq->load, se->load.weight); - cfs_rq->nr_running++; - se->on_rq = 1; - - schedstat_add(cfs_rq, wait_runtime, se->wait_runtime); } -static inline void -__dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) +static void __dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) { if (cfs_rq->rb_leftmost == &se->run_node) cfs_rq->rb_leftmost = rb_next(&se->run_node); - rb_erase(&se->run_node, &cfs_rq->tasks_timeline); - update_load_sub(&cfs_rq->load, se->load.weight); - cfs_rq->nr_running--; - se->on_rq = 0; - schedstat_add(cfs_rq, wait_runtime, -se->wait_runtime); + rb_erase(&se->run_node, &cfs_rq->tasks_timeline); } static inline struct rb_node *first_fair(struct cfs_rq *cfs_rq) @@ -229,118 +193,86 @@ static struct sched_entity *__pick_next_entity(struct cfs_rq *cfs_rq) return rb_entry(first_fair(cfs_rq), struct sched_entity, run_node); } +static inline struct sched_entity *__pick_last_entity(struct cfs_rq *cfs_rq) +{ + struct rb_node **link = &cfs_rq->tasks_timeline.rb_node; + struct sched_entity *se = NULL; + struct rb_node *parent; + + while (*link) { + parent = *link; + se = rb_entry(parent, struct sched_entity, run_node); + link = &parent->rb_right; + } + + return se; +} + /************************************************************** * Scheduling class statistics methods: */ + /* - * Calculate the preemption granularity needed to schedule every - * runnable task once per sysctl_sched_latency amount of time. - * (down to a sensible low limit on granularity) - * - * For example, if there are 2 tasks running and latency is 10 msecs, - * we switch tasks every 5 msecs. If we have 3 tasks running, we have - * to switch tasks every 3.33 msecs to get a 10 msecs observed latency - * for each task. We do finer and finer scheduling up to until we - * reach the minimum granularity value. - * - * To achieve this we use the following dynamic-granularity rule: + * The idea is to set a period in which each task runs once. * - * gran = lat/nr - lat/nr/nr + * When there are too many tasks (sysctl_sched_nr_latency) we have to stretch + * this period because otherwise the slices get too small. * - * This comes out of the following equations: - * - * kA1 + gran = kB1 - * kB2 + gran = kA2 - * kA2 = kA1 - * kB2 = kB1 - d + d/nr - * lat = d * nr - * - * Where 'k' is key, 'A' is task A (waiting), 'B' is task B (running), - * '1' is start of time, '2' is end of time, 'd' is delay between - * 1 and 2 (during which task B was running), 'nr' is number of tasks - * running, 'lat' is the the period of each task. ('lat' is the - * sched_latency that we aim for.) + * p = (nr <= nl) ? l : l*nr/nl */ -static long -sched_granularity(struct cfs_rq *cfs_rq) +static u64 __sched_period(unsigned long nr_running) { - unsigned int gran = sysctl_sched_latency; - unsigned int nr = cfs_rq->nr_running; + u64 period = sysctl_sched_latency; + unsigned long nr_latency = sysctl_sched_nr_latency; - if (nr > 1) { - gran = gran/nr - gran/nr/nr; - gran = max(gran, sysctl_sched_min_granularity); + if (unlikely(nr_running > nr_latency)) { + period *= nr_running; + do_div(period, nr_latency); } - return gran; + return period; } /* - * We rescale the rescheduling granularity of tasks according to their - * nice level, but only linearly, not exponentially: + * We calculate the wall-time slice from the period by taking a part + * proportional to the weight. + * + * s = p*w/rw */ -static long -niced_granularity(struct sched_entity *curr, unsigned long granularity) +static u64 sched_slice(struct cfs_rq *cfs_rq, struct sched_entity *se) { - u64 tmp; + u64 slice = __sched_period(cfs_rq->nr_running); - if (likely(curr->load.weight == NICE_0_LOAD)) - return granularity; - /* - * Positive nice levels get the same granularity as nice-0: - */ - if (likely(curr->load.weight < NICE_0_LOAD)) { - tmp = curr->load.weight * (u64)granularity; - return (long) (tmp >> NICE_0_SHIFT); - } - /* - * Negative nice level tasks get linearly finer - * granularity: - */ - tmp = curr->load.inv_weight * (u64)granularity; + slice *= se->load.weight; + do_div(slice, cfs_rq->load.weight); - /* - * It will always fit into 'long': - */ - return (long) (tmp >> (WMULT_SHIFT-NICE_0_SHIFT)); + return slice; } -static inline void -limit_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se) +/* + * We calculate the vruntime slice. + * + * vs = s/w = p/rw + */ +static u64 __sched_vslice(unsigned long rq_weight, unsigned long nr_running) { - long limit = sysctl_sched_runtime_limit; + u64 vslice = __sched_period(nr_running); - /* - * Niced tasks have the same history dynamic range as - * non-niced tasks: - */ - if (unlikely(se->wait_runtime > limit)) { - se->wait_runtime = limit; - schedstat_inc(se, wait_runtime_overruns); - schedstat_inc(cfs_rq, wait_runtime_overruns); - } - if (unlikely(se->wait_runtime < -limit)) { - se->wait_runtime = -limit; - schedstat_inc(se, wait_runtime_underruns); - schedstat_inc(cfs_rq, wait_runtime_underruns); - } + do_div(vslice, rq_weight); + + return vslice; } -static inline void -__add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta) +static u64 sched_vslice(struct cfs_rq *cfs_rq) { - se->wait_runtime += delta; - schedstat_add(se, sum_wait_runtime, delta); - limit_wait_runtime(cfs_rq, se); + return __sched_vslice(cfs_rq->load.weight, cfs_rq->nr_running); } -static void -add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta) +static u64 sched_vslice_add(struct cfs_rq *cfs_rq, struct sched_entity *se) { - schedstat_add(cfs_rq, wait_runtime, -se->wait_runtime); - __add_wait_runtime(cfs_rq, se, delta); - schedstat_add(cfs_rq, wait_runtime, se->wait_runtime); + return __sched_vslice(cfs_rq->load.weight + se->load.weight, + cfs_rq->nr_running + 1); } /* @@ -348,46 +280,41 @@ add_wait_runtime(struct cfs_rq *cfs_rq, struct sched_entity *se, long delta) * are not in our scheduling class. */ static inline void -__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr) +__update_curr(struct cfs_rq *cfs_rq, struct sched_entity *curr, + unsigned long delta_exec) { - unsigned long delta, delta_exec, delta_fair, delta_mine; - struct load_weight *lw = &cfs_rq->load; - unsigned long load = lw->weight; + unsigned long delta_exec_weighted; + u64 vruntime; - delta_exec = curr->delta_exec; schedstat_set(curr->exec_max, max((u64)delta_exec, curr->exec_max)); curr->sum_exec_runtime += delta_exec; - cfs_rq->exec_clock += delta_exec; - - if (unlikely(!load)) - return; - - delta_fair = calc_delta_fair(delta_exec, lw); - delta_mine = calc_delta_mine(delta_exec, curr->load.weight, lw); - - if (cfs_rq->sleeper_bonus > sysctl_sched_min_granularity) { - delta = min((u64)delta_mine, cfs_rq->sleeper_bonus); - delta = min(delta, (unsigned long)( - (long)sysctl_sched_runtime_limit - curr->wait_runtime)); - cfs_rq->sleeper_bonus -= delta; - delta_mine -= delta; + schedstat_add(cfs_rq, exec_clock, delta_exec); + delta_exec_weighted = delta_exec; + if (unlikely(curr->load.weight != NICE_0_LOAD)) { + delta_exec_weighted = calc_delta_fair(delta_exec_weighted, + &curr->load); } + curr->vruntime += delta_exec_weighted; - cfs_rq->fair_clock += delta_fair; /* - * We executed delta_exec amount of time on the CPU, - * but we were only entitled to delta_mine amount of - * time during that period (if nr_running == 1 then - * the two values are equal) - * [Note: delta_mine - delta_exec is negative]: + * maintain cfs_rq->min_vruntime to be a monotonic increasing + * value tracking the leftmost vruntime in the tree. */ - add_wait_runtime(cfs_rq, curr, delta_mine - delta_exec); + if (first_fair(cfs_rq)) { + vruntime = min_vruntime(curr->vruntime, + __pick_next_entity(cfs_rq)->vruntime); + } else + vruntime = curr->vruntime; + + cfs_rq->min_vruntime = + max_vruntime(cfs_rq->min_vruntime, vruntime); } static void update_curr(struct cfs_rq *cfs_rq) { - struct sched_entity *curr = cfs_rq_curr(cfs_rq); + struct sched_entity *curr = cfs_rq->curr; + u64 now = rq_of(cfs_rq)->clock; unsigned long delta_exec; if (unlikely(!curr)) @@ -398,135 +325,47 @@ static void update_curr(struct cfs_rq *cfs_rq) * since the last time we changed load (this cannot * overflow on 32 bits): */ - delta_exec = (unsigned long)(rq_of(cfs_rq)->clock - curr->exec_start); + delta_exec = (unsigned long)(now - curr->exec_start); - curr->delta_exec += delta_exec; - - if (unlikely(curr->delta_exec > sysctl_sched_stat_granularity)) { - __update_curr(cfs_rq, curr); - curr->delta_exec = 0; - } - curr->exec_start = rq_of(cfs_rq)->clock; + __update_curr(cfs_rq, curr, delta_exec); + curr->exec_start = now; } static inline void update_stats_wait_start(struct cfs_rq *cfs_rq, struct sched_entity *se) { - se->wait_start_fair = cfs_rq->fair_clock; schedstat_set(se->wait_start, rq_of(cfs_rq)->clock); } /* - * We calculate fair deltas here, so protect against the random effects - * of a multiplication overflow by capping it to the runtime limit: - */ -#if BITS_PER_LONG == 32 -static inline unsigned long -calc_weighted(unsigned long delta, unsigned long weight, int shift) -{ - u64 tmp = (u64)delta * weight >> shift; - - if (unlikely(tmp > sysctl_sched_runtime_limit*2)) - return sysctl_sched_runtime_limit*2; - return tmp; -} -#else -static inline unsigned long -calc_weighted(unsigned long delta, unsigned long weight, int shift) -{ - return delta * weight >> shift; -} -#endif - -/* * Task is being enqueued - update stats: */ static void update_stats_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se) { - s64 key; - /* * Are we enqueueing a waiting task? (for current tasks * a dequeue/enqueue event is a NOP) */ - if (se != cfs_rq_curr(cfs_rq)) + if (se != cfs_rq->curr) update_stats_wait_start(cfs_rq, se); - /* - * Update the key: - */ - key = cfs_rq->fair_clock; - - /* - * Optimize the common nice 0 case: - */ - if (likely(se->load.weight == NICE_0_LOAD)) { - key -= se->wait_runtime; - } else { - u64 tmp; - - if (se->wait_runtime < 0) { - tmp = -se->wait_runtime; - key += (tmp * se->load.inv_weight) >> - (WMULT_SHIFT - NICE_0_SHIFT); - } else { - tmp = se->wait_runtime; - key -= (tmp * se->load.inv_weight) >> - (WMULT_SHIFT - NICE_0_SHIFT); - } - } - - se->fair_key = key; -} - -/* - * Note: must be called with a freshly updated rq->fair_clock. - */ -static inline void -__update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se) -{ - unsigned long delta_fair = se->delta_fair_run; - - schedstat_set(se->wait_max, max(se->wait_max, - rq_of(cfs_rq)->clock - se->wait_start)); - - if (unlikely(se->load.weight != NICE_0_LOAD)) - delta_fair = calc_weighted(delta_fair, se->load.weight, - NICE_0_SHIFT); - - add_wait_runtime(cfs_rq, se, delta_fair); } static void update_stats_wait_end(struct cfs_rq *cfs_rq, struct sched_entity *se) { - unsigned long delta_fair; - - if (unlikely(!se->wait_start_fair)) - return; - - delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit), - (u64)(cfs_rq->fair_clock - se->wait_start_fair)); - - se->delta_fair_run += delta_fair; - if (unlikely(abs(se->delta_fair_run) >= - sysctl_sched_stat_granularity)) { - __update_stats_wait_end(cfs_rq, se); - se->delta_fair_run = 0; - } - - se->wait_start_fair = 0; + schedstat_set(se->wait_max, max(se->wait_max, + rq_of(cfs_rq)->clock - se->wait_start)); schedstat_set(se->wait_start, 0); } static inline void update_stats_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se) { - update_curr(cfs_rq); /* * Mark the end of the wait period if dequeueing a * waiting task: */ - if (se != cfs_rq_curr(cfs_rq)) + if (se != cfs_rq->curr) update_stats_wait_end(cfs_rq, se); } @@ -542,79 +381,28 @@ update_stats_curr_start(struct cfs_rq *cfs_rq, struct sched_entity *se) se->exec_start = rq_of(cfs_rq)->clock; } -/* - * We are descheduling a task - update its stats: - */ -static inline void -update_stats_curr_end(struct cfs_rq *cfs_rq, struct sched_entity *se) -{ - se->exec_start = 0; -} - /************************************************** * Scheduling class queueing methods: */ -static void __enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) +static void +account_entity_enqueue(struct cfs_rq *cfs_rq, struct sched_entity *se) { - unsigned long load = cfs_rq->load.weight, delta_fair; - long prev_runtime; - - /* - * Do not boost sleepers if there's too much bonus 'in flight' - * already: - */ - if (unlikely(cfs_rq->sleeper_bonus > sysctl_sched_runtime_limit)) - return; - - if (sysctl_sched_features & SCHED_FEAT_SLEEPER_LOAD_AVG) - load = rq_of(cfs_rq)->cpu_load[2]; - - delta_fair = se->delta_fair_sleep; - - /* - * Fix up delta_fair with the effect of us running - * during the whole sleep period: - */ - if (sysctl_sched_features & SCHED_FEAT_SLEEPER_AVG) - delta_fair = div64_likely32((u64)delta_fair * load, - load + se->load.weight); - - if (unlikely(se->load.weight != NICE_0_LOAD)) - delta_fair = calc_weighted(delta_fair, se->load.weight, - NICE_0_SHIFT); - - prev_runtime = se->wait_runtime; - __add_wait_runtime(cfs_rq, se, delta_fair); - delta_fair = se->wait_runtime - prev_runtime; + update_load_add(&cfs_rq->load, se->load.weight); + cfs_rq->nr_running++; + se->on_rq = 1; +} - /* - * Track the amount of bonus we've given to sleepers: - */ - cfs_rq->sleeper_bonus += delta_fair; +static void +account_entity_dequeue(struct cfs_rq *cfs_rq, struct sched_entity *se) +{ + update_load_sub(&cfs_rq->load, se->load.weight); + cfs_rq->nr_running--; + se->on_rq = 0; } static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) { - struct task_struct *tsk = task_of(se); - unsigned long delta_fair; - - if ((entity_is_task(se) && tsk->policy == SCHED_BATCH) || - !(sysctl_sched_features & SCHED_FEAT_FAIR_SLEEPERS)) - return; - - delta_fair = (unsigned long)min((u64)(2*sysctl_sched_runtime_limit), - (u64)(cfs_rq->fair_clock - se->sleep_start_fair)); - - se->delta_fair_sleep += delta_fair; - if (unlikely(abs(se->delta_fair_sleep) >= - sysctl_sched_stat_granularity)) { - __enqueue_sleeper(cfs_rq, se); - se->delta_fair_sleep = 0; - } - - se->sleep_start_fair = 0; - #ifdef CONFIG_SCHEDSTATS if (se->sleep_start) { u64 delta = rq_of(cfs_rq)->clock - se->sleep_start; @@ -646,6 +434,8 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) * time that the task spent sleeping: */ if (unlikely(prof_on == SLEEP_PROFILING)) { + struct task_struct *tsk = task_of(se); + profile_hits(SLEEP_PROFILING, (void *)get_wchan(tsk), delta >> 20); } @@ -653,27 +443,81 @@ static void enqueue_sleeper(struct cfs_rq *cfs_rq, struct sched_entity *se) #endif } +static void check_spread(struct cfs_rq *cfs_rq, struct sched_entity *se) +{ +#ifdef CONFIG_SCHED_DEBUG + s64 d = se->vruntime - cfs_rq->min_vruntime; + + if (d < 0) + d = -d; + + if (d > 3*sysctl_sched_latency) + schedstat_inc(cfs_rq, nr_spread_over); +#endif +} + +static void +place_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int initial) +{ + u64 vruntime; + + vruntime = cfs_rq->min_vruntime; + + if (sched_feat(TREE_AVG)) { + struct sched_entity *last = __pick_last_entity(cfs_rq); + if (last) { + vruntime += last->vruntime; + vruntime >>= 1; + } + } else if (sched_feat(APPROX_AVG) && cfs_rq->nr_running) + vruntime += sched_vslice(cfs_rq)/2; + + if (initial && sched_feat(START_DEBIT)) + vruntime += sched_vslice_add(cfs_rq, se); + + if (!initial) { + if (sched_feat(NEW_FAIR_SLEEPERS) && entity_is_task(se) && + task_of(se)->policy != SCHED_BATCH) + vruntime -= sysctl_sched_latency; + + vruntime = max_t(s64, vruntime, se->vruntime); + } + + se->vruntime = vruntime; + +} + static void enqueue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int wakeup) { /* - * Update the fair clock. + * Update run-time statistics of the 'current'. */ update_curr(cfs_rq); - if (wakeup) + if (wakeup) { + place_entity(cfs_rq, se, 0); enqueue_sleeper(cfs_rq, se); + } update_stats_enqueue(cfs_rq, se); - __enqueue_entity(cfs_rq, se); + check_spread(cfs_rq, se); + if (se != cfs_rq->curr) + __enqueue_entity(cfs_rq, se); + account_entity_enqueue(cfs_rq, se); } static void dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) { + /* + * Update run-time statistics of the 'current'. + */ + update_curr(cfs_rq); + update_stats_dequeue(cfs_rq, se); if (sleep) { - se->sleep_start_fair = cfs_rq->fair_clock; + se->peer_preempt = 0; #ifdef CONFIG_SCHEDSTATS if (entity_is_task(se)) { struct task_struct *tsk = task_of(se); @@ -685,68 +529,66 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int sleep) } #endif } - __dequeue_entity(cfs_rq, se); + + if (se != cfs_rq->curr) + __dequeue_entity(cfs_rq, se); + account_entity_dequeue(cfs_rq, se); } /* * Preempt the current task with a newly woken task if needed: */ static void -__check_preempt_curr_fair(struct cfs_rq *cfs_rq, struct sched_entity *se, - struct sched_entity *curr, unsigned long granularity) +check_preempt_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) { - s64 __delta = curr->fair_key - se->fair_key; unsigned long ideal_runtime, delta_exec; - /* - * ideal_runtime is compared against sum_exec_runtime, which is - * walltime, hence do not scale. - */ - ideal_runtime = max(sysctl_sched_latency / cfs_rq->nr_running, - (unsigned long)sysctl_sched_min_granularity); - - /* - * If we executed more than what the latency constraint suggests, - * reduce the rescheduling granularity. This way the total latency - * of how much a task is not scheduled converges to - * sysctl_sched_latency: - */ + ideal_runtime = sched_slice(cfs_rq, curr); delta_exec = curr->sum_exec_runtime - curr->prev_sum_exec_runtime; - if (delta_exec > ideal_runtime) - granularity = 0; - - /* - * Take scheduling granularity into account - do not - * preempt the current task unless the best task has - * a larger than sched_granularity fairness advantage: - * - * scale granularity as key space is in fair_clock. - */ - if (__delta > niced_granularity(curr, granularity)) + if (delta_exec > ideal_runtime || + (sched_feat(PREEMPT_RESTRICT) && curr->peer_preempt)) resched_task(rq_of(cfs_rq)->curr); + curr->peer_preempt = 0; } -static inline void +static void set_next_entity(struct cfs_rq *cfs_rq, struct sched_entity *se) { + /* 'current' is not kept within the tree. */ + if (se->on_rq) { + /* + * Any task has to be enqueued before it get to execute on + * a CPU. So account for the time it spent waiting on the + * runqueue. + */ + update_stats_wait_end(cfs_rq, se); + __dequeue_entity(cfs_rq, se); + } + + update_stats_curr_start(cfs_rq, se); + cfs_rq->curr = se; +#ifdef CONFIG_SCHEDSTATS /* - * Any task has to be enqueued before it get to execute on - * a CPU. So account for the time it spent waiting on the - * runqueue. (note, here we rely on pick_next_task() having - * done a put_prev_task_fair() shortly before this, which - * updated rq->fair_clock - used by update_stats_wait_end()) + * Track our maximum slice length, if the CPU's load is at + * least twice that of our own weight (i.e. dont track it + * when there are only lesser-weight tasks around): */ - update_stats_wait_end(cfs_rq, se); - update_stats_curr_start(cfs_rq, se); - set_cfs_rq_curr(cfs_rq, se); + if (rq_of(cfs_rq)->load.weight >= 2*se->load.weight) { + se->slice_max = max(se->slice_max, + se->sum_exec_runtime - se->prev_sum_exec_runtime); + } +#endif se->prev_sum_exec_runtime = se->sum_exec_runtime; } static struct sched_entity *pick_next_entity(struct cfs_rq *cfs_rq) { - struct sched_entity *se = __pick_next_entity(cfs_rq); + struct sched_entity *se = NULL; - set_next_entity(cfs_rq, se); + if (first_fair(cfs_rq)) { + se = __pick_next_entity(cfs_rq); + set_next_entity(cfs_rq, se); + } return se; } @@ -760,33 +602,24 @@ static void put_prev_entity(struct cfs_rq *cfs_rq, struct sched_entity *prev) if (prev->on_rq) update_curr(cfs_rq); - update_stats_curr_end(cfs_rq, prev); - - if (prev->on_rq) + check_spread(cfs_rq, prev); + if (prev->on_rq) { update_stats_wait_start(cfs_rq, prev); - set_cfs_rq_curr(cfs_rq, NULL); + /* Put 'current' back into the tree. */ + __enqueue_entity(cfs_rq, prev); + } + cfs_rq->curr = NULL; } static void entity_tick(struct cfs_rq *cfs_rq, struct sched_entity *curr) { - struct sched_entity *next; - /* - * Dequeue and enqueue the task to update its - * position within the tree: + * Update run-time statistics of the 'current'. */ - dequeue_entity(cfs_rq, curr, 0); - enqueue_entity(cfs_rq, curr, 0); - - /* - * Reschedule if another task tops the current one. - */ - next = __pick_next_entity(cfs_rq); - if (next == curr) - return; + update_curr(cfs_rq); - __check_preempt_curr_fair(cfs_rq, next, curr, - sched_granularity(cfs_rq)); + if (cfs_rq->nr_running > 1 || !sched_feat(WAKEUP_PREEMPT)) + check_preempt_tick(cfs_rq, curr); } /************************************************** @@ -821,23 +654,28 @@ static inline struct cfs_rq *group_cfs_rq(struct sched_entity *grp) */ static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu) { - /* A later patch will take group into account */ - return &cpu_rq(this_cpu)->cfs; + return cfs_rq->tg->cfs_rq[this_cpu]; } /* Iterate thr' all leaf cfs_rq's on a runqueue */ #define for_each_leaf_cfs_rq(rq, cfs_rq) \ list_for_each_entry(cfs_rq, &rq->leaf_cfs_rq_list, leaf_cfs_rq_list) -/* Do the two (enqueued) tasks belong to the same group ? */ -static inline int is_same_group(struct task_struct *curr, struct task_struct *p) +/* Do the two (enqueued) entities belong to the same group ? */ +static inline int +is_same_group(struct sched_entity *se, struct sched_entity *pse) { - if (curr->se.cfs_rq == p->se.cfs_rq) + if (se->cfs_rq == pse->cfs_rq) return 1; return 0; } +static inline struct sched_entity *parent_entity(struct sched_entity *se) +{ + return se->parent; +} + #else /* CONFIG_FAIR_GROUP_SCHED */ #define for_each_sched_entity(se) \ @@ -870,11 +708,17 @@ static inline struct cfs_rq *cpu_cfs_rq(struct cfs_rq *cfs_rq, int this_cpu) #define for_each_leaf_cfs_rq(rq, cfs_rq) \ for (cfs_rq = &rq->cfs; cfs_rq; cfs_rq = NULL) -static inline int is_same_group(struct task_struct *curr, struct task_struct *p) +static inline int +is_same_group(struct sched_entity *se, struct sched_entity *pse) { return 1; } +static inline struct sched_entity *parent_entity(struct sched_entity *se) +{ + return NULL; +} + #endif /* CONFIG_FAIR_GROUP_SCHED */ /* @@ -892,6 +736,7 @@ static void enqueue_task_fair(struct rq *rq, struct task_struct *p, int wakeup) break; cfs_rq = cfs_rq_of(se); enqueue_entity(cfs_rq, se, wakeup); + wakeup = 1; } } @@ -911,6 +756,7 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep) /* Don't dequeue parent if it has other entities besides us */ if (cfs_rq->load.weight) break; + sleep = 1; } } @@ -919,12 +765,10 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int sleep) * * If compat_yield is turned on then we requeue to the end of the tree. */ -static void yield_task_fair(struct rq *rq, struct task_struct *p) +static void yield_task_fair(struct rq *rq) { - struct cfs_rq *cfs_rq = task_cfs_rq(p); - struct rb_node **link = &cfs_rq->tasks_timeline.rb_node; - struct sched_entity *rightmost, *se = &p->se; - struct rb_node *parent; + struct cfs_rq *cfs_rq = task_cfs_rq(rq->curr); + struct sched_entity *rightmost, *se = &rq->curr->se; /* * Are we the only task in the tree? @@ -935,52 +779,39 @@ static void yield_task_fair(struct rq *rq, struct task_struct *p) if (likely(!sysctl_sched_compat_yield)) { __update_rq_clock(rq); /* - * Dequeue and enqueue the task to update its - * position within the tree: + * Update run-time statistics of the 'current'. */ - dequeue_entity(cfs_rq, &p->se, 0); - enqueue_entity(cfs_rq, &p->se, 0); + update_curr(cfs_rq); return; } /* * Find the rightmost entry in the rbtree: */ - do { - parent = *link; - link = &parent->rb_right; - } while (*link); - - rightmost = rb_entry(parent, struct sched_entity, run_node); + rightmost = __pick_last_entity(cfs_rq); /* * Already in the rightmost position? */ - if (unlikely(rightmost == se)) + if (unlikely(rightmost->vruntime < se->vruntime)) return; /* * Minimally necessary key value to be last in the tree: + * Upon rescheduling, sched_class::put_prev_task() will place + * 'current' within the tree based on its new key value. */ - se->fair_key = rightmost->fair_key + 1; - - if (cfs_rq->rb_leftmost == &se->run_node) - cfs_rq->rb_leftmost = rb_next(&se->run_node); - /* - * Relink the task to the rightmost position: - */ - rb_erase(&se->run_node, &cfs_rq->tasks_timeline); - rb_link_node(&se->run_node, parent, link); - rb_insert_color(&se->run_node, &cfs_rq->tasks_timeline); + se->vruntime = rightmost->vruntime + 1; } /* * Preempt the current task with a newly woken task if needed: */ -static void check_preempt_curr_fair(struct rq *rq, struct task_struct *p) +static void check_preempt_wakeup(struct rq *rq, struct task_struct *p) { struct task_struct *curr = rq->curr; struct cfs_rq *cfs_rq = task_cfs_rq(curr); - unsigned long gran; + struct sched_entity *se = &curr->se, *pse = &p->se; + s64 delta, gran; if (unlikely(rt_prio(p->prio))) { update_rq_clock(rq); @@ -988,16 +819,31 @@ static void check_preempt_curr_fair(struct rq *rq, struct task_struct *p) resched_task(curr); return; } - - gran = sysctl_sched_wakeup_granularity; /* - * Batch tasks prefer throughput over latency: + * Batch tasks do not preempt (their preemption is driven by + * the tick): */ if (unlikely(p->policy == SCHED_BATCH)) - gran = sysctl_sched_batch_wakeup_granularity; + return; + + if (sched_feat(WAKEUP_PREEMPT)) { + while (!is_same_group(se, pse)) { + se = parent_entity(se); + pse = parent_entity(pse); + } - if (is_same_group(curr, p)) - __check_preempt_curr_fair(cfs_rq, &p->se, &curr->se, gran); + delta = se->vruntime - pse->vruntime; + gran = sysctl_sched_wakeup_granularity; + if (unlikely(se->load.weight != NICE_0_LOAD)) + gran = calc_delta_fair(gran, &se->load); + + if (delta > gran) { + int now = !sched_feat(PREEMPT_RESTRICT); + + if (now || p->prio < curr->prio || !se->peer_preempt++) + resched_task(curr); + } + } } static struct task_struct *pick_next_task_fair(struct rq *rq) @@ -1041,7 +887,7 @@ static void put_prev_task_fair(struct rq *rq, struct task_struct *prev) * achieve that by always pre-iterating before returning * the current task: */ -static inline struct task_struct * +static struct task_struct * __load_balance_iterator(struct cfs_rq *cfs_rq, struct rb_node *curr) { struct task_struct *p; @@ -1078,7 +924,10 @@ static int cfs_rq_best_prio(struct cfs_rq *cfs_rq) if (!cfs_rq->nr_running) return MAX_PRIO; - curr = __pick_next_entity(cfs_rq); + curr = cfs_rq->curr; + if (!curr) + curr = __pick_next_entity(cfs_rq); + p = task_of(curr); return p->prio; @@ -1153,6 +1002,8 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr) } } +#define swap(a,b) do { typeof(a) tmp = (a); (a) = (b); (b) = tmp; } while (0) + /* * Share the fairness runtime between parent and child, thus the * total amount of pressure for CPU stays equal - new tasks @@ -1163,37 +1014,32 @@ static void task_tick_fair(struct rq *rq, struct task_struct *curr) static void task_new_fair(struct rq *rq, struct task_struct *p) { struct cfs_rq *cfs_rq = task_cfs_rq(p); - struct sched_entity *se = &p->se, *curr = cfs_rq_curr(cfs_rq); + struct sched_entity *se = &p->se, *curr = cfs_rq->curr; + int this_cpu = smp_processor_id(); sched_info_queued(p); update_curr(cfs_rq); - update_stats_enqueue(cfs_rq, se); - /* - * Child runs first: we let it run before the parent - * until it reschedules once. We set up the key so that - * it will preempt the parent: - */ - se->fair_key = curr->fair_key - - niced_granularity(curr, sched_granularity(cfs_rq)) - 1; - /* - * The first wait is dominated by the child-runs-first logic, - * so do not credit it with that waiting time yet: - */ - if (sysctl_sched_features & SCHED_FEAT_SKIP_INITIAL) - se->wait_start_fair = 0; + place_entity(cfs_rq, se, 1); - /* - * The statistical average of wait_runtime is about - * -granularity/2, so initialize the task with that: - */ - if (sysctl_sched_features & SCHED_FEAT_START_DEBIT) - se->wait_runtime = -(sched_granularity(cfs_rq) / 2); + if (sysctl_sched_child_runs_first && this_cpu == task_cpu(p) && + curr->vruntime < se->vruntime) { + /* + * Upon rescheduling, sched_class::put_prev_task() will place + * 'current' within the tree based on its new key value. + */ + swap(curr->vruntime, se->vruntime); + } + update_stats_enqueue(cfs_rq, se); + check_spread(cfs_rq, se); + check_spread(cfs_rq, curr); __enqueue_entity(cfs_rq, se); + account_entity_enqueue(cfs_rq, se); + se->peer_preempt = 0; + resched_task(rq->curr); } -#ifdef CONFIG_FAIR_GROUP_SCHED /* Account for a task changing its policy or group. * * This routine is mostly called to set cfs_rq->curr field when a task @@ -1206,21 +1052,17 @@ static void set_curr_task_fair(struct rq *rq) for_each_sched_entity(se) set_next_entity(cfs_rq_of(se), se); } -#else -static void set_curr_task_fair(struct rq *rq) -{ -} -#endif /* * All the scheduling class methods: */ -struct sched_class fair_sched_class __read_mostly = { +static const struct sched_class fair_sched_class = { + .next = &idle_sched_class, .enqueue_task = enqueue_task_fair, .dequeue_task = dequeue_task_fair, .yield_task = yield_task_fair, - .check_preempt_curr = check_preempt_curr_fair, + .check_preempt_curr = check_preempt_wakeup, .pick_next_task = pick_next_task_fair, .put_prev_task = put_prev_task_fair, @@ -1237,6 +1079,9 @@ static void print_cfs_stats(struct seq_file *m, int cpu) { struct cfs_rq *cfs_rq; +#ifdef CONFIG_FAIR_GROUP_SCHED + print_cfs_rq(m, cpu, &cpu_rq(cpu)->cfs); +#endif for_each_leaf_cfs_rq(cpu_rq(cpu), cfs_rq) print_cfs_rq(m, cpu, cfs_rq); } diff --git a/kernel/sched_idletask.c b/kernel/sched_idletask.c index 3503fb2d9f96..6e2ead41516e 100644 --- a/kernel/sched_idletask.c +++ b/kernel/sched_idletask.c @@ -50,10 +50,15 @@ static void task_tick_idle(struct rq *rq, struct task_struct *curr) { } +static void set_curr_task_idle(struct rq *rq) +{ +} + /* * Simple, special scheduling class for the per-CPU idle tasks: */ -static struct sched_class idle_sched_class __read_mostly = { +const struct sched_class idle_sched_class = { + /* .next is NULL */ /* no enqueue/yield_task for idle tasks */ /* dequeue is not valid, we print a debug message there: */ @@ -66,6 +71,7 @@ static struct sched_class idle_sched_class __read_mostly = { .load_balance = load_balance_idle, + .set_curr_task = set_curr_task_idle, .task_tick = task_tick_idle, /* no .task_new for idle tasks */ }; diff --git a/kernel/sched_rt.c b/kernel/sched_rt.c index 4b87476a02d0..d0097a0634e5 100644 --- a/kernel/sched_rt.c +++ b/kernel/sched_rt.c @@ -7,7 +7,7 @@ * Update the current task's runtime statistics. Skip current tasks that * are not in our scheduling class. */ -static inline void update_curr_rt(struct rq *rq) +static void update_curr_rt(struct rq *rq) { struct task_struct *curr = rq->curr; u64 delta_exec; @@ -59,9 +59,9 @@ static void requeue_task_rt(struct rq *rq, struct task_struct *p) } static void -yield_task_rt(struct rq *rq, struct task_struct *p) +yield_task_rt(struct rq *rq) { - requeue_task_rt(rq, p); + requeue_task_rt(rq, rq->curr); } /* @@ -206,7 +206,7 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p) if (--p->time_slice) return; - p->time_slice = static_prio_timeslice(p->static_prio); + p->time_slice = DEF_TIMESLICE; /* * Requeue to the end of queue if we are not the only element @@ -218,7 +218,15 @@ static void task_tick_rt(struct rq *rq, struct task_struct *p) } } -static struct sched_class rt_sched_class __read_mostly = { +static void set_curr_task_rt(struct rq *rq) +{ + struct task_struct *p = rq->curr; + + p->se.exec_start = rq->clock; +} + +const struct sched_class rt_sched_class = { + .next = &fair_sched_class, .enqueue_task = enqueue_task_rt, .dequeue_task = dequeue_task_rt, .yield_task = yield_task_rt, @@ -230,5 +238,6 @@ static struct sched_class rt_sched_class __read_mostly = { .load_balance = load_balance_rt, + .set_curr_task = set_curr_task_rt, .task_tick = task_tick_rt, }; diff --git a/kernel/sched_stats.h b/kernel/sched_stats.h index c20a94dda61e..1c084842c3e7 100644 --- a/kernel/sched_stats.h +++ b/kernel/sched_stats.h @@ -16,18 +16,18 @@ static int show_schedstat(struct seq_file *seq, void *v) struct rq *rq = cpu_rq(cpu); #ifdef CONFIG_SMP struct sched_domain *sd; - int dcnt = 0; + int dcount = 0; #endif /* runqueue-specific stats */ seq_printf(seq, "cpu%d %lu %lu %lu %lu %lu %lu %lu %lu %lu %llu %llu %lu", cpu, rq->yld_both_empty, - rq->yld_act_empty, rq->yld_exp_empty, rq->yld_cnt, - rq->sched_switch, rq->sched_cnt, rq->sched_goidle, - rq->ttwu_cnt, rq->ttwu_local, + rq->yld_act_empty, rq->yld_exp_empty, rq->yld_count, + rq->sched_switch, rq->sched_count, rq->sched_goidle, + rq->ttwu_count, rq->ttwu_local, rq->rq_sched_info.cpu_time, - rq->rq_sched_info.run_delay, rq->rq_sched_info.pcnt); + rq->rq_sched_info.run_delay, rq->rq_sched_info.pcount); seq_printf(seq, "\n"); @@ -39,12 +39,12 @@ static int show_schedstat(struct seq_file *seq, void *v) char mask_str[NR_CPUS]; cpumask_scnprintf(mask_str, NR_CPUS, sd->span); - seq_printf(seq, "domain%d %s", dcnt++, mask_str); + seq_printf(seq, "domain%d %s", dcount++, mask_str); for (itype = CPU_IDLE; itype < CPU_MAX_IDLE_TYPES; itype++) { seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu " "%lu", - sd->lb_cnt[itype], + sd->lb_count[itype], sd->lb_balanced[itype], sd->lb_failed[itype], sd->lb_imbalance[itype], @@ -55,9 +55,9 @@ static int show_schedstat(struct seq_file *seq, void *v) } seq_printf(seq, " %lu %lu %lu %lu %lu %lu %lu %lu %lu" " %lu %lu %lu\n", - sd->alb_cnt, sd->alb_failed, sd->alb_pushed, - sd->sbe_cnt, sd->sbe_balanced, sd->sbe_pushed, - sd->sbf_cnt, sd->sbf_balanced, sd->sbf_pushed, + sd->alb_count, sd->alb_failed, sd->alb_pushed, + sd->sbe_count, sd->sbe_balanced, sd->sbe_pushed, + sd->sbf_count, sd->sbf_balanced, sd->sbf_pushed, sd->ttwu_wake_remote, sd->ttwu_move_affine, sd->ttwu_move_balance); } @@ -101,7 +101,7 @@ rq_sched_info_arrive(struct rq *rq, unsigned long long delta) { if (rq) { rq->rq_sched_info.run_delay += delta; - rq->rq_sched_info.pcnt++; + rq->rq_sched_info.pcount++; } } @@ -129,7 +129,7 @@ rq_sched_info_depart(struct rq *rq, unsigned long long delta) # define schedstat_set(var, val) do { } while (0) #endif -#if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) +#ifdef CONFIG_SCHEDSTATS /* * Called when a process is dequeued from the active array and given * the cpu. We should note that with the exception of interactive @@ -164,7 +164,7 @@ static void sched_info_arrive(struct task_struct *t) sched_info_dequeued(t); t->sched_info.run_delay += delta; t->sched_info.last_arrival = now; - t->sched_info.pcnt++; + t->sched_info.pcount++; rq_sched_info_arrive(task_rq(t), delta); } @@ -233,5 +233,5 @@ sched_info_switch(struct task_struct *prev, struct task_struct *next) #else #define sched_info_queued(t) do { } while (0) #define sched_info_switch(t, next) do { } while (0) -#endif /* CONFIG_SCHEDSTATS || CONFIG_TASK_DELAY_ACCT */ +#endif /* CONFIG_SCHEDSTATS */ diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 6c97259e863e..ec14aa8ac51f 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c @@ -222,14 +222,11 @@ static ctl_table kern_table[] = { #ifdef CONFIG_SCHED_DEBUG { .ctl_name = CTL_UNNUMBERED, - .procname = "sched_min_granularity_ns", - .data = &sysctl_sched_min_granularity, + .procname = "sched_nr_latency", + .data = &sysctl_sched_nr_latency, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &min_sched_granularity_ns, - .extra2 = &max_sched_granularity_ns, + .proc_handler = &proc_dointvec, }, { .ctl_name = CTL_UNNUMBERED, @@ -266,38 +263,24 @@ static ctl_table kern_table[] = { }, { .ctl_name = CTL_UNNUMBERED, - .procname = "sched_stat_granularity_ns", - .data = &sysctl_sched_stat_granularity, - .maxlen = sizeof(unsigned int), - .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &min_wakeup_granularity_ns, - .extra2 = &max_wakeup_granularity_ns, - }, - { - .ctl_name = CTL_UNNUMBERED, - .procname = "sched_runtime_limit_ns", - .data = &sysctl_sched_runtime_limit, + .procname = "sched_child_runs_first", + .data = &sysctl_sched_child_runs_first, .maxlen = sizeof(unsigned int), .mode = 0644, - .proc_handler = &proc_dointvec_minmax, - .strategy = &sysctl_intvec, - .extra1 = &min_sched_granularity_ns, - .extra2 = &max_sched_granularity_ns, + .proc_handler = &proc_dointvec, }, { .ctl_name = CTL_UNNUMBERED, - .procname = "sched_child_runs_first", - .data = &sysctl_sched_child_runs_first, + .procname = "sched_features", + .data = &sysctl_sched_features, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec, }, { .ctl_name = CTL_UNNUMBERED, - .procname = "sched_features", - .data = &sysctl_sched_features, + .procname = "sched_migration_cost", + .data = &sysctl_sched_migration_cost, .maxlen = sizeof(unsigned int), .mode = 0644, .proc_handler = &proc_dointvec, diff --git a/kernel/user.c b/kernel/user.c index 9ca2848fc356..f0e561e6d085 100644 --- a/kernel/user.c +++ b/kernel/user.c @@ -50,12 +50,16 @@ struct user_struct root_user = { .uid_keyring = &root_user_keyring, .session_keyring = &root_session_keyring, #endif +#ifdef CONFIG_FAIR_USER_SCHED + .tg = &init_task_group, +#endif }; /* * These routines must be called with the uidhash spinlock held! */ -static inline void uid_hash_insert(struct user_struct *up, struct hlist_head *hashent) +static inline void uid_hash_insert(struct user_struct *up, + struct hlist_head *hashent) { hlist_add_head(&up->uidhash_node, hashent); } @@ -65,13 +69,14 @@ static inline void uid_hash_remove(struct user_struct *up) hlist_del_init(&up->uidhash_node); } -static inline struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *hashent) +static inline struct user_struct *uid_hash_find(uid_t uid, + struct hlist_head *hashent) { struct user_struct *user; struct hlist_node *h; hlist_for_each_entry(user, h, hashent, uidhash_node) { - if(user->uid == uid) { + if (user->uid == uid) { atomic_inc(&user->__count); return user; } @@ -80,6 +85,203 @@ static inline struct user_struct *uid_hash_find(uid_t uid, struct hlist_head *ha return NULL; } +#ifdef CONFIG_FAIR_USER_SCHED + +static struct kobject uids_kobject; /* represents /sys/kernel/uids directory */ +static DEFINE_MUTEX(uids_mutex); + +static void sched_destroy_user(struct user_struct *up) +{ + sched_destroy_group(up->tg); +} + +static int sched_create_user(struct user_struct *up) +{ + int rc = 0; + + up->tg = sched_create_group(); + if (IS_ERR(up->tg)) + rc = -ENOMEM; + + return rc; +} + +static void sched_switch_user(struct task_struct *p) +{ + sched_move_task(p); +} + +static inline void uids_mutex_lock(void) +{ + mutex_lock(&uids_mutex); +} + +static inline void uids_mutex_unlock(void) +{ + mutex_unlock(&uids_mutex); +} + +/* return cpu shares held by the user */ +ssize_t cpu_shares_show(struct kset *kset, char *buffer) +{ + struct user_struct *up = container_of(kset, struct user_struct, kset); + + return sprintf(buffer, "%lu\n", sched_group_shares(up->tg)); +} + +/* modify cpu shares held by the user */ +ssize_t cpu_shares_store(struct kset *kset, const char *buffer, size_t size) +{ + struct user_struct *up = container_of(kset, struct user_struct, kset); + unsigned long shares; + int rc; + + sscanf(buffer, "%lu", &shares); + + rc = sched_group_set_shares(up->tg, shares); + + return (rc ? rc : size); +} + +static void user_attr_init(struct subsys_attribute *sa, char *name, int mode) +{ + sa->attr.name = name; + sa->attr.mode = mode; + sa->show = cpu_shares_show; + sa->store = cpu_shares_store; +} + +/* Create "/sys/kernel/uids/<uid>" directory and + * "/sys/kernel/uids/<uid>/cpu_share" file for this user. + */ +static int user_kobject_create(struct user_struct *up) +{ + struct kset *kset = &up->kset; + struct kobject *kobj = &kset->kobj; + int error; + + memset(kset, 0, sizeof(struct kset)); + kobj->parent = &uids_kobject; /* create under /sys/kernel/uids dir */ + kobject_set_name(kobj, "%d", up->uid); + kset_init(kset); + user_attr_init(&up->user_attr, "cpu_share", 0644); + + error = kobject_add(kobj); + if (error) + goto done; + + error = sysfs_create_file(kobj, &up->user_attr.attr); + if (error) + kobject_del(kobj); + + kobject_uevent(kobj, KOBJ_ADD); + +done: + return error; +} + +/* create these in sysfs filesystem: + * "/sys/kernel/uids" directory + * "/sys/kernel/uids/0" directory (for root user) + * "/sys/kernel/uids/0/cpu_share" file (for root user) + */ +int __init uids_kobject_init(void) +{ + int error; + + /* create under /sys/kernel dir */ + uids_kobject.parent = &kernel_subsys.kobj; + uids_kobject.kset = &kernel_subsys; + kobject_set_name(&uids_kobject, "uids"); + kobject_init(&uids_kobject); + + error = kobject_add(&uids_kobject); + if (!error) + error = user_kobject_create(&root_user); + + return error; +} + +/* work function to remove sysfs directory for a user and free up + * corresponding structures. + */ +static void remove_user_sysfs_dir(struct work_struct *w) +{ + struct user_struct *up = container_of(w, struct user_struct, work); + struct kobject *kobj = &up->kset.kobj; + unsigned long flags; + int remove_user = 0; + + /* Make uid_hash_remove() + sysfs_remove_file() + kobject_del() + * atomic. + */ + uids_mutex_lock(); + + local_irq_save(flags); + + if (atomic_dec_and_lock(&up->__count, &uidhash_lock)) { + uid_hash_remove(up); + remove_user = 1; + spin_unlock_irqrestore(&uidhash_lock, flags); + } else { + local_irq_restore(flags); + } + + if (!remove_user) + goto done; + + sysfs_remove_file(kobj, &up->user_attr.attr); + kobject_uevent(kobj, KOBJ_REMOVE); + kobject_del(kobj); + + sched_destroy_user(up); + key_put(up->uid_keyring); + key_put(up->session_keyring); + kmem_cache_free(uid_cachep, up); + +done: + uids_mutex_unlock(); +} + +/* IRQs are disabled and uidhash_lock is held upon function entry. + * IRQ state (as stored in flags) is restored and uidhash_lock released + * upon function exit. + */ +static inline void free_user(struct user_struct *up, unsigned long flags) +{ + /* restore back the count */ + atomic_inc(&up->__count); + spin_unlock_irqrestore(&uidhash_lock, flags); + + INIT_WORK(&up->work, remove_user_sysfs_dir); + schedule_work(&up->work); +} + +#else /* CONFIG_FAIR_USER_SCHED */ + +static void sched_destroy_user(struct user_struct *up) { } +static int sched_create_user(struct user_struct *up) { return 0; } +static void sched_switch_user(struct task_struct *p) { } +static inline int user_kobject_create(struct user_struct *up) { return 0; } +static inline void uids_mutex_lock(void) { } +static inline void uids_mutex_unlock(void) { } + +/* IRQs are disabled and uidhash_lock is held upon function entry. + * IRQ state (as stored in flags) is restored and uidhash_lock released + * upon function exit. + */ +static inline void free_user(struct user_struct *up, unsigned long flags) +{ + uid_hash_remove(up); + spin_unlock_irqrestore(&uidhash_lock, flags); + sched_destroy_user(up); + key_put(up->uid_keyring); + key_put(up->session_keyring); + kmem_cache_free(uid_cachep, up); +} + +#endif /* CONFIG_FAIR_USER_SCHED */ + /* * Locate the user_struct for the passed UID. If found, take a ref on it. The * caller must undo that ref with free_uid(). @@ -106,15 +308,10 @@ void free_uid(struct user_struct *up) return; local_irq_save(flags); - if (atomic_dec_and_lock(&up->__count, &uidhash_lock)) { - uid_hash_remove(up); - spin_unlock_irqrestore(&uidhash_lock, flags); - key_put(up->uid_keyring); - key_put(up->session_keyring); - kmem_cache_free(uid_cachep, up); - } else { + if (atomic_dec_and_lock(&up->__count, &uidhash_lock)) + free_user(up, flags); + else local_irq_restore(flags); - } } struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) @@ -122,6 +319,11 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) struct hlist_head *hashent = uidhashentry(ns, uid); struct user_struct *up; + /* Make uid_hash_find() + user_kobject_create() + uid_hash_insert() + * atomic. + */ + uids_mutex_lock(); + spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); spin_unlock_irq(&uidhash_lock); @@ -150,6 +352,22 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) return NULL; } + if (sched_create_user(new) < 0) { + key_put(new->uid_keyring); + key_put(new->session_keyring); + kmem_cache_free(uid_cachep, new); + return NULL; + } + + if (user_kobject_create(new)) { + sched_destroy_user(new); + key_put(new->uid_keyring); + key_put(new->session_keyring); + kmem_cache_free(uid_cachep, new); + uids_mutex_unlock(); + return NULL; + } + /* * Before adding this, check whether we raced * on adding the same user already.. @@ -157,6 +375,11 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) spin_lock_irq(&uidhash_lock); up = uid_hash_find(uid, hashent); if (up) { + /* This case is not possible when CONFIG_FAIR_USER_SCHED + * is defined, since we serialize alloc_uid() using + * uids_mutex. Hence no need to call + * sched_destroy_user() or remove_user_sysfs_dir(). + */ key_put(new->uid_keyring); key_put(new->session_keyring); kmem_cache_free(uid_cachep, new); @@ -167,6 +390,9 @@ struct user_struct * alloc_uid(struct user_namespace *ns, uid_t uid) spin_unlock_irq(&uidhash_lock); } + + uids_mutex_unlock(); + return up; } @@ -184,6 +410,7 @@ void switch_uid(struct user_struct *new_user) atomic_dec(&old_user->processes); switch_uid_keyring(new_user); current->user = new_user; + sched_switch_user(current); /* * We need to synchronize with __sigqueue_alloc() diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 7da7050f06c3..73940df6c460 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c @@ -631,7 +631,8 @@ svc_safe_putnetobj(struct kvec *resv, struct xdr_netobj *o) return 0; } -/* Verify the checksum on the header and return SVC_OK on success. +/* + * Verify the checksum on the header and return SVC_OK on success. * Otherwise, return SVC_DROP (in the case of a bad sequence number) * or return SVC_DENIED and indicate error in authp. */ @@ -961,6 +962,78 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) } /* + * Having read the cred already and found we're in the context + * initiation case, read the verifier and initiate (or check the results + * of) upcalls to userspace for help with context initiation. If + * the upcall results are available, write the verifier and result. + * Otherwise, drop the request pending an answer to the upcall. + */ +static int svcauth_gss_handle_init(struct svc_rqst *rqstp, + struct rpc_gss_wire_cred *gc, __be32 *authp) +{ + struct kvec *argv = &rqstp->rq_arg.head[0]; + struct kvec *resv = &rqstp->rq_res.head[0]; + struct xdr_netobj tmpobj; + struct rsi *rsip, rsikey; + + /* Read the verifier; should be NULL: */ + *authp = rpc_autherr_badverf; + if (argv->iov_len < 2 * 4) + return SVC_DENIED; + if (svc_getnl(argv) != RPC_AUTH_NULL) + return SVC_DENIED; + if (svc_getnl(argv) != 0) + return SVC_DENIED; + + /* Martial context handle and token for upcall: */ + *authp = rpc_autherr_badcred; + if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) + return SVC_DENIED; + memset(&rsikey, 0, sizeof(rsikey)); + if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) + return SVC_DROP; + *authp = rpc_autherr_badverf; + if (svc_safe_getnetobj(argv, &tmpobj)) { + kfree(rsikey.in_handle.data); + return SVC_DENIED; + } + if (dup_netobj(&rsikey.in_token, &tmpobj)) { + kfree(rsikey.in_handle.data); + return SVC_DROP; + } + + /* Perform upcall, or find upcall result: */ + rsip = rsi_lookup(&rsikey); + rsi_free(&rsikey); + if (!rsip) + return SVC_DROP; + switch (cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { + case -EAGAIN: + case -ETIMEDOUT: + case -ENOENT: + /* No upcall result: */ + return SVC_DROP; + case 0: + /* Got an answer to the upcall; use it: */ + if (gss_write_init_verf(rqstp, rsip)) + return SVC_DROP; + if (resv->iov_len + 4 > PAGE_SIZE) + return SVC_DROP; + svc_putnl(resv, RPC_SUCCESS); + if (svc_safe_putnetobj(resv, &rsip->out_handle)) + return SVC_DROP; + if (resv->iov_len + 3 * 4 > PAGE_SIZE) + return SVC_DROP; + svc_putnl(resv, rsip->major_status); + svc_putnl(resv, rsip->minor_status); + svc_putnl(resv, GSS_SEQ_WIN); + if (svc_safe_putnetobj(resv, &rsip->out_token)) + return SVC_DROP; + } + return SVC_COMPLETE; +} + +/* * Accept an rpcsec packet. * If context establishment, punt to user space * If data exchange, verify/decrypt @@ -974,11 +1047,9 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) struct kvec *argv = &rqstp->rq_arg.head[0]; struct kvec *resv = &rqstp->rq_res.head[0]; u32 crlen; - struct xdr_netobj tmpobj; struct gss_svc_data *svcdata = rqstp->rq_auth_data; struct rpc_gss_wire_cred *gc; struct rsc *rsci = NULL; - struct rsi *rsip, rsikey; __be32 *rpcstart; __be32 *reject_stat = resv->iov_base + resv->iov_len; int ret; @@ -1023,30 +1094,14 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) if ((gc->gc_proc != RPC_GSS_PROC_DATA) && (rqstp->rq_proc != 0)) goto auth_err; - /* - * We've successfully parsed the credential. Let's check out the - * verifier. An AUTH_NULL verifier is allowed (and required) for - * INIT and CONTINUE_INIT requests. AUTH_RPCSEC_GSS is required for - * PROC_DATA and PROC_DESTROY. - * - * AUTH_NULL verifier is 0 (AUTH_NULL), 0 (length). - * AUTH_RPCSEC_GSS verifier is: - * 6 (AUTH_RPCSEC_GSS), length, checksum. - * checksum is calculated over rpcheader from xid up to here. - */ *authp = rpc_autherr_badverf; switch (gc->gc_proc) { case RPC_GSS_PROC_INIT: case RPC_GSS_PROC_CONTINUE_INIT: - if (argv->iov_len < 2 * 4) - goto auth_err; - if (svc_getnl(argv) != RPC_AUTH_NULL) - goto auth_err; - if (svc_getnl(argv) != 0) - goto auth_err; - break; + return svcauth_gss_handle_init(rqstp, gc, authp); case RPC_GSS_PROC_DATA: case RPC_GSS_PROC_DESTROY: + /* Look up the context, and check the verifier: */ *authp = rpcsec_gsserr_credproblem; rsci = gss_svc_searchbyctx(&gc->gc_ctx); if (!rsci) @@ -1067,51 +1122,6 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) /* now act upon the command: */ switch (gc->gc_proc) { - case RPC_GSS_PROC_INIT: - case RPC_GSS_PROC_CONTINUE_INIT: - *authp = rpc_autherr_badcred; - if (gc->gc_proc == RPC_GSS_PROC_INIT && gc->gc_ctx.len != 0) - goto auth_err; - memset(&rsikey, 0, sizeof(rsikey)); - if (dup_netobj(&rsikey.in_handle, &gc->gc_ctx)) - goto drop; - *authp = rpc_autherr_badverf; - if (svc_safe_getnetobj(argv, &tmpobj)) { - kfree(rsikey.in_handle.data); - goto auth_err; - } - if (dup_netobj(&rsikey.in_token, &tmpobj)) { - kfree(rsikey.in_handle.data); - goto drop; - } - - rsip = rsi_lookup(&rsikey); - rsi_free(&rsikey); - if (!rsip) { - goto drop; - } - switch(cache_check(&rsi_cache, &rsip->h, &rqstp->rq_chandle)) { - case -EAGAIN: - case -ETIMEDOUT: - case -ENOENT: - goto drop; - case 0: - if (gss_write_init_verf(rqstp, rsip)) - goto drop; - if (resv->iov_len + 4 > PAGE_SIZE) - goto drop; - svc_putnl(resv, RPC_SUCCESS); - if (svc_safe_putnetobj(resv, &rsip->out_handle)) - goto drop; - if (resv->iov_len + 3 * 4 > PAGE_SIZE) - goto drop; - svc_putnl(resv, rsip->major_status); - svc_putnl(resv, rsip->minor_status); - svc_putnl(resv, GSS_SEQ_WIN); - if (svc_safe_putnetobj(resv, &rsip->out_token)) - goto drop; - } - goto complete; case RPC_GSS_PROC_DESTROY: if (gss_write_verf(rqstp, rsci->mechctx, gc->gc_seq)) goto auth_err; @@ -1158,7 +1168,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) goto out; } auth_err: - /* Restore write pointer to original value: */ + /* Restore write pointer to its original value: */ xdr_ressize_check(rqstp, reject_stat); ret = SVC_DENIED; goto out; diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 55ea6df069de..a4a6bf7deaa4 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -777,6 +777,30 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) } /* + * Printk the given error with the address of the client that caused it. + */ +static int +__attribute__ ((format (printf, 2, 3))) +svc_printk(struct svc_rqst *rqstp, const char *fmt, ...) +{ + va_list args; + int r; + char buf[RPC_MAX_ADDRBUFLEN]; + + if (!net_ratelimit()) + return 0; + + printk(KERN_WARNING "svc: %s: ", + svc_print_addr(rqstp, buf, sizeof(buf))); + + va_start(args, fmt); + r = vprintk(fmt, args); + va_end(args); + + return r; +} + +/* * Process the RPC request. */ int @@ -963,14 +987,13 @@ svc_process(struct svc_rqst *rqstp) return 0; err_short_len: - if (net_ratelimit()) - printk("svc: short len %Zd, dropping request\n", argv->iov_len); + svc_printk(rqstp, "short len %Zd, dropping request\n", + argv->iov_len); goto dropit; /* drop request */ err_bad_dir: - if (net_ratelimit()) - printk("svc: bad direction %d, dropping request\n", dir); + svc_printk(rqstp, "bad direction %d, dropping request\n", dir); serv->sv_stats->rpcbadfmt++; goto dropit; /* drop request */ @@ -1000,8 +1023,7 @@ err_bad_prog: goto sendit; err_bad_vers: - if (net_ratelimit()) - printk("svc: unknown version (%d for prog %d, %s)\n", + svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", vers, prog, progp->pg_name); serv->sv_stats->rpcbadfmt++; @@ -1011,16 +1033,14 @@ err_bad_vers: goto sendit; err_bad_proc: - if (net_ratelimit()) - printk("svc: unknown procedure (%d)\n", proc); + svc_printk(rqstp, "unknown procedure (%d)\n", proc); serv->sv_stats->rpcbadfmt++; svc_putnl(resv, RPC_PROC_UNAVAIL); goto sendit; err_garbage: - if (net_ratelimit()) - printk("svc: failed to decode args\n"); + svc_printk(rqstp, "failed to decode args\n"); rpc_stat = rpc_garbage_args; err_bad: diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 2b57eaf66abc..6996cba5aa96 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -334,7 +334,7 @@ static void unix_write_space(struct sock *sk) read_lock(&sk->sk_callback_lock); if (unix_writable(sk)) { if (sk->sk_sleep && waitqueue_active(sk->sk_sleep)) - wake_up_interruptible(sk->sk_sleep); + wake_up_interruptible_sync(sk->sk_sleep); sk_wake_async(sk, 2, POLL_OUT); } read_unlock(&sk->sk_callback_lock); @@ -1639,7 +1639,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, if (!skb) goto out_unlock; - wake_up_interruptible(&u->peer_wait); + wake_up_interruptible_sync(&u->peer_wait); if (msg->msg_name) unix_copy_addr(msg, skb->sk); |