diff --git a/[refs] b/[refs] index 1f1c89518727..70e87a6027f4 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: df3d80f5a5c74168be42788364d13cf6c83c7b9c +refs/heads/master: 44142fac3446d08c08c5d717ec11d50a737e8640 diff --git a/trunk/Documentation/scsi/00-INDEX b/trunk/Documentation/scsi/00-INDEX index aa1f7e927834..12354830c6b0 100644 --- a/trunk/Documentation/scsi/00-INDEX +++ b/trunk/Documentation/scsi/00-INDEX @@ -2,20 +2,14 @@ - 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.1992-1997 +ChangeLog - 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 @@ -26,44 +20,26 @@ 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 @@ -74,8 +50,6 @@ 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 @@ -84,8 +58,6 @@ 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/trunk/Documentation/scsi/ChangeLog.arcmsr b/trunk/Documentation/scsi/ChangeLog.arcmsr index cd8403a33ee6..162c47fdf45f 100644 --- a/trunk/Documentation/scsi/ChangeLog.arcmsr +++ b/trunk/Documentation/scsi/ChangeLog.arcmsr @@ -53,19 +53,4 @@ ** for linux standard list ** enable usage of pci message signal interrupt ** follow Randy.Danlup kindness suggestion cleanup this code -** 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 -************************************************************************** +************************************************************************** \ No newline at end of file diff --git a/trunk/Documentation/scsi/aacraid.txt b/trunk/Documentation/scsi/aacraid.txt index a8257840695a..cc12b55d4b3d 100644 --- a/trunk/Documentation/scsi/aacraid.txt +++ b/trunk/Documentation/scsi/aacraid.txt @@ -38,8 +38,10 @@ 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) @@ -48,14 +50,9 @@ 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) @@ -106,7 +103,6 @@ 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/trunk/Documentation/scsi/advansys.txt b/trunk/Documentation/scsi/advansys.txt deleted file mode 100644 index 4a3db62b7424..000000000000 --- a/trunk/Documentation/scsi/advansys.txt +++ /dev/null @@ -1,243 +0,0 @@ -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 wrote the AdvanSys SCSI driver -and maintained it up to 3.3F. He continues to answer questions -and help maintain the driver. - -Nathan Hartwell provided the directions and -basis for the Linux v1.3.X changes which were included in the -1.2 release. - -Thomas E Zerucha pointed out a bug -in advansys_biosparam() which was fixed in the 1.3 release. - -Erik Ratcliffe has done testing of the -AdvanSys driver in the Caldera releases. - -Rik van Riel provided a patch to -AscWaitTixISRDone() which he found necessary to make the -driver work with a SCSI-1 disk. - -Mark Moran has helped test Ultra-Wide -support in the 3.1A driver. - -Doug Gilbert has made changes and -suggestions to improve the driver and done a lot of testing. - -Ken Mort reported a DEBUG compile bug fixed -in 3.2K. - -Tom Rini provided the CONFIG_ISA -patch and helped with PowerPC wide and narrow board support. - -Philip Blundell provided an -advansys_interrupts_enabled patch. - -Dave Jones reported the compiler -warnings generated when CONFIG_PROC_FS was not defined in -the 3.2M driver. - -Jerry Quinn fixed PowerPC support (endian -problems) for wide cards. - -Bryan Henderson helped debug narrow -card error handling. - -Manuel Veloso worked hard on PowerPC narrow -board support and fixed a bug in AscGetEEPConfig(). - -Arnaldo Carvalho de Melo made -save_flags/restore_flags changes. - -Andy Kellner 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/trunk/MAINTAINERS b/trunk/MAINTAINERS index 12cee3da2625..012fa837845d 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -297,12 +297,6 @@ 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 @@ -1895,11 +1889,6 @@ M: Gadi Oxman 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 @@ -2415,7 +2404,7 @@ LSILOGIC MPT FUSION DRIVERS (FC/SAS/SPI) P: Eric Moore M: Eric.Moore@lsi.com M: support@lsi.com -L: DL-MPTFusionLinux@lsi.com +L: mpt_linux_developer@lsi.com L: linux-scsi@vger.kernel.org W: http://www.lsilogic.com/support S: Supported diff --git a/trunk/arch/ia64/hp/sim/simscsi.c b/trunk/arch/ia64/hp/sim/simscsi.c index d62fa76e5a7d..4552a1cf5b33 100644 --- a/trunk/arch/ia64/hp/sim/simscsi.c +++ b/trunk/arch/ia64/hp/sim/simscsi.c @@ -372,13 +372,8 @@ simscsi_init(void) return -ENOMEM; error = scsi_add_host(host, NULL); - if (error) - goto free_host; - scsi_scan_host(host); - return 0; - - free_host: - scsi_host_put(host); + if (!error) + scsi_scan_host(host); return error; } diff --git a/trunk/arch/powerpc/platforms/ps3/system-bus.c b/trunk/arch/powerpc/platforms/ps3/system-bus.c index 190ff4b59a55..ea0b2c790412 100644 --- a/trunk/arch/powerpc/platforms/ps3/system-bus.c +++ b/trunk/arch/powerpc/platforms/ps3/system-bus.c @@ -440,6 +440,7 @@ 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/trunk/drivers/char/agp/agp.h b/trunk/drivers/char/agp/agp.h index b83824c41329..8955e7ff759a 100644 --- a/trunk/drivers/char/agp/agp.h +++ b/trunk/drivers/char/agp/agp.h @@ -58,9 +58,6 @@ 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; @@ -116,7 +113,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 *, int flags); + void (*agp_destroy_page)(void *); int (*agp_type_to_mask_type) (struct agp_bridge_data *, int); }; @@ -270,7 +267,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, int flags); +void agp_generic_destroy_page(void *addr); 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/trunk/drivers/char/agp/ali-agp.c b/trunk/drivers/char/agp/ali-agp.c index aa5ddb716ffb..4941ddb78939 100644 --- a/trunk/drivers/char/agp/ali-agp.c +++ b/trunk/drivers/char/agp/ali-agp.c @@ -156,34 +156,29 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge) return addr; } -static void ali_destroy_page(void * addr, int flags) +static void ali_destroy_page(void * addr) { if (addr) { - 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); + global_cache_flush(); /* is this really needed? --hch */ + agp_generic_destroy_page(addr); + global_flush_tlb(); } } -static void m1541_destroy_page(void * addr, int flags) +static void m1541_destroy_page(void * addr) { u32 temp; if (addr == NULL) return; - if (flags & AGP_PAGE_DESTROY_UNMAP) { - global_cache_flush(); + 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, flags); + 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); } diff --git a/trunk/drivers/char/agp/amd-k7-agp.c b/trunk/drivers/char/agp/amd-k7-agp.c index 1405a42585e1..f60bca70d1fb 100644 --- a/trunk/drivers/char/agp/amd-k7-agp.c +++ b/trunk/drivers/char/agp/amd-k7-agp.c @@ -100,16 +100,21 @@ 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 = i; + amd_irongate_private.num_tables = nr_tables; amd_irongate_private.gatt_pages = tables; if (retval != 0) diff --git a/trunk/drivers/char/agp/backend.c b/trunk/drivers/char/agp/backend.c index 832ded20fe70..1b47c89a1b99 100644 --- a/trunk/drivers/char/agp/backend.c +++ b/trunk/drivers/char/agp/backend.c @@ -189,11 +189,9 @@ 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), - AGP_PAGE_DESTROY_UNMAP); + bridge->driver->agp_destroy_page( + gart_to_virt(bridge->scratch_page_real)); 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); @@ -217,11 +215,9 @@ 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), - AGP_PAGE_DESTROY_UNMAP); + bridge->driver->agp_destroy_page( + gart_to_virt(bridge->scratch_page_real)); flush_agp_mappings(); - bridge->driver->agp_destroy_page(gart_to_virt(bridge->scratch_page_real), - AGP_PAGE_DESTROY_FREE); } } diff --git a/trunk/drivers/char/agp/generic.c b/trunk/drivers/char/agp/generic.c index 64b2f6d7059d..3db4f4076ed4 100644 --- a/trunk/drivers/char/agp/generic.c +++ b/trunk/drivers/char/agp/generic.c @@ -195,12 +195,9 @@ 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]), AGP_PAGE_DESTROY_UNMAP); + curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i])); } 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); @@ -1179,7 +1176,7 @@ void *agp_generic_alloc_page(struct agp_bridge_data *bridge) EXPORT_SYMBOL(agp_generic_alloc_page); -void agp_generic_destroy_page(void *addr, int flags) +void agp_generic_destroy_page(void *addr) { struct page *page; @@ -1187,14 +1184,10 @@ void agp_generic_destroy_page(void *addr, int flags) return; page = virt_to_page(addr); - 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); - } + unmap_page_from_agp(page); + put_page(page); + free_page((unsigned long)addr); + atomic_dec(&agp_bridge->current_memory_agp); } EXPORT_SYMBOL(agp_generic_destroy_page); diff --git a/trunk/drivers/char/agp/i460-agp.c b/trunk/drivers/char/agp/i460-agp.c index 70117df4d067..75d2aca6353d 100644 --- a/trunk/drivers/char/agp/i460-agp.c +++ b/trunk/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, int flags) +static void i460_destroy_page (void *page) { if (I460_IO_PAGE_SHIFT <= PAGE_SHIFT) { - agp_generic_destroy_page(page, flags); + agp_generic_destroy_page(page); global_flush_tlb(); } } diff --git a/trunk/drivers/char/agp/intel-agp.c b/trunk/drivers/char/agp/intel-agp.c index d87961993ccf..141ca176c397 100644 --- a/trunk/drivers/char/agp/intel-agp.c +++ b/trunk/drivers/char/agp/intel-agp.c @@ -400,11 +400,9 @@ 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_PAGE_DESTROY_UNMAP); + agp_bridge->driver->agp_destroy_page( + gart_to_virt(curr->memory[0])); 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/trunk/drivers/char/drm/drm.h b/trunk/drivers/char/drm/drm.h index 82fb3d0d2785..2d6f2d0bd02b 100644 --- a/trunk/drivers/char/drm/drm.h +++ b/trunk/drivers/char/drm/drm.h @@ -63,9 +63,27 @@ #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/trunk/drivers/char/drm/drmP.h b/trunk/drivers/char/drm/drmP.h index 9dd0760dd87a..0df87fc3dcb2 100644 --- a/trunk/drivers/char/drm/drmP.h +++ b/trunk/drivers/char/drm/drmP.h @@ -80,9 +80,6 @@ #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" @@ -234,13 +231,12 @@ struct drm_device; * \param dev DRM device. * \param filp file pointer of the caller. */ -#define LOCK_TEST_WITH_RETURN( dev, file_priv ) \ +#define LOCK_TEST_WITH_RETURN( dev, filp ) \ do { \ if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || \ - 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 ); \ + dev->lock.filp != filp ) { \ + DRM_ERROR( "%s called without lock held\n", \ + __FUNCTION__ ); \ return -EINVAL; \ } \ } while (0) @@ -261,12 +257,12 @@ do { \ * Ioctl function type. * * \param inode device inode. - * \param file_priv DRM file private pointer. + * \param filp file pointer. * \param cmd command. * \param arg argument. */ -typedef int drm_ioctl_t(struct drm_device *dev, void *data, - struct drm_file *file_priv); +typedef int drm_ioctl_t(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, unsigned long arg); @@ -275,18 +271,10 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, #define DRM_MASTER 0x2 #define DRM_ROOT_ONLY 0x4 -struct drm_ioctl_desc { - unsigned int cmd; +typedef struct drm_ioctl_desc { drm_ioctl_t *func; int flags; -}; - -/** - * 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} +} drm_ioctl_desc_t; struct drm_magic_entry { struct list_head head; @@ -316,7 +304,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 drm_file *file_priv; /**< Private of holding file descr */ + struct file *filp; /**< Pointer to holding file descr */ int context; /**< Kernel queue for this buffer */ int while_locked; /**< Dispatch this buffer while locked */ enum { @@ -389,7 +377,6 @@ struct drm_file { int remove_auth_on_close; unsigned long lock_count; void *driver_priv; - struct file *filp; }; /** Wait queue */ @@ -416,7 +403,7 @@ struct drm_queue { */ struct drm_lock_data { struct drm_hw_lock *hw_lock; /**< Hardware lock */ - struct drm_file *file_priv; /**< File descr of lock holder (0=kernel) */ + struct file *filp; /**< 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; @@ -565,11 +552,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 drm_file *file_priv); + void (*preclose) (struct drm_device *, struct file * filp); void (*postclose) (struct drm_device *, struct drm_file *); void (*lastclose) (struct drm_device *); int (*unload) (struct drm_device *); - int (*dma_ioctl) (struct drm_device *dev, void *data, struct drm_file *file_priv); + int (*dma_ioctl) (DRM_IOCTL_ARGS); void (*dma_ready) (struct drm_device *); int (*dma_quiescent) (struct drm_device *); int (*context_ctor) (struct drm_device *dev, int context); @@ -600,12 +587,11 @@ 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 drm_file * file_priv); + void (*reclaim_buffers) (struct drm_device *dev, struct file * filp); void (*reclaim_buffers_locked) (struct drm_device *dev, - struct drm_file *file_priv); + struct file *filp); void (*reclaim_buffers_idlelocked) (struct drm_device *dev, - struct drm_file *file_priv); + struct file * filp); 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, @@ -620,7 +606,7 @@ struct drm_driver { u32 driver_features; int dev_priv_size; - struct drm_ioctl_desc *ioctls; + drm_ioctl_desc_t *ioctls; int num_ioctls; struct file_operations fops; struct pci_driver pci_driver; @@ -864,70 +850,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 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); +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); /* Context IOCTL support (drm_context.h) */ -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_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_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 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); +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); /* Drawable IOCTL support (drm_drawable.h) */ -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 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 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 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); +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); /* Locking IOCTL support (drm_lock.h) */ -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(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_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); @@ -938,7 +924,8 @@ 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 drm_device *dev, struct drm_file *file_priv); +extern int drm_i_have_hw_lock(struct file *filp); +extern int drm_kernel_take_hw_lock(struct file *filp); /* Buffer management support (drm_bufs.h) */ extern int drm_addbufs_agp(struct drm_device *dev, struct drm_buf_desc * request); @@ -946,23 +933,24 @@ 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 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_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_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, @@ -972,20 +960,19 @@ 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 drm_file *filp); +extern void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp); /* IRQ support (drm_irq.h) */ -extern int drm_control(struct drm_device *dev, void *data, - struct drm_file *file_priv); +extern int drm_control(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); 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 drm_device *dev, void *data, - struct drm_file *file_priv); +extern int drm_wait_vblank(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); 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*)); @@ -993,30 +980,31 @@ 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 drm_device *dev, void *data, - struct drm_file *file_priv); +extern int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int drm_agp_release(struct drm_device *dev); -extern int drm_agp_release_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); +extern int drm_agp_release_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int drm_agp_enable(struct drm_device *dev, struct drm_agp_mode mode); -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_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_alloc(struct drm_device *dev, struct drm_agp_buffer *request); -extern int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); +extern int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request); -extern int drm_agp_free_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); +extern int drm_agp_free_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request); -extern int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv); +extern int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); extern int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request); -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_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_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); @@ -1045,11 +1033,10 @@ 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_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); +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); /* ATI PCIGART support (ati_pcigart.h) */ extern int drm_ati_pcigart_init(struct drm_device *dev, diff --git a/trunk/drivers/char/drm/drm_agpsupport.c b/trunk/drivers/char/drm/drm_agpsupport.c index 214f4fbcba73..354f0e3674bf 100644 --- a/trunk/drivers/char/drm/drm_agpsupport.c +++ b/trunk/drivers/char/drm/drm_agpsupport.c @@ -40,7 +40,7 @@ * Get AGP information. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a (output) drm_agp_info structure. * \return zero on success or a negative number on failure. @@ -71,16 +71,20 @@ int drm_agp_info(struct drm_device *dev, struct drm_agp_info *info) EXPORT_SYMBOL(drm_agp_info); -int drm_agp_info_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_agp_info_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_agp_info *info = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_agp_info info; 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; } @@ -111,7 +115,7 @@ EXPORT_SYMBOL(drm_agp_acquire); * Acquire the AGP device (ioctl). * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg user argument. * \return zero on success or a negative number on failure. @@ -119,10 +123,12 @@ 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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_agp_acquire_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - return drm_agp_acquire((struct drm_device *) file_priv->head->dev); + struct drm_file *priv = filp->private_data; + + return drm_agp_acquire((struct drm_device *) priv->head->dev); } /** @@ -143,9 +149,12 @@ int drm_agp_release(struct drm_device * dev) } EXPORT_SYMBOL(drm_agp_release); -int drm_agp_release_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_agp_release_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; + return drm_agp_release(dev); } @@ -173,19 +182,24 @@ int drm_agp_enable(struct drm_device * dev, struct drm_agp_mode mode) EXPORT_SYMBOL(drm_agp_enable); -int drm_agp_enable_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_agp_enable_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_agp_mode *mode = data; + 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; - return drm_agp_enable(dev, *mode); + return drm_agp_enable(dev, mode); } /** * Allocate AGP memory. * * \param inode device inode. - * \param file_priv file private pointer. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_agp_buffer structure. * \return zero on success or a negative number on failure. @@ -227,13 +241,35 @@ int drm_agp_alloc(struct drm_device *dev, struct drm_agp_buffer *request) } EXPORT_SYMBOL(drm_agp_alloc); - -int drm_agp_alloc_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_agp_alloc_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_agp_buffer *request = data; + 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; - return drm_agp_alloc(dev, request); + 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; + } + + return 0; } /** @@ -261,7 +297,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 file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_agp_binding structure. * \return zero on success or a negative number on failure. @@ -287,20 +323,25 @@ int drm_agp_unbind(struct drm_device *dev, struct drm_agp_binding *request) } EXPORT_SYMBOL(drm_agp_unbind); - -int drm_agp_unbind_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_agp_unbind_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_agp_binding *request = data; + 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; - return drm_agp_unbind(dev, request); + return drm_agp_unbind(dev, &request); } /** * Bind AGP memory into the GATT (ioctl) * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_agp_binding structure. * \return zero on success or a negative number on failure. @@ -331,20 +372,25 @@ int drm_agp_bind(struct drm_device *dev, struct drm_agp_binding *request) } EXPORT_SYMBOL(drm_agp_bind); - -int drm_agp_bind_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_agp_bind_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_agp_binding *request = data; + 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; - return drm_agp_bind(dev, request); + return drm_agp_bind(dev, &request); } /** * Free AGP memory (ioctl). * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_agp_buffer structure. * \return zero on success or a negative number on failure. @@ -373,14 +419,18 @@ int drm_agp_free(struct drm_device *dev, struct drm_agp_buffer *request) } EXPORT_SYMBOL(drm_agp_free); - - -int drm_agp_free_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_agp_free_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_agp_buffer *request = data; + 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); + return drm_agp_free(dev, &request); } /** diff --git a/trunk/drivers/char/drm/drm_auth.c b/trunk/drivers/char/drm/drm_auth.c index a73462723d2d..7f777da872cd 100644 --- a/trunk/drivers/char/drm/drm_auth.c +++ b/trunk/drivers/char/drm/drm_auth.c @@ -128,38 +128,42 @@ static int drm_remove_magic(struct drm_device * dev, drm_magic_t magic) * Get a unique magic number (ioctl). * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 - * file_priv. + * filp. */ -int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) +int drm_getmagic(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { static drm_magic_t sequence = 0; static DEFINE_SPINLOCK(lock); - struct drm_auth *auth = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_auth auth; /* Find unique magic */ - if (file_priv->magic) { - auth->magic = file_priv->magic; + if (priv->magic) { + auth.magic = 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)); - file_priv->magic = auth->magic; - drm_add_magic(dev, file_priv, auth->magic); + } while (drm_find_file(dev, auth.magic)); + priv->magic = auth.magic; + drm_add_magic(dev, priv, auth.magic); } - DRM_DEBUG("%u\n", auth->magic); - + DRM_DEBUG("%u\n", auth.magic); + if (copy_to_user((struct drm_auth __user *) arg, &auth, sizeof(auth))) + return -EFAULT; return 0; } @@ -167,23 +171,27 @@ int drm_getmagic(struct drm_device *dev, void *data, struct drm_file *file_priv) * Authenticate with a magic. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_auth structure. * \return zero if authentication successed, or a negative number otherwise. * - * Checks if \p file_priv is associated with the magic number passed in \arg. + * Checks if \p filp is associated with the magic number passed in \arg. */ -int drm_authmagic(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_authmagic(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_auth *auth = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_auth auth; struct drm_file *file; - DRM_DEBUG("%u\n", auth->magic); - if ((file = drm_find_file(dev, auth->magic))) { + 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))) { file->authenticated = 1; - drm_remove_magic(dev, auth->magic); + drm_remove_magic(dev, auth.magic); return 0; } return -EINVAL; diff --git a/trunk/drivers/char/drm/drm_bufs.c b/trunk/drivers/char/drm/drm_bufs.c index 856774fbe025..c115b39b8517 100644 --- a/trunk/drivers/char/drm/drm_bufs.c +++ b/trunk/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 file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_map structure. * \return zero on success or a negative value on error. @@ -332,24 +332,38 @@ int drm_addmap(struct drm_device * dev, unsigned int offset, EXPORT_SYMBOL(drm_addmap); -int drm_addmap_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_addmap_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_map *map = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_map map; struct drm_map_list *maplist; + struct drm_map __user *argp = (void __user *)arg; int err; - if (!(capable(CAP_SYS_ADMIN) || map->type == _DRM_AGP)) + 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)) 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 */ - map->handle = (void *)(unsigned long)maplist->user_token; + if (put_user((void *)(unsigned long)maplist->user_token, &argp->handle)) + return -EFAULT; return 0; } @@ -358,7 +372,7 @@ int drm_addmap_ioctl(struct drm_device *dev, void *data, * isn't in use. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a struct drm_map structure. * \return zero on success or a negative value on error. @@ -439,18 +453,24 @@ 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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_rmmap_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_map *request = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_map request; 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; @@ -641,7 +661,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->file_priv = NULL; + buf->filp = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); @@ -852,7 +872,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->file_priv = NULL; + buf->filp = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; buf->dev_private = drm_alloc(buf->dev_priv_size, @@ -1030,7 +1050,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->file_priv = NULL; + buf->filp = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); @@ -1191,7 +1211,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->file_priv = NULL; + buf->filp = NULL; buf->dev_priv_size = dev->driver->dev_priv_size; buf->dev_private = drm_alloc(buf->dev_priv_size, DRM_MEM_BUFS); @@ -1255,7 +1275,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 file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a struct drm_buf_desc request. * \return zero on success or a negative number on failure. @@ -1265,27 +1285,38 @@ 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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_addbufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_buf_desc *request = data; + struct drm_buf_desc request; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; 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; } @@ -1297,7 +1328,7 @@ int drm_addbufs(struct drm_device *dev, void *data, * large buffers can be used for image transfer). * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_buf_info structure. * \return zero on success or a negative number on failure. @@ -1306,11 +1337,14 @@ int drm_addbufs(struct drm_device *dev, void *data, * lock, preventing of allocating more buffers after this call. Information * about each requested buffer is then copied into user space. */ -int drm_infobufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_infobufs(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_device_dma *dma = dev->dma; - struct drm_buf_info *request = data; + struct drm_buf_info request; + struct drm_buf_info __user *argp = (void __user *)arg; int i; int count; @@ -1328,6 +1362,9 @@ int drm_infobufs(struct drm_device *dev, void *data, ++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; @@ -1335,11 +1372,11 @@ int drm_infobufs(struct drm_device *dev, void *data, 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, @@ -1366,7 +1403,10 @@ int drm_infobufs(struct drm_device *dev, void *data, } } } - request->count = count; + request.count = count; + + if (copy_to_user(argp, &request, sizeof(request))) + return -EFAULT; return 0; } @@ -1375,7 +1415,7 @@ int drm_infobufs(struct drm_device *dev, void *data, * Specifies a low and high water mark for buffer allocation * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg a pointer to a drm_buf_desc structure. * \return zero on success or a negative number on failure. @@ -1385,11 +1425,13 @@ int drm_infobufs(struct drm_device *dev, void *data, * * \note This ioctl is deprecated and mostly never used. */ -int drm_markbufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_markbufs(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_device_dma *dma = dev->dma; - struct drm_buf_desc *request = data; + struct drm_buf_desc request; int order; struct drm_buf_entry *entry; @@ -1399,20 +1441,24 @@ int drm_markbufs(struct drm_device *dev, void *data, 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; } @@ -1421,7 +1467,7 @@ int drm_markbufs(struct drm_device *dev, void *data, * Unreserve the buffers in list, previously reserved using drmDMA. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_buf_free structure. * \return zero on success or a negative number on failure. @@ -1429,11 +1475,13 @@ int drm_markbufs(struct drm_device *dev, void *data, * Calls free_buffer() for each used buffer. * This function is primarily used for debugging. */ -int drm_freebufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_freebufs(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_device_dma *dma = dev->dma; - struct drm_buf_free *request = data; + struct drm_buf_free request; int i; int idx; struct drm_buf *buf; @@ -1444,9 +1492,13 @@ int drm_freebufs(struct drm_device *dev, void *data, if (!dma) return -EINVAL; - DRM_DEBUG("%d\n", request->count); - for (i = 0; i < request->count; i++) { - if (copy_from_user(&idx, &request->list[i], sizeof(idx))) + 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))) return -EFAULT; if (idx < 0 || idx >= dma->buf_count) { DRM_ERROR("Index %d (of %d max)\n", @@ -1454,7 +1506,7 @@ int drm_freebufs(struct drm_device *dev, void *data, return -EINVAL; } buf = dma->buflist[idx]; - if (buf->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("Process %d freeing buffer not owned\n", current->pid); return -EINVAL; @@ -1469,7 +1521,7 @@ int drm_freebufs(struct drm_device *dev, void *data, * Maps all of the DMA buffers into client-virtual space (ioctl). * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg pointer to a drm_buf_map structure. * \return zero on success or a negative number on failure. @@ -1479,15 +1531,18 @@ int drm_freebufs(struct drm_device *dev, void *data, * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls * drm_mmap_dma(). */ -int drm_mapbufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_mapbufs(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_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 = data; + struct drm_buf_map request; int i; if (!drm_core_check_feature(dev, DRIVER_HAVE_DMA)) @@ -1504,7 +1559,10 @@ int drm_mapbufs(struct drm_device *dev, void *data, dev->buf_use++; /* Can't allocate more after this call */ spin_unlock(&dev->count_lock); - if (request->count >= dma->buf_count) { + if (copy_from_user(&request, argp, sizeof(request))) + return -EFAULT; + + 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)) @@ -1517,15 +1575,15 @@ int drm_mapbufs(struct drm_device *dev, void *data, retcode = -EINVAL; goto done; } + down_write(¤t->mm->mmap_sem); - virtual = do_mmap(file_priv->filp, 0, map->size, + virtual = do_mmap(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(file_priv->filp, 0, dma->byte_count, + virtual = do_mmap(filp, 0, dma->byte_count, PROT_READ | PROT_WRITE, MAP_SHARED, 0); up_write(¤t->mm->mmap_sem); @@ -1535,28 +1593,28 @@ int drm_mapbufs(struct drm_device *dev, void *data, 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; @@ -1564,8 +1622,11 @@ int drm_mapbufs(struct drm_device *dev, void *data, } } done: - request->count = dma->buf_count; - DRM_DEBUG("%d buffers, retcode = %d\n", request->count, retcode); + 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; return retcode; } diff --git a/trunk/drivers/char/drm/drm_context.c b/trunk/drivers/char/drm/drm_context.c index 17fe69e7bfc1..61ad986baa8d 100644 --- a/trunk/drivers/char/drm/drm_context.c +++ b/trunk/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 file_priv DRM file private. + * \param filp file pointer. * \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,16 +139,22 @@ 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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_getsareactx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_ctx_priv_map *request = data; + 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_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; @@ -156,17 +162,19 @@ int drm_getsareactx(struct drm_device *dev, void *data, 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; } @@ -174,7 +182,7 @@ int drm_getsareactx(struct drm_device *dev, void *data, * Set per-context SAREA. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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. @@ -182,17 +190,24 @@ int drm_getsareactx(struct drm_device *dev, void *data, * Searches the mapping specified in \p arg and update the entry in * drm_device::ctx_idr with it. */ -int drm_setsareactx(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_setsareactx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_ctx_priv_map *request = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_ctx_priv_map request; 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: @@ -204,11 +219,10 @@ int drm_setsareactx(struct drm_device *dev, void *data, 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; } @@ -278,28 +292,34 @@ static int drm_context_switch_complete(struct drm_device * dev, int new) * Reserve contexts. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_resctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_ctx_res *res = data; + struct drm_ctx_res res; + struct drm_ctx_res __user *argp = (void __user *)arg; struct drm_ctx ctx; int i; - if (res->count >= DRM_RESERVED_CONTEXTS) { + if (copy_from_user(&res, argp, sizeof(res))) + return -EFAULT; + + 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; } @@ -307,34 +327,40 @@ int drm_resctx(struct drm_device *dev, void *data, * Add context. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_addctx(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_ctx_list *ctx_entry; - struct drm_ctx *ctx = data; + struct drm_ctx __user *argp = (void __user *)arg; + struct drm_ctx ctx; + + if (copy_from_user(&ctx, argp, sizeof(ctx))) + return -EFAULT; - 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; } @@ -347,18 +373,21 @@ int drm_addctx(struct drm_device *dev, void *data, } INIT_LIST_HEAD(&ctx_entry->head); - ctx_entry->handle = ctx->handle; - ctx_entry->tag = file_priv; + ctx_entry->handle = ctx.handle; + ctx_entry->tag = 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 drm_device *dev, void *data, struct drm_file *file_priv) +int drm_modctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { /* This does nothing */ return 0; @@ -368,18 +397,25 @@ int drm_modctx(struct drm_device *dev, void *data, struct drm_file *file_priv) * Get context. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, struct drm_file *file_priv) +int drm_getctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_ctx *ctx = data; + struct drm_ctx __user *argp = (void __user *)arg; + struct drm_ctx ctx; + + if (copy_from_user(&ctx, argp, sizeof(ctx))) + return -EFAULT; /* 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; } @@ -387,40 +423,50 @@ int drm_getctx(struct drm_device *dev, void *data, struct drm_file *file_priv) * Switch context. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_switchctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_ctx *ctx = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_ctx ctx; - DRM_DEBUG("%d\n", ctx->handle); - return drm_context_switch(dev, dev->last_context, ctx->handle); + 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); } /** * New context. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_newctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_ctx *ctx = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_ctx ctx; - DRM_DEBUG("%d\n", ctx->handle); - drm_context_switch_complete(dev, ctx->handle); + 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); return 0; } @@ -429,26 +475,31 @@ int drm_newctx(struct drm_device *dev, void *data, * Remove context. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_rmctx(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_ctx *ctx = data; + 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; - DRM_DEBUG("%d\n", ctx->handle); - if (ctx->handle == DRM_KERNEL_CONTEXT + 1) { - file_priv->remove_auth_on_close = 1; + DRM_DEBUG("%d\n", ctx.handle); + if (ctx.handle == DRM_KERNEL_CONTEXT + 1) { + 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); @@ -456,7 +507,7 @@ int drm_rmctx(struct drm_device *dev, void *data, 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/trunk/drivers/char/drm/drm_dma.c b/trunk/drivers/char/drm/drm_dma.c index 7a8e2fba4678..802fbdbfe1b3 100644 --- a/trunk/drivers/char/drm/drm_dma.c +++ b/trunk/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->file_priv = NULL; + buf->filp = NULL; buf->used = 0; if (drm_core_check_feature(dev, DRIVER_DMA_QUEUE) @@ -148,12 +148,11 @@ void drm_free_buffer(struct drm_device *dev, struct drm_buf * buf) /** * Reclaim the buffers. * - * \param file_priv DRM file private. + * \param filp file pointer. * - * Frees each buffer associated with \p file_priv not already on the hardware. + * Frees each buffer associated with \p filp not already on the hardware. */ -void drm_core_reclaim_buffers(struct drm_device *dev, - struct drm_file *file_priv) +void drm_core_reclaim_buffers(struct drm_device *dev, struct file *filp) { struct drm_device_dma *dma = dev->dma; int i; @@ -161,7 +160,7 @@ void drm_core_reclaim_buffers(struct drm_device *dev, if (!dma) return; for (i = 0; i < dma->buf_count; i++) { - if (dma->buflist[i]->file_priv == file_priv) { + if (dma->buflist[i]->filp == filp) { switch (dma->buflist[i]->list) { case DRM_LIST_NONE: drm_free_buffer(dev, dma->buflist[i]); diff --git a/trunk/drivers/char/drm/drm_drawable.c b/trunk/drivers/char/drm/drm_drawable.c index 1839c57663c5..d6cdba5644e2 100644 --- a/trunk/drivers/char/drm/drm_drawable.c +++ b/trunk/drivers/char/drm/drm_drawable.c @@ -40,10 +40,11 @@ /** * Allocate drawable ID and memory to store information about it. */ -int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) +int drm_adddraw(DRM_IOCTL_ARGS) { + DRM_DEVICE; unsigned long irqflags; - struct drm_draw *draw = data; + struct drm_draw draw; int new_id = 0; int ret; @@ -62,9 +63,11 @@ int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) spin_unlock_irqrestore(&dev->drw_lock, irqflags); - draw->handle = new_id; + draw.handle = new_id; - DRM_DEBUG("%d\n", draw->handle); + DRM_DEBUG("%d\n", draw.handle); + + DRM_COPY_TO_USER_IOCTL((struct drm_draw __user *)data, draw, sizeof(draw)); return 0; } @@ -72,64 +75,72 @@ int drm_adddraw(struct drm_device *dev, void *data, struct drm_file *file_priv) /** * Free drawable ID and memory to store information about it. */ -int drm_rmdraw(struct drm_device *dev, void *data, struct drm_file *file_priv) +int drm_rmdraw(DRM_IOCTL_ARGS) { - struct drm_draw *draw = data; + DRM_DEVICE; + struct drm_draw draw; 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(struct drm_device *dev, void *data, struct drm_file *file_priv) +int drm_update_drawable_info(DRM_IOCTL_ARGS) { - struct drm_update_draw *update = data; + DRM_DEVICE; + struct drm_update_draw update; unsigned long irqflags; struct drm_clip_rect *rects; struct drm_drawable_info *info; int err; - info = idr_find(&dev->drw_idr, update->handle); + DRM_COPY_FROM_USER_IOCTL(update, (struct drm_update_draw __user *) data, + sizeof(update)); + + 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 = -ENOMEM; + err = DRM_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 = -EFAULT; + err = DRM_ERR(EFAULT); goto error; } @@ -141,23 +152,23 @@ int drm_update_drawable_info(struct drm_device *dev, void *data, struct drm_file } 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 -EINVAL; + DRM_ERROR("Invalid update type %d\n", update.type); + return DRM_ERR(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/trunk/drivers/char/drm/drm_drv.c b/trunk/drivers/char/drm/drm_drv.c index 72668b15e5ce..19994cd865de 100644 --- a/trunk/drivers/char/drm/drm_drv.c +++ b/trunk/drivers/char/drm/drm_drv.c @@ -49,74 +49,73 @@ #include "drmP.h" #include "drm_core.h" -static int drm_version(struct drm_device *dev, void *data, - struct drm_file *file_priv); +static int drm_version(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg); /** Ioctl table */ -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), +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}, /* The DRM_IOCTL_DMA ioctl should be defined by the driver. */ - DRM_IOCTL_DEF(DRM_IOCTL_DMA, NULL, DRM_AUTH), + [DRM_IOCTL_NR(DRM_IOCTL_DMA)] = {NULL, DRM_AUTH}, - DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + [DRM_IOCTL_NR(DRM_IOCTL_CONTROL)] = {drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, #if __OS_HAS_AGP - 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), + [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}, #endif - 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_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_WAIT_VBLANK, drm_wait_vblank, 0), + [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK)] = {drm_wait_vblank, 0}, - DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), + [DRM_IOCTL_NR(DRM_IOCTL_UPDATE_DRAW)] = {drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY}, }; #define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) @@ -225,7 +224,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.file_priv = NULL; + dev->lock.filp = NULL; wake_up_interruptible(&dev->lock.lock_queue); } mutex_unlock(&dev->struct_mutex); @@ -419,19 +418,27 @@ module_exit(drm_core_exit); * * Fills in the version information in \p arg. */ -static int drm_version(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int drm_version(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_version *version = data; + 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; int len; - 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_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); + + if (copy_to_user(argp, &version, sizeof(version))) + return -EFAULT; return 0; } @@ -439,7 +446,7 @@ static int drm_version(struct drm_device *dev, void *data, * Called whenever a process performs an ioctl on /dev/drm. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg user argument. * \return zero on success or negative number on failure. @@ -450,22 +457,21 @@ static int drm_version(struct drm_device *dev, void *data, int drm_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg) { - struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->head->dev; - struct drm_ioctl_desc *ioctl; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + drm_ioctl_desc_t *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]); - ++file_priv->ioctl_count; + ++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(file_priv->head->device), - file_priv->authenticated); + (long)old_encode_dev(priv->head->device), + priv->authenticated); if ((nr >= DRM_CORE_IOCTL_COUNT) && ((nr < DRM_COMMAND_BASE) || (nr >= DRM_COMMAND_END))) @@ -483,40 +489,18 @@ 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) && !file_priv->authenticated) || - ((ioctl->flags & DRM_MASTER) && !file_priv->master)) { + ((ioctl->flags & DRM_AUTH) && !priv->authenticated) || + ((ioctl->flags & DRM_MASTER) && !priv->master)) { retcode = -EACCES; } else { - 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; - } + retcode = func(inode, filp, cmd, arg); } err_i1: - if (kdata) - kfree(kdata); atomic_dec(&dev->ioctl_count); if (retcode) DRM_DEBUG("ret = %x\n", retcode); diff --git a/trunk/drivers/char/drm/drm_fops.c b/trunk/drivers/char/drm/drm_fops.c index f383fc37190c..7bc51bac450d 100644 --- a/trunk/drivers/char/drm/drm_fops.c +++ b/trunk/drivers/char/drm/drm_fops.c @@ -242,7 +242,6 @@ 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; @@ -313,7 +312,7 @@ EXPORT_SYMBOL(drm_fasync); * Release file. * * \param inode device inode - * \param file_priv DRM file private. + * \param filp file pointer. * \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 @@ -323,28 +322,29 @@ EXPORT_SYMBOL(drm_fasync); */ int drm_release(struct inode *inode, struct file *filp) { - struct drm_file *file_priv = filp->private_data; - struct drm_device *dev = file_priv->head->dev; + struct drm_file *priv = filp->private_data; + struct drm_device *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, file_priv); + dev->driver->preclose(dev, filp); /* ======================================================== * Begin inline drm_release */ DRM_DEBUG("pid = %d, device = 0x%lx, open_count = %d\n", - current->pid, (long)old_encode_dev(file_priv->head->device), + current->pid, (long)old_encode_dev(priv->head->device), dev->open_count); if (dev->driver->reclaim_buffers_locked && dev->lock.hw_lock) { - if (drm_i_have_hw_lock(dev, file_priv)) { - dev->driver->reclaim_buffers_locked(dev, file_priv); + if (drm_i_have_hw_lock(filp)) { + dev->driver->reclaim_buffers_locked(dev, filp); } 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, file_priv); + dev->driver->reclaim_buffers_locked(dev, filp); 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, file_priv); + dev->driver->reclaim_buffers_idlelocked(dev, filp); drm_idlelock_release(&dev->lock); } - if (drm_i_have_hw_lock(dev, file_priv)) { + if (drm_i_have_hw_lock(filp)) { 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, file_priv); + dev->driver->reclaim_buffers(dev, filp); } 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 == file_priv && + if (pos->tag == 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 (file_priv->remove_auth_on_close == 1) { + if (priv->remove_auth_on_close == 1) { struct drm_file *temp; list_for_each_entry(temp, &dev->filelist, lhead) temp->authenticated = 0; } - list_del(&file_priv->lhead); + list_del(&priv->lhead); mutex_unlock(&dev->struct_mutex); if (dev->driver->postclose) - dev->driver->postclose(dev, file_priv); - drm_free(file_priv, sizeof(*file_priv), DRM_MEM_FILES); + dev->driver->postclose(dev, priv); + drm_free(priv, sizeof(*priv), DRM_MEM_FILES); /* ======================================================== * End inline drm_release diff --git a/trunk/drivers/char/drm/drm_ioc32.c b/trunk/drivers/char/drm/drm_ioc32.c index 2286f3312c5c..462f46f2049a 100644 --- a/trunk/drivers/char/drm/drm_ioc32.c +++ b/trunk/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 file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg user argument. * \return zero on success or negative number on failure. diff --git a/trunk/drivers/char/drm/drm_ioctl.c b/trunk/drivers/char/drm/drm_ioctl.c index d9be14624526..b195e102e737 100644 --- a/trunk/drivers/char/drm/drm_ioctl.c +++ b/trunk/drivers/char/drm/drm_ioctl.c @@ -42,24 +42,30 @@ * Get the bus id. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_getunique(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_unique *u = data; + 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; - if (u->unique_len >= dev->unique_len) { - if (copy_to_user(u->unique, dev->unique, dev->unique_len)) + 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)) return -EFAULT; } - u->unique_len = dev->unique_len; - + u.unique_len = dev->unique_len; + if (copy_to_user(argp, &u, sizeof(u))) + return -EFAULT; return 0; } @@ -67,7 +73,7 @@ int drm_getunique(struct drm_device *dev, void *data, * Set the bus id. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg user argument, pointing to a drm_unique structure. * \return zero on success or a negative number on failure. @@ -77,23 +83,28 @@ int drm_getunique(struct drm_device *dev, void *data, * in interface version 1.1 and will return EBUSY when setversion has requested * version 1.1 or greater. */ -int drm_setunique(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_setunique(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_unique *u = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_unique u; int domain, bus, slot, func, ret; if (dev->unique_len || dev->unique) return -EBUSY; - if (!u->unique_len || u->unique_len > 1024) + if (copy_from_user(&u, (struct drm_unique __user *) arg, sizeof(u))) + return -EFAULT; + + 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'; @@ -112,7 +123,7 @@ int drm_setunique(struct drm_device *dev, void *data, */ ret = sscanf(dev->unique, "PCI:%d:%d:%d", &bus, &slot, &func); if (ret != 3) - return -EINVAL; + return DRM_ERR(EINVAL); domain = bus >> 8; bus &= 0xff; @@ -161,7 +172,7 @@ static int drm_set_busid(struct drm_device * dev) * Get a mapping information. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg user argument, pointing to a drm_map structure. * @@ -170,16 +181,21 @@ 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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_getmap(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_map *map = data; + 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_list *r_list = NULL; struct list_head *list; int idx; int i; - idx = map->offset; + if (copy_from_user(&map, argp, sizeof(map))) + return -EFAULT; + idx = map.offset; mutex_lock(&dev->struct_mutex); if (idx < 0) { @@ -200,14 +216,16 @@ int drm_getmap(struct drm_device *dev, void *data, 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; } @@ -215,7 +233,7 @@ int drm_getmap(struct drm_device *dev, void *data, * Get client information. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param arg user argument, pointing to a drm_client structure. * @@ -224,15 +242,20 @@ int drm_getmap(struct drm_device *dev, void *data, * Searches for the client with the specified index and copies its information * into userspace */ -int drm_getclient(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_getclient(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_client *client = data; + 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_file *pt; int idx; int i; - idx = client->idx; + if (copy_from_user(&client, argp, sizeof(client))) + return -EFAULT; + idx = client.idx; mutex_lock(&dev->struct_mutex); if (list_empty(&dev->filelist)) { @@ -246,13 +269,15 @@ int drm_getclient(struct drm_device *dev, void *data, 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; } @@ -260,35 +285,39 @@ int drm_getclient(struct drm_device *dev, void *data, * Get statistics information. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_getstats(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_stats *stats = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_stats stats; 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; } @@ -296,59 +325,64 @@ int drm_getstats(struct drm_device *dev, void *data, * Setversion ioctl. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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(struct drm_device *dev, void *data, struct drm_file *file_priv) +int drm_setversion(DRM_IOCTL_ARGS) { - 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); + 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); 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 */ - drm_set_busid(dev); + ret = drm_set_busid(dev); + if (ret) + return ret; } } - 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 (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 (dev->driver->set_version) - dev->driver->set_version(dev, sv); + dev->driver->set_version(dev, &sv); } - -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; + return 0; } /** No-op ioctl. */ -int drm_noop(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_noop(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) { DRM_DEBUG("\n"); return 0; diff --git a/trunk/drivers/char/drm/drm_irq.c b/trunk/drivers/char/drm/drm_irq.c index 05eae63f85ba..871d2fde09b3 100644 --- a/trunk/drivers/char/drm/drm_irq.c +++ b/trunk/drivers/char/drm/drm_irq.c @@ -41,7 +41,7 @@ * Get interrupt from bus id. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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,24 +50,30 @@ * 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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_irq_by_busid(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_irq_busid *p = data; + 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; if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) return -EINVAL; - 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; + if (copy_from_user(&p, argp, sizeof(p))) + return -EFAULT; - p->irq = dev->irq; + 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; - DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum, - p->irq); + p.irq = dev->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; } @@ -181,27 +187,31 @@ EXPORT_SYMBOL(drm_irq_uninstall); * IRQ control ioctl. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_control(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_control *ctl = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_control ctl; /* 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: @@ -217,7 +227,7 @@ int drm_control(struct drm_device *dev, void *data, * Wait for VBLANK. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \param cmd command. * \param data user argument, pointing to a drm_wait_vblank structure. * \return zero on success or a negative number on failure. @@ -232,25 +242,31 @@ int drm_control(struct drm_device *dev, void *data, * * If a signal is not requested, then calls vblank_wait(). */ -int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv) +int drm_wait_vblank(DRM_IOCTL_ARGS) { - union drm_wait_vblank *vblwait = data; + 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; struct timeval now; int ret = 0; unsigned int flags, seq; - if ((!dev->irq) || (!dev->irq_enabled)) + if (!dev->irq) return -EINVAL; - if (vblwait->request.type & + if (copy_from_user(&vblwait, argp, sizeof(vblwait))) + return -EFAULT; + + 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)) @@ -259,10 +275,10 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr 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: @@ -270,8 +286,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr } 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) { @@ -287,13 +303,12 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr * 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; } } @@ -315,8 +330,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr 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); @@ -325,22 +340,25 @@ int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_pr 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/trunk/drivers/char/drm/drm_lock.c b/trunk/drivers/char/drm/drm_lock.c index c6b73e744d67..c0534b5a8b78 100644 --- a/trunk/drivers/char/drm/drm_lock.c +++ b/trunk/drivers/char/drm/drm_lock.c @@ -41,33 +41,39 @@ static int drm_notifier(void *priv); * Lock ioctl. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, struct drm_file *file_priv) +int drm_lock(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; DECLARE_WAITQUEUE(entry, current); - struct drm_lock *lock = data; + struct drm_lock lock; int ret = 0; - ++file_priv->lock_count; + ++priv->lock_count; - if (lock->context == DRM_KERNEL_CONTEXT) { + if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock))) + return -EFAULT; + + 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); @@ -81,8 +87,8 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ret = -EINTR; break; } - if (drm_lock_take(&dev->lock, lock->context)) { - dev->lock.file_priv = file_priv; + if (drm_lock_take(&dev->lock, lock.context)) { + dev->lock.filp = filp; dev->lock.lock_time = jiffies; atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); break; /* Got lock */ @@ -101,8 +107,7 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) __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); @@ -110,26 +115,24 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) 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 -EBUSY; + DRM_DEBUG("%d waiting for DMA quiescent\n", lock.context); + return DRM_ERR(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; @@ -139,21 +142,27 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) * Unlock ioctl. * * \param inode device inode. - * \param file_priv DRM file private. + * \param filp file pointer. * \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 drm_device *dev, void *data, struct drm_file *file_priv) +int drm_unlock(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - struct drm_lock *lock = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_lock lock; unsigned long irqflags; - if (lock->context == DRM_KERNEL_CONTEXT) { + if (copy_from_user(&lock, (struct drm_lock __user *) arg, sizeof(lock))) + return -EFAULT; + + 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; } @@ -175,7 +184,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) 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. */ } } @@ -248,7 +257,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->file_priv = NULL; + lock_data->filp = NULL; do { old = *lock; new = context | _DRM_LOCK_HELD; @@ -381,11 +390,13 @@ void drm_idlelock_release(struct drm_lock_data *lock_data) EXPORT_SYMBOL(drm_idlelock_release); -int drm_i_have_hw_lock(struct drm_device *dev, struct drm_file *file_priv) +int drm_i_have_hw_lock(struct file *filp) { - return (file_priv->lock_count && dev->lock.hw_lock && + DRM_DEVICE; + + return (priv->lock_count && dev->lock.hw_lock && _DRM_LOCK_IS_HELD(dev->lock.hw_lock->lock) && - dev->lock.file_priv == file_priv); + dev->lock.filp == filp); } EXPORT_SYMBOL(drm_i_have_hw_lock); diff --git a/trunk/drivers/char/drm/drm_os_linux.h b/trunk/drivers/char/drm/drm_os_linux.h index 114e54e0f61b..0b8d3433386d 100644 --- a/trunk/drivers/char/drm/drm_os_linux.h +++ b/trunk/drivers/char/drm/drm_os_linux.h @@ -6,6 +6,11 @@ #include /* For task queue support */ #include +/** 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) @@ -28,6 +33,9 @@ #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 @@ -86,6 +94,8 @@ 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/trunk/drivers/char/drm/drm_pciids.h b/trunk/drivers/char/drm/drm_pciids.h index f3593974496c..30b200b01314 100644 --- a/trunk/drivers/char/drm/drm_pciids.h +++ b/trunk/drivers/char/drm/drm_pciids.h @@ -236,8 +236,10 @@ {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/trunk/drivers/char/drm/drm_scatter.c b/trunk/drivers/char/drm/drm_scatter.c index eb7fa437355e..067d25daaf17 100644 --- a/trunk/drivers/char/drm/drm_scatter.c +++ b/trunk/drivers/char/drm/drm_scatter.c @@ -62,8 +62,13 @@ void drm_sg_cleanup(struct drm_sg_mem * entry) # define ScatterHandle(x) (unsigned int)(x) #endif -int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) +int drm_sg_alloc(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_scatter_gather __user *argp = (void __user *)arg; + struct drm_scatter_gather request; struct drm_sg_mem *entry; unsigned long pages, i, j; @@ -75,13 +80,17 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) 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), @@ -133,7 +142,12 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) SetPageReserved(entry->pagelist[j]); } - request->handle = entry->handle; + request.handle = entry->handle; + + if (copy_to_user(argp, &request, sizeof(request))) { + drm_sg_cleanup(entry); + return -EFAULT; + } dev->sg = entry; @@ -183,31 +197,27 @@ int drm_sg_alloc(struct drm_device *dev, struct drm_scatter_gather * request) drm_sg_cleanup(entry); return -ENOMEM; } -EXPORT_SYMBOL(drm_sg_alloc); - -int drm_sg_alloc_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int drm_sg_free(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - 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_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + struct drm_scatter_gather request; 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/trunk/drivers/char/drm/drm_vm.c b/trunk/drivers/char/drm/drm_vm.c index e8d50af58201..68e36e51ba0c 100644 --- a/trunk/drivers/char/drm/drm_vm.c +++ b/trunk/drivers/char/drm/drm_vm.c @@ -463,7 +463,7 @@ static void drm_vm_close(struct vm_area_struct *vma) /** * mmap DMA memory. * - * \param file_priv DRM file private. + * \param filp file pointer. * \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 file_priv DRM file private. + * \param filp file pointer. * \param vma virtual memory area. * \return zero on success or a negative number on failure. * diff --git a/trunk/drivers/char/drm/i810_dma.c b/trunk/drivers/char/drm/i810_dma.c index 8e841bdee6dc..cb449999d0ef 100644 --- a/trunk/drivers/char/drm/i810_dma.c +++ b/trunk/drivers/char/drm/i810_dma.c @@ -120,9 +120,10 @@ static const struct file_operations i810_buffer_fops = { .fasync = drm_fasync, }; -static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) +static int i810_map_buffer(struct drm_buf * buf, struct file *filp) { - struct drm_device *dev = file_priv->head->dev; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = 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; @@ -132,14 +133,14 @@ static int i810_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) return -EINVAL; down_write(¤t->mm->mmap_sem); - old_fops = file_priv->filp->f_op; - file_priv->filp->f_op = &i810_buffer_fops; + old_fops = filp->f_op; + filp->f_op = &i810_buffer_fops; dev_priv->mmap_buffer = buf; - buf_priv->virtual = (void *)do_mmap(file_priv->filp, 0, buf->total, + buf_priv->virtual = (void *)do_mmap(filp, 0, buf->total, PROT_READ | PROT_WRITE, MAP_SHARED, buf->bus_address); dev_priv->mmap_buffer = NULL; - file_priv->filp->f_op = old_fops; + filp->f_op = old_fops; if (IS_ERR(buf_priv->virtual)) { /* Real error */ DRM_ERROR("mmap error\n"); @@ -172,7 +173,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 drm_file *file_priv) + struct file *filp) { struct drm_buf *buf; drm_i810_buf_priv_t *buf_priv; @@ -185,13 +186,13 @@ static int i810_dma_get_buffer(struct drm_device * dev, drm_i810_dma_t * d, return retcode; } - retcode = i810_map_buffer(buf, file_priv); + retcode = i810_map_buffer(buf, filp); if (retcode) { i810_freelist_put(dev, buf); DRM_ERROR("mapbuf failed, retcode %d\n", retcode); return retcode; } - buf->file_priv = file_priv; + buf->filp = filp; buf_priv = buf->dev_private; d->granted = 1; d->request_idx = buf->idx; @@ -379,7 +380,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 -ENOMEM; + return DRM_ERR(ENOMEM); } dev_priv->ring.virtual_start = dev_priv->ring.map.handle; @@ -429,29 +430,99 @@ static int i810_dma_initialize(struct drm_device * dev, return 0; } -static int i810_dma_init(struct drm_device *dev, void *data, - struct drm_file *file_priv) +/* 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) { + + /* 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 = data; + drm_i810_init_t init; int retcode = 0; - switch (init->func) { + /* 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: 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; @@ -897,8 +968,7 @@ 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 drm_file *file_priv) +static void i810_reclaim_buffers(struct drm_device * dev, struct file *filp) { struct drm_device_dma *dma = dev->dma; int i; @@ -916,7 +986,7 @@ static void i810_reclaim_buffers(struct drm_device * dev, struct drm_buf *buf = dma->buflist[i]; drm_i810_buf_priv_t *buf_priv = buf->dev_private; - if (buf->file_priv == file_priv && buf_priv) { + if (buf->filp == filp && buf_priv) { int used = cmpxchg(buf_priv->in_use, I810_BUF_CLIENT, I810_BUF_FREE); @@ -928,38 +998,47 @@ static void i810_reclaim_buffers(struct drm_device * dev, } } -static int i810_flush_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_flush_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - LOCK_TEST_WITH_RETURN(dev, file_priv); + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + + LOCK_TEST_WITH_RETURN(dev, filp); i810_flush_queue(dev); return 0; } -static int i810_dma_vertex(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_dma_vertex(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_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 = data; + drm_i810_vertex_t vertex; + + if (copy_from_user + (&vertex, (drm_i810_vertex_t __user *) arg, sizeof(vertex))) + return -EFAULT; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); 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]; @@ -967,37 +1046,48 @@ static int i810_dma_vertex(struct drm_device *dev, void *data, return 0; } -static int i810_clear_bufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_clear_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - drm_i810_clear_t *clear = data; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + drm_i810_clear_t clear; - LOCK_TEST_WITH_RETURN(dev, file_priv); + if (copy_from_user + (&clear, (drm_i810_clear_t __user *) arg, sizeof(clear))) + return -EFAULT; + + LOCK_TEST_WITH_RETURN(dev, filp); /* 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 drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_swap_bufs(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_DEBUG("i810_swap_bufs\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); i810_dma_dispatch_swap(dev); return 0; } -static int i810_getage(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_getage(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_private_t *) dev->dev_private; u32 *hw_status = dev_priv->hw_status_page; drm_i810_sarea_t *sarea_priv = (drm_i810_sarea_t *) @@ -1007,39 +1097,46 @@ static int i810_getage(struct drm_device *dev, void *data, return 0; } -static int i810_getbuf(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_getbuf(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; int retcode = 0; - drm_i810_dma_t *d = data; + drm_i810_dma_t d; 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; - LOCK_TEST_WITH_RETURN(dev, file_priv); + if (copy_from_user(&d, (drm_i810_dma_t __user *) arg, sizeof(d))) + return -EFAULT; + + LOCK_TEST_WITH_RETURN(dev, filp); - d->granted = 0; + d.granted = 0; - retcode = i810_dma_get_buffer(dev, d, file_priv); + retcode = i810_dma_get_buffer(dev, &d, filp); 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 drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_copybuf(struct inode *inode, + struct file *filp, unsigned int cmd, unsigned long arg) { /* Never copy - 2.4.x doesn't need it */ return 0; } -static int i810_docopy(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_docopy(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) { /* Never copy - 2.4.x doesn't need it */ return 0; @@ -1105,25 +1202,30 @@ static void i810_dma_dispatch_mc(struct drm_device * dev, struct drm_buf * buf, ADVANCE_LP_RING(); } -static int i810_dma_mc(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_dma_mc(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_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 = data; + drm_i810_mc_t mc; + + if (copy_from_user(&mc, (drm_i810_mc_t __user *) arg, sizeof(mc))) + return -EFAULT; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - 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]; @@ -1131,41 +1233,52 @@ static int i810_dma_mc(struct drm_device *dev, void *data, return 0; } -static int i810_rstatus(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_rstatus(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_private_t *) dev->dev_private; return (int)(((u32 *) (dev_priv->hw_status_page))[4]); } -static int i810_ov0_info(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_ov0_info(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_private_t *) dev->dev_private; - drm_i810_overlay_t *ov = data; - - ov->offset = dev_priv->overlay_offset; - ov->physical = dev_priv->overlay_physical; + drm_i810_overlay_t data; + 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 drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_fstatus(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_private_t *) dev->dev_private; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + return I810_READ(0x30008); } -static int i810_ov0_flip(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_ov0_flip(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_private_t *) dev->dev_private; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); //Tell the overlay to update I810_WRITE(0x30000, dev_priv->overlay_physical | 0x80000000); @@ -1197,14 +1310,16 @@ static int i810_do_cleanup_pageflip(struct drm_device * dev) return 0; } -static int i810_flip_bufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i810_flip_bufs(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 = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv->page_flipping) i810_do_init_pageflip(dev); @@ -1230,7 +1345,7 @@ void i810_driver_lastclose(struct drm_device * dev) i810_dma_cleanup(dev); } -void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) +void i810_driver_preclose(struct drm_device * dev, DRMFILE filp) { if (dev->dev_private) { drm_i810_private_t *dev_priv = dev->dev_private; @@ -1240,10 +1355,9 @@ void i810_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) } } -void i810_driver_reclaim_buffers_locked(struct drm_device * dev, - struct drm_file *file_priv) +void i810_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) { - i810_reclaim_buffers(dev, file_priv); + i810_reclaim_buffers(dev, filp); } int i810_driver_dma_quiescent(struct drm_device * dev) @@ -1252,22 +1366,22 @@ int i810_driver_dma_quiescent(struct drm_device * dev) return 0; } -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) +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} }; int i810_max_ioctl = DRM_ARRAY_SIZE(i810_ioctls); diff --git a/trunk/drivers/char/drm/i810_drm.h b/trunk/drivers/char/drm/i810_drm.h index 7a10bb6f2c0f..614977dbce45 100644 --- a/trunk/drivers/char/drm/i810_drm.h +++ b/trunk/drivers/char/drm/i810_drm.h @@ -102,8 +102,13 @@ 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/trunk/drivers/char/drm/i810_drv.h b/trunk/drivers/char/drm/i810_drv.h index 0af45872f67e..648833844c7f 100644 --- a/trunk/drivers/char/drm/i810_drv.h +++ b/trunk/drivers/char/drm/i810_drv.h @@ -117,16 +117,15 @@ 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 drm_file *file_priv); + struct file *filp); 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, - struct drm_file *file_priv); +extern void i810_driver_preclose(struct drm_device * dev, DRMFILE filp); extern void i810_driver_reclaim_buffers_locked(struct drm_device * dev, - struct drm_file *file_priv); + struct file *filp); extern int i810_driver_device_is_agp(struct drm_device * dev); -extern struct drm_ioctl_desc i810_ioctls[]; +extern drm_ioctl_desc_t i810_ioctls[]; extern int i810_max_ioctl; #define I810_BASE(reg) ((unsigned long) \ diff --git a/trunk/drivers/char/drm/i830_dma.c b/trunk/drivers/char/drm/i830_dma.c index 43a1f78712d6..dc20c1a7834e 100644 --- a/trunk/drivers/char/drm/i830_dma.c +++ b/trunk/drivers/char/drm/i830_dma.c @@ -122,9 +122,10 @@ static const struct file_operations i830_buffer_fops = { .fasync = drm_fasync, }; -static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) +static int i830_map_buffer(struct drm_buf * buf, struct file *filp) { - struct drm_device *dev = file_priv->head->dev; + struct drm_file *priv = filp->private_data; + struct drm_device *dev = 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; @@ -135,13 +136,13 @@ static int i830_map_buffer(struct drm_buf * buf, struct drm_file *file_priv) return -EINVAL; down_write(¤t->mm->mmap_sem); - old_fops = file_priv->filp->f_op; - file_priv->filp->f_op = &i830_buffer_fops; + old_fops = filp->f_op; + filp->f_op = &i830_buffer_fops; dev_priv->mmap_buffer = buf; - virtual = do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE, + virtual = do_mmap(filp, 0, buf->total, PROT_READ | PROT_WRITE, MAP_SHARED, buf->bus_address); dev_priv->mmap_buffer = NULL; - file_priv->filp->f_op = old_fops; + filp->f_op = old_fops; if (IS_ERR((void *)virtual)) { /* ugh */ /* Real error */ DRM_ERROR("mmap error\n"); @@ -176,7 +177,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 drm_file *file_priv) + struct file *filp) { struct drm_buf *buf; drm_i830_buf_priv_t *buf_priv; @@ -189,13 +190,13 @@ static int i830_dma_get_buffer(struct drm_device * dev, drm_i830_dma_t * d, return retcode; } - retcode = i830_map_buffer(buf, file_priv); + retcode = i830_map_buffer(buf, filp); if (retcode) { i830_freelist_put(dev, buf); DRM_ERROR("mapbuf failed, retcode %d\n", retcode); return retcode; } - buf->file_priv = file_priv; + buf->filp = filp; buf_priv = buf->dev_private; d->granted = 1; d->request_idx = buf->idx; @@ -388,7 +389,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 -ENOMEM; + return DRM_ERR(ENOMEM); } dev_priv->ring.virtual_start = dev_priv->ring.map.handle; @@ -450,20 +451,25 @@ static int i830_dma_initialize(struct drm_device * dev, return 0; } -static int i830_dma_init(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_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_i830_private_t *dev_priv; - drm_i830_init_t *init = data; + drm_i830_init_t init; int retcode = 0; - switch (init->func) { + if (copy_from_user(&init, (void *__user)arg, sizeof(init))) + return -EFAULT; + + switch (init.func) { case I830_INIT_DMA: dev_priv = drm_alloc(sizeof(drm_i830_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) return -ENOMEM; - retcode = i830_dma_initialize(dev, dev_priv, init); + retcode = i830_dma_initialize(dev, dev_priv, &init); break; case I830_CLEANUP_DMA: retcode = i830_dma_cleanup(dev); @@ -1242,7 +1248,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 drm_file *file_priv) +static void i830_reclaim_buffers(struct drm_device * dev, struct file *filp) { struct drm_device_dma *dma = dev->dma; int i; @@ -1260,7 +1266,7 @@ static void i830_reclaim_buffers(struct drm_device * dev, struct drm_file *file_ struct drm_buf *buf = dma->buflist[i]; drm_i830_buf_priv_t *buf_priv = buf->dev_private; - if (buf->file_priv == file_priv && buf_priv) { + if (buf->filp == filp && buf_priv) { int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE); @@ -1272,36 +1278,45 @@ static void i830_reclaim_buffers(struct drm_device * dev, struct drm_file *file_ } } -static int i830_flush_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_flush_ioctl(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - LOCK_TEST_WITH_RETURN(dev, file_priv); + struct drm_file *priv = filp->private_data; + struct drm_device *dev = priv->head->dev; + + LOCK_TEST_WITH_RETURN(dev, filp); i830_flush_queue(dev); return 0; } -static int i830_dma_vertex(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_dma_vertex(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_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 = data; + drm_i830_vertex_t vertex; + + if (copy_from_user + (&vertex, (drm_i830_vertex_t __user *) arg, sizeof(vertex))) + return -EFAULT; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); 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]; @@ -1309,30 +1324,39 @@ static int i830_dma_vertex(struct drm_device *dev, void *data, return 0; } -static int i830_clear_bufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_clear_bufs(struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg) { - drm_i830_clear_t *clear = data; + 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; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); /* 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 drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_swap_bufs(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_DEBUG("i830_swap_bufs\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); i830_dma_dispatch_swap(dev); return 0; @@ -1362,14 +1386,16 @@ static int i830_do_cleanup_pageflip(struct drm_device * dev) return 0; } -static int i830_flip_bufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_flip_bufs(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_i830_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv->page_flipping) i830_do_init_pageflip(dev); @@ -1378,9 +1404,11 @@ static int i830_flip_bufs(struct drm_device *dev, void *data, return 0; } -static int i830_getage(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_getage(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_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 *) @@ -1390,50 +1418,58 @@ static int i830_getage(struct drm_device *dev, void *data, return 0; } -static int i830_getbuf(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_getbuf(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; int retcode = 0; - drm_i830_dma_t *d = data; + drm_i830_dma_t d; 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, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - d->granted = 0; + d.granted = 0; - retcode = i830_dma_get_buffer(dev, d, file_priv); + retcode = i830_dma_get_buffer(dev, &d, filp); 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 drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_copybuf(struct inode *inode, + struct file *filp, unsigned int cmd, unsigned long arg) { /* Never copy - 2.4.x doesn't need it */ return 0; } -static int i830_docopy(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_docopy(struct inode *inode, struct file *filp, unsigned int cmd, + unsigned long arg) { return 0; } -static int i830_getparam(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_getparam(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_i830_private_t *dev_priv = dev->dev_private; - drm_i830_getparam_t *param = data; + drm_i830_getparam_t param; int value; if (!dev_priv) { @@ -1441,7 +1477,11 @@ static int i830_getparam(struct drm_device *dev, void *data, return -EINVAL; } - switch (param->param) { + if (copy_from_user + (¶m, (drm_i830_getparam_t __user *) arg, sizeof(param))) + return -EFAULT; + + switch (param.param) { case I830_PARAM_IRQ_ACTIVE: value = dev->irq_enabled; break; @@ -1449,7 +1489,7 @@ static int i830_getparam(struct drm_device *dev, void *data, 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; } @@ -1457,20 +1497,26 @@ static int i830_getparam(struct drm_device *dev, void *data, return 0; } -static int i830_setparam(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i830_setparam(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_i830_private_t *dev_priv = dev->dev_private; - drm_i830_setparam_t *param = data; + drm_i830_setparam_t param; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return -EINVAL; } - switch (param->param) { + if (copy_from_user + (¶m, (drm_i830_setparam_t __user *) arg, sizeof(param))) + return -EFAULT; + + 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; @@ -1496,7 +1542,7 @@ void i830_driver_lastclose(struct drm_device * dev) i830_dma_cleanup(dev); } -void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) +void i830_driver_preclose(struct drm_device * dev, DRMFILE filp) { if (dev->dev_private) { drm_i830_private_t *dev_priv = dev->dev_private; @@ -1506,9 +1552,9 @@ void i830_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) } } -void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct drm_file *file_priv) +void i830_driver_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) { - i830_reclaim_buffers(dev, file_priv); + i830_reclaim_buffers(dev, filp); } int i830_driver_dma_quiescent(struct drm_device * dev) @@ -1517,21 +1563,21 @@ int i830_driver_dma_quiescent(struct drm_device * dev) return 0; } -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) +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} }; int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls); diff --git a/trunk/drivers/char/drm/i830_drv.h b/trunk/drivers/char/drm/i830_drv.h index db3a9fa83960..ddda67956dea 100644 --- a/trunk/drivers/char/drm/i830_drv.h +++ b/trunk/drivers/char/drm/i830_drv.h @@ -122,25 +122,24 @@ typedef struct drm_i830_private { } drm_i830_private_t; -extern struct drm_ioctl_desc i830_ioctls[]; +extern drm_ioctl_desc_t i830_ioctls[]; extern int i830_max_ioctl; /* i830_irq.c */ -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 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 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, - struct drm_file *file_priv); +extern void i830_driver_preclose(struct drm_device * dev, DRMFILE filp); extern void i830_driver_lastclose(struct drm_device * dev); extern void i830_driver_reclaim_buffers_locked(struct drm_device * dev, - struct drm_file *file_priv); + struct file *filp); extern int i830_driver_dma_quiescent(struct drm_device * dev); extern int i830_driver_device_is_agp(struct drm_device * dev); diff --git a/trunk/drivers/char/drm/i830_irq.c b/trunk/drivers/char/drm/i830_irq.c index 76403f4b6200..a1b5c63c3c3e 100644 --- a/trunk/drivers/char/drm/i830_irq.c +++ b/trunk/drivers/char/drm/i830_irq.c @@ -114,23 +114,29 @@ 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 drm_device *dev, void *data, - struct drm_file *file_priv) +int i830_irq_emit(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_i830_private_t *dev_priv = dev->dev_private; - drm_i830_irq_emit_t *emit = data; + drm_i830_irq_emit_t emit; int result; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); 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; } @@ -140,18 +146,24 @@ int i830_irq_emit(struct drm_device *dev, void *data, /* Doesn't need the hardware lock. */ -int i830_irq_wait(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i830_irq_wait(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_i830_private_t *dev_priv = dev->dev_private; - drm_i830_irq_wait_t *irqwait = data; + drm_i830_irq_wait_t irqwait; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); return -EINVAL; } - return i830_wait_irq(dev, irqwait->irq_seq); + if (copy_from_user(&irqwait, (drm_i830_irq_wait_t __user *) arg, + sizeof(irqwait))) + return -EFAULT; + + return i830_wait_irq(dev, irqwait.irq_seq); } /* drm_dma.h hooks diff --git a/trunk/drivers/char/drm/i915_dma.c b/trunk/drivers/char/drm/i915_dma.c index e61a43e5b3ac..8e7d713a5a15 100644 --- a/trunk/drivers/char/drm/i915_dma.c +++ b/trunk/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 -EBUSY; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (!dev_priv->mmio_map) { DRM_ERROR("can not find mmio map!\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } if (dev_priv->ring.map.handle == NULL) { DRM_ERROR("can not ioremap virtual address for" " ring buffer\n"); - return -ENOMEM; + return DRM_ERR(ENOMEM); } /* Program Hardware Status Page */ if (!dev_priv->hw_status_page) { DRM_ERROR("Can not find hardware status page\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page); @@ -251,20 +251,23 @@ static int i915_dma_resume(struct drm_device * dev) return 0; } -static int i915_dma_init(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_dma_init(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv; - drm_i915_init_t *init = data; + drm_i915_init_t init; int retcode = 0; - switch (init->func) { + DRM_COPY_FROM_USER_IOCTL(init, (drm_i915_init_t __user *) data, + sizeof(init)); + + switch (init.func) { case I915_INIT_DMA: dev_priv = drm_alloc(sizeof(drm_i915_private_t), DRM_MEM_DRIVER); if (dev_priv == NULL) - return -ENOMEM; - retcode = i915_initialize(dev, dev_priv, init); + return DRM_ERR(ENOMEM); + retcode = i915_initialize(dev, dev_priv, &init); break; case I915_CLEANUP_DMA: retcode = i915_dma_cleanup(dev); @@ -273,7 +276,7 @@ static int i915_dma_init(struct drm_device *dev, void *data, retcode = i915_dma_resume(dev); break; default: - retcode = -EINVAL; + retcode = DRM_ERR(EINVAL); break; } @@ -363,7 +366,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 -EINVAL; + return DRM_ERR(EINVAL); BEGIN_LP_RING((dwords+1)&~1); @@ -371,17 +374,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 -EINVAL; + return DRM_ERR(EINVAL); if ((sz = validate_cmd(cmd)) == 0 || i + sz > dwords) - return -EINVAL; + return DRM_ERR(EINVAL); OUT_RING(cmd); while (++i, --sz) { if (DRM_COPY_FROM_USER_UNCHECKED(&cmd, &buffer[i], sizeof(cmd))) { - return -EINVAL; + return DRM_ERR(EINVAL); } OUT_RING(cmd); } @@ -404,13 +407,13 @@ static int i915_emit_box(struct drm_device * dev, RING_LOCALS; if (DRM_COPY_FROM_USER_UNCHECKED(&box, &boxes[i], sizeof(box))) { - return -EFAULT; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (IS_I965G(dev)) { @@ -464,7 +467,7 @@ static int i915_dispatch_cmdbuffer(struct drm_device * dev, if (cmd->sz & 0x3) { DRM_ERROR("alignment"); - return -EINVAL; + return DRM_ERR(EINVAL); } i915_kernel_lost_context(dev); @@ -499,7 +502,7 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev, if ((batch->start | batch->used) & 0x7) { DRM_ERROR("alignment"); - return -EINVAL; + return DRM_ERR(EINVAL); } i915_kernel_lost_context(dev); @@ -595,69 +598,76 @@ static int i915_quiescent(struct drm_device * dev) return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__); } -static int i915_flush_ioctl(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_flush_ioctl(DRM_IOCTL_ARGS) { - LOCK_TEST_WITH_RETURN(dev, file_priv); + DRM_DEVICE; + + LOCK_TEST_WITH_RETURN(dev, filp); return i915_quiescent(dev); } -static int i915_batchbuffer(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_batchbuffer(DRM_IOCTL_ARGS) { + 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 = data; + drm_i915_batchbuffer_t batch; int ret; if (!dev_priv->allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); - return -EINVAL; + return DRM_ERR(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, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - 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 -EFAULT; + return DRM_ERR(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(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_cmdbuffer(DRM_IOCTL_ARGS) { + 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 = data; + drm_i915_cmdbuffer_t cmdbuf; 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, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - 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 -EFAULT; + return DRM_ERR(EFAULT); } - ret = i915_dispatch_cmdbuffer(dev, cmdbuf); + ret = i915_dispatch_cmdbuffer(dev, &cmdbuf); if (ret) { DRM_ERROR("i915_dispatch_cmdbuffer failed\n"); return ret; @@ -667,29 +677,33 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data, return 0; } -static int i915_flip_bufs(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_flip_bufs(DRM_IOCTL_ARGS) { + DRM_DEVICE; + DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); return i915_dispatch_flip(dev); } -static int i915_getparam(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_getparam(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_getparam_t *param = data; + drm_i915_getparam_t param; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - switch (param->param) { + DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_getparam_t __user *) data, + sizeof(param)); + + switch (param.param) { case I915_PARAM_IRQ_ACTIVE: value = dev->irq ? 1 : 0; break; @@ -700,64 +714,68 @@ static int i915_getparam(struct drm_device *dev, void *data, value = READ_BREADCRUMB(dev_priv); break; default: - DRM_ERROR("Unknown parameter %d\n", param->param); - return -EINVAL; + DRM_ERROR("Unknown parameter %d\n", param.param); + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } return 0; } -static int i915_setparam(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_setparam(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_setparam_t *param = data; + drm_i915_setparam_t param; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - switch (param->param) { + DRM_COPY_FROM_USER_IOCTL(param, (drm_i915_setparam_t __user *) data, + sizeof(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 -EINVAL; + DRM_ERROR("unknown parameter %d\n", param.param); + return DRM_ERR(EINVAL); } return 0; } -static int i915_set_status_page(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int i915_set_status_page(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_hws_addr_t *hws = data; + drm_i915_hws_addr_t hws; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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); - printk(KERN_DEBUG "set status page addr 0x%08x\n", (u32)hws->addr); - - dev_priv->status_gfx_addr = hws->addr & (0x1ffff<<12); + 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; @@ -770,7 +788,7 @@ static int i915_set_status_page(struct drm_device *dev, void *data, dev_priv->status_gfx_addr = 0; DRM_ERROR("can not ioremap virtual address for" " G33 hw status page\n"); - return -ENOMEM; + return DRM_ERR(ENOMEM); } dev_priv->hw_status_page = dev_priv->hws_map.handle; @@ -803,32 +821,32 @@ void i915_driver_lastclose(struct drm_device * dev) i915_dma_cleanup(dev); } -void i915_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) +void i915_driver_preclose(struct drm_device * dev, DRMFILE filp) { if (dev->dev_private) { drm_i915_private_t *dev_priv = dev->dev_private; - i915_mem_release(dev, file_priv, dev_priv->agp_heap); + i915_mem_release(dev, filp, dev_priv->agp_heap); } } -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), +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}, }; int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls); diff --git a/trunk/drivers/char/drm/i915_drv.h b/trunk/drivers/char/drm/i915_drv.h index e064292e703a..28b98733beb8 100644 --- a/trunk/drivers/char/drm/i915_drv.h +++ b/trunk/drivers/char/drm/i915_drv.h @@ -70,7 +70,7 @@ struct mem_block { struct mem_block *prev; int start; int size; - struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ + DRMFILE filp; /* 0: free, -1: heap, other: real files */ }; typedef struct _drm_i915_vbl_swap { @@ -116,24 +116,21 @@ typedef struct drm_i915_private { unsigned int swaps_pending; } drm_i915_private_t; -extern struct drm_ioctl_desc i915_ioctls[]; +extern drm_ioctl_desc_t 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, - struct drm_file *file_priv); +extern void i915_driver_preclose(struct drm_device * dev, DRMFILE filp); 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(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_irq_emit(DRM_IOCTL_ARGS); +extern int i915_irq_wait(DRM_IOCTL_ARGS); 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); @@ -141,25 +138,18 @@ 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(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); +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); /* i915_mem.c */ -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 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 void i915_mem_takedown(struct mem_block **heap); extern void i915_mem_release(struct drm_device * dev, - struct drm_file *file_priv, struct mem_block *heap); + DRMFILE filp, 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/trunk/drivers/char/drm/i915_irq.c b/trunk/drivers/char/drm/i915_irq.c index a443f4a202e3..bb8e9e9c8201 100644 --- a/trunk/drivers/char/drm/i915_irq.c +++ b/trunk/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 == -EBUSY) { + if (ret == DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, @@ -355,25 +355,28 @@ int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) /* Needs the lock as it touches the ring. */ -int i915_irq_emit(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_irq_emit(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_irq_emit_t *emit = data; + drm_i915_irq_emit_t emit; int result; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } return 0; @@ -381,18 +384,21 @@ int i915_irq_emit(struct drm_device *dev, void *data, /* Doesn't need the hardware lock. */ -int i915_irq_wait(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_irq_wait(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_irq_wait_t *irqwait = data; + drm_i915_irq_wait_t irqwait; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - return i915_wait_irq(dev, irqwait->irq_seq); + DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_i915_irq_wait_t __user *) data, + sizeof(irqwait)); + + return i915_wait_irq(dev, irqwait.irq_seq); } static void i915_enable_interrupt (struct drm_device *dev) @@ -411,60 +417,64 @@ static void i915_enable_interrupt (struct drm_device *dev) /* Set the vblank monitor pipe */ -int i915_vblank_pipe_set(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_vblank_pipe_set(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_pipe_t *pipe = data; + drm_i915_vblank_pipe_t pipe; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - if (pipe->pipe & ~(DRM_I915_VBLANK_PIPE_A|DRM_I915_VBLANK_PIPE_B)) { + 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)) { DRM_ERROR("%s called with invalid pipe 0x%x\n", - __FUNCTION__, pipe->pipe); - return -EINVAL; + __FUNCTION__, pipe.pipe); + return DRM_ERR(EINVAL); } - dev_priv->vblank_pipe = pipe->pipe; + dev_priv->vblank_pipe = pipe.pipe; i915_enable_interrupt (dev); return 0; } -int i915_vblank_pipe_get(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_vblank_pipe_get(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_pipe_t *pipe = data; + drm_i915_vblank_pipe_t pipe; u16 flag; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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; - + pipe.pipe |= DRM_I915_VBLANK_PIPE_B; + DRM_COPY_TO_USER_IOCTL((drm_i915_vblank_pipe_t __user *) data, pipe, + sizeof(pipe)); return 0; } /** * Schedule buffer swap at given vertical blank. */ -int i915_vblank_swap(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_vblank_swap(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_vblank_swap_t *swap = data; + drm_i915_vblank_swap_t swap; drm_i915_vbl_swap_t *vbl_swap; unsigned int pipe, seqtype, curseq; unsigned long irqflags; @@ -472,35 +482,38 @@ int i915_vblank_swap(struct drm_device *dev, void *data, if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __func__); - return -EINVAL; + return DRM_ERR(EINVAL); } if (dev_priv->sarea_priv->rotation) { DRM_DEBUG("Rotation not supported\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } - if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE | + DRM_COPY_FROM_USER_IOCTL(swap, (drm_i915_vblank_swap_t __user *) data, + sizeof(swap)); + + 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 -EINVAL; + DRM_ERROR("Invalid sequence type 0x%x\n", swap.seqtype); + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + DRM_DEBUG("Invalid drawable ID %d\n", swap.drawable); + return DRM_ERR(EINVAL); } spin_unlock_irqrestore(&dev->drw_lock, irqflags); @@ -508,14 +521,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data, 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 -EINVAL; + return DRM_ERR(EINVAL); } } @@ -524,9 +537,9 @@ int i915_vblank_swap(struct drm_device *dev, void *data, 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; @@ -537,21 +550,21 @@ int i915_vblank_swap(struct drm_device *dev, void *data, if (dev_priv->swaps_pending >= 100) { DRM_DEBUG("Too many swaps queued\n"); - return -EBUSY; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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); @@ -560,6 +573,9 @@ int i915_vblank_swap(struct drm_device *dev, void *data, 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/trunk/drivers/char/drm/i915_mem.c b/trunk/drivers/char/drm/i915_mem.c index 56fb9b30a5d7..50b4bacef0e0 100644 --- a/trunk/drivers/char/drm/i915_mem.c +++ b/trunk/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, - struct drm_file *file_priv) + DRMFILE filp) { /* 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->file_priv = NULL; + newblock->filp = 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->file_priv = NULL; + newblock->filp = 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->file_priv = file_priv; + p->filp = filp; return p; } static struct mem_block *alloc_block(struct mem_block *heap, int size, - int align2, struct drm_file *file_priv) + int align2, DRMFILE filp) { 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->file_priv == NULL && start + size <= p->start + p->size) - return split_block(p, start, size, file_priv); + if (p->filp == NULL && start + size <= p->start + p->size) + return split_block(p, start, size, filp); } 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->file_priv = NULL; + p->filp = NULL; - /* Assumes a single contiguous range. Needs a special file_priv in + /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ - if (p->next->file_priv == NULL) { + if (p->next->filp == 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->file_priv == NULL) { + if (p->prev->filp == NULL) { struct mem_block *q = p->prev; q->size += p->size; q->next = p->next; @@ -197,19 +197,18 @@ static int init_heap(struct mem_block **heap, int start, int size) blocks->start = start; blocks->size = size; - blocks->file_priv = NULL; + blocks->filp = NULL; blocks->next = blocks->prev = *heap; memset(*heap, 0, sizeof(**heap)); - (*heap)->file_priv = (struct drm_file *) - 1; + (*heap)->filp = (DRMFILE) - 1; (*heap)->next = (*heap)->prev = blocks; return 0; } /* Free all blocks associated with the releasing file. */ -void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv, - struct mem_block *heap) +void i915_mem_release(struct drm_device * dev, DRMFILE filp, struct mem_block *heap) { struct mem_block *p; @@ -217,17 +216,17 @@ void i915_mem_release(struct drm_device * dev, struct drm_file *file_priv, return; for (p = heap->next; p != heap; p = p->next) { - if (p->file_priv == file_priv) { - p->file_priv = NULL; + if (p->filp == filp) { + p->filp = NULL; mark_block(dev, p, 0); } } - /* Assumes a single contiguous range. Needs a special file_priv in + /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ for (p = heap->next; p != heap; p = p->next) { - while (p->file_priv == NULL && p->next->file_priv == NULL) { + while (p->filp == NULL && p->next->filp == NULL) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; @@ -268,117 +267,129 @@ static struct mem_block **get_heap(drm_i915_private_t * dev_priv, int region) /* IOCTL HANDLERS */ -int i915_mem_alloc(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_mem_alloc(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_alloc_t *alloc = data; + drm_i915_mem_alloc_t alloc; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - heap = get_heap(dev_priv, alloc->region); + DRM_COPY_FROM_USER_IOCTL(alloc, (drm_i915_mem_alloc_t __user *) data, + sizeof(alloc)); + + heap = get_heap(dev_priv, alloc.region); if (!heap || !*heap) - return -EFAULT; + return DRM_ERR(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, file_priv); + block = alloc_block(*heap, alloc.size, alloc.alignment, filp); if (!block) - return -ENOMEM; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } return 0; } -int i915_mem_free(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_mem_free(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_free_t *memfree = data; + drm_i915_mem_free_t memfree; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - heap = get_heap(dev_priv, memfree->region); + DRM_COPY_FROM_USER_IOCTL(memfree, (drm_i915_mem_free_t __user *) data, + sizeof(memfree)); + + heap = get_heap(dev_priv, memfree.region); if (!heap || !*heap) - return -EFAULT; + return DRM_ERR(EFAULT); - block = find_block(*heap, memfree->region_offset); + block = find_block(*heap, memfree.region_offset); if (!block) - return -EFAULT; + return DRM_ERR(EFAULT); - if (block->file_priv != file_priv) - return -EPERM; + if (block->filp != filp) + return DRM_ERR(EPERM); mark_block(dev, block, 0); free_block(block); return 0; } -int i915_mem_init_heap(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int i915_mem_init_heap(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_init_heap_t *initheap = data; + drm_i915_mem_init_heap_t initheap; struct mem_block **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - heap = get_heap(dev_priv, initheap->region); + DRM_COPY_FROM_USER_IOCTL(initheap, + (drm_i915_mem_init_heap_t __user *) data, + sizeof(initheap)); + + heap = get_heap(dev_priv, initheap.region); if (!heap) - return -EFAULT; + return DRM_ERR(EFAULT); if (*heap) { DRM_ERROR("heap already initialized?"); - return -EFAULT; + return DRM_ERR(EFAULT); } - return init_heap(heap, initheap->start, initheap->size); + return init_heap(heap, initheap.start, initheap.size); } -int i915_mem_destroy_heap( struct drm_device *dev, void *data, - struct drm_file *file_priv ) +int i915_mem_destroy_heap( DRM_IOCTL_ARGS ) { + DRM_DEVICE; drm_i915_private_t *dev_priv = dev->dev_private; - drm_i915_mem_destroy_heap_t *destroyheap = data; + drm_i915_mem_destroy_heap_t destroyheap; struct mem_block **heap; if ( !dev_priv ) { DRM_ERROR( "%s called with no initialization\n", __FUNCTION__ ); - return -EINVAL; + return DRM_ERR(EINVAL); } - heap = get_heap( dev_priv, destroyheap->region ); + DRM_COPY_FROM_USER_IOCTL( destroyheap, (drm_i915_mem_destroy_heap_t *)data, + sizeof(destroyheap) ); + + heap = get_heap( dev_priv, destroyheap.region ); if (!heap) { DRM_ERROR("get_heap failed"); - return -EFAULT; + return DRM_ERR(EFAULT); } if (!*heap) { DRM_ERROR("heap not initialized?"); - return -EFAULT; + return DRM_ERR(EFAULT); } i915_mem_takedown( heap ); diff --git a/trunk/drivers/char/drm/mga_dma.c b/trunk/drivers/char/drm/mga_dma.c index c567c34cda78..9c73a6e3861b 100644 --- a/trunk/drivers/char/drm/mga_dma.c +++ b/trunk/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 -EBUSY; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(ENOMEM); } if (dev_priv->primary->size != dma_bs->primary_size) { @@ -759,30 +759,36 @@ static int mga_do_dma_bootstrap(struct drm_device * dev, return err; } -int mga_dma_bootstrap(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int mga_dma_bootstrap(DRM_IOCTL_ARGS) { - drm_mga_dma_bootstrap_t *bootstrap = data; + DRM_DEVICE; + drm_mga_dma_bootstrap_t bootstrap; 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; - err = mga_do_dma_bootstrap(dev, bootstrap); + DRM_COPY_FROM_USER_IOCTL(bootstrap, + (drm_mga_dma_bootstrap_t __user *) data, + sizeof(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]; + bootstrap.agp_mode = modes[bootstrap.agp_mode & 0x07]; + DRM_COPY_TO_USER_IOCTL((drm_mga_dma_bootstrap_t __user *)data, + bootstrap, sizeof(bootstrap)); return err; } @@ -820,7 +826,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 -EINVAL; + return DRM_ERR(EINVAL); } if (!dev_priv->used_new_dma_init) { @@ -831,29 +837,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 -EINVAL; + return DRM_ERR(EINVAL); } dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset); if (!dev_priv->mmio) { DRM_ERROR("failed to find mmio region!\n"); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } drm_core_ioremap(dev_priv->warp, dev); @@ -871,7 +877,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 -ENOMEM; + return DRM_ERR(ENOMEM); } ret = mga_warp_install_microcode(dev_priv); @@ -921,7 +927,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 -ENOMEM; + return DRM_ERR(ENOMEM); } return 0; @@ -1001,17 +1007,20 @@ static int mga_do_cleanup_dma(struct drm_device *dev, int full_cleanup) return 0; } -int mga_dma_init(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int mga_dma_init(DRM_IOCTL_ARGS) { - drm_mga_init_t *init = data; + DRM_DEVICE; + drm_mga_init_t init; int err; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(init, (drm_mga_init_t __user *) data, + sizeof(init)); - 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); } @@ -1020,33 +1029,36 @@ int mga_dma_init(struct drm_device *dev, void *data, return mga_do_cleanup_dma(dev, FULL_CLEANUP); } - return -EINVAL; + return DRM_ERR(EINVAL); } /* ================================================================ * Primary DMA stream management */ -int mga_dma_flush(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int mga_dma_flush(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - struct drm_lock *lock = data; + struct drm_lock lock; + + LOCK_TEST_WITH_RETURN(dev, filp); - LOCK_TEST_WITH_RETURN(dev, file_priv); + DRM_COPY_FROM_USER_IOCTL(lock, (struct drm_lock __user *) data, + sizeof(lock)); 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) @@ -1060,12 +1072,12 @@ int mga_dma_flush(struct drm_device *dev, void *data, } } -int mga_dma_reset(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int mga_dma_reset(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); return mga_do_dma_reset(dev_priv); } @@ -1074,8 +1086,7 @@ int mga_dma_reset(struct drm_device *dev, void *data, * DMA buffer management */ -static int mga_dma_get_buffers(struct drm_device * dev, - struct drm_file *file_priv, struct drm_dma * d) +static int mga_dma_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d) { struct drm_buf *buf; int i; @@ -1083,56 +1094,61 @@ static int mga_dma_get_buffers(struct drm_device * dev, for (i = d->granted_count; i < d->request_count; i++) { buf = mga_freelist_get(dev); if (!buf) - return -EAGAIN; + return DRM_ERR(EAGAIN); - buf->file_priv = file_priv; + buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return -EFAULT; + return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return -EFAULT; + return DRM_ERR(EFAULT); d->granted_count++; } return 0; } -int mga_dma_buffers(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int mga_dma_buffers(DRM_IOCTL_ARGS) { + 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 *d = data; + struct drm_dma __user *argp = (void __user *)data; + struct drm_dma d; int ret = 0; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); /* 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 -EINVAL; + DRM_CURRENTPID, d.send_count); + return DRM_ERR(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 -EINVAL; + DRM_CURRENTPID, d.request_count, dma->buf_count); + return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN(dev_priv); - d->granted_count = 0; + d.granted_count = 0; - if (d->request_count) { - ret = mga_dma_get_buffers(dev, file_priv, d); + if (d.request_count) { + ret = mga_dma_get_buffers(filp, dev, &d); } + DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); + return ret; } diff --git a/trunk/drivers/char/drm/mga_drv.h b/trunk/drivers/char/drm/mga_drv.h index cd94c04e31c0..49253affa475 100644 --- a/trunk/drivers/char/drm/mga_drv.h +++ b/trunk/drivers/char/drm/mga_drv.h @@ -148,20 +148,15 @@ typedef struct drm_mga_private { unsigned int agp_size; } drm_mga_private_t; -extern struct drm_ioctl_desc mga_ioctls[]; +extern drm_ioctl_desc_t mga_ioctls[]; extern int mga_max_ioctl; /* mga_dma.c */ -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_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_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); @@ -250,7 +245,7 @@ do { \ dev_priv->prim.high_mark ) { \ if ( MGA_DMA_DEBUG ) \ DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ - return -EBUSY; \ + return DRM_ERR(EBUSY); \ } \ } \ } while (0) @@ -261,7 +256,7 @@ do { \ if ( mga_do_wait_for_idle( dev_priv ) < 0 ) { \ if ( MGA_DMA_DEBUG ) \ DRM_INFO( "%s: wrap...\n", __FUNCTION__ ); \ - return -EBUSY; \ + return DRM_ERR(EBUSY); \ } \ mga_do_dma_wrap_end( dev_priv ); \ } \ diff --git a/trunk/drivers/char/drm/mga_state.c b/trunk/drivers/char/drm/mga_state.c index 5ec8b61c5d45..d448b0aef33c 100644 --- a/trunk/drivers/char/drm/mga_state.c +++ b/trunk/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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (length & MGA_ILOAD_MASK) { DRM_ERROR("*** bad iload length: 0x%x\n", length & MGA_ILOAD_MASK); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } return 0; } @@ -828,20 +828,24 @@ static void mga_dma_dispatch_blit(struct drm_device * dev, drm_mga_blit_t * blit * */ -static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int mga_dma_clear(DRM_IOCTL_ARGS) { + 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 = data; + drm_mga_clear_t clear; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(clear, (drm_mga_clear_t __user *) data, + sizeof(clear)); 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. */ @@ -850,12 +854,13 @@ static int mga_dma_clear(struct drm_device *dev, void *data, struct drm_file *fi return 0; } -static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int mga_dma_swap(DRM_IOCTL_ARGS) { + 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, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (sarea_priv->nbox > MGA_NR_SAREA_CLIPRECTS) sarea_priv->nbox = MGA_NR_SAREA_CLIPRECTS; @@ -871,32 +876,37 @@ static int mga_dma_swap(struct drm_device *dev, void *data, struct drm_file *fil return 0; } -static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int mga_dma_vertex(DRM_IOCTL_ARGS) { + 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 = data; + drm_mga_vertex_t vertex; + + LOCK_TEST_WITH_RETURN(dev, filp); - LOCK_TEST_WITH_RETURN(dev, file_priv); + DRM_COPY_FROM_USER_IOCTL(vertex, + (drm_mga_vertex_t __user *) data, + sizeof(vertex)); - if (vertex->idx < 0 || vertex->idx > dma->buf_count) - return -EINVAL; - buf = dma->buflist[vertex->idx]; + if (vertex.idx < 0 || vertex.idx > dma->buf_count) + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } WRAP_TEST_WITH_RETURN(dev_priv); @@ -906,73 +916,82 @@ static int mga_dma_vertex(struct drm_device *dev, void *data, struct drm_file *f return 0; } -static int mga_dma_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int mga_dma_indices(DRM_IOCTL_ARGS) { + 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 = data; + drm_mga_indices_t indices; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - if (indices->idx < 0 || indices->idx > dma->buf_count) - return -EINVAL; + DRM_COPY_FROM_USER_IOCTL(indices, + (drm_mga_indices_t __user *) data, + sizeof(indices)); - buf = dma->buflist[indices->idx]; + if (indices.idx < 0 || indices.idx > dma->buf_count) + return DRM_ERR(EINVAL); + + 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 -EINVAL; + return DRM_ERR(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(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int mga_dma_iload(DRM_IOCTL_ARGS) { + 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 = data; + drm_mga_iload_t iload; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(iload, (drm_mga_iload_t __user *) data, + sizeof(iload)); #if 0 if (mga_do_wait_for_idle(dev_priv) < 0) { if (MGA_DMA_DEBUG) DRM_INFO("%s: -EBUSY\n", __FUNCTION__); - return -EBUSY; + return DRM_ERR(EBUSY); } #endif - if (iload->idx < 0 || iload->idx > dma->buf_count) - return -EINVAL; + if (iload.idx < 0 || iload.idx > dma->buf_count) + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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. */ @@ -981,24 +1000,28 @@ static int mga_dma_iload(struct drm_device *dev, void *data, struct drm_file *fi return 0; } -static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int mga_dma_blit(DRM_IOCTL_ARGS) { + 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 = data; + drm_mga_blit_t blit; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(blit, (drm_mga_blit_t __user *) data, + sizeof(blit)); 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 -EINVAL; + if (mga_verify_blit(dev_priv, blit.srcorg, blit.dstorg)) + return DRM_ERR(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. */ @@ -1007,20 +1030,24 @@ static int mga_dma_blit(struct drm_device *dev, void *data, struct drm_file *fil return 0; } -static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int mga_getparam(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; - drm_mga_getparam_t *param = data; + drm_mga_getparam_t param; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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; @@ -1028,35 +1055,36 @@ static int mga_getparam(struct drm_device *dev, void *data, struct drm_file *fil value = dev_priv->chipset; break; default: - return -EINVAL; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } return 0; } -static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int mga_set_fence(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; - u32 *fence = data; + u32 temp; DMA_LOCALS; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); - /* I would normal do this assignment in the declaration of fence, + /* I would normal do this assignment in the declaration of temp, * but dev_priv may be NULL. */ - *fence = dev_priv->next_fence_to_post; + temp = dev_priv->next_fence_to_post; dev_priv->next_fence_to_post++; BEGIN_DMA(1); @@ -1065,40 +1093,53 @@ static int mga_set_fence(struct drm_device *dev, void *data, struct drm_file *fi 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(struct drm_device *dev, void *data, struct drm_file * -file_priv) +static int mga_wait_fence(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_mga_private_t *dev_priv = dev->dev_private; - u32 *fence = data; + u32 fence; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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); + 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); + } + return 0; } -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), +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}, }; int mga_max_ioctl = DRM_ARRAY_SIZE(mga_ioctls); diff --git a/trunk/drivers/char/drm/mga_warp.c b/trunk/drivers/char/drm/mga_warp.c index 651b93c8ab5d..d67f4925fbac 100644 --- a/trunk/drivers/char/drm/mga_warp.c +++ b/trunk/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 -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } } @@ -177,7 +177,7 @@ int mga_warp_init(drm_mga_private_t * dev_priv) MGA_WRITE(MGA_WVRTXSZ, 7); break; default: - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } return 0; diff --git a/trunk/drivers/char/drm/r128_cce.c b/trunk/drivers/char/drm/r128_cce.c index 7d550aba165e..b163ed09bd81 100644 --- a/trunk/drivers/char/drm/r128_cce.c +++ b/trunk/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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(ENOMEM); } R128_WRITE(R128_PCI_GART_PAGE, dev_priv->gart_info.bus_addr); #if __OS_HAS_AGP @@ -625,30 +625,35 @@ int r128_do_cleanup_cce(struct drm_device * dev) return 0; } -int r128_cce_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_cce_init(DRM_IOCTL_ARGS) { - drm_r128_init_t *init = data; + DRM_DEVICE; + drm_r128_init_t init; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - switch (init->func) { + DRM_COPY_FROM_USER_IOCTL(init, (drm_r128_init_t __user *) data, + sizeof(init)); + + 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 -EINVAL; + return DRM_ERR(EINVAL); } -int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_cce_start(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (dev_priv->cce_running || dev_priv->cce_mode == R128_PM4_NONPM4) { DRM_DEBUG("%s while CCE running\n", __FUNCTION__); @@ -663,26 +668,30 @@ int r128_cce_start(struct drm_device *dev, void *data, struct drm_file *file_pri /* Stop the CCE. The engine must have been idled before calling this * routine. */ -int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_cce_stop(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_cce_stop_t *stop = data; + drm_r128_cce_stop_t stop; int ret; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(stop, (drm_r128_cce_stop_t __user *) data, + sizeof(stop)); /* 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; @@ -702,16 +711,17 @@ int r128_cce_stop(struct drm_device *dev, void *data, struct drm_file *file_priv /* Just reset the CCE ring. Called as part of an X Server engine reset. */ -int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_cce_reset(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_DEBUG("%s called before init done\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } r128_do_cce_reset(dev_priv); @@ -722,12 +732,13 @@ int r128_cce_reset(struct drm_device *dev, void *data, struct drm_file *file_pri return 0; } -int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_cce_idle(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (dev_priv->cce_running) { r128_do_cce_flush(dev_priv); @@ -736,18 +747,19 @@ int r128_cce_idle(struct drm_device *dev, void *data, struct drm_file *file_priv return r128_do_cce_idle(dev_priv); } -int r128_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_engine_reset(DRM_IOCTL_ARGS) { + DRM_DEVICE; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); return r128_do_engine_reset(dev); } -int r128_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_fullscreen(DRM_IOCTL_ARGS) { - return -EINVAL; + return DRM_ERR(EINVAL); } /* ================================================================ @@ -768,7 +780,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 -ENOMEM; + return DRM_ERR(ENOMEM); memset(dev_priv->head, 0, sizeof(drm_r128_freelist_t)); dev_priv->head->age = R128_BUFFER_USED; @@ -779,7 +791,7 @@ static int r128_freelist_init(struct drm_device * dev) entry = drm_alloc(sizeof(drm_r128_freelist_t), DRM_MEM_DRIVER); if (!entry) - return -ENOMEM; + return DRM_ERR(ENOMEM); entry->age = R128_BUFFER_FREE; entry->buf = buf; @@ -816,7 +828,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->file_priv == 0) + if (buf->filp == 0) return buf; } @@ -871,12 +883,10 @@ int r128_wait_ring(drm_r128_private_t * dev_priv, int n) /* FIXME: This is being ignored... */ DRM_ERROR("failed!\n"); - return -EBUSY; + return DRM_ERR(EBUSY); } -static int r128_cce_get_buffers(struct drm_device * dev, - struct drm_file *file_priv, - struct drm_dma * d) +static int r128_cce_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d) { int i; struct drm_buf *buf; @@ -884,51 +894,57 @@ static int r128_cce_get_buffers(struct drm_device * dev, for (i = d->granted_count; i < d->request_count; i++) { buf = r128_freelist_get(dev); if (!buf) - return -EAGAIN; + return DRM_ERR(EAGAIN); - buf->file_priv = file_priv; + buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return -EFAULT; + return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return -EFAULT; + return DRM_ERR(EFAULT); d->granted_count++; } return 0; } -int r128_cce_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) +int r128_cce_buffers(DRM_IOCTL_ARGS) { + DRM_DEVICE; struct drm_device_dma *dma = dev->dma; int ret = 0; - struct drm_dma *d = data; + struct drm_dma __user *argp = (void __user *)data; + struct drm_dma d; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); /* 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 -EINVAL; + DRM_CURRENTPID, d.send_count); + return DRM_ERR(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 -EINVAL; + DRM_CURRENTPID, d.request_count, dma->buf_count); + return DRM_ERR(EINVAL); } - d->granted_count = 0; + d.granted_count = 0; - if (d->request_count) { - ret = r128_cce_get_buffers(dev, file_priv, d); + if (d.request_count) { + ret = r128_cce_get_buffers(filp, dev, &d); } + DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); + return ret; } diff --git a/trunk/drivers/char/drm/r128_drm.h b/trunk/drivers/char/drm/r128_drm.h index 8d8878b55f55..e94a39c6e327 100644 --- a/trunk/drivers/char/drm/r128_drm.h +++ b/trunk/drivers/char/drm/r128_drm.h @@ -222,7 +222,11 @@ 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; @@ -236,12 +240,21 @@ 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 { @@ -251,10 +264,15 @@ 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/trunk/drivers/char/drm/r128_drv.h b/trunk/drivers/char/drm/r128_drv.h index 250d2aa46581..72249fb2fd1c 100644 --- a/trunk/drivers/char/drm/r128_drv.h +++ b/trunk/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 struct drm_ioctl_desc r128_ioctls[]; +extern drm_ioctl_desc_t r128_ioctls[]; extern int r128_max_ioctl; /* r128_cce.c */ -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 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 void r128_freelist_reset(struct drm_device * dev); @@ -156,8 +156,7 @@ 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, - struct drm_file *file_priv); +extern void r128_driver_preclose(struct drm_device * dev, DRMFILE filp); extern long r128_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); @@ -429,7 +428,7 @@ do { \ DRM_UDELAY(1); \ } \ DRM_ERROR( "ring space check failed!\n" ); \ - return -EBUSY; \ + return DRM_ERR(EBUSY); \ } \ __ring_space_done: \ ; \ diff --git a/trunk/drivers/char/drm/r128_state.c b/trunk/drivers/char/drm/r128_state.c index b7f483cac6d4..7b334fb7d649 100644 --- a/trunk/drivers/char/drm/r128_state.c +++ b/trunk/drivers/char/drm/r128_state.c @@ -776,9 +776,8 @@ static void r128_cce_dispatch_indices(struct drm_device * dev, sarea_priv->nbox = 0; } -static int r128_cce_dispatch_blit(struct drm_device * dev, - struct drm_file *file_priv, - drm_r128_blit_t * blit) +static int r128_cce_dispatch_blit(DRMFILE filp, + struct drm_device * dev, drm_r128_blit_t * blit) { drm_r128_private_t *dev_priv = dev->dev_private; struct drm_device_dma *dma = dev->dma; @@ -810,7 +809,7 @@ static int r128_cce_dispatch_blit(struct drm_device * dev, break; default: DRM_ERROR("invalid blit format %d\n", blit->format); - return -EINVAL; + return DRM_ERR(EINVAL); } /* Flush the pixel cache, and mark the contents as Read Invalid. @@ -830,14 +829,14 @@ static int r128_cce_dispatch_blit(struct drm_device * dev, buf = dma->buflist[blit->idx]; buf_priv = buf->dev_private; - if (buf->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; + DRM_CURRENTPID, buf->filp); + return DRM_ERR(EINVAL); } if (buf->pending) { DRM_ERROR("sending pending buffer %d\n", blit->idx); - return -EINVAL; + return DRM_ERR(EINVAL); } buf_priv->discard = 1; @@ -901,22 +900,22 @@ static int r128_cce_dispatch_write_span(struct drm_device * dev, count = depth->n; if (count > 4096 || count <= 0) - return -EMSGSIZE; + return DRM_ERR(EMSGSIZE); if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) { - return -EFAULT; + return DRM_ERR(EFAULT); } if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) { - return -EFAULT; + return DRM_ERR(EFAULT); } buffer_size = depth->n * sizeof(u32); buffer = drm_alloc(buffer_size, DRM_MEM_BUFS); if (buffer == NULL) - return -ENOMEM; + return DRM_ERR(ENOMEM); if (DRM_COPY_FROM_USER(buffer, depth->buffer, buffer_size)) { drm_free(buffer, buffer_size, DRM_MEM_BUFS); - return -EFAULT; + return DRM_ERR(EFAULT); } mask_size = depth->n * sizeof(u8); @@ -924,12 +923,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 -ENOMEM; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } for (i = 0; i < count; i++, x++) { @@ -997,28 +996,28 @@ static int r128_cce_dispatch_write_pixels(struct drm_device * dev, count = depth->n; if (count > 4096 || count <= 0) - return -EMSGSIZE; + return DRM_ERR(EMSGSIZE); xbuf_size = count * sizeof(*x); ybuf_size = count * sizeof(*y); x = drm_alloc(xbuf_size, DRM_MEM_BUFS); if (x == NULL) { - return -ENOMEM; + return DRM_ERR(ENOMEM); } y = drm_alloc(ybuf_size, DRM_MEM_BUFS); if (y == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); - return -ENOMEM; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } buffer_size = depth->n * sizeof(u32); @@ -1026,13 +1025,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 -ENOMEM; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } if (depth->mask) { @@ -1042,14 +1041,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 -ENOMEM; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } for (i = 0; i < count; i++) { @@ -1116,13 +1115,13 @@ static int r128_cce_dispatch_read_span(struct drm_device * dev, count = depth->n; if (count > 4096 || count <= 0) - return -EMSGSIZE; + return DRM_ERR(EMSGSIZE); if (DRM_COPY_FROM_USER(&x, depth->x, sizeof(x))) { - return -EFAULT; + return DRM_ERR(EFAULT); } if (DRM_COPY_FROM_USER(&y, depth->y, sizeof(y))) { - return -EFAULT; + return DRM_ERR(EFAULT); } BEGIN_RING(7); @@ -1160,7 +1159,7 @@ static int r128_cce_dispatch_read_pixels(struct drm_device * dev, count = depth->n; if (count > 4096 || count <= 0) - return -EMSGSIZE; + return DRM_ERR(EMSGSIZE); if (count > dev_priv->depth_pitch) { count = dev_priv->depth_pitch; @@ -1170,22 +1169,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 -ENOMEM; + return DRM_ERR(ENOMEM); } y = drm_alloc(ybuf_size, DRM_MEM_BUFS); if (y == NULL) { drm_free(x, xbuf_size, DRM_MEM_BUFS); - return -ENOMEM; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } for (i = 0; i < count; i++) { @@ -1242,21 +1241,25 @@ static void r128_cce_dispatch_stipple(struct drm_device * dev, u32 * stipple) * IOCTL functions */ -static int r128_cce_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_clear(DRM_IOCTL_ARGS) { + 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 = data; + drm_r128_clear_t clear; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(clear, (drm_r128_clear_t __user *) data, + sizeof(clear)); 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. @@ -1306,12 +1309,13 @@ 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(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_flip(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; DRM_DEBUG("%s\n", __FUNCTION__); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -1324,13 +1328,14 @@ static int r128_cce_flip(struct drm_device *dev, void *data, struct drm_file *fi return 0; } -static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_swap(DRM_IOCTL_ARGS) { + 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, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -1345,54 +1350,58 @@ static int r128_cce_swap(struct drm_device *dev, void *data, struct drm_file *fi return 0; } -static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_vertex(DRM_IOCTL_ARGS) { + 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 = data; + drm_r128_vertex_t vertex; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + vertex.idx, dma->buf_count - 1); + 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; + 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); } 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->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; + DRM_CURRENTPID, buf->filp); + return DRM_ERR(EINVAL); } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex->idx); - return -EINVAL; + DRM_ERROR("sending pending buffer %d\n", vertex.idx); + return DRM_ERR(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); @@ -1400,123 +1409,134 @@ static int r128_cce_vertex(struct drm_device *dev, void *data, struct drm_file * return 0; } -static int r128_cce_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_indices(DRM_IOCTL_ARGS) { + 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 = data; + drm_r128_indices_t elts; int count; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + elts.idx, dma->buf_count - 1); + 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; + 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); } 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->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; + DRM_CURRENTPID, buf->filp); + return DRM_ERR(EINVAL); } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", elts->idx); - return -EINVAL; + DRM_ERROR("sending pending buffer %d\n", elts.idx); + return DRM_ERR(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 -EINVAL; + if (elts.start & 0x7) { + DRM_ERROR("misaligned buffer 0x%x\n", elts.start); + return DRM_ERR(EINVAL); } - if (elts->start < buf->used) { - DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); - return -EINVAL; + if (elts.start < buf->used) { + DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used); + return DRM_ERR(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(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_blit(DRM_IOCTL_ARGS) { + DRM_DEVICE; struct drm_device_dma *dma = dev->dma; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_blit_t *blit = data; + drm_r128_blit_t blit; int ret; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(blit, (drm_r128_blit_t __user *) data, + sizeof(blit)); - 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 -EINVAL; + blit.idx, dma->buf_count - 1); + return DRM_ERR(EINVAL); } RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - ret = r128_cce_dispatch_blit(dev, file_priv, blit); + ret = r128_cce_dispatch_blit(filp, dev, &blit); COMMIT_RING(); return ret; } -static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_depth(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_depth_t *depth = data; + drm_r128_depth_t depth; int ret; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(depth, (drm_r128_depth_t __user *) data, + sizeof(depth)); RING_SPACE_TEST_WITH_RETURN(dev_priv); - ret = -EINVAL; - switch (depth->func) { + ret = DRM_ERR(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; } @@ -1524,16 +1544,20 @@ static int r128_cce_depth(struct drm_device *dev, void *data, struct drm_file *f return ret; } -static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_stipple(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_stipple_t *stipple = data; + drm_r128_stipple_t stipple; u32 mask[32]; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(stipple, (drm_r128_stipple_t __user *) data, + sizeof(stipple)); - if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) - return -EFAULT; + if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32))) + return DRM_ERR(EFAULT); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -1543,58 +1567,61 @@ static int r128_cce_stipple(struct drm_device *dev, void *data, struct drm_file return 0; } -static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_cce_indirect(DRM_IOCTL_ARGS) { + 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 = data; + drm_r128_indirect_t indirect; #if 0 RING_LOCALS; #endif - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + indirect.idx, dma->buf_count - 1); + return DRM_ERR(EINVAL); } - buf = dma->buflist[indirect->idx]; + buf = dma->buflist[indirect.idx]; buf_priv = buf->dev_private; - if (buf->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; + DRM_CURRENTPID, buf->filp); + return DRM_ERR(EINVAL); } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", indirect->idx); - return -EINVAL; + DRM_ERROR("sending pending buffer %d\n", indirect.idx); + return DRM_ERR(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 -EINVAL; + indirect.start, buf->used); + return DRM_ERR(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 @@ -1609,42 +1636,46 @@ static int r128_cce_indirect(struct drm_device *dev, void *data, struct drm_file * 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(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int r128_getparam(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_r128_private_t *dev_priv = dev->dev_private; - drm_r128_getparam_t *param = data; + drm_r128_getparam_t param; int value; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } return 0; } -void r128_driver_preclose(struct drm_device * dev, struct drm_file *file_priv) +void r128_driver_preclose(struct drm_device * dev, DRMFILE filp) { if (dev->dev_private) { drm_r128_private_t *dev_priv = dev->dev_private; @@ -1659,24 +1690,24 @@ void r128_driver_lastclose(struct drm_device * dev) r128_do_cleanup_cce(dev); } -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), +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}, }; int r128_max_ioctl = DRM_ARRAY_SIZE(r128_ioctls); diff --git a/trunk/drivers/char/drm/r300_cmdbuf.c b/trunk/drivers/char/drm/r300_cmdbuf.c index 59b2944811c5..4e5aca6ba59a 100644 --- a/trunk/drivers/char/drm/r300_cmdbuf.c +++ b/trunk/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 -EFAULT; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } break; default: DRM_ERROR("Register %04x failed check as flag=%02x\n", reg + i * 4, r300_reg_flags[(reg >> 2) + i]); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); if (reg + sz * 4 >= 0x10000) { DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, sz); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } ret = !radeon_check_offset(dev_priv, cmd[2]); if (ret) { DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (header.scratch.reg >= 5) { - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (DRM_COPY_FROM_USER(&h_pending, ref_age_base + buf_idx + 1, sizeof(u32))) { - return -EINVAL; + return DRM_ERR(EINVAL); } if (h_pending == 0) { - return -EINVAL; + return DRM_ERR(EINVAL); } h_pending--; if (DRM_COPY_TO_USER(ref_age_base + buf_idx + 1, &h_pending, sizeof(u32))) { - return -EINVAL; + return DRM_ERR(EINVAL); } cmdbuf->buf += sizeof(buf_idx); @@ -780,7 +780,8 @@ 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, - struct drm_file *file_priv, + DRMFILE filp, + struct drm_file *filp_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -878,16 +879,15 @@ 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 = -EINVAL; + ret = DRM_ERR(EINVAL); goto cleanup; } buf = dma->buflist[idx]; - if (buf->file_priv != file_priv || buf->pending) { + if (buf->filp != filp || buf->pending) { DRM_ERROR("bad buffer %p %p %d\n", - buf->file_priv, file_priv, - buf->pending); - ret = -EINVAL; + buf->filp, filp, buf->pending); + ret = DRM_ERR(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 = -EINVAL; + ret = DRM_ERR(EINVAL); goto cleanup; } } diff --git a/trunk/drivers/char/drm/radeon_cp.c b/trunk/drivers/char/drm/radeon_cp.c index 335423c5c186..af5790f8fd53 100644 --- a/trunk/drivers/char/drm/radeon_cp.c +++ b/trunk/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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } DRM_DEBUG("Starting radeon_do_resume_cp()\n"); @@ -1823,33 +1823,38 @@ static int radeon_do_resume_cp(struct drm_device * dev) return 0; } -int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_cp_init(DRM_IOCTL_ARGS) { - drm_radeon_init_t *init = data; + DRM_DEVICE; + drm_radeon_init_t init; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - if (init->func == RADEON_INIT_R300_CP) + DRM_COPY_FROM_USER_IOCTL(init, (drm_radeon_init_t __user *) data, + sizeof(init)); + + 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 -EINVAL; + return DRM_ERR(EINVAL); } -int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_cp_start(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (dev_priv->cp_running) { DRM_DEBUG("%s while CP running\n", __FUNCTION__); @@ -1869,14 +1874,18 @@ int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_pr /* Stop the CP. The engine must have been idled before calling this * routine. */ -int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_cp_stop(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_cp_stop_t *stop = data; + drm_radeon_cp_stop_t stop; int ret; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(stop, (drm_radeon_cp_stop_t __user *) data, + sizeof(stop)); if (!dev_priv->cp_running) return 0; @@ -1884,14 +1893,14 @@ int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_pri /* 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; @@ -1954,16 +1963,17 @@ 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(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_cp_reset(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_DEBUG("%s called before init done\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } radeon_do_cp_reset(dev_priv); @@ -1974,29 +1984,32 @@ int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_pr return 0; } -int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_cp_idle(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); return radeon_do_cp_idle(dev_priv); } /* Added by Charl P. Botha to call radeon_do_resume_cp(). */ -int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_cp_resume(DRM_IOCTL_ARGS) { + DRM_DEVICE; return radeon_do_resume_cp(dev); } -int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_engine_reset(DRM_IOCTL_ARGS) { + DRM_DEVICE; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); return radeon_do_engine_reset(dev); } @@ -2007,7 +2020,7 @@ int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *fil /* KW: Deprecated to say the least: */ -int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_fullscreen(DRM_IOCTL_ARGS) { return 0; } @@ -2053,9 +2066,8 @@ 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->file_priv == NULL || (buf->pending && - buf_priv->age <= - done_age)) { + if (buf->filp == 0 || (buf->pending && + buf_priv->age <= done_age)) { dev_priv->stats.requested_bufs++; buf->pending = 0; return buf; @@ -2094,9 +2106,8 @@ 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->file_priv == 0 || (buf->pending && - buf_priv->age <= - done_age)) { + if (buf->filp == 0 || (buf->pending && + buf_priv->age <= done_age)) { dev_priv->stats.requested_bufs++; buf->pending = 0; return buf; @@ -2156,11 +2167,10 @@ int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n) radeon_status(dev_priv); DRM_ERROR("failed!\n"); #endif - return -EBUSY; + return DRM_ERR(EBUSY); } -static int radeon_cp_get_buffers(struct drm_device *dev, - struct drm_file *file_priv, +static int radeon_cp_get_buffers(DRMFILE filp, struct drm_device * dev, struct drm_dma * d) { int i; @@ -2169,52 +2179,58 @@ static int radeon_cp_get_buffers(struct drm_device *dev, for (i = d->granted_count; i < d->request_count; i++) { buf = radeon_freelist_get(dev); if (!buf) - return -EBUSY; /* NOTE: broken client */ + return DRM_ERR(EBUSY); /* NOTE: broken client */ - buf->file_priv = file_priv; + buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return -EFAULT; + return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return -EFAULT; + return DRM_ERR(EFAULT); d->granted_count++; } return 0; } -int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_cp_buffers(DRM_IOCTL_ARGS) { + DRM_DEVICE; struct drm_device_dma *dma = dev->dma; int ret = 0; - struct drm_dma *d = data; + struct drm_dma __user *argp = (void __user *)data; + struct drm_dma d; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(d, argp, sizeof(d)); /* 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 -EINVAL; + DRM_CURRENTPID, d.send_count); + return DRM_ERR(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 -EINVAL; + DRM_CURRENTPID, d.request_count, dma->buf_count); + return DRM_ERR(EINVAL); } - d->granted_count = 0; + d.granted_count = 0; - if (d->request_count) { - ret = radeon_cp_get_buffers(dev, file_priv, d); + if (d.request_count) { + ret = radeon_cp_get_buffers(filp, dev, &d); } + DRM_COPY_TO_USER_IOCTL(argp, d, sizeof(d)); + return ret; } @@ -2225,7 +2241,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 -ENOMEM; + return DRM_ERR(ENOMEM); memset(dev_priv, 0, sizeof(drm_radeon_private_t)); dev->dev_private = (void *)dev_priv; diff --git a/trunk/drivers/char/drm/radeon_drv.h b/trunk/drivers/char/drm/radeon_drv.h index e4077bc212b3..3b3d9357201c 100644 --- a/trunk/drivers/char/drm/radeon_drv.h +++ b/trunk/drivers/char/drm/radeon_drv.h @@ -188,7 +188,7 @@ struct mem_block { struct mem_block *prev; int start; int size; - struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ + DRMFILE filp; /* 0: free, -1: heap, other: real files */ }; struct radeon_surface { @@ -203,7 +203,7 @@ struct radeon_virt_surface { u32 lower; u32 upper; u32 flags; - struct drm_file *file_priv; + DRMFILE filp; }; 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 struct drm_ioctl_desc radeon_ioctls[]; +extern drm_ioctl_desc_t 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(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 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 void radeon_freelist_reset(struct drm_device * dev); extern struct drm_buf *radeon_freelist_get(struct drm_device * dev); @@ -347,16 +347,15 @@ 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(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 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 void radeon_mem_takedown(struct mem_block **heap); -extern void radeon_mem_release(struct drm_file *file_priv, - struct mem_block *heap); +extern void radeon_mem_release(DRMFILE filp, struct mem_block *heap); /* radeon_irq.c */ -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 int radeon_irq_emit(DRM_IOCTL_ARGS); +extern int radeon_irq_wait(DRM_IOCTL_ARGS); extern void radeon_do_release(struct drm_device * dev); extern int radeon_driver_vblank_wait(struct drm_device * dev, @@ -373,7 +372,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, struct drm_file *file_priv); +extern void radeon_driver_preclose(struct drm_device * dev, DRMFILE filp); 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); @@ -383,8 +382,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, - struct drm_file *file_priv, +extern int r300_do_cp_cmdbuf(struct drm_device * dev, DRMFILE filp, + struct drm_file * filp_priv, drm_radeon_kcmd_buffer_t * cmdbuf); /* Flags for stats.boxes diff --git a/trunk/drivers/char/drm/radeon_irq.c b/trunk/drivers/char/drm/radeon_irq.c index f89e57665b64..ad8a0ac7182e 100644 --- a/trunk/drivers/char/drm/radeon_irq.c +++ b/trunk/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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); radeon_acknowledge_irqs(dev_priv, ack); @@ -196,24 +196,28 @@ int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence) /* Needs the lock as it touches the ring. */ -int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_irq_emit(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_irq_emit_t *emit = data; + drm_radeon_irq_emit_t emit; int result; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } return 0; @@ -221,17 +225,21 @@ int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_pr /* Doesn't need the hardware lock. */ -int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_irq_wait(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_irq_wait_t *irqwait = data; + drm_radeon_irq_wait_t irqwait; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - return radeon_wait_irq(dev, irqwait->irq_seq); + DRM_COPY_FROM_USER_IOCTL(irqwait, (drm_radeon_irq_wait_t __user *) data, + sizeof(irqwait)); + + return radeon_wait_irq(dev, irqwait.irq_seq); } static void radeon_enable_interrupt(struct drm_device *dev) @@ -312,7 +320,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 -EINVAL; + return DRM_ERR(EINVAL); } dev_priv->vblank_crtc = (unsigned int)value; radeon_enable_interrupt(dev); diff --git a/trunk/drivers/char/drm/radeon_mem.c b/trunk/drivers/char/drm/radeon_mem.c index a29acfe2f973..517cad8b6e3a 100644 --- a/trunk/drivers/char/drm/radeon_mem.c +++ b/trunk/drivers/char/drm/radeon_mem.c @@ -39,7 +39,7 @@ */ static struct mem_block *split_block(struct mem_block *p, int start, int size, - struct drm_file *file_priv) + DRMFILE filp) { /* 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->file_priv = NULL; + newblock->filp = 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->file_priv = NULL; + newblock->filp = 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->file_priv = file_priv; + p->filp = filp; return p; } static struct mem_block *alloc_block(struct mem_block *heap, int size, - int align2, struct drm_file *file_priv) + int align2, DRMFILE filp) { struct mem_block *p; int mask = (1 << align2) - 1; list_for_each(p, heap) { int start = (p->start + mask) & ~mask; - if (p->file_priv == 0 && start + size <= p->start + p->size) - return split_block(p, start, size, file_priv); + if (p->filp == 0 && start + size <= p->start + p->size) + return split_block(p, start, size, filp); } 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->file_priv = NULL; + p->filp = NULL; - /* Assumes a single contiguous range. Needs a special file_priv in + /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ - if (p->next->file_priv == 0) { + if (p->next->filp == 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->file_priv == 0) { + if (p->prev->filp == 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 -ENOMEM; + return DRM_ERR(ENOMEM); *heap = drm_alloc(sizeof(**heap), DRM_MEM_BUFS); if (!*heap) { drm_free(blocks, sizeof(*blocks), DRM_MEM_BUFS); - return -ENOMEM; + return DRM_ERR(ENOMEM); } blocks->start = start; blocks->size = size; - blocks->file_priv = NULL; + blocks->filp = NULL; blocks->next = blocks->prev = *heap; memset(*heap, 0, sizeof(**heap)); - (*heap)->file_priv = (struct drm_file *) - 1; + (*heap)->filp = (DRMFILE) - 1; (*heap)->next = (*heap)->prev = blocks; return 0; } /* Free all blocks associated with the releasing file. */ -void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap) +void radeon_mem_release(DRMFILE filp, struct mem_block *heap) { struct mem_block *p; @@ -166,15 +166,15 @@ void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap) return; list_for_each(p, heap) { - if (p->file_priv == file_priv) - p->file_priv = NULL; + if (p->filp == filp) + p->filp = NULL; } - /* Assumes a single contiguous range. Needs a special file_priv in + /* Assumes a single contiguous range. Needs a special filp in * 'heap' to stop it being subsumed. */ list_for_each(p, heap) { - while (p->file_priv == 0 && p->next->file_priv == 0) { + while (p->filp == 0 && p->next->filp == 0) { struct mem_block *q = p->next; p->size += q->size; p->next = q->next; @@ -217,86 +217,98 @@ static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region) } } -int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_mem_alloc(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_alloc_t *alloc = data; + drm_radeon_mem_alloc_t alloc; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - heap = get_heap(dev_priv, alloc->region); + DRM_COPY_FROM_USER_IOCTL(alloc, (drm_radeon_mem_alloc_t __user *) data, + sizeof(alloc)); + + heap = get_heap(dev_priv, alloc.region); if (!heap || !*heap) - return -EFAULT; + return DRM_ERR(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, file_priv); + block = alloc_block(*heap, alloc.size, alloc.alignment, filp); if (!block) - return -ENOMEM; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } return 0; } -int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_mem_free(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_free_t *memfree = data; + drm_radeon_mem_free_t memfree; struct mem_block *block, **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - heap = get_heap(dev_priv, memfree->region); + DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_mem_free_t __user *) data, + sizeof(memfree)); + + heap = get_heap(dev_priv, memfree.region); if (!heap || !*heap) - return -EFAULT; + return DRM_ERR(EFAULT); - block = find_block(*heap, memfree->region_offset); + block = find_block(*heap, memfree.region_offset); if (!block) - return -EFAULT; + return DRM_ERR(EFAULT); - if (block->file_priv != file_priv) - return -EPERM; + if (block->filp != filp) + return DRM_ERR(EPERM); free_block(block); return 0; } -int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv) +int radeon_mem_init_heap(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_init_heap_t *initheap = data; + drm_radeon_mem_init_heap_t initheap; struct mem_block **heap; if (!dev_priv) { DRM_ERROR("%s called with no initialization\n", __FUNCTION__); - return -EINVAL; + return DRM_ERR(EINVAL); } - heap = get_heap(dev_priv, initheap->region); + DRM_COPY_FROM_USER_IOCTL(initheap, + (drm_radeon_mem_init_heap_t __user *) data, + sizeof(initheap)); + + heap = get_heap(dev_priv, initheap.region); if (!heap) - return -EFAULT; + return DRM_ERR(EFAULT); if (*heap) { DRM_ERROR("heap already initialized?"); - return -EFAULT; + return DRM_ERR(EFAULT); } - return init_heap(heap, initheap->start, initheap->size); + return init_heap(heap, initheap.start, initheap.size); } diff --git a/trunk/drivers/char/drm/radeon_state.c b/trunk/drivers/char/drm/radeon_state.c index 69c9f2febf43..3ddf86f2abf0 100644 --- a/trunk/drivers/char/drm/radeon_state.c +++ b/trunk/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 * file_priv, + struct drm_file * filp_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 = file_priv->driver_priv; + radeon_priv = filp_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 -EINVAL; + return DRM_ERR(EINVAL); } static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * dev_priv, - struct drm_file *file_priv, + struct drm_file * filp_priv, int id, u32 *data) { switch (id) { case RADEON_EMIT_PP_MISC: - if (radeon_check_and_fixup_offset(dev_priv, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[(RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4])) { DRM_ERROR("Invalid depth buffer offset\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } break; case RADEON_EMIT_PP_CNTL: - if (radeon_check_and_fixup_offset(dev_priv, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[(RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4])) { DRM_ERROR("Invalid colour buffer offset\n"); - return -EINVAL; + return DRM_ERR(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, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[0])) { DRM_ERROR("Invalid R200 texture offset\n"); - return -EINVAL; + return DRM_ERR(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, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &data[(RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4])) { DRM_ERROR("Invalid R100 texture offset\n"); - return -EINVAL; + return DRM_ERR(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, - file_priv, + filp_priv, &data[i])) { DRM_ERROR ("Invalid R200 cubic texture offset\n"); - return -EINVAL; + return DRM_ERR(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, - file_priv, + filp_priv, &data[i])) { DRM_ERROR ("Invalid R100 cubic texture offset\n"); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 *file_priv, + struct drm_file *filp_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 -EINVAL; + return DRM_ERR(EINVAL); } if (4 * *cmdsz > cmdbuf->bufsz) { DRM_ERROR("Packet size larger than size of data provided\n"); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } /* carefully check packet contents */ @@ -326,25 +326,22 @@ 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, file_priv, - &cmd[i])) { + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { DRM_ERROR ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", k, i); - return -EINVAL; + return DRM_ERR(EINVAL); } k++; i++; if (k == narrays) break; /* have one more to process, they come in pairs */ - if (radeon_check_and_fixup_offset(dev_priv, - file_priv, &cmd[i])) - { + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[i])) { DRM_ERROR ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", k, i); - return -EINVAL; + return DRM_ERR(EINVAL); } k++; i++; @@ -354,33 +351,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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } - if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[1])) { + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[1])) { DRM_ERROR("Invalid rndr_gen_indx offset\n"); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if ((cmd[1] & 0x8000ffff) != 0x80000810) { DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); - return -EINVAL; + return DRM_ERR(EINVAL); } - if (radeon_check_and_fixup_offset(dev_priv, file_priv, &cmd[2])) { + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &cmd[2])) { DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); - return -EINVAL; + return DRM_ERR(EINVAL); } break; @@ -392,9 +389,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, file_priv, &offset)) { + (dev_priv, filp_priv, &offset)) { DRM_ERROR("Invalid first packet offset\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } cmd[2] = (cmd[2] & 0xffc00000) | offset >> 10; } @@ -403,9 +400,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, file_priv, &offset)) { + (dev_priv, filp_priv, &offset)) { DRM_ERROR("Invalid second packet offset\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } cmd[3] = (cmd[3] & 0xffc00000) | offset >> 10; } @@ -413,7 +410,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 -EINVAL; + return DRM_ERR(EINVAL); } return 0; @@ -442,7 +439,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 *file_priv, + struct drm_file * filp_priv, drm_radeon_context_regs_t * ctx, drm_radeon_texture_regs_t * tex, unsigned int dirty) @@ -451,16 +448,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, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &ctx->rb3d_depthoffset)) { DRM_ERROR("Invalid depth buffer offset\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } - if (radeon_check_and_fixup_offset(dev_priv, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &ctx->rb3d_coloroffset)) { DRM_ERROR("Invalid depth buffer offset\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } BEGIN_RING(14); @@ -546,10 +543,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, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex[0].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 0\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } BEGIN_RING(9); @@ -566,10 +563,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, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex[1].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 1\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } BEGIN_RING(9); @@ -586,10 +583,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, file_priv, + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex[2].pp_txoffset)) { DRM_ERROR("Invalid texture offset for unit 2\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } BEGIN_RING(9); @@ -611,7 +608,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 *file_priv, + struct drm_file * filp_priv, drm_radeon_state_t * state) { RING_LOCALS; @@ -624,7 +621,7 @@ static int radeon_emit_state2(drm_radeon_private_t * dev_priv, ADVANCE_RING(); } - return radeon_emit_state(dev_priv, file_priv, &state->context, + return radeon_emit_state(dev_priv, filp_priv, &state->context, state->tex, state->dirty); } @@ -1649,12 +1646,13 @@ static void radeon_cp_dispatch_indices(struct drm_device * dev, #define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE -static int radeon_cp_dispatch_texture(struct drm_device * dev, - struct drm_file *file_priv, +static int radeon_cp_dispatch_texture(DRMFILE filp, + struct drm_device * dev, 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; @@ -1666,9 +1664,11 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, u32 offset; RING_LOCALS; - if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) { + DRM_GET_PRIV_WITH_RETURN(filp_priv, filp); + + if (radeon_check_and_fixup_offset(dev_priv, filp_priv, &tex->offset)) { DRM_ERROR("Invalid destination offset\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; @@ -1711,11 +1711,11 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, break; default: DRM_ERROR("invalid texture format %d\n", tex->format); - return -EINVAL; + return DRM_ERR(EINVAL); } spitch = blit_width >> 6; if (spitch == 0 && image->height > 1) - return -EINVAL; + return DRM_ERR(EINVAL); texpitch = tex->pitch; if ((texpitch << 22) & RADEON_DST_TILE_MICRO) { @@ -1760,8 +1760,8 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, if (!buf) { DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n"); if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image))) - return -EFAULT; - return -EAGAIN; + return DRM_ERR(EFAULT); + return DRM_ERR(EAGAIN); } /* Dispatch the indirect buffer. @@ -1774,7 +1774,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, do { \ if (DRM_COPY_FROM_USER(_buf, _data, (_width))) {\ DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \ - return -EFAULT; \ + return DRM_ERR(EFAULT); \ } \ } while(0) @@ -1841,7 +1841,7 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, } #undef RADEON_COPY_MT - buf->file_priv = file_priv; + buf->filp = filp; buf->used = size; offset = dev_priv->gart_buffers_offset + buf->offset; BEGIN_RING(9); @@ -1861,7 +1861,6 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, OUT_RING((image->width << 16) | height); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); - COMMIT_RING(); radeon_cp_discard_buffer(dev, buf); @@ -1879,8 +1878,6 @@ static int radeon_cp_dispatch_texture(struct drm_device * dev, RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING(); - COMMIT_RING(); - return 0; } @@ -1932,8 +1929,7 @@ 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, - struct drm_file *file_priv) + drm_radeon_private_t *dev_priv, DRMFILE filp) { struct radeon_virt_surface *s; int i; @@ -1963,7 +1959,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].file_priv == 0) + if (dev_priv->virt_surfaces[i].filp == 0) break; if (i == 2 * RADEON_MAX_SURFACES) { return -1; @@ -1981,7 +1977,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; - s->file_priv = file_priv; + s->filp = filp; dev_priv->surfaces[i].refcount++; dev_priv->surfaces[i].lower = s->lower; radeon_apply_surface_regs(s->surface_index, dev_priv); @@ -1997,7 +1993,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; - s->file_priv = file_priv; + s->filp = filp; dev_priv->surfaces[i].refcount++; dev_priv->surfaces[i].upper = s->upper; radeon_apply_surface_regs(s->surface_index, dev_priv); @@ -2013,7 +2009,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, s->lower = new_lower; s->upper = new_upper; s->flags = new->flags; - s->file_priv = file_priv; + s->filp = filp; dev_priv->surfaces[i].refcount = 1; dev_priv->surfaces[i].lower = s->lower; dev_priv->surfaces[i].upper = s->upper; @@ -2027,8 +2023,7 @@ static int alloc_surface(drm_radeon_surface_alloc_t *new, return -1; } -static int free_surface(struct drm_file *file_priv, - drm_radeon_private_t * dev_priv, +static int free_surface(DRMFILE filp, drm_radeon_private_t * dev_priv, int lower) { struct radeon_virt_surface *s; @@ -2036,9 +2031,8 @@ static int free_surface(struct drm_file *file_priv, /* find the virtual surface */ for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { s = &(dev_priv->virt_surfaces[i]); - if (s->file_priv) { - if ((lower == s->lower) && (file_priv == s->file_priv)) - { + if (s->filp) { + if ((lower == s->lower) && (filp == s->filp)) { if (dev_priv->surfaces[s->surface_index]. lower == s->lower) dev_priv->surfaces[s->surface_index]. @@ -2054,7 +2048,7 @@ static int free_surface(struct drm_file *file_priv, refcount == 0) dev_priv->surfaces[s->surface_index]. flags = 0; - s->file_priv = NULL; + s->filp = NULL; radeon_apply_surface_regs(s->surface_index, dev_priv); return 0; @@ -2064,13 +2058,13 @@ static int free_surface(struct drm_file *file_priv, return 1; } -static void radeon_surfaces_release(struct drm_file *file_priv, +static void radeon_surfaces_release(DRMFILE filp, drm_radeon_private_t * dev_priv) { int i; for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { - if (dev_priv->virt_surfaces[i].file_priv == file_priv) - free_surface(file_priv, dev_priv, + if (dev_priv->virt_surfaces[i].filp == filp) + free_surface(filp, dev_priv, dev_priv->virt_surfaces[i].lower); } } @@ -2078,48 +2072,61 @@ static void radeon_surfaces_release(struct drm_file *file_priv, /* ================================================================ * IOCTL functions */ -static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_surface_alloc(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_surface_alloc_t *alloc = data; + drm_radeon_surface_alloc_t alloc; - if (alloc_surface(alloc, dev_priv, file_priv) == -1) - return -EINVAL; + 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); else return 0; } -static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_surface_free(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_surface_free_t *memfree = data; + drm_radeon_surface_free_t memfree; + + DRM_COPY_FROM_USER_IOCTL(memfree, (drm_radeon_surface_free_t __user *) data, + sizeof(memfree)); - if (free_surface(file_priv, dev_priv, memfree->address)) - return -EINVAL; + if (free_surface(filp, dev_priv, memfree.address)) + return DRM_ERR(EINVAL); else return 0; } -static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_clear(DRM_IOCTL_ARGS) { + 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 = data; + drm_radeon_clear_t clear; drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(clear, (drm_radeon_clear_t __user *) data, + sizeof(clear)); 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 -EFAULT; + return DRM_ERR(EFAULT); - radeon_cp_dispatch_clear(dev, clear, depth_boxes); + radeon_cp_dispatch_clear(dev, &clear, depth_boxes); COMMIT_RING(); return 0; @@ -2155,12 +2162,13 @@ 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(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_flip(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -2173,13 +2181,14 @@ static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *f return 0; } -static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_swap(DRM_IOCTL_ARGS) { + 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, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -2193,57 +2202,64 @@ static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *f return 0; } -static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_vertex(DRM_IOCTL_ARGS) { + 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 = data; + drm_radeon_vertex_t vertex; drm_radeon_tcl_prim_t prim; - LOCK_TEST_WITH_RETURN(dev, file_priv); + 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)); 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 -EINVAL; + vertex.idx, dma->buf_count - 1); + 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; + if (vertex.prim < 0 || vertex.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { + DRM_ERROR("buffer prim %d\n", vertex.prim); + return DRM_ERR(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->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; + DRM_CURRENTPID, buf->filp); + return DRM_ERR(EINVAL); } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex->idx); - return -EINVAL; + DRM_ERROR("sending pending buffer %d\n", vertex.idx); + return DRM_ERR(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, file_priv, + if (radeon_emit_state(dev_priv, filp_priv, &sarea_priv->context_state, sarea_priv->tex_state, sarea_priv->dirty)) { DRM_ERROR("radeon_emit_state failed\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | @@ -2253,15 +2269,15 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file } 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); } @@ -2269,68 +2285,74 @@ static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file return 0; } -static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_indices(DRM_IOCTL_ARGS) { + 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 = data; + drm_radeon_indices_t elts; drm_radeon_tcl_prim_t prim; int count; - LOCK_TEST_WITH_RETURN(dev, file_priv); + 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)); 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 -EINVAL; + elts.idx, dma->buf_count - 1); + 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; + if (elts.prim < 0 || elts.prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { + DRM_ERROR("buffer prim %d\n", elts.prim); + return DRM_ERR(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->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; + DRM_CURRENTPID, buf->filp); + return DRM_ERR(EINVAL); } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", elts->idx); - return -EINVAL; + DRM_ERROR("sending pending buffer %d\n", elts.idx); + return DRM_ERR(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 -EINVAL; + if (elts.start & 0x7) { + DRM_ERROR("misaligned buffer 0x%x\n", elts.start); + return DRM_ERR(EINVAL); } - if (elts->start < buf->used) { - DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); - return -EINVAL; + if (elts.start < buf->used) { + DRM_ERROR("no header 0x%x - 0x%x\n", elts.start, buf->used); + return DRM_ERR(EINVAL); } - buf->used = elts->end; + buf->used = elts.end; if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { - if (radeon_emit_state(dev_priv, file_priv, + if (radeon_emit_state(dev_priv, filp_priv, &sarea_priv->context_state, sarea_priv->tex_state, sarea_priv->dirty)) { DRM_ERROR("radeon_emit_state failed\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | @@ -2341,15 +2363,15 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file /* 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); } @@ -2357,43 +2379,52 @@ static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file return 0; } -static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_texture(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_texture_t *tex = data; + drm_radeon_texture_t tex; drm_radeon_tex_image_t image; int ret; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(tex, (drm_radeon_texture_t __user *) data, + sizeof(tex)); - if (tex->image == NULL) { + if (tex.image == NULL) { DRM_ERROR("null texture image!\n"); - return -EINVAL; + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image); + ret = radeon_cp_dispatch_texture(filp, dev, &tex, &image); + COMMIT_RING(); return ret; } -static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_stipple(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_stipple_t *stipple = data; + drm_radeon_stipple_t stipple; u32 mask[32]; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(stipple, (drm_radeon_stipple_t __user *) data, + sizeof(stipple)); - if (DRM_COPY_FROM_USER(&mask, stipple->mask, 32 * sizeof(u32))) - return -EFAULT; + if (DRM_COPY_FROM_USER(&mask, stipple.mask, 32 * sizeof(u32))) + return DRM_ERR(EFAULT); RING_SPACE_TEST_WITH_RETURN(dev_priv); @@ -2403,48 +2434,52 @@ static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file return 0; } -static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_indirect(DRM_IOCTL_ARGS) { + 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 = data; + drm_radeon_indirect_t indirect; RING_LOCALS; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(indirect, + (drm_radeon_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 -EINVAL; + indirect.idx, dma->buf_count - 1); + return DRM_ERR(EINVAL); } - buf = dma->buflist[indirect->idx]; + buf = dma->buflist[indirect.idx]; - if (buf->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; + DRM_CURRENTPID, buf->filp); + return DRM_ERR(EINVAL); } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", indirect->idx); - return -EINVAL; + DRM_ERROR("sending pending buffer %d\n", indirect.idx); + return DRM_ERR(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 -EINVAL; + indirect.start, buf->used); + return DRM_ERR(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. @@ -2459,8 +2494,8 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil * 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); } @@ -2468,64 +2503,71 @@ static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_fil return 0; } -static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_vertex2(DRM_IOCTL_ARGS) { + 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 = data; + drm_radeon_vertex2_t vertex; int i; unsigned char laststate; - LOCK_TEST_WITH_RETURN(dev, file_priv); + 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)); 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 -EINVAL; + vertex.idx, dma->buf_count - 1); + return DRM_ERR(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->file_priv != file_priv) { + if (buf->filp != filp) { DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; + DRM_CURRENTPID, buf->filp); + return DRM_ERR(EINVAL); } if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex->idx); - return -EINVAL; + DRM_ERROR("sending pending buffer %d\n", vertex.idx); + return DRM_ERR(EINVAL); } if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) - return -EINVAL; + return DRM_ERR(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 -EFAULT; + if (DRM_COPY_FROM_USER(&prim, &vertex.prim[i], sizeof(prim))) + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); - if (radeon_emit_state2(dev_priv, file_priv, &state)) { + if (radeon_emit_state2(dev_priv, filp_priv, &state)) { DRM_ERROR("radeon_emit_state2 failed\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } laststate = prim.stateidx; @@ -2552,7 +2594,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file sarea_priv->nbox = 0; } - if (vertex->discard) { + if (vertex.discard) { radeon_cp_discard_buffer(dev, buf); } @@ -2561,7 +2603,7 @@ static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file } static int radeon_emit_packets(drm_radeon_private_t * dev_priv, - struct drm_file *file_priv, + struct drm_file * filp_priv, drm_radeon_cmd_header_t header, drm_radeon_kcmd_buffer_t *cmdbuf) { @@ -2571,19 +2613,19 @@ static int radeon_emit_packets(drm_radeon_private_t * dev_priv, RING_LOCALS; if (id >= RADEON_MAX_STATE_PACKETS) - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } - if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, data)) { + if (radeon_check_and_fixup_packets(dev_priv, filp_priv, id, data)) { DRM_ERROR("Packet verification failed\n"); - return -EINVAL; + return DRM_ERR(EINVAL); } BEGIN_RING(sz + 1); @@ -2671,7 +2713,7 @@ static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, if (!sz) return 0; if (sz * 4 > cmdbuf->bufsz) - return -EINVAL; + return DRM_ERR(EINVAL); BEGIN_RING(5 + sz); OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); @@ -2687,7 +2729,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 *file_priv, + struct drm_file * filp_priv, drm_radeon_kcmd_buffer_t *cmdbuf) { drm_radeon_private_t *dev_priv = dev->dev_private; @@ -2697,7 +2739,7 @@ static int radeon_emit_packet3(struct drm_device * dev, DRM_DEBUG("\n"); - if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, + if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv, cmdbuf, &cmdsz))) { DRM_ERROR("Packet verification failed\n"); return ret; @@ -2713,7 +2755,7 @@ static int radeon_emit_packet3(struct drm_device * dev, } static int radeon_emit_packet3_cliprect(struct drm_device *dev, - struct drm_file *file_priv, + struct drm_file *filp_priv, drm_radeon_kcmd_buffer_t *cmdbuf, int orig_nbox) { @@ -2727,7 +2769,7 @@ static int radeon_emit_packet3_cliprect(struct drm_device *dev, DRM_DEBUG("\n"); - if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, + if ((ret = radeon_check_and_fixup_packet3(dev_priv, filp_priv, cmdbuf, &cmdsz))) { DRM_ERROR("Packet verification failed\n"); return ret; @@ -2739,7 +2781,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 -EFAULT; + return DRM_ERR(EFAULT); /* FIXME The second and subsequent times round * this loop, send a WAIT_UNTIL_3D_IDLE before * calling emit_clip_rect(). This fixes a @@ -2797,54 +2839,62 @@ static int radeon_emit_wait(struct drm_device * dev, int flags) ADVANCE_RING(); break; default: - return -EINVAL; + return DRM_ERR(EINVAL); } return 0; } -static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_cmdbuf(DRM_IOCTL_ARGS) { + 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 = data; + drm_radeon_kcmd_buffer_t cmdbuf; drm_radeon_cmd_header_t header; int orig_nbox, orig_bufsz; char *kbuf = NULL; - LOCK_TEST_WITH_RETURN(dev, file_priv); + 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)); RING_SPACE_TEST_WITH_RETURN(dev_priv); VB_AGE_TEST_WITH_RETURN(dev_priv); - if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) { - return -EINVAL; + if (cmdbuf.bufsz > 64 * 1024 || cmdbuf.bufsz < 0) { + return DRM_ERR(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 -ENOMEM; - if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf->buf, - cmdbuf->bufsz)) { + return DRM_ERR(ENOMEM); + if (DRM_COPY_FROM_USER(kbuf, (void __user *)cmdbuf.buf, + cmdbuf.bufsz)) { drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); - return -EFAULT; + return DRM_ERR(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, file_priv, cmdbuf); + temp = r300_do_cp_cmdbuf(dev, filp, filp_priv, &cmdbuf); if (orig_bufsz != 0) drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); @@ -2853,17 +2903,17 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file } /* 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, file_priv, header, cmdbuf)) { + (dev_priv, filp_priv, header, &cmdbuf)) { DRM_ERROR("radeon_emit_packets failed\n"); goto err; } @@ -2871,7 +2921,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file 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; } @@ -2879,7 +2929,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file 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; } @@ -2895,10 +2945,9 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file } buf = dma->buflist[idx]; - if (buf->file_priv != file_priv || buf->pending) { + if (buf->filp != filp || buf->pending) { DRM_ERROR("bad buffer %p %p %d\n", - buf->file_priv, file_priv, - buf->pending); + buf->filp, filp, buf->pending); goto err; } @@ -2907,7 +2956,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file case RADEON_CMD_PACKET3: DRM_DEBUG("RADEON_CMD_PACKET3\n"); - if (radeon_emit_packet3(dev, file_priv, cmdbuf)) { + if (radeon_emit_packet3(dev, filp_priv, &cmdbuf)) { DRM_ERROR("radeon_emit_packet3 failed\n"); goto err; } @@ -2916,7 +2965,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file case RADEON_CMD_PACKET3_CLIP: DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); if (radeon_emit_packet3_cliprect - (dev, file_priv, cmdbuf, orig_nbox)) { + (dev, filp_priv, &cmdbuf, orig_nbox)) { DRM_ERROR("radeon_emit_packet3_clip failed\n"); goto err; } @@ -2924,7 +2973,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file 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; } @@ -2939,7 +2988,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file 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; } @@ -2948,7 +2997,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file default: DRM_ERROR("bad cmd_type %d at %p\n", header.header.cmd_type, - cmdbuf->buf - sizeof(header)); + cmdbuf.buf - sizeof(header)); goto err; } } @@ -2963,18 +3012,22 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, struct drm_file err: if (orig_bufsz != 0) drm_free(kbuf, orig_bufsz, DRM_MEM_DRIVER); - return -EINVAL; + return DRM_ERR(EINVAL); } -static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_getparam(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_getparam_t *param = data; + drm_radeon_getparam_t param; 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; @@ -3021,7 +3074,7 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil break; case RADEON_PARAM_SCRATCH_OFFSET: if (!dev_priv->writeback_works) - return -EINVAL; + return DRM_ERR(EINVAL); value = RADEON_SCRATCH_REG_OFFSET; break; case RADEON_PARAM_CARD_TYPE: @@ -3036,37 +3089,43 @@ static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_fil value = radeon_vblank_crtc_get(dev); break; default: - DRM_DEBUG("Invalid parameter %d\n", param->param); - return -EINVAL; + DRM_DEBUG("Invalid parameter %d\n", param.param); + return DRM_ERR(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 -EFAULT; + return DRM_ERR(EFAULT); } return 0; } -static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int radeon_cp_setparam(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_setparam_t *sp = data; + struct drm_file *filp_priv; + drm_radeon_setparam_t sp; struct drm_radeon_driver_file_fields *radeon_priv; - switch (sp->param) { + 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) { case RADEON_SETPARAM_FB_LOCATION: - radeon_priv = file_priv->driver_priv; - radeon_priv->radeon_fb_delta = dev_priv->fb_location - - sp->value; + radeon_priv = filp_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; @@ -3074,23 +3133,23 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil } 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 -EINVAL; + DRM_DEBUG("Invalid parameter %d\n", sp.param); + return DRM_ERR(EINVAL); } return 0; @@ -3103,14 +3162,14 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil * * DRM infrastructure takes care of reclaiming dma buffers. */ -void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) +void radeon_driver_preclose(struct drm_device *dev, DRMFILE filp) { if (dev->dev_private) { drm_radeon_private_t *dev_priv = dev->dev_private; dev_priv->page_flipping = 0; - 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); + radeon_mem_release(filp, dev_priv->gart_heap); + radeon_mem_release(filp, dev_priv->fb_heap); + radeon_surfaces_release(filp, dev_priv); } } @@ -3127,7 +3186,7 @@ void radeon_driver_lastclose(struct drm_device *dev) radeon_do_release(dev); } -int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv) +int radeon_driver_open(struct drm_device *dev, struct drm_file *filp_priv) { drm_radeon_private_t *dev_priv = dev->dev_private; struct drm_radeon_driver_file_fields *radeon_priv; @@ -3140,7 +3199,7 @@ int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv) if (!radeon_priv) return -ENOMEM; - file_priv->driver_priv = radeon_priv; + filp_priv->driver_priv = radeon_priv; if (dev_priv) radeon_priv->radeon_fb_delta = dev_priv->fb_location; @@ -3149,42 +3208,42 @@ int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv) return 0; } -void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) +void radeon_driver_postclose(struct drm_device *dev, struct drm_file *filp_priv) { struct drm_radeon_driver_file_fields *radeon_priv = - file_priv->driver_priv; + filp_priv->driver_priv; drm_free(radeon_priv, sizeof(*radeon_priv), DRM_MEM_FILES); } -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) +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} }; int radeon_max_ioctl = DRM_ARRAY_SIZE(radeon_ioctls); diff --git a/trunk/drivers/char/drm/savage_bci.c b/trunk/drivers/char/drm/savage_bci.c index 59484d56b333..18c7235f6b73 100644 --- a/trunk/drivers/char/drm/savage_bci.c +++ b/trunk/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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -EBUSY; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (init->depth_bpp != 16 && init->depth_bpp != 32) { DRM_ERROR("invalid depth buffer bpp %d!\n", init->fb_bpp); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(ENOMEM); } if (savage_dma_init(dev_priv) < 0) { DRM_ERROR("could not initialize command DMA\n"); savage_do_cleanup_bci(dev); - return -ENOMEM; + return DRM_ERR(ENOMEM); } return 0; @@ -928,41 +928,51 @@ static int savage_do_cleanup_bci(struct drm_device * dev) return 0; } -static int savage_bci_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int savage_bci_init(DRM_IOCTL_ARGS) { - drm_savage_init_t *init = data; + DRM_DEVICE; + drm_savage_init_t init; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - switch (init->func) { + DRM_COPY_FROM_USER_IOCTL(init, (drm_savage_init_t __user *) data, + sizeof(init)); + + 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 -EINVAL; + return DRM_ERR(EINVAL); } -static int savage_bci_event_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int savage_bci_event_emit(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; - drm_savage_event_emit_t *event = data; + drm_savage_event_emit_t event; DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - event->count = savage_bci_emit_event(dev_priv, event->flags); - event->count |= dev_priv->event_wrap << 16; + 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; + DRM_COPY_TO_USER_IOCTL((drm_savage_event_emit_t __user *) data, + event, sizeof(event)); return 0; } -static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int savage_bci_event_wait(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_savage_private_t *dev_priv = dev->dev_private; - drm_savage_event_wait_t *event = data; + drm_savage_event_wait_t event; unsigned int event_e, hw_e; unsigned int event_w, hw_w; @@ -980,8 +990,8 @@ static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_ 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 @@ -997,9 +1007,7 @@ static int savage_bci_event_wait(struct drm_device *dev, void *data, struct drm_ * DMA buffer management */ -static int savage_bci_get_buffers(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_dma *d) +static int savage_bci_get_buffers(DRMFILE filp, struct drm_device *dev, struct drm_dma *d) { struct drm_buf *buf; int i; @@ -1007,56 +1015,61 @@ static int savage_bci_get_buffers(struct drm_device *dev, for (i = d->granted_count; i < d->request_count; i++) { buf = savage_freelist_get(dev); if (!buf) - return -EAGAIN; + return DRM_ERR(EAGAIN); - buf->file_priv = file_priv; + buf->filp = filp; if (DRM_COPY_TO_USER(&d->request_indices[i], &buf->idx, sizeof(buf->idx))) - return -EFAULT; + return DRM_ERR(EFAULT); if (DRM_COPY_TO_USER(&d->request_sizes[i], &buf->total, sizeof(buf->total))) - return -EFAULT; + return DRM_ERR(EFAULT); d->granted_count++; } return 0; } -int savage_bci_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) +int savage_bci_buffers(DRM_IOCTL_ARGS) { + DRM_DEVICE; struct drm_device_dma *dma = dev->dma; - struct drm_dma *d = data; + struct drm_dma d; int ret = 0; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(d, (struct drm_dma __user *) data, sizeof(d)); /* 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 -EINVAL; + DRM_CURRENTPID, d.send_count); + return DRM_ERR(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 -EINVAL; + DRM_CURRENTPID, d.request_count, dma->buf_count); + return DRM_ERR(EINVAL); } - d->granted_count = 0; + d.granted_count = 0; - if (d->request_count) { - ret = savage_bci_get_buffers(dev, file_priv, d); + if (d.request_count) { + ret = savage_bci_get_buffers(filp, dev, &d); } + DRM_COPY_TO_USER_IOCTL((struct drm_dma __user *) data, d, sizeof(d)); + return ret; } -void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) +void savage_reclaim_buffers(struct drm_device *dev, DRMFILE filp) { struct drm_device_dma *dma = dev->dma; drm_savage_private_t *dev_priv = dev->dev_private; @@ -1075,7 +1088,7 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) struct drm_buf *buf = dma->buflist[i]; drm_savage_buf_priv_t *buf_priv = buf->dev_private; - if (buf->file_priv == file_priv && buf_priv && + if (buf->filp == filp && buf_priv && buf_priv->next == NULL && buf_priv->prev == NULL) { uint16_t event; DRM_DEBUG("reclaimed from client\n"); @@ -1085,14 +1098,14 @@ void savage_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv) } } - drm_core_reclaim_buffers(dev, file_priv); + drm_core_reclaim_buffers(dev, filp); } -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), +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}, }; int savage_max_ioctl = DRM_ARRAY_SIZE(savage_ioctls); diff --git a/trunk/drivers/char/drm/savage_drv.h b/trunk/drivers/char/drm/savage_drv.h index df2aac6636f7..5fd54de4280e 100644 --- a/trunk/drivers/char/drm/savage_drv.h +++ b/trunk/drivers/char/drm/savage_drv.h @@ -104,7 +104,7 @@ enum savage_family { S3_LAST }; -extern struct drm_ioctl_desc savage_ioctls[]; +extern drm_ioctl_desc_t 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(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); +extern int savage_bci_cmdbuf(DRM_IOCTL_ARGS); +extern int savage_bci_buffers(DRM_IOCTL_ARGS); /* BCI functions */ extern uint16_t savage_bci_emit_event(drm_savage_private_t * dev_priv, @@ -212,8 +212,7 @@ 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, - struct drm_file *file_priv); +extern void savage_reclaim_buffers(struct drm_device * dev, DRMFILE filp); /* state functions */ extern void savage_emit_clip_rect_s3d(drm_savage_private_t * dev_priv, diff --git a/trunk/drivers/char/drm/savage_state.c b/trunk/drivers/char/drm/savage_state.c index bf8e0e10fe21..77497841478a 100644 --- a/trunk/drivers/char/drm/savage_state.c +++ b/trunk/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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } } else { /* AGP */ if (!dev_priv->agp_textures) { DRM_ERROR("bad texAddr%d %08x (AGP not available)\n", unit, addr); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); - return -EINVAL; + return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip != 0) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (reorder) { DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); - return -EINVAL; + return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip > SAVAGE_SKIP_ALL_S3D) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return -EINVAL; + return DRM_ERR(EINVAL); } vtx_size = 8; /* full vertex */ } else { if (skip > SAVAGE_SKIP_ALL_S4) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); - return -EINVAL; + return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip != 0) { DRM_ERROR("invalid skip flags 0x%04x for DMA\n", skip); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (reorder) { DRM_ERROR("TRILIST_201 used on Savage4 hardware\n"); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } break; default: DRM_ERROR("invalid primitive type %u\n", prim); - return -EINVAL; + return DRM_ERR(EINVAL); } if (S3_SAVAGE3D_SERIES(dev_priv->chipset)) { if (skip > SAVAGE_SKIP_ALL_S3D) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return -EINVAL; + return DRM_ERR(EINVAL); } vtx_size = 8; /* full vertex */ } else { if (skip > SAVAGE_SKIP_ALL_S4) { DRM_ERROR("invalid skip flags 0x%04x\n", skip); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } if (ret != 0) @@ -953,12 +953,13 @@ static int savage_dispatch_draw(drm_savage_private_t * dev_priv, return 0; } -int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_priv) +int savage_bci_cmdbuf(DRM_IOCTL_ARGS) { + 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 = data; + drm_savage_cmdbuf_t cmdbuf; drm_savage_cmd_header_t *kcmd_addr = NULL; drm_savage_cmd_header_t *first_draw_cmd; unsigned int *kvb_addr = NULL; @@ -968,16 +969,19 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ DRM_DEBUG("\n"); - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_savage_cmdbuf_t __user *) data, + sizeof(cmdbuf)); 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 -EINVAL; + cmdbuf.dma_idx, dma->buf_count - 1); + return DRM_ERR(EINVAL); } - dmabuf = dma->buflist[cmdbuf->dma_idx]; + dmabuf = dma->buflist[cmdbuf.dma_idx]; } else { dmabuf = NULL; } @@ -987,47 +991,47 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ * 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 -ENOMEM; + return DRM_ERR(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 -EFAULT; + drm_free(kcmd_addr, cmdbuf.size * 8, DRM_MEM_DRIVER); + return DRM_ERR(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 = -ENOMEM; + ret = DRM_ERR(ENOMEM); goto done; } - if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf->vb_addr, - cmdbuf->vb_size)) { - ret = -EFAULT; + if (DRM_COPY_FROM_USER(kvb_addr, cmdbuf.vb_addr, + cmdbuf.vb_size)) { + ret = DRM_ERR(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 = -ENOMEM; + ret = DRM_ERR(ENOMEM); goto done; } - if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf->box_addr, - cmdbuf->nbox * sizeof(struct drm_clip_rect))) { - ret = -EFAULT; + if (DRM_COPY_FROM_USER(kbox_addr, cmdbuf.box_addr, + cmdbuf.nbox * sizeof(struct drm_clip_rect))) { + ret = DRM_ERR(EFAULT); goto done; } - cmdbuf->box_addr = kbox_addr; + cmdbuf.box_addr = kbox_addr; } /* Make sure writes to DMA buffers are finished before sending @@ -1040,10 +1044,10 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ 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 @@ -1053,28 +1057,28 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ 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 -EINVAL; + return DRM_ERR(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; @@ -1086,42 +1090,40 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ 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 = -EINVAL; + ret = DRM_ERR(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 = -EINVAL; + ret = DRM_ERR(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 = -EINVAL; + ret = DRM_ERR(EINVAL); goto done; } @@ -1133,9 +1135,9 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ 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; @@ -1144,7 +1146,7 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ 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); @@ -1154,9 +1156,9 @@ int savage_bci_cmdbuf(struct drm_device *dev, void *data, struct drm_file *file_ 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/trunk/drivers/char/drm/sis_drv.c b/trunk/drivers/char/drm/sis_drv.c index 7dacc64e9b56..1912f5857051 100644 --- a/trunk/drivers/char/drm/sis_drv.c +++ b/trunk/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 -ENOMEM; + return DRM_ERR(ENOMEM); dev->dev_private = (void *)dev_priv; dev_priv->chipset = chipset; diff --git a/trunk/drivers/char/drm/sis_drv.h b/trunk/drivers/char/drm/sis_drv.h index ef940bad63f7..5630df874353 100644 --- a/trunk/drivers/char/drm/sis_drv.h +++ b/trunk/drivers/char/drm/sis_drv.h @@ -63,11 +63,10 @@ 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 drm_file *file_priv); +extern void sis_reclaim_buffers_locked(struct drm_device *dev, struct file *filp); extern void sis_lastclose(struct drm_device *dev); -extern struct drm_ioctl_desc sis_ioctls[]; +extern drm_ioctl_desc_t sis_ioctls[]; extern int sis_max_ioctl; #endif diff --git a/trunk/drivers/char/drm/sis_mm.c b/trunk/drivers/char/drm/sis_mm.c index 8c66838ff515..441bbdbf1510 100644 --- a/trunk/drivers/char/drm/sis_mm.c +++ b/trunk/drivers/char/drm/sis_mm.c @@ -82,12 +82,15 @@ static unsigned long sis_sman_mm_offset(void *private, void *ref) #endif /* CONFIG_FB_SIS */ -static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int sis_fb_init(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_sis_private_t *dev_priv = dev->dev_private; - drm_sis_fb_t *fb = data; + drm_sis_fb_t fb; 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) { @@ -102,7 +105,7 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file } #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) { @@ -112,87 +115,98 @@ static int sis_fb_init(struct drm_device *dev, void *data, struct drm_file *file } 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 *file_priv, - void *data, int pool) +static int sis_drm_alloc(struct drm_device *dev, struct drm_file * priv, + unsigned long data, int pool) { drm_sis_private_t *dev_priv = dev->dev_private; - drm_sis_mem_t *mem = data; + drm_sis_mem_t __user *argp = (drm_sis_mem_t __user *) data; + drm_sis_mem_t mem; 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 -EINVAL; + return DRM_ERR(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)file_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)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 = -ENOMEM; + mem.offset = 0; + mem.size = 0; + mem.free = 0; + retval = DRM_ERR(ENOMEM); } - DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem->size, - mem->offset); + DRM_COPY_TO_USER_IOCTL(argp, mem, sizeof(mem)); + + DRM_DEBUG("alloc %d, size = %d, offset = %d\n", pool, mem.size, + mem.offset); return retval; } -static int sis_drm_free(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int sis_drm_free(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_sis_private_t *dev_priv = dev->dev_private; - drm_sis_mem_t *mem = data; + drm_sis_mem_t mem; 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(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int sis_fb_alloc(DRM_IOCTL_ARGS) { - return sis_drm_alloc(dev, file_priv, data, VIDEO_TYPE); + DRM_DEVICE; + return sis_drm_alloc(dev, priv, data, VIDEO_TYPE); } -static int sis_ioctl_agp_init(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int sis_ioctl_agp_init(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_sis_private_t *dev_priv = dev->dev_private; - drm_sis_agp_t *agp = data; + drm_sis_agp_t agp; 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"); @@ -201,18 +215,18 @@ static int sis_ioctl_agp_init(struct drm_device *dev, void *data, } 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(struct drm_device *dev, void *data, - struct drm_file *file_priv) +static int sis_ioctl_agp_alloc(DRM_IOCTL_ARGS) { + DRM_DEVICE; - return sis_drm_alloc(dev, file_priv, data, AGP_TYPE); + return sis_drm_alloc(dev, priv, data, AGP_TYPE); } static drm_local_map_t *sis_reg_init(struct drm_device *dev) @@ -300,13 +314,13 @@ void sis_lastclose(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); } -void sis_reclaim_buffers_locked(struct drm_device * dev, - struct drm_file *file_priv) +void sis_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) { 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)file_priv)) { + if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) { mutex_unlock(&dev->struct_mutex); return; } @@ -315,18 +329,20 @@ void sis_reclaim_buffers_locked(struct drm_device * dev, dev->driver->dma_quiescent(dev); } - drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); + drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv); mutex_unlock(&dev->struct_mutex); return; } -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), +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} }; int sis_max_ioctl = DRM_ARRAY_SIZE(sis_ioctls); diff --git a/trunk/drivers/char/drm/via_dma.c b/trunk/drivers/char/drm/via_dma.c index 75d6b748c2c0..7ff2b623c2d4 100644 --- a/trunk/drivers/char/drm/via_dma.c +++ b/trunk/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 -EFAULT; + return DRM_ERR(EFAULT); } if (dev_priv->ring.virtual_start != NULL) { DRM_ERROR("%s called again without calling cleanup\n", __FUNCTION__); - return -EFAULT; + return DRM_ERR(EFAULT); } if (!dev->agp || !dev->agp->base) { DRM_ERROR("%s called with no agp memory available\n", __FUNCTION__); - return -EFAULT; + return DRM_ERR(EFAULT); } if (dev_priv->chipset == VIA_DX9_0) { DRM_ERROR("AGP DMA is not supported on this chip\n"); - return -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(ENOMEM); } dev_priv->ring.virtual_start = dev_priv->ring.map.handle; @@ -227,31 +227,35 @@ static int via_initialize(struct drm_device * dev, return 0; } -static int via_dma_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int via_dma_init(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; - drm_via_dma_init_t *init = data; + drm_via_dma_init_t init; int retcode = 0; - switch (init->func) { + DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t __user *) data, + sizeof(init)); + + switch (init.func) { case VIA_INIT_DMA: if (!DRM_SUSER(DRM_CURPROC)) - retcode = -EPERM; + retcode = DRM_ERR(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 = -EPERM; + retcode = DRM_ERR(EPERM); else retcode = via_dma_cleanup(dev); break; case VIA_DMA_INITIALIZED: retcode = (dev_priv->ring.virtual_start != NULL) ? - 0 : -EFAULT; + 0 : DRM_ERR(EFAULT); break; default: - retcode = -EINVAL; + retcode = DRM_ERR(EINVAL); break; } @@ -269,15 +273,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 -EFAULT; + return DRM_ERR(EFAULT); } if (cmd->size > VIA_PCI_BUF_SIZE) { - return -ENOMEM; + return DRM_ERR(ENOMEM); } if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) - return -EFAULT; + return DRM_ERR(EFAULT); /* * Running this function on AGP memory is dead slow. Therefore @@ -293,7 +297,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 -EAGAIN; + return DRM_ERR(EAGAIN); } memcpy(vb, dev_priv->pci_buf, cmd->size); @@ -317,30 +321,34 @@ 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 -EBUSY; + return DRM_ERR(EBUSY); } return 0; } -static int via_flush_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int via_flush_ioctl(DRM_IOCTL_ARGS) { + DRM_DEVICE; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); return via_driver_dma_quiescent(dev); } -static int via_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int via_cmdbuffer(DRM_IOCTL_ARGS) { - drm_via_cmdbuffer_t *cmdbuf = data; + DRM_DEVICE; + drm_via_cmdbuffer_t cmdbuf; int ret; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); + + DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data, + sizeof(cmdbuf)); - 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; } @@ -355,10 +363,10 @@ static int via_dispatch_pci_cmdbuffer(struct drm_device * dev, int ret; if (cmd->size > VIA_PCI_BUF_SIZE) { - return -ENOMEM; + return DRM_ERR(ENOMEM); } if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size)) - return -EFAULT; + return DRM_ERR(EFAULT); if ((ret = via_verify_command_stream((uint32_t *) dev_priv->pci_buf, @@ -372,17 +380,21 @@ static int via_dispatch_pci_cmdbuffer(struct drm_device * dev, return ret; } -static int via_pci_cmdbuffer(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int via_pci_cmdbuffer(DRM_IOCTL_ARGS) { - drm_via_cmdbuffer_t *cmdbuf = data; + DRM_DEVICE; + drm_via_cmdbuffer_t cmdbuf; int ret; - LOCK_TEST_WITH_RETURN(dev, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); - DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf->buf, - cmdbuf->size); + DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data, + sizeof(cmdbuf)); - ret = via_dispatch_pci_cmdbuffer(dev, cmdbuf); + DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf, + cmdbuf.size); + + ret = via_dispatch_pci_cmdbuffer(dev, &cmdbuf); if (ret) { return ret; } @@ -641,74 +653,80 @@ static void via_cmdbuf_reset(drm_via_private_t * dev_priv) * User interface to the space and lag functions. */ -static int via_cmdbuf_size(struct drm_device *dev, void *data, struct drm_file *file_priv) +static int via_cmdbuf_size(DRM_IOCTL_ARGS) { - drm_via_cmdbuf_size_t *d_siz = data; + DRM_DEVICE; + drm_via_cmdbuf_size_t d_siz; 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, file_priv); + LOCK_TEST_WITH_RETURN(dev, filp); 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 -EFAULT; + return DRM_ERR(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 = -EAGAIN; + ret = DRM_ERR(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 = -EAGAIN; + ret = DRM_ERR(EAGAIN); } break; default: - ret = -EFAULT; + ret = DRM_ERR(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; } -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) +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} }; int via_max_ioctl = DRM_ARRAY_SIZE(via_ioctls); diff --git a/trunk/drivers/char/drm/via_dmablit.c b/trunk/drivers/char/drm/via_dmablit.c index c6fd16f3cb43..3dd1ed3d1bf5 100644 --- a/trunk/drivers/char/drm/via_dmablit.c +++ b/trunk/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 -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(ENOMEM); vsg->state = dr_via_desc_pages_alloc; for (i=0; inum_desc_pages; ++i) { if (NULL == (vsg->desc_pages[i] = (drm_via_descriptor_t *) __get_free_page(GFP_KERNEL))) - return -ENOMEM; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 (-EINTR == ret) ? -EAGAIN : ret; + return (DRM_ERR(EINTR) == ret) ? DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -ENOMEM; + return DRM_ERR(ENOMEM); } if (0 != (ret = via_build_sg_info(dev, vsg, xfer))) { via_dmablit_release_slot(blitq); @@ -781,18 +781,21 @@ via_dmablit(struct drm_device *dev, drm_via_dmablit_t *xfer) */ int -via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_priv ) +via_dma_blit_sync( DRM_IOCTL_ARGS ) { - drm_via_blitsync_t *sync = data; + drm_via_blitsync_t sync; int err; + DRM_DEVICE; - if (sync->engine >= VIA_NUM_BLIT_ENGINES) - return -EINVAL; + DRM_COPY_FROM_USER_IOCTL(sync, (drm_via_blitsync_t *)data, sizeof(sync)); + + if (sync.engine >= VIA_NUM_BLIT_ENGINES) + return DRM_ERR(EINVAL); - err = via_dmablit_sync(dev, sync->sync_handle, sync->engine); + err = via_dmablit_sync(dev, sync.sync_handle, sync.engine); - if (-EINTR == err) - err = -EAGAIN; + if (DRM_ERR(EINTR) == err) + err = DRM_ERR(EAGAIN); return err; } @@ -805,12 +808,17 @@ via_dma_blit_sync( struct drm_device *dev, void *data, struct drm_file *file_pri */ int -via_dma_blit( struct drm_device *dev, void *data, struct drm_file *file_priv ) +via_dma_blit( DRM_IOCTL_ARGS ) { - drm_via_dmablit_t *xfer = data; + drm_via_dmablit_t xfer; int err; + DRM_DEVICE; + + DRM_COPY_FROM_USER_IOCTL(xfer, (drm_via_dmablit_t __user *)data, sizeof(xfer)); + + err = via_dmablit(dev, &xfer); - err = via_dmablit(dev, xfer); + DRM_COPY_TO_USER_IOCTL((void __user *)data, xfer, sizeof(xfer)); return err; } diff --git a/trunk/drivers/char/drm/via_drv.h b/trunk/drivers/char/drm/via_drv.h index 2daae81874cd..576711564a11 100644 --- a/trunk/drivers/char/drm/via_drv.h +++ b/trunk/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 struct drm_ioctl_desc via_ioctls[]; +extern drm_ioctl_desc_t via_ioctls[]; extern int via_max_ioctl; -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_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_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 drm_file *file_priv); +extern void via_reclaim_buffers_locked(struct drm_device *dev, struct file *filp); 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/trunk/drivers/char/drm/via_irq.c b/trunk/drivers/char/drm/via_irq.c index 9c1d52bc92d7..8dc99b5fbab6 100644 --- a/trunk/drivers/char/drm/via_irq.c +++ b/trunk/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 -EINVAL; + return DRM_ERR(EINVAL); } if (irq >= drm_via_irq_num) { DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, irq); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } masks = dev_priv->irq_masks; @@ -331,9 +331,11 @@ void via_driver_irq_uninstall(struct drm_device * dev) } } -int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) +int via_wait_irq(DRM_IOCTL_ARGS) { - drm_via_irqwait_t *irqwait = data; + DRM_DEVICE; + drm_via_irqwait_t __user *argp = (void __user *)data; + drm_via_irqwait_t irqwait; struct timeval now; int ret = 0; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; @@ -341,39 +343,42 @@ int via_wait_irq(struct drm_device *dev, void *data, struct drm_file *file_priv) int force_sequence; if (!dev->irq) - return -EINVAL; + return DRM_ERR(EINVAL); - if (irqwait->request.irq >= dev_priv->num_irqs) { + DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait)); + if (irqwait.request.irq >= dev_priv->num_irqs) { DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, - irqwait->request.irq); - return -EINVAL; + irqwait.request.irq); + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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; + irqwait.reply.tval_sec = now.tv_sec; + irqwait.reply.tval_usec = now.tv_usec; + + DRM_COPY_TO_USER_IOCTL(argp, irqwait, sizeof(irqwait)); return ret; } diff --git a/trunk/drivers/char/drm/via_map.c b/trunk/drivers/char/drm/via_map.c index 10091507a0dc..7fb9d2a2cce2 100644 --- a/trunk/drivers/char/drm/via_map.c +++ b/trunk/drivers/char/drm/via_map.c @@ -75,15 +75,19 @@ int via_do_cleanup_map(struct drm_device * dev) return 0; } -int via_map_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +int via_map_init(DRM_IOCTL_ARGS) { - drm_via_init_t *init = data; + DRM_DEVICE; + drm_via_init_t init; DRM_DEBUG("%s\n", __FUNCTION__); - switch (init->func) { + DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t __user *) data, + sizeof(init)); + + 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); } @@ -98,7 +102,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 -ENOMEM; + return DRM_ERR(ENOMEM); dev->dev_private = (void *)dev_priv; diff --git a/trunk/drivers/char/drm/via_mm.c b/trunk/drivers/char/drm/via_mm.c index 9afc1684348d..85d56acd9d82 100644 --- a/trunk/drivers/char/drm/via_mm.c +++ b/trunk/drivers/char/drm/via_mm.c @@ -33,15 +33,18 @@ #define VIA_MM_ALIGN_SHIFT 4 #define VIA_MM_ALIGN_MASK ( (1 << VIA_MM_ALIGN_SHIFT) - 1) -int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) +int via_agp_init(DRM_IOCTL_ARGS) { - drm_via_agp_t *agp = data; + DRM_DEVICE; + drm_via_agp_t agp; 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"); @@ -50,22 +53,25 @@ int via_agp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) } 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(struct drm_device *dev, void *data, struct drm_file *file_priv) +int via_fb_init(DRM_IOCTL_ARGS) { - drm_via_fb_t *fb = data; + DRM_DEVICE; + drm_via_fb_t fb; 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"); @@ -74,10 +80,10 @@ int via_fb_init(struct drm_device *dev, void *data, struct drm_file *file_priv) } 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; @@ -115,71 +121,80 @@ void via_lastclose(struct drm_device *dev) mutex_unlock(&dev->struct_mutex); } -int via_mem_alloc(struct drm_device *dev, void *data, - struct drm_file *file_priv) +int via_mem_alloc(DRM_IOCTL_ARGS) { - drm_via_mem_t *mem = data; + DRM_DEVICE; + + drm_via_mem_t mem; int retval = 0; struct drm_memblock_item *item; drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private; unsigned long tmpSize; - if (mem->type > VIA_MEM_AGP) { + DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data, + sizeof(mem)); + + if (mem.type > VIA_MEM_AGP) { DRM_ERROR("Unknown memory type allocation\n"); - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(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)file_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)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 = -ENOMEM; + retval = DRM_ERR(ENOMEM); } + DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem, sizeof(mem)); return retval; } -int via_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) +int via_mem_free(DRM_IOCTL_ARGS) { + DRM_DEVICE; drm_via_private_t *dev_priv = dev->dev_private; - drm_via_mem_t *mem = data; + drm_via_mem_t mem; 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 drm_file *file_priv) +void via_reclaim_buffers_locked(struct drm_device * dev, struct file *filp) { 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)file_priv)) { + if (drm_sman_owner_clean(&dev_priv->sman, (unsigned long)priv)) { mutex_unlock(&dev->struct_mutex); return; } @@ -188,7 +203,7 @@ void via_reclaim_buffers_locked(struct drm_device * dev, dev->driver->dma_quiescent(dev); } - drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)file_priv); + drm_sman_owner_cleanup(&dev_priv->sman, (unsigned long)priv); mutex_unlock(&dev->struct_mutex); return; } diff --git a/trunk/drivers/char/drm/via_verifier.c b/trunk/drivers/char/drm/via_verifier.c index 46a579198747..832d48356e91 100644 --- a/trunk/drivers/char/drm/via_verifier.c +++ b/trunk/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 -EINVAL; + return DRM_ERR(EINVAL); } } if (state == state_error) { *hc_state = saved_state; - return -EINVAL; + return DRM_ERR(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 -EINVAL; + return DRM_ERR(EINVAL); } } if (state == state_error) { - return -EINVAL; + return DRM_ERR(EINVAL); } return 0; } diff --git a/trunk/drivers/char/drm/via_video.c b/trunk/drivers/char/drm/via_video.c index c15e75b54cb1..300ac61b09ed 100644 --- a/trunk/drivers/char/drm/via_video.c +++ b/trunk/drivers/char/drm/via_video.c @@ -65,9 +65,10 @@ void via_release_futex(drm_via_private_t * dev_priv, int context) } } -int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_priv) +int via_decoder_futex(DRM_IOCTL_ARGS) { - drm_via_futex_t *fx = data; + DRM_DEVICE; + drm_via_futex_t fx; 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; @@ -75,18 +76,21 @@ int via_decoder_futex(struct drm_device *dev, void *data, struct drm_file *file_ DRM_DEBUG("%s\n", __FUNCTION__); - if (fx->lock > VIA_NR_XVMC_LOCKS) + DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t __user *) data, + sizeof(fx)); + + 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/trunk/drivers/fc4/fc.c b/trunk/drivers/fc4/fc.c index 82de9e1adb1e..22b62b3cd14e 100644 --- a/trunk/drivers/fc4/fc.c +++ b/trunk/drivers/fc4/fc.c @@ -427,10 +427,15 @@ 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) - dma_unmap_sg(fc->dev, scsi_sglist(SCpnt), - scsi_sg_count(SCpnt), - SCpnt->sc_data_direction); + 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); + } break; default: host_status=DID_ERROR; /* FIXME */ @@ -788,14 +793,10 @@ 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 (!scsi_bufflen(SCpnt)) { + if (!SCpnt->request_bufflen && !SCpnt->use_sg) { 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: @@ -804,12 +805,22 @@ static int fcp_scsi_queue_it(fc_channel *fc, struct scsi_cmnd *SCpnt, default: cmd->fcp_cntl = (FCP_CNTL_READ | fcp_cntl); break; } - - 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); + 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); + } } 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/trunk/drivers/hid/hidraw.c b/trunk/drivers/hid/hidraw.c index a702e2f6da7d..8503197a8131 100644 --- a/trunk/drivers/hid/hidraw.c +++ b/trunk/drivers/hid/hidraw.c @@ -229,15 +229,9 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd if (get_user(len, (int __user *)arg)) return -EFAULT; - - 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))) + if (copy_to_user(*((__u8 **)(user_arg + + sizeof(__u32))), + dev->hid->rdesc, len)) return -EFAULT; return 0; } diff --git a/trunk/drivers/infiniband/ulp/srp/Kconfig b/trunk/drivers/infiniband/ulp/srp/Kconfig index c74ee9633041..3432dce29520 100644 --- a/trunk/drivers/infiniband/ulp/srp/Kconfig +++ b/trunk/drivers/infiniband/ulp/srp/Kconfig @@ -1,7 +1,6 @@ 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/trunk/drivers/infiniband/ulp/srp/ib_srp.c b/trunk/drivers/infiniband/ulp/srp/ib_srp.c index 950228fb009f..9ccc63886d92 100644 --- a/trunk/drivers/infiniband/ulp/srp/ib_srp.c +++ b/trunk/drivers/infiniband/ulp/srp/ib_srp.c @@ -47,7 +47,6 @@ #include #include #include -#include #include @@ -87,8 +86,6 @@ 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, @@ -423,7 +420,6 @@ 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); @@ -1548,24 +1544,12 @@ 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); @@ -1791,7 +1775,6 @@ 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; @@ -2071,18 +2054,10 @@ 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) + @@ -2091,7 +2066,6 @@ 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; } @@ -2100,7 +2074,6 @@ 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; @@ -2114,7 +2087,6 @@ 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/trunk/drivers/message/fusion/Kconfig b/trunk/drivers/message/fusion/Kconfig index a34a11d2fef2..f55cc03a75c9 100644 --- a/trunk/drivers/message/fusion/Kconfig +++ b/trunk/drivers/message/fusion/Kconfig @@ -1,19 +1,15 @@ -menuconfig FUSION - bool "Fusion MPT device support" +menu "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. -if FUSION +config FUSION + bool + default n 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. @@ -24,11 +20,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. @@ -41,13 +37,12 @@ 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. @@ -58,10 +53,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 @@ -109,6 +104,7 @@ 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. @@ -117,7 +113,7 @@ config FUSION_LOGGING echo [level] > /sys/class/scsi_host/host#/debug_level - There are various debug levels that can be found in the source: + There are various debug levels that an be found in the source: file:drivers/message/fusion/mptdebug.h -endif # FUSION +endmenu diff --git a/trunk/drivers/message/fusion/lsi/mpi.h b/trunk/drivers/message/fusion/lsi/mpi.h index 1acbdd61b670..6a92e3d118fe 100644 --- a/trunk/drivers/message/fusion/lsi/mpi.h +++ b/trunk/drivers/message/fusion/lsi/mpi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Corporation. + * Copyright (c) 2000-2007 LSI Logic Corporation. * * * Name: mpi.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_cnfg.h b/trunk/drivers/message/fusion/lsi/mpi_cnfg.h index 2bd8adae0f00..eda769730e39 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_cnfg.h +++ b/trunk/drivers/message/fusion/lsi/mpi_cnfg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Corporation. + * Copyright (c) 2000-2007 LSI Logic Corporation. * * * Name: mpi_cnfg.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_fc.h b/trunk/drivers/message/fusion/lsi/mpi_fc.h index 627acfbb8623..51a6aeb990ba 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_fc.h +++ b/trunk/drivers/message/fusion/lsi/mpi_fc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 LSI Corporation. + * Copyright (c) 2000-2004 LSI Logic Corporation. * * * Name: mpi_fc.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_history.txt b/trunk/drivers/message/fusion/lsi/mpi_history.txt index 241592ab13ad..a1f479057ea3 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_history.txt +++ b/trunk/drivers/message/fusion/lsi/mpi_history.txt @@ -3,7 +3,7 @@ MPI Header File Change History ============================== - Copyright (c) 2000-2007 LSI Corporation. + Copyright (c) 2000-2007 LSI Logic Corporation. --------------------------------------- Header Set Release Version: 01.05.16 diff --git a/trunk/drivers/message/fusion/lsi/mpi_init.h b/trunk/drivers/message/fusion/lsi/mpi_init.h index a9e3693601a7..3a02615f12d6 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_init.h +++ b/trunk/drivers/message/fusion/lsi/mpi_init.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Corporation. + * Copyright (c) 2000-2007 LSI Logic Corporation. * * * Name: mpi_init.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_ioc.h b/trunk/drivers/message/fusion/lsi/mpi_ioc.h index 5cbb6bd048e1..b1893d185bc4 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_ioc.h +++ b/trunk/drivers/message/fusion/lsi/mpi_ioc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2007 LSI Corporation. + * Copyright (c) 2000-2007 LSI Logic Corporation. * * * Name: mpi_ioc.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_lan.h b/trunk/drivers/message/fusion/lsi/mpi_lan.h index 03253b53b785..dc0b52ae83dd 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_lan.h +++ b/trunk/drivers/message/fusion/lsi/mpi_lan.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 LSI Corporation. + * Copyright (c) 2000-2004 LSI Logic Corporation. * * * Name: mpi_lan.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_log_fc.h b/trunk/drivers/message/fusion/lsi/mpi_log_fc.h index e4dafcefeecd..dc98d46f9071 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_log_fc.h +++ b/trunk/drivers/message/fusion/lsi/mpi_log_fc.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2001 LSI Corporation. All rights reserved. + * Copyright (c) 2000-2001 LSI Logic Corporation. All rights reserved. * * NAME: fc_log.h * SUMMARY: MPI IocLogInfo definitions for the SYMFC9xx chips diff --git a/trunk/drivers/message/fusion/lsi/mpi_log_sas.h b/trunk/drivers/message/fusion/lsi/mpi_log_sas.h index 6be1f6b65777..635bbe04513e 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_log_sas.h +++ b/trunk/drivers/message/fusion/lsi/mpi_log_sas.h @@ -1,6 +1,6 @@ /*************************************************************************** * * - * Copyright 2003 LSI Corporation. All rights reserved. * + * Copyright 2003 LSI Logic Corporation. All rights reserved. * * * * Description * * ------------ * diff --git a/trunk/drivers/message/fusion/lsi/mpi_raid.h b/trunk/drivers/message/fusion/lsi/mpi_raid.h index 2856108421d7..32819b1ec8ec 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_raid.h +++ b/trunk/drivers/message/fusion/lsi/mpi_raid.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2007 LSI Corporation. + * Copyright (c) 2001-2007 LSI Logic Corporation. * * * Name: mpi_raid.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_sas.h b/trunk/drivers/message/fusion/lsi/mpi_sas.h index 33fca83cefc2..8e990a0fa7a2 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_sas.h +++ b/trunk/drivers/message/fusion/lsi/mpi_sas.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2006 LSI Corporation. + * Copyright (c) 2004-2006 LSI Logic Corporation. * * * Name: mpi_sas.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_targ.h b/trunk/drivers/message/fusion/lsi/mpi_targ.h index ff8c37d3fdcb..20b667315773 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_targ.h +++ b/trunk/drivers/message/fusion/lsi/mpi_targ.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 LSI Corporation. + * Copyright (c) 2000-2004 LSI Logic Corporation. * * * Name: mpi_targ.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_tool.h b/trunk/drivers/message/fusion/lsi/mpi_tool.h index 8834ae6ce0f2..aa9053da1f58 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_tool.h +++ b/trunk/drivers/message/fusion/lsi/mpi_tool.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2005 LSI Corporation. + * Copyright (c) 2001-2005 LSI Logic Corporation. * * * Name: mpi_tool.h diff --git a/trunk/drivers/message/fusion/lsi/mpi_type.h b/trunk/drivers/message/fusion/lsi/mpi_type.h index 08dad9c1e446..32cc9b1151b8 100644 --- a/trunk/drivers/message/fusion/lsi/mpi_type.h +++ b/trunk/drivers/message/fusion/lsi/mpi_type.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2004 LSI Corporation. + * Copyright (c) 2000-2004 LSI Logic Corporation. * * * Name: mpi_type.h diff --git a/trunk/drivers/message/fusion/mptbase.c b/trunk/drivers/message/fusion/mptbase.c index 52fb216dfe74..414c109f4cf5 100644 --- a/trunk/drivers/message/fusion/mptbase.c +++ b/trunk/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 PCI chip/adapter(s) - * running LSI Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -102,6 +102,8 @@ static int mfcounter = 0; /* * Public data... */ +int mpt_lan_index = -1; +int mpt_stm_index = -1; struct proc_dir_entry *mpt_proc_root_dir; @@ -123,13 +125,10 @@ 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 DECLARE_WAIT_QUEUE_HEAD(mpt_waitq); +static int mpt_base_index = -1; +static int last_drv_idx = -1; -/* - * Driver Callback Index's - */ -static u8 mpt_base_index = MPT_MAX_PROTOCOL_DRIVERS; -static u8 last_drv_idx; +static DECLARE_WAIT_QUEUE_HEAD(mpt_waitq); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -236,23 +235,6 @@ 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... */ @@ -261,8 +243,8 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) { MPT_FRAME_HDR *mf = NULL; MPT_FRAME_HDR *mr = NULL; - u16 req_idx = 0; - u8 cb_idx; + int req_idx = 0; + int cb_idx; dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Got TURBO reply req_idx=%08x\n", ioc->name, pa)); @@ -274,7 +256,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_get_cb_idx(MPTLAN_DRIVER); + cb_idx = mpt_lan_index; /* * Blind set of mf to NULL here was fatal * after lan_reply says "freeme" @@ -295,7 +277,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_get_cb_idx(MPTSTM_DRIVER); + cb_idx = mpt_stm_index; mr = (MPT_FRAME_HDR *) CAST_U32_TO_PTR(pa); break; default: @@ -304,8 +286,8 @@ mpt_turbo_reply(MPT_ADAPTER *ioc, u32 pa) } /* Check for (valid) IO callback! */ - if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || - MptCallbacks[cb_idx] == NULL) { + if (cb_idx < 1 || 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; @@ -322,8 +304,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) { MPT_FRAME_HDR *mf; MPT_FRAME_HDR *mr; - u16 req_idx; - u8 cb_idx; + int req_idx; + int cb_idx; int freeme; u32 reply_dma_low; @@ -349,7 +331,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 */ @@ -368,8 +350,8 @@ mpt_reply(MPT_ADAPTER *ioc, u32 pa) mpt_iocstatus_info(ioc, (u32)ioc_stat, mf); /* Check for (valid) IO callback! */ - if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS || - MptCallbacks[cb_idx] == NULL) { + if (cb_idx < 1 || 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; @@ -451,9 +433,8 @@ 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(MYIOC_s_INFO_FMT ": Original request frame (@%p) header\n", - ioc->name, mf)); - DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf); + dmfprintk(ioc, printk(KERN_INFO MYNAM ": Original request frame (@%p) header\n", mf)); + DBG_DUMP_REQUEST_FRAME_HDR(ioc, (u32 *)mf) } #endif @@ -518,8 +499,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(MYIOC_s_NOTE_FMT " IOCStatus=%04xh, IOCLogInfo=%08xh\n", - ioc->name, status, le32_to_cpu(pReply->IOCLogInfo))); + dcprintk(ioc, printk(KERN_NOTICE " IOCStatus=%04xh, IOCLogInfo=%08xh\n", + status, le32_to_cpu(pReply->IOCLogInfo))); pCfg->status = status; if (status == MPI_IOCSTATUS_SUCCESS) { @@ -582,27 +563,28 @@ 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 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. + * 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. */ -u8 +int mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) { - u8 cb_idx; - last_drv_idx = MPT_MAX_PROTOCOL_DRIVERS; + int i; + + last_drv_idx = -1; /* * Search for empty callback slot in this order: {N,...,7,6,5,...,1} * (slot/handle 0 is reserved!) */ - 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; + 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; break; } } @@ -619,9 +601,9 @@ mpt_register(MPT_CALLBACK cbfunc, MPT_DRIVER_CLASS dclass) * module is unloaded. */ void -mpt_deregister(u8 cb_idx) +mpt_deregister(int cb_idx) { - if (cb_idx && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) { + if ((cb_idx >= 0) && (cb_idx < MPT_MAX_PROTOCOL_DRIVERS)) { MptCallbacks[cb_idx] = NULL; MptDriverClass[cb_idx] = MPTUNKNOWN_DRIVER; MptEvHandlers[cb_idx] = NULL; @@ -643,9 +625,9 @@ mpt_deregister(u8 cb_idx) * Returns 0 for success. */ int -mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc) +mpt_event_register(int cb_idx, MPT_EVHANDLER ev_cbfunc) { - if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return -1; MptEvHandlers[cb_idx] = ev_cbfunc; @@ -663,9 +645,9 @@ mpt_event_register(u8 cb_idx, MPT_EVHANDLER ev_cbfunc) * or when its module is unloaded. */ void -mpt_event_deregister(u8 cb_idx) +mpt_event_deregister(int cb_idx) { - if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; MptEvHandlers[cb_idx] = NULL; @@ -683,9 +665,9 @@ mpt_event_deregister(u8 cb_idx) * Returns 0 for success. */ int -mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func) +mpt_reset_register(int cb_idx, MPT_RESETHANDLER reset_func) { - if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return -1; MptResetHandlers[cb_idx] = reset_func; @@ -702,9 +684,9 @@ mpt_reset_register(u8 cb_idx, MPT_RESETHANDLER reset_func) * or when its module is unloaded. */ void -mpt_reset_deregister(u8 cb_idx) +mpt_reset_deregister(int cb_idx) { - if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; MptResetHandlers[cb_idx] = NULL; @@ -717,12 +699,12 @@ mpt_reset_deregister(u8 cb_idx) * @cb_idx: MPT protocol driver index */ int -mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx) +mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, int cb_idx) { MPT_ADAPTER *ioc; const struct pci_device_id *id; - if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return -EINVAL; MptDeviceDriverHandlers[cb_idx] = dd_cbfunc; @@ -744,12 +726,12 @@ mpt_device_driver_register(struct mpt_pci_driver * dd_cbfunc, u8 cb_idx) * @cb_idx: MPT protocol driver index */ void -mpt_device_driver_deregister(u8 cb_idx) +mpt_device_driver_deregister(int cb_idx) { struct mpt_pci_driver *dd_cbfunc; MPT_ADAPTER *ioc; - if (!cb_idx || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) + if (cb_idx < 1 || cb_idx >= MPT_MAX_PROTOCOL_DRIVERS) return; dd_cbfunc = MptDeviceDriverHandlers[cb_idx]; @@ -767,14 +749,14 @@ mpt_device_driver_deregister(u8 cb_idx) /** * mpt_get_msg_frame - Obtain a MPT request frame from the pool (of 1024) * allocated per MPT adapter. - * @cb_idx: Handle of registered MPT protocol driver + * @handle: 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(u8 cb_idx, MPT_ADAPTER *ioc) +mpt_get_msg_frame(int handle, MPT_ADAPTER *ioc) { MPT_FRAME_HDR *mf; unsigned long flags; @@ -784,8 +766,7 @@ mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc) #ifdef MFCNT if (!ioc->active) - printk(MYIOC_s_WARN_FMT "IOC Not Active! mpt_get_msg_frame " - "returning NULL!\n", ioc->name); + printk(KERN_WARNING "IOC Not Active! mpt_get_msg_frame returning NULL!\n"); #endif /* If interrupts are not attached, do not return a request frame */ @@ -800,14 +781,13 @@ mpt_get_msg_frame(u8 cb_idx, 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 = cb_idx; /* byte */ + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* 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; - /* Default, will be changed if necessary in SG generation */ - ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; + ioc->RequestNB[req_idx] = ioc->NB_for_64_byte_frame; /* Default, will be changed if necessary in SG generation */ #ifdef MFCNT ioc->mfcnt++; #endif @@ -818,17 +798,14 @@ mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc) #ifdef MFCNT if (mf == NULL) - 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); + printk(KERN_WARNING "IOC Active. No free Msg Frames! Count 0x%x Max 0x%x\n", ioc->mfcnt, ioc->req_depth); mfcounter++; if (mfcounter == PRINT_MF_COUNT) - printk(MYIOC_s_INFO_FMT "MF Count 0x%x Max 0x%x \n", ioc->name, - ioc->mfcnt, ioc->req_depth); + printk(KERN_INFO "MF Count 0x%x Max 0x%x \n", ioc->mfcnt, ioc->req_depth); #endif - dmfprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_get_msg_frame(%d,%d), got mf=%p\n", - ioc->name, cb_idx, ioc->id, mf)); + dmfprintk(ioc, printk(KERN_INFO MYNAM ": %s: mpt_get_msg_frame(%d,%d), got mf=%p\n", + ioc->name, handle, ioc->id, mf)); return mf; } @@ -836,7 +813,7 @@ mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc) /** * mpt_put_msg_frame - Send a protocol specific MPT request frame * to a IOC. - * @cb_idx: Handle of registered MPT protocol driver + * @handle: Handle of registered MPT protocol driver * @ioc: Pointer to MPT adapter structure * @mf: Pointer to MPT request frame * @@ -844,14 +821,14 @@ mpt_get_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc) * specific MPT adapter. */ void -mpt_put_msg_frame(u8 cb_idx, MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf) +mpt_put_msg_frame(int handle, 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; /* byte */ + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; /* byte */ req_offset = (u8 *)mf - (u8 *)ioc->req_frames; /* u16! */ req_idx = req_offset / ioc->req_sz; @@ -861,44 +838,10 @@ mpt_put_msg_frame(u8 cb_idx, 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. @@ -956,7 +899,7 @@ mpt_add_sge(char *pAddr, u32 flagslength, dma_addr_t dma_addr) /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /** * mpt_send_handshake_request - Send MPT request via doorbell handshake method. - * @cb_idx: Handle of registered MPT protocol driver + * @handle: 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 @@ -971,7 +914,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(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) +mpt_send_handshake_request(int handle, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag) { int r = 0; u8 *req_as_bytes; @@ -991,7 +934,7 @@ mpt_send_handshake_request(u8 cb_idx, 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 = cb_idx; + mf->u.frame.hwhdr.msgctxu.fld.cb_idx = handle; } /* Make sure there are no doorbells */ @@ -1010,7 +953,7 @@ mpt_send_handshake_request(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, if (!(CHIPREG_READ32(&ioc->chip->Doorbell) & MPI_DOORBELL_ACTIVE)) return -5; - dhsprintk(ioc, printk(MYIOC_s_DEBUG_FMT "mpt_send_handshake_request start, WaitCnt=%d\n", + dhsprintk(ioc, printk(KERN_INFO MYNAM ": %s: mpt_send_handshake_request start, WaitCnt=%d\n", ioc->name, ii)); CHIPREG_WRITE32(&ioc->chip->IntStatus, 0); @@ -1452,13 +1395,11 @@ 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; @@ -1467,39 +1408,35 @@ 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; - ioc->id = mpt_ids++; - sprintf(ioc->name, "ioc%d", ioc->id); + if (mpt_debug_level) + printk(KERN_INFO MYNAM ": mpt_debug_level=%xh\n", mpt_debug_level); + + if (pci_enable_device(pdev)) + return r; - dinitprintk(ioc, printk(MYIOC_s_INFO_FMT ": mpt_adapter_install\n", ioc->name)); + dinitprintk(ioc, printk(KERN_WARNING MYNAM ": mpt_adapter_install\n")); if (!pci_set_dma_mask(pdev, DMA_64BIT_MASK)) { - dprintk(ioc, printk(MYIOC_s_INFO_FMT - ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n", ioc->name)); + dprintk(ioc, printk(KERN_INFO MYNAM + ": 64 BIT PCI BUS DMA ADDRESSING SUPPORTED\n")); } else if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { - printk(MYIOC_s_WARN_FMT ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n", - ioc->name); - kfree(ioc); + printk(KERN_WARNING MYNAM ": 32 BIT PCI BUS DMA ADDRESSING NOT SUPPORTED\n"); return r; } if (!pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK)) { - dprintk(ioc, printk(MYIOC_s_INFO_FMT - ": Using 64 bit consistent mask\n", ioc->name)); + dprintk(ioc, printk(KERN_INFO MYNAM + ": Using 64 bit consistent mask\n")); } else { - dprintk(ioc, printk(MYIOC_s_INFO_FMT - ": Not using 64 bit consistent mask\n", ioc->name)); + dprintk(ioc, printk(KERN_INFO MYNAM + ": Not using 64 bit consistent mask\n")); } ioc->alloc_total = sizeof(MPT_ADAPTER); @@ -1538,6 +1475,7 @@ 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; @@ -1563,23 +1501,25 @@ 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(MYIOC_s_ERR_FMT "Unable to map adapter memory!\n", ioc->name); + printk(KERN_ERR MYNAM ": ERROR - Unable to map adapter memory!\n"); kfree(ioc); return -EINVAL; } ioc->memmap = mem; - dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "mem = %p, mem_phys = %lx\n", ioc->name, mem, mem_phys)); + dinitprintk(ioc, printk(KERN_INFO MYNAM ": mem = %p, mem_phys = %lx\n", mem, mem_phys)); - dinitprintk(ioc, printk(MYIOC_s_INFO_FMT "facts @ %p, pfacts[0] @ %p\n", - ioc->name, &ioc->facts, &ioc->pfacts[0])); + dinitprintk(ioc, printk(KERN_INFO MYNAM ": facts @ %p, pfacts[0] @ %p\n", + &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 */ - ioc->pio_mem_phys = port; - pmem = (u8 __iomem *)port; - ioc->pio_chip = (SYSIF_REGS __iomem *)pmem; + { + u8 *pmem = (u8*)port; + ioc->pio_mem_phys = 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); @@ -1651,6 +1591,8 @@ 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! */ @@ -1667,8 +1609,9 @@ 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(MYIOC_s_ERR_FMT "didn't initialize properly! (%d)\n", - ioc->name, r); + printk(KERN_WARNING MYNAM + ": WARNING - %s did not initialize properly! (%d)\n", + ioc->name, r); list_del(&ioc->list); if (ioc->alt_ioc) @@ -1680,10 +1623,10 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) } /* call per device driver probe entry point */ - 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); + for(ii=0; iiprobe) { + MptDeviceDriverHandlers[ii]->probe(pdev,id); } } @@ -1720,7 +1663,7 @@ mpt_detach(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); char pname[32]; - u8 cb_idx; + int ii; sprintf(pname, MPT_PROCFS_MPTBASEDIR "/%s/summary", ioc->name); remove_proc_entry(pname, NULL); @@ -1730,10 +1673,10 @@ mpt_detach(struct pci_dev *pdev) remove_proc_entry(pname, NULL); /* call per device driver remove entry point */ - 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); + for(ii=0; iiremove) { + MptDeviceDriverHandlers[ii]->remove(pdev); } } @@ -1845,7 +1788,7 @@ mpt_resume(struct pci_dev *pdev) #endif static int -mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase) +mpt_signal_reset(int index, MPT_ADAPTER *ioc, int reset_phase) { if ((MptDriverClass[index] == MPTSPI_DRIVER && ioc->bus_type != SPI) || @@ -1887,15 +1830,14 @@ 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(MYIOC_s_INFO_FMT "Initiating %s\n", ioc->name, - reason == MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); + printk(KERN_INFO MYNAM ": Initiating %s %s\n", + ioc->name, reason==MPT_HOSTEVENT_IOC_BRINGUP ? "bringup" : "recovery"); /* Disable reply interrupts (also blocks FreeQ) */ CHIPREG_WRITE32(&ioc->chip->IntMask, 0xFFFFFFFF); @@ -1916,19 +1858,21 @@ 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(MYIOC_s_WARN_FMT "Owned by PEER..skipping!\n", - ioc->name); + printk(KERN_WARNING MYNAM ": %s 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(MYIOC_s_INFO_FMT - "alt_ioc reply irq re-enabled\n", ioc->alt_ioc->name)); + dprintk(ioc, printk(KERN_INFO MYNAM + ": alt-%s 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(MYIOC_s_WARN_FMT "NOT READY!\n", ioc->name); + printk(KERN_WARNING MYNAM ": %s NOT READY WARNING!\n", + ioc->name); } return -1; } @@ -1940,7 +1884,9 @@ 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(MYIOC_s_WARN_FMT "alt_ioc not ready!\n", ioc->alt_ioc->name); + printk(KERN_WARNING MYNAM + ": alt-%s: Not ready WARNING!\n", + ioc->alt_ioc->name); } for (ii=0; ii<5; ii++) { @@ -1951,8 +1897,7 @@ 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); @@ -1961,14 +1906,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) { @@ -1986,12 +1931,13 @@ 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; @@ -2000,8 +1946,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(MYIOC_s_INFO_FMT "installed at interrupt " - "%d\n", ioc->name, ioc->pcidev->irq)); + dprintk(ioc, printk(KERN_INFO MYNAM ": %s installed at interrupt " + "%d\n", ioc->name, ioc->pcidev->irq)); } } @@ -2020,8 +1966,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(MYIOC_s_WARN_FMT ": alt_ioc (%d) FIFO mgmt alloc!\n", - ioc->alt_ioc->name, rc); + printk(KERN_WARNING MYNAM ": alt-%s: (%d) FIFO mgmt alloc WARNING!\n", + ioc->alt_ioc->name, rc); alt_ioc_ready = 0; reset_alt_ioc_active = 0; } @@ -2030,15 +1976,16 @@ 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(MYIOC_s_WARN_FMT "alt_ioc (%d) init failure!\n", - ioc->alt_ioc->name, rc); + printk(KERN_WARNING MYNAM + ": alt-%s: (%d) init failure WARNING!\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 */ @@ -2054,13 +2001,12 @@ 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(MYIOC_s_WARN_FMT - "firmware upload failure!\n", ioc->name); + printk(KERN_WARNING MYNAM ": firmware upload failure!\n"); ret = -5; } } @@ -2075,8 +2021,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(MYIOC_s_INFO_FMT "alt_ioc reply irq re-enabled\n", - ioc->alt_ioc->name)); + dinitprintk(ioc, printk(KERN_INFO MYNAM ": alt-%s reply irq re-enabled\n", + ioc->alt_ioc->name)); CHIPREG_WRITE32(&ioc->alt_ioc->chip->IntMask, MPI_HIM_DIM); ioc->alt_ioc->active = 1; } @@ -2129,8 +2075,10 @@ 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 { @@ -2166,20 +2114,20 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) */ if (hard_reset_done) { rc = handlers = 0; - for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { - if ((ret == 0) && MptResetHandlers[cb_idx]) { + for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { + if ((ret == 0) && MptResetHandlers[ii]) { dprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "Calling IOC post_reset handler #%d\n", - ioc->name, cb_idx)); - rc += mpt_signal_reset(cb_idx, ioc, MPT_IOC_POST_RESET); + "Calling IOC post_reset handler #%d\n", + ioc->name, ii)); + rc += mpt_signal_reset(ii, ioc, MPT_IOC_POST_RESET); handlers++; } - if (alt_ioc_ready && MptResetHandlers[cb_idx]) { + if (alt_ioc_ready && MptResetHandlers[ii]) { drsprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "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); + "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); handlers++; } } @@ -2218,8 +2166,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) { @@ -2233,15 +2181,15 @@ mpt_detect_bound_ports(MPT_ADAPTER *ioc, struct pci_dev *pdev) if (_pcidev == peer) { /* Paranoia checks */ if (ioc->alt_ioc != NULL) { - printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n", + printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", ioc->name, ioc->alt_ioc->name); break; } else if (ioc_srch->alt_ioc != NULL) { - printk(MYIOC_s_WARN_FMT "Oops, already bound to %s!\n", + printk(KERN_WARNING MYNAM ": Oops, already bound (%s <==> %s)!\n", ioc_srch->name, ioc_srch->alt_ioc->name); break; } - dprintk(ioc, printk(MYIOC_s_INFO_FMT "FOUND! binding to %s\n", + dprintk(ioc, printk(KERN_INFO MYNAM ": FOUND! binding %s <==> %s\n", ioc->name, ioc_srch->name)); ioc_srch->alt_ioc = ioc; ioc->alt_ioc = ioc_srch; @@ -2262,11 +2210,10 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) int ret; if (ioc->cached_fw != NULL) { - ddlprintk(ioc, printk(MYIOC_s_INFO_FMT - "mpt_adapter_disable: Pushing FW onto adapter\n", ioc->name)); + ddlprintk(ioc, printk(KERN_INFO MYNAM ": mpt_adapter_disable: Pushing FW onto adapter\n")); if ((ret = mpt_downloadboot(ioc, (MpiFwHeader_t *)ioc->cached_fw, NO_SLEEP)) < 0) { - printk(MYIOC_s_WARN_FMT "firmware downloadboot failure (%d)!\n", - ioc->name, ret); + printk(KERN_WARNING MYNAM + ": firmware downloadboot failure (%d)!\n", ret); } } @@ -2278,8 +2225,8 @@ mpt_adapter_disable(MPT_ADAPTER *ioc) if (ioc->alloc != NULL) { sz = ioc->alloc_sz; - dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "free @ %p, sz=%d bytes\n", - ioc->name, ioc->alloc, ioc->alloc_sz)); + dexitprintk(ioc, printk(KERN_INFO MYNAM ": %s.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; @@ -2339,14 +2286,15 @@ 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(MYIOC_s_ERR_FMT - "host page buffers free failed (%d)!\n", - ioc->name, ret); + printk(KERN_ERR MYNAM + ": %s: host page buffers free failed (%d)!\n", + __FUNCTION__, ret); } - dexitprintk(ioc, printk(MYIOC_s_INFO_FMT "HostPageBuffer free @ %p, sz=%d bytes\n", + dexitprintk(ioc, printk(KERN_INFO MYNAM ": %s 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; @@ -2388,7 +2336,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(MYIOC_s_INFO_FMT "MTRR region de-registered\n", ioc->name)); + dprintk(ioc, printk(KERN_INFO MYNAM ": %s: MTRR region de-registered\n", ioc->name)); } #endif @@ -2396,8 +2344,8 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) list_del(&ioc->list); sz_last = ioc->alloc_total; - 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)); + 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)); if (ioc->alt_ioc) ioc->alt_ioc->alt_ioc = NULL; @@ -2476,7 +2424,7 @@ MakeIocReady(MPT_ADAPTER *ioc, int force, int sleepFlag) /* Get current [raw] IOC state */ ioc_state = mpt_GetIocState(ioc, 0); - dhsprintk(ioc, printk(MYIOC_s_INFO_FMT "MakeIocReady [raw] state=%08x\n", ioc->name, ioc_state)); + dhsprintk(ioc, printk(KERN_INFO MYNAM "::MakeIocReady, %s [raw] state=%08x\n", ioc->name, ioc_state)); /* * Check to see if IOC got left/stuck in doorbell handshake @@ -2498,9 +2446,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(MYIOC_s_WARN_FMT " FAULT code = %04xh\n", - ioc->name, ioc_state & MPI_DOORBELL_DATA_MASK); + ioc->name); + printk(KERN_WARNING " FAULT code = %04xh\n", + ioc_state & MPI_DOORBELL_DATA_MASK); } /* @@ -2516,9 +2464,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(MYIOC_s_INFO_FMT - "whoinit 0x%x statefault %d force %d\n", - ioc->name, whoinit, statefault, force)); + dinitprintk(ioc, printk(KERN_INFO MYNAM + ": whoinit 0x%x statefault %d force %d\n", + whoinit, statefault, force)); if (whoinit == MPI_WHOINIT_PCI_PEER) return -4; else { @@ -2601,6 +2549,7 @@ 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! */ @@ -2632,8 +2581,9 @@ GetIocFacts(MPT_ADAPTER *ioc, int sleepFlag, int reason) /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { - printk(MYIOC_s_ERR_FMT "Can't get IOCFacts NOT READY! (%08x)\n", - ioc->name, ioc->last_state ); + printk(KERN_ERR MYNAM ": ERROR - Can't get IOCFacts, %s NOT READY! (%08x)\n", + ioc->name, + ioc->last_state ); return -44; } @@ -2753,8 +2703,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) { /* @@ -2807,8 +2757,9 @@ GetPortFacts(MPT_ADAPTER *ioc, int portnum, int sleepFlag) /* IOC *must* NOT be in RESET state! */ if (ioc->last_state == MPI_IOC_STATE_RESET) { - printk(MYIOC_s_ERR_FMT "Can't get PortFacts NOT READY! (%08x)\n", - ioc->name, ioc->last_state ); + printk(KERN_ERR MYNAM ": ERROR - Can't get PortFacts, %s NOT READY! (%08x)\n", + ioc->name, + ioc->last_state ); return -4; } @@ -2983,7 +2934,7 @@ SendIocInit(MPT_ADAPTER *ioc, int sleepFlag) state = mpt_GetIocState(ioc, 1); count++; } - dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Wait IOC_OPERATIONAL state (cnt=%d)\n", + dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "INFO - Wait IOC_OPERATIONAL state (cnt=%d)\n", ioc->name, count)); ioc->aen_event_read_flag=0; @@ -3076,9 +3027,10 @@ mpt_free_fw_memory(MPT_ADAPTER *ioc) int sz; sz = ioc->facts.FWImageSize; - 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); + 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); ioc->cached_fw = NULL; return; @@ -3102,6 +3054,7 @@ 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; @@ -3118,8 +3071,8 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) mpt_alloc_fw_memory(ioc, 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)); + 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)); if (ioc->cached_fw == NULL) { /* Major Failure. @@ -3127,17 +3080,12 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) return -ENOMEM; } - 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; - } - + prequest = (FWUpload_t *)&request; preply = (FWUploadReply_t *)&reply; + /* Destination... */ + memset(prequest, 0, ioc->req_sz); + reply_sz = sizeof(reply); memset(preply, 0, reply_sz); @@ -3148,22 +3096,21 @@ 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((char *)ptcsge, flagsLength, ioc->cached_fw_dma); + mpt_add_sge(&request[sgeoffset], flagsLength, ioc->cached_fw_dma); sgeoffset += sizeof(u32) + sizeof(dma_addr_t); - 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); + dinitprintk(ioc, printk(KERN_INFO MYNAM ": Sending FW Upload (req @ %p) sgeoffset=%d \n", + 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(MYIOC_s_INFO_FMT ": FW Upload completed rc=%x \n", ioc->name, ii)); + dinitprintk(ioc, printk(KERN_INFO MYNAM ": FW Upload completed rc=%x \n", ii)); cmdStatus = -EFAULT; if (ii == 0) { @@ -3188,7 +3135,6 @@ mpt_do_upload(MPT_ADAPTER *ioc, int sleepFlag) ioc->name)); mpt_free_fw_memory(ioc); } - kfree(prequest); return cmdStatus; } @@ -3435,7 +3381,7 @@ KickStart(MPT_ADAPTER *ioc, int force, int sleepFlag) u32 ioc_state=0; int cnt,cntdn; - dinitprintk(ioc, printk(MYIOC_s_DEBUG_FMT "KickStarting!\n", ioc->name)); + dinitprintk(ioc, printk(KERN_WARNING MYNAM ": KickStarting %s!\n", ioc->name)); if (ioc->bus_type == SPI) { /* Always issue a Msg Unit Reset first. This will clear some * SCSI bus hang conditions. @@ -3454,7 +3400,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; cntname, mpt_GetIocState(ioc, 0))); + printk(MYIOC_s_ERR_FMT "Failed to come READY after reset! IocState=%x\n", + ioc->name, ioc_state); return -1; } @@ -3614,20 +3560,20 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) * MptResetHandlers[] registered yet. */ { - u8 cb_idx; + int ii; int r = 0; - for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { - if (MptResetHandlers[cb_idx]) { + for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { + if (MptResetHandlers[ii]) { dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC pre_reset handler #%d\n", - ioc->name, cb_idx)); - r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_PRE_RESET); + ioc->name, ii)); + r += mpt_signal_reset(ii, 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, cb_idx)); - r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_PRE_RESET); + ioc->name, ioc->alt_ioc->name, ii)); + r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_PRE_RESET); } } } @@ -3660,8 +3606,8 @@ mpt_diag_reset(MPT_ADAPTER *ioc, int ignore, int sleepFlag) } if ((count = mpt_downloadboot(ioc, (MpiFwHeader_t *)iocp->cached_fw, sleepFlag)) < 0) { - printk(MYIOC_s_WARN_FMT - "firmware downloadboot failure (%d)!\n", ioc->name, count); + printk(KERN_WARNING MYNAM + ": firmware downloadboot failure (%d)!\n", count); } } else { @@ -3804,8 +3750,8 @@ SendIocReset(MPT_ADAPTER *ioc, u8 reset_type, int sleepFlag) if (sleepFlag != CAN_SLEEP) count *= 10; - printk(MYIOC_s_ERR_FMT "Wait IOC_READY state timeout(%d)!\n", - ioc->name, (int)((count+5)/HZ)); + printk(KERN_ERR MYNAM ": %s: ERROR - Wait IOC_READY state timeout(%d)!\n", + ioc->name, (int)((count+5)/HZ)); return -ETIME; } @@ -4198,7 +4144,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!" : "")); @@ -4403,7 +4349,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)); @@ -4878,8 +4824,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(MYIOC_s_DEBUG_FMT - "noQas due to Capabilities=%x\n", + ddvprintk(ioc, printk(KERN_INFO MYNAM + " :%s noQas due to Capabilities=%x\n", ioc->name, pPP0->Capabilities)); } ioc->spi_data.maxBusWidth = pPP0->Capabilities & MPI_SCSIPORTPAGE0_CAP_WIDE ? 1 : 0; @@ -4942,38 +4888,6 @@ 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; @@ -5787,10 +5701,10 @@ mpt_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) CONFIGPARMS *pCfg; unsigned long flags; - 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"))); + 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"))); if (reset_phase == MPT_IOC_SETUP_RESET) { ; @@ -5929,7 +5843,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) { - u8 cb_idx; + int ii; int scsi, fc, sas, lan, ctl, targ, dmp; char *drvname; int len; @@ -5938,10 +5852,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 (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { + for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { drvname = NULL; - if (MptCallbacks[cb_idx]) { - switch (MptDriverClass[cb_idx]) { + if (MptCallbacks[ii]) { + switch (MptDriverClass[ii]) { case MPTSPI_DRIVER: if (!scsi++) drvname = "SPI host"; break; @@ -6185,25 +6099,26 @@ mpt_HardResetHandler(MPT_ADAPTER *ioc, int sleepFlag) * For all other protocol drivers, this is a no-op. */ { - u8 cb_idx; + int ii; int r = 0; - for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { - if (MptResetHandlers[cb_idx]) { + for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { + if (MptResetHandlers[ii]) { dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Calling IOC reset_setup handler #%d\n", - ioc->name, cb_idx)); - r += mpt_signal_reset(cb_idx, ioc, MPT_IOC_SETUP_RESET); + ioc->name, ii)); + r += mpt_signal_reset(ii, 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, cb_idx)); - r += mpt_signal_reset(cb_idx, ioc->alt_ioc, MPT_IOC_SETUP_RESET); + ioc->name, ioc->alt_ioc->name, ii)); + r += mpt_signal_reset(ii, ioc->alt_ioc, MPT_IOC_SETUP_RESET); } } } } if ((rc = mpt_do_ioc_recovery(ioc, MPT_HOSTEVENT_IOC_RECOVER, sleepFlag)) != 0) { - printk(MYIOC_s_WARN_FMT "Cannot recover rc = %d!\n", ioc->name, rc); + printk(KERN_WARNING MYNAM ": WARNING - (%d) Cannot recover %s\n", + rc, ioc->name); } ioc->reload_fw = 0; if (ioc->alt_ioc) @@ -6600,7 +6515,6 @@ 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]; @@ -6623,12 +6537,12 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply evStr)); #ifdef CONFIG_FUSION_LOGGING - devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT - ": Event data:\n", ioc->name)); + devtverboseprintk(ioc, printk(KERN_DEBUG MYNAM + ": Event data:\n")); for (ii = 0; ii < evDataLen; ii++) devtverboseprintk(ioc, printk(" %08x", le32_to_cpu(pEventReply->Data[ii]))); - devtverboseprintk(ioc, printk("\n")); + devtverboseprintk(ioc, printk(KERN_DEBUG "\n")); #endif /* @@ -6681,11 +6595,11 @@ ProcessEventNotification(MPT_ADAPTER *ioc, EventNotificationReply_t *pEventReply /* * Call each currently registered protocol event handler. */ - for (cb_idx = MPT_MAX_PROTOCOL_DRIVERS-1; cb_idx; cb_idx--) { - if (MptEvHandlers[cb_idx]) { + for (ii=MPT_MAX_PROTOCOL_DRIVERS-1; ii; ii--) { + if (MptEvHandlers[ii]) { devtverboseprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Routing Event to event handler #%d\n", - ioc->name, cb_idx)); - r += (*(MptEvHandlers[cb_idx]))(ioc, pEventReply); + ioc->name, ii)); + r += (*(MptEvHandlers[ii]))(ioc, pEventReply); handlers++; } } @@ -7120,8 +7034,8 @@ mpt_iocstatus_info_config(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) if (!desc) return; - dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s: %s\n", - ioc->name, ioc_status, desc, extend_desc)); + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s: %s\n", + ioc->name, ioc_status, desc, extend_desc); } /** @@ -7347,8 +7261,7 @@ mpt_iocstatus_info(MPT_ADAPTER *ioc, u32 ioc_status, MPT_FRAME_HDR *mf) if (!desc) return; - dreplyprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IOCStatus(0x%04X): %s\n", - ioc->name, status, desc)); + printk(MYIOC_s_INFO_FMT "IOCStatus(0x%04X): %s\n", ioc->name, status, desc); } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -7370,13 +7283,14 @@ 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); @@ -7394,16 +7308,16 @@ EXPORT_SYMBOL(mpt_raid_phys_disk_pg0); static int __init fusion_init(void) { - u8 cb_idx; + int i; show_mptmod_ver(my_NAME, my_VERSION); printk(KERN_INFO COPYRIGHT "\n"); - 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; + for (i = 0; i < MPT_MAX_PROTOCOL_DRIVERS; i++) { + MptCallbacks[i] = NULL; + MptDriverClass[i] = MPTUNKNOWN_DRIVER; + MptEvHandlers[i] = NULL; + MptResetHandlers[i] = NULL; } /* Register ourselves (mptbase) in order to facilitate diff --git a/trunk/drivers/message/fusion/mptbase.h b/trunk/drivers/message/fusion/mptbase.h index d7682e083f59..15ff22645844 100644 --- a/trunk/drivers/message/fusion/mptbase.h +++ b/trunk/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 Fusion MPT (Message Passing Technology) firmware. + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -68,15 +68,15 @@ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ #ifndef MODULEAUTHOR -#define MODULEAUTHOR "LSI Corporation" +#define MODULEAUTHOR "LSI Logic Corporation" #endif #ifndef COPYRIGHT #define COPYRIGHT "Copyright (c) 1999-2007 " MODULEAUTHOR #endif -#define MPT_LINUX_VERSION_COMMON "3.04.06" -#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.06" +#define MPT_LINUX_VERSION_COMMON "3.04.05" +#define MPT_LINUX_PACKAGE_NAME "@(#)mptlinux-3.04.05" #define WHAT_MAGIC_STRING "@" "(" "#" ")" #define show_mptmod_ver(s,ver) \ @@ -186,42 +186,12 @@ * 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: " #define MYIOC_s_WARN_FMT KERN_WARNING MYNAM ": %s: WARNING - " #define MYIOC_s_ERR_FMT KERN_ERR MYNAM ": %s: ERROR - " -/*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -/* - * 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... @@ -337,8 +307,7 @@ 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 RequestHiPriFifo; /* 48 Hi Priority Request FIFO */ - u32 Reserved3; /* 4C-4F reserved for future use */ + u32 Reserved3[2]; /* 48-4F reserved for future use */ u32 HostIndex; /* 50 Host Index register */ u32 Reserved4[15]; /* 54-8F */ u32 Fubar; /* 90 For Fubar usage */ @@ -680,9 +649,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]; - u8 DoneCtx; - u8 TaskCtx; - u8 InternalCtx; + int DoneCtx; + int TaskCtx; + int InternalCtx; spinlock_t initializing_hba_lock; int initializing_hba_lock_flag; struct list_head list; @@ -699,14 +668,10 @@ 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; /* @@ -820,6 +785,7 @@ 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 @@ -887,21 +853,20 @@ 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 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 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 void mpt_free_msg_frame(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_put_msg_frame(int handle, 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(u8 cb_idx, MPT_ADAPTER *ioc, int reqBytes, u32 *req, int sleepFlag); +extern int mpt_send_handshake_request(int handle, 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); @@ -919,6 +884,9 @@ 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/trunk/drivers/message/fusion/mptctl.c b/trunk/drivers/message/fusion/mptctl.c index 6029509702d3..89695e705bdc 100644 --- a/trunk/drivers/message/fusion/mptctl.c +++ b/trunk/drivers/message/fusion/mptctl.c @@ -1,10 +1,10 @@ /* * linux/drivers/message/fusion/mptctl.c * mpt Ioctl driver. - * For use with LSI PCI chip/adapters - * running LSI Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Logic PCI chip/adapters + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -66,8 +66,8 @@ #include #include -#define COPYRIGHT "Copyright (c) 1999-2007 LSI Corporation" -#define MODULEAUTHOR "LSI Corporation" +#define COPYRIGHT "Copyright (c) 1999-2007 LSI Logic Corporation" +#define MODULEAUTHOR "LSI Logic Corporation" #include "mptbase.h" #include "mptctl.h" @@ -83,7 +83,7 @@ MODULE_VERSION(my_VERSION); /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ -static u8 mptctl_id = MPT_MAX_PROTOCOL_DRIVERS; +static int mptctl_id = -1; static DECLARE_WAIT_QUEUE_HEAD ( mptctl_wait ); @@ -181,6 +181,7 @@ 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)) @@ -189,6 +190,7 @@ 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; } @@ -340,7 +342,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) SCSITaskMgmt_t *pScsiTm; MPT_SCSI_HOST *hd; int ii; - int retval=0; + int retval; ioctl->reset &= ~MPTCTL_RESET_OK; @@ -348,7 +350,7 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) if (ioctl->ioc->sh == NULL) return -EPERM; - hd = shost_priv(ioctl->ioc->sh); + hd = (MPT_SCSI_HOST *) ioctl->ioc->sh->hostdata; if (hd == NULL) return -EPERM; @@ -393,19 +395,12 @@ static int mptctl_bus_reset(MPT_IOCTL *ioctl) DBG_DUMP_TM_REQUEST_FRAME(ioctl->ioc, (u32 *)mf); ioctl->wait_done=0; - - 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; - } + 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; } /* Now wait for the command to complete */ @@ -449,7 +444,7 @@ mptctl_free_tm_flags(MPT_ADAPTER *ioc) MPT_SCSI_HOST * hd; unsigned long flags; - hd = shost_priv(ioc->sh); + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; if (hd == NULL) return; @@ -473,7 +468,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"))); @@ -579,7 +574,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 MYNAM "%s::mptctl_ioctl() @%d - " + printk(KERN_ERR "%s::mptctl_ioctl() @%d - " "Unable to copy mpt_ioctl_header data @ %p\n", __FILE__, __LINE__, uhdr); return -EFAULT; @@ -592,13 +587,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 MYNAM "%s::mptctl_ioctl() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_ioctl() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnumX); return -ENODEV; } if (!iocp->active) { - printk(KERN_DEBUG MYNAM "%s::mptctl_ioctl() @%d - Controller disabled.\n", + printk(KERN_DEBUG "%s::mptctl_ioctl() @%d - Controller disabled.\n", __FILE__, __LINE__); return -EFAULT; } @@ -665,14 +660,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 MYNAM "%s@%d::mptctl_do_reset - " + printk(KERN_ERR "%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 MYNAM "%s@%d::mptctl_do_reset - ioc%d not found!\n", + printk(KERN_DEBUG "%s@%d::mptctl_do_reset - ioc%d not found!\n", __FILE__, __LINE__, krinfo.hdr.iocnum); return -ENODEV; /* (-6) No such device or address */ } @@ -681,8 +676,8 @@ static int mptctl_do_reset(unsigned long arg) iocp->name)); if (mpt_HardResetHandler(iocp, CAN_SLEEP) != 0) { - printk (MYIOC_s_ERR_FMT "%s@%d::mptctl_do_reset - reset failed.\n", - iocp->name, __FILE__, __LINE__); + printk (KERN_ERR "%s@%d::mptctl_do_reset - reset failed.\n", + __FILE__, __LINE__); return -1; } @@ -713,7 +708,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 MYNAM "%s@%d::_ioctl_fwdl - " + printk(KERN_ERR "%s@%d::_ioctl_fwdl - " "Unable to copy mpt_fw_xfer struct @ %p\n", __FILE__, __LINE__, ufwdl); return -EFAULT; @@ -761,8 +756,7 @@ 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 MYNAM "ioctl_fwdl - ioc%d not found!\n", - ioc); + printk(KERN_DEBUG "ioctl_fwdl - ioc%d not found!\n", ioc); return -ENODEV; /* (-6) No such device or address */ } else { @@ -874,9 +868,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(MYIOC_s_ERR_FMT "%s@%d::_ioctl_fwdl - " - "Unable to copy f/w buffer hunk#%d @ %p\n", - iocp->name, __FILE__, __LINE__, n, ufwbuf); + printk(KERN_ERR "%s@%d::_ioctl_fwdl - " + "Unable to copy f/w buffer hunk#%d @ %p\n", + __FILE__, __LINE__, n, ufwbuf); goto fwdl_out; } fw_bytes_copied += bl->len; @@ -912,22 +906,21 @@ 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(MYIOC_s_INFO_FMT "F/W update successfull!\n", iocp->name); + printk(KERN_INFO MYNAM ": F/W update successfully sent to %s!\n", iocp->name); return 0; } else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) { - 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); + 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"); return -EBADRQC; } else if (iocstat == MPI_IOCSTATUS_BUSY) { - printk(MYIOC_s_WARN_FMT "IOC_BUSY!\n", iocp->name); - printk(MYIOC_s_WARN_FMT "(try again later?)\n", iocp->name); + printk(KERN_WARNING MYNAM ": Warning! %s says: IOC_BUSY!\n", iocp->name); + printk(KERN_WARNING MYNAM ": (try again later?)\n"); return -EBUSY; } else { - 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); + printk(KERN_WARNING MYNAM "::ioctl_fwdl() ERROR! %s returned [bad] status = %04xh\n", + iocp->name, iocstat); + printk(KERN_WARNING MYNAM ": (bad VooDoo)\n"); return -ENOMSG; } return 0; @@ -977,9 +970,10 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, * structures for the SG elements. */ i = MAX_SGL_BYTES / 8; - buflist = kzalloc(i, GFP_USER); - if (!buflist) + buflist = kmalloc(i, GFP_USER); + if (buflist == NULL) return NULL; + memset(buflist, 0, i); buflist_ent = 0; /* Allocate a single block of memory to store the sg elements and @@ -1014,10 +1008,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(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); + printk(KERN_WARNING MYNAM "-SG: No can do - " + "not enough memory! :-(\n"); + printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n", + numfrags); goto free_and_fail; } continue; @@ -1040,19 +1034,18 @@ kbuf_alloc_2_sgl(int bytes, u32 sgdir, int sge_offset, int *frags, /* Need to chain? */ if (fragcnt == sg_spill) { - 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); + printk(KERN_WARNING MYNAM "-SG: No can do - " "Chain required! :-(\n"); + printk(KERN_WARNING MYNAM "(freeing %d frags)\n", numfrags); goto free_and_fail; } /* overflow check... */ if (numfrags*8 > MAX_SGL_BYTES){ /* GRRRRR... */ - 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); + printk(KERN_WARNING MYNAM "-SG: No can do - " + "too many SG frags! :-(\n"); + printk(KERN_WARNING MYNAM "-SG: (freeing %d frags)\n", + numfrags); goto free_and_fail; } } @@ -1073,6 +1066,8 @@ 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; @@ -1175,7 +1170,7 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) int cim_rev; u8 revision; struct scsi_device *sdev; - VirtDevice *vdevice; + VirtDevice *vdev; /* Add of PCI INFO results in unaligned access for * IA64 and Sparc. Reset long to int. Return no PCI @@ -1194,13 +1189,13 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) karg = kmalloc(data_size, GFP_KERNEL); if (karg == NULL) { - printk(KERN_ERR MYNAM "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", + printk(KERN_ERR "%s::mpt_ioctl_iocinfo() @%d - no memory available!\n", __FILE__, __LINE__); return -ENOMEM; } if (copy_from_user(karg, uarg, data_size)) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_getiocinfo - " + printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to read in mpt_ioctl_iocinfo struct @ %p\n", __FILE__, __LINE__, uarg); kfree(karg); @@ -1209,7 +1204,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 MYNAM "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_getiocinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); kfree(karg); return -ENODEV; @@ -1217,9 +1212,9 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) /* Verify the data transfer size is correct. */ if (karg->hdr.maxDataSize != data_size) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - " + printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Structure size mismatch. Command not completed.\n", - ioc->name, __FILE__, __LINE__); + __FILE__, __LINE__); kfree(karg); return -EFAULT; } @@ -1270,8 +1265,8 @@ mptctl_getiocinfo (unsigned long arg, unsigned int data_size) karg->numDevices = 0; if (ioc->sh) { shost_for_each_device(sdev, ioc->sh) { - vdevice = sdev->hostdata; - if (vdevice->vtarget->tflags & + vdev = sdev->hostdata; + if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) continue; karg->numDevices++; @@ -1295,9 +1290,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_getiocinfo - " + printk(KERN_ERR "%s@%d::mptctl_getiocinfo - " "Unable to write out mpt_ioctl_iocinfo struct @ %p\n", - ioc->name, __FILE__, __LINE__, uarg); + __FILE__, __LINE__, uarg); kfree(karg); return -EFAULT; } @@ -1322,7 +1317,7 @@ mptctl_gettargetinfo (unsigned long arg) struct mpt_ioctl_targetinfo __user *uarg = (void __user *) arg; struct mpt_ioctl_targetinfo karg; MPT_ADAPTER *ioc; - VirtDevice *vdevice; + VirtDevice *vdev; char *pmem; int *pdata; int iocnum; @@ -1334,7 +1329,7 @@ mptctl_gettargetinfo (unsigned long arg) struct scsi_device *sdev; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_targetinfo))) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_gettargetinfo - " + printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to read in mpt_ioctl_targetinfo struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1342,7 +1337,7 @@ mptctl_gettargetinfo (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_gettargetinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1358,8 +1353,8 @@ mptctl_gettargetinfo (unsigned long arg) port = karg.hdr.port; if (maxWordsLeft <= 0) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n", - ioc->name, __FILE__, __LINE__); + printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", + __FILE__, __LINE__); return -ENOMEM; } @@ -1377,12 +1372,13 @@ mptctl_gettargetinfo (unsigned long arg) * 15- 8: Bus Number * 7- 0: Target ID */ - pmem = kzalloc(numBytes, GFP_KERNEL); - if (!pmem) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo() - no memory available!\n", - ioc->name, __FILE__, __LINE__); + pmem = kmalloc(numBytes, GFP_KERNEL); + if (pmem == NULL) { + printk(KERN_ERR "%s::mptctl_gettargetinfo() @%d - no memory available!\n", + __FILE__, __LINE__); return -ENOMEM; } + memset(pmem, 0, numBytes); pdata = (int *) pmem; /* Get number of devices @@ -1391,13 +1387,13 @@ mptctl_gettargetinfo (unsigned long arg) shost_for_each_device(sdev, ioc->sh) { if (!maxWordsLeft) continue; - vdevice = sdev->hostdata; - if (vdevice->vtarget->tflags & + vdev = sdev->hostdata; + if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) continue; - lun = (vdevice->vtarget->raidVolume) ? 0x80 : vdevice->lun; - *pdata = (((u8)lun << 16) + (vdevice->vtarget->channel << 8) + - (vdevice->vtarget->id )); + lun = (vdev->vtarget->raidVolume) ? 0x80 : vdev->lun; + *pdata = (((u8)lun << 16) + (vdev->vtarget->channel << 8) + + (vdev->vtarget->id )); pdata++; numDevices++; --maxWordsLeft; @@ -1409,9 +1405,9 @@ mptctl_gettargetinfo (unsigned long arg) */ if (copy_to_user((char __user *)arg, &karg, sizeof(struct mpt_ioctl_targetinfo))) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo - " + printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - ioc->name, __FILE__, __LINE__, uarg); + __FILE__, __LINE__, uarg); kfree(pmem); return -EFAULT; } @@ -1419,9 +1415,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_gettargetinfo - " + printk(KERN_ERR "%s@%d::mptctl_gettargetinfo - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - ioc->name, __FILE__, __LINE__, pdata); + __FILE__, __LINE__, pdata); kfree(pmem); return -EFAULT; } @@ -1448,7 +1444,7 @@ mptctl_readtest (unsigned long arg) int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_test))) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_readtest - " + printk(KERN_ERR "%s@%d::mptctl_readtest - " "Unable to read in mpt_ioctl_test struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1456,7 +1452,7 @@ mptctl_readtest (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_readtest() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_readtest() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1480,9 +1476,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_readtest - " + printk(KERN_ERR "%s@%d::mptctl_readtest - " "Unable to write out mpt_ioctl_test struct @ %p\n", - ioc->name, __FILE__, __LINE__, uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -1509,7 +1505,7 @@ mptctl_eventquery (unsigned long arg) int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventquery))) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_eventquery - " + printk(KERN_ERR "%s@%d::mptctl_eventquery - " "Unable to read in mpt_ioctl_eventquery struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1517,7 +1513,7 @@ mptctl_eventquery (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_eventquery() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_eventquery() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1530,9 +1526,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_eventquery - " + printk(KERN_ERR "%s@%d::mptctl_eventquery - " "Unable to write out mpt_ioctl_eventquery struct @ %p\n", - ioc->name, __FILE__, __LINE__, uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } return 0; @@ -1548,7 +1544,7 @@ mptctl_eventenable (unsigned long arg) int iocnum; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventenable))) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_eventenable - " + printk(KERN_ERR "%s@%d::mptctl_eventenable - " "Unable to read in mpt_ioctl_eventenable struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1556,7 +1552,7 @@ mptctl_eventenable (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_eventenable() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_eventenable() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1567,13 +1563,12 @@ 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 = kzalloc(sz, GFP_KERNEL); - if (!ioc->events) { - printk(MYIOC_s_ERR_FMT - ": ERROR - Insufficient memory to add adapter!\n", - ioc->name); + ioc->events = kmalloc(sz, GFP_KERNEL); + if (ioc->events == NULL) { + printk(KERN_ERR MYNAM ": ERROR - Insufficient memory to add adapter!\n"); return -ENOMEM; } + memset(ioc->events, 0, sz); ioc->alloc_total += sz; ioc->eventContext = 0; @@ -1597,7 +1592,7 @@ mptctl_eventreport (unsigned long arg) int numBytes, maxEvents, max; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_eventreport))) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_eventreport - " + printk(KERN_ERR "%s@%d::mptctl_eventreport - " "Unable to read in mpt_ioctl_eventreport struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1605,7 +1600,7 @@ mptctl_eventreport (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_eventreport() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_eventreport() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1631,9 +1626,9 @@ mptctl_eventreport (unsigned long arg) */ numBytes = max * sizeof(MPT_IOCTL_EVENTS); if (copy_to_user(uarg->eventData, ioc->events, numBytes)) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_eventreport - " + printk(KERN_ERR "%s@%d::mptctl_eventreport - " "Unable to write out mpt_ioctl_eventreport struct @ %p\n", - ioc->name, __FILE__, __LINE__, ioc->events); + __FILE__, __LINE__, ioc->events); return -EFAULT; } @@ -1651,7 +1646,7 @@ mptctl_replace_fw (unsigned long arg) int newFwSize; if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_replace_fw))) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_replace_fw - " + printk(KERN_ERR "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1659,7 +1654,7 @@ mptctl_replace_fw (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_replace_fw() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1689,9 +1684,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_replace_fw - " + printk(KERN_ERR "%s@%d::mptctl_replace_fw - " "Unable to read in mpt_ioctl_replace_fw image " - "@ %p\n", ioc->name, __FILE__, __LINE__, uarg); + "@ %p\n", __FILE__, __LINE__, uarg); mpt_free_fw_memory(ioc); return -EFAULT; } @@ -1725,7 +1720,7 @@ mptctl_mpt_command (unsigned long arg) if (copy_from_user(&karg, uarg, sizeof(struct mpt_ioctl_command))) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_mpt_command - " "Unable to read in mpt_ioctl_command struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -1733,7 +1728,7 @@ mptctl_mpt_command (unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -1774,24 +1769,21 @@ 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 MYNAM "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_do_mpt_command() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } if (!ioc->ioctl) { - printk(KERN_ERR MYNAM "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%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 MYNAM "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Busy with IOC Reset \n", __FILE__, __LINE__); return -EBUSY; } @@ -1805,9 +1797,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Request frame too large (%d) maximum (%d)\n", - ioc->name, __FILE__, __LINE__, sz, ioc->req_sz); + __FILE__, __LINE__, sz, ioc->req_sz); return -EFAULT; } @@ -1825,9 +1817,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to read MF from mpt_ioctl_command struct @ %p\n", - ioc->name, __FILE__, __LINE__, mfPtr); + __FILE__, __LINE__, mfPtr); rc = -EFAULT; goto done_free_mem; } @@ -1878,17 +1870,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Target ID out of bounds. \n", - ioc->name, __FILE__, __LINE__); + __FILE__, __LINE__); rc = -ENODEV; goto done_free_mem; } if (pScsiReq->Bus >= ioc->number_of_buses) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Target Bus out of bounds. \n", - ioc->name, __FILE__, __LINE__); + __FILE__, __LINE__); rc = -ENODEV; goto done_free_mem; } @@ -1940,9 +1932,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) ioc->ioctl->id = pScsiReq->TargetID; } else { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", - ioc->name, __FILE__, __LINE__); + __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } @@ -1959,9 +1951,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) case MPI_FUNCTION_SATA_PASSTHROUGH: if (!ioc->sh) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", - ioc->name, __FILE__, __LINE__); + __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } @@ -2018,9 +2010,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver is not loaded. \n", - ioc->name, __FILE__, __LINE__); + __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } @@ -2029,10 +2021,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 = shost_priv(ioc->sh)) == NULL)) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + if ((ioc->sh == NULL) || ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) { + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "SCSI driver not loaded or SCSI host not found. \n", - ioc->name, __FILE__, __LINE__); + __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } else if (mptctl_set_tm_flags(hd) != 0) { @@ -2063,9 +2055,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "IOC_INIT issued with 1 or more incorrect parameters. Rejected.\n", - ioc->name, __FILE__, __LINE__); + __FILE__, __LINE__); rc = -EFAULT; goto done_free_mem; } @@ -2096,9 +2088,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) MPI_FUNCTION_LAN_RESET */ - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Illegal request (function 0x%x) \n", - ioc->name, __FILE__, __LINE__, hdr->Function); + __FILE__, __LINE__, hdr->Function); rc = -EFAULT; goto done_free_mem; } @@ -2111,6 +2103,11 @@ 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 ++; @@ -2150,11 +2147,11 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) if (copy_from_user(bufOut.kptr, karg.dataOutBufPtr, bufOut.len)) { - printk(MYIOC_s_ERR_FMT + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - Unable " "to read user data " "struct @ %p\n", - ioc->name, __FILE__, __LINE__,karg.dataOutBufPtr); + __FILE__, __LINE__,karg.dataOutBufPtr); rc = -EFAULT; goto done_free_mem; } @@ -2190,20 +2187,15 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); - 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; - } + 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; } } else @@ -2241,10 +2233,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(MYIOC_s_ERR_FMT + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write out reply frame %p\n", - ioc->name, __FILE__, __LINE__, karg.replyFrameBufPtr); + __FILE__, __LINE__, karg.replyFrameBufPtr); rc = -ENODATA; goto done_free_mem; } @@ -2257,9 +2249,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write sense data to user %p\n", - ioc->name, __FILE__, __LINE__, + __FILE__, __LINE__, karg.senseDataPtr); rc = -ENODATA; goto done_free_mem; @@ -2275,9 +2267,9 @@ mptctl_do_mpt_command (struct mpt_ioctl_command karg, void __user *mfPtr) if (copy_to_user(karg.dataInBufPtr, bufIn.kptr, karg.dataInSize)) { - printk(MYIOC_s_ERR_FMT "%s@%d::mptctl_do_mpt_command - " + printk(KERN_ERR "%s@%d::mptctl_do_mpt_command - " "Unable to write data to user %p\n", - ioc->name, __FILE__, __LINE__, + __FILE__, __LINE__, karg.dataInBufPtr); rc = -ENODATA; } @@ -2348,7 +2340,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 MYNAM "%s@%d::mptctl_hp_host_info - " + printk(KERN_ERR "%s@%d::mptctl_hp_host_info - " "Unable to read in hp_host_info struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -2356,7 +2348,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 MYNAM "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%s::mptctl_hp_hostinfo() @%d - ioc%d not found!\n", __FILE__, __LINE__, iocnum); return -ENODEV; } @@ -2464,7 +2456,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 = shost_priv(ioc->sh); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; if (hd && (cim_rev == 1)) { karg.hard_resets = hd->hard_resets; @@ -2537,9 +2529,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(MYIOC_s_ERR_FMT "%s@%d::mptctl_hpgethostinfo - " + printk(KERN_ERR "%s@%d::mptctl_hpgethostinfo - " "Unable to write out hp_host_info @ %p\n", - ioc->name, __FILE__, __LINE__, uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -2575,7 +2567,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 MYNAM "%s@%d::mptctl_hp_targetinfo - " + printk(KERN_ERR "%s@%d::mptctl_hp_targetinfo - " "Unable to read in hp_host_targetinfo struct @ %p\n", __FILE__, __LINE__, uarg); return -EFAULT; @@ -2583,11 +2575,11 @@ mptctl_hp_targetinfo(unsigned long arg) if (((iocnum = mpt_verify_adapter(karg.hdr.iocnum, &ioc)) < 0) || (ioc == NULL)) { - printk(KERN_DEBUG MYNAM "%s::mptctl_hp_targetinfo() @%d - ioc%d not found!\n", + printk(KERN_DEBUG "%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. @@ -2681,16 +2673,16 @@ mptctl_hp_targetinfo(unsigned long arg) pci_free_consistent(ioc->pcidev, data_sz, (u8 *) pg3_alloc, page_dma); } } - hd = shost_priv(ioc->sh); + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; 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(MYIOC_s_ERR_FMT "%s@%d::mptctl_hp_target_info - " + printk(KERN_ERR "%s@%d::mptctl_hp_target_info - " "Unable to write out mpt_ioctl_targetinfo struct @ %p\n", - ioc->name, __FILE__, __LINE__, uarg); + __FILE__, __LINE__, uarg); return -EFAULT; } @@ -2740,7 +2732,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; } @@ -2780,7 +2772,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; } @@ -2861,22 +2853,31 @@ 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) { - MPT_IOCTL *mem; + int err; + int sz; + u8 *mem; MPT_ADAPTER *ioc = pci_get_drvdata(pdev); /* * Allocate and inite a MPT_IOCTL structure */ - mem = kzalloc(sizeof(MPT_IOCTL), GFP_KERNEL); - if (!mem) { - mptctl_remove(pdev); - return -ENOMEM; + sz = sizeof (MPT_IOCTL); + mem = kmalloc(sz, GFP_KERNEL); + if (mem == NULL) { + err = -ENOMEM; + goto out_fail; } - ioc->ioctl = mem; + memset(mem, 0, sz); + ioc->ioctl = (MPT_IOCTL *) mem; ioc->ioctl->ioc = ioc; mutex_init(&ioc->ioctl->ioctl_mutex); return 0; + +out_fail: + + mptctl_remove(pdev); + return err; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2923,8 +2924,7 @@ static int __init mptctl_init(void) * Install our handler */ ++where; - mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER); - if (!mptctl_id || mptctl_id >= MPT_MAX_PROTOCOL_DRIVERS) { + if ((mptctl_id = mpt_register(mptctl_reply, MPTCTL_DRIVER)) < 0) { printk(KERN_ERR MYNAM ": ERROR: Failed to register with Fusion MPT base driver\n"); misc_deregister(&mptctl_miscdev); err = -EBUSY; diff --git a/trunk/drivers/message/fusion/mptctl.h b/trunk/drivers/message/fusion/mptctl.h index 2c1890127e15..180b3c156247 100644 --- a/trunk/drivers/message/fusion/mptctl.h +++ b/trunk/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 Fusion MPT (Message Passing Technology) firmware. + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ diff --git a/trunk/drivers/message/fusion/mptfc.c b/trunk/drivers/message/fusion/mptfc.c index 3cdd4e962115..8422c25e4a3e 100644 --- a/trunk/drivers/message/fusion/mptfc.c +++ b/trunk/drivers/message/fusion/mptfc.c @@ -1,9 +1,9 @@ /* * linux/drivers/message/fusion/mptfc.c - * For use with LSI PCI chip/adapter(s) - * running LSI Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic 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 u8 mptfcDoneCtx = MPT_MAX_PROTOCOL_DRIVERS; -static u8 mptfcTaskCtx = MPT_MAX_PROTOCOL_DRIVERS; -static u8 mptfcInternalCtx = MPT_MAX_PROTOCOL_DRIVERS; +static int mptfcDoneCtx = -1; +static int mptfcTaskCtx = -1; +static int mptfcInternalCtx = -1; /* Used only for internal commands */ static int mptfc_target_alloc(struct scsi_target *starget); static int mptfc_slave_alloc(struct scsi_device *sdev); @@ -194,36 +194,37 @@ 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 = shost_priv(SCpnt->device->host); - ioc = hd->ioc; + hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; 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 (ioc, printk(MYIOC_s_DEBUG_FMT + dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT "mptfc_block_error_handler.%d: %d:%d, port status is " "DID_IMM_RETRY, deferring %s recovery.\n", - ioc->name, ioc->sh->host_no, - SCpnt->device->id, SCpnt->device->lun, caller)); + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, + ((MPT_SCSI_HOST *) shost->hostdata)->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 (ioc, printk(MYIOC_s_DEBUG_FMT + dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT "%s.%d: %d:%d, failing recovery, " - "port state %d, vdevice %p.\n", caller, - ioc->name, ioc->sh->host_no, - SCpnt->device->id, SCpnt->device->lun, ready, + "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, SCpnt->device->hostdata)); return FAILED; } - dfcprintk (ioc, printk(MYIOC_s_DEBUG_FMT + dfcprintk (hd->ioc, printk(MYIOC_s_DEBUG_FMT "%s.%d: %d:%d, executing recovery.\n", caller, - ioc->name, ioc->sh->host_no, - SCpnt->device->id, SCpnt->device->lun)); + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->name, + ((MPT_SCSI_HOST *) shost->hostdata)->ioc->sh->host_no, + SCpnt->device->id,SCpnt->device->lun)); return (*func)(SCpnt); } @@ -469,7 +470,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 vdevice from vtarget. + * slave_alloc will fill in vdev from vtarget. */ if (ri->starget) { vtarget = ri->starget->hostdata; @@ -601,10 +602,10 @@ mptfc_slave_alloc(struct scsi_device *sdev) { MPT_SCSI_HOST *hd; VirtTarget *vtarget; - VirtDevice *vdevice; + VirtDevice *vdev; struct scsi_target *starget; struct fc_rport *rport; - MPT_ADAPTER *ioc; + starget = scsi_target(sdev); rport = starget_to_rport(starget); @@ -612,32 +613,31 @@ mptfc_slave_alloc(struct scsi_device *sdev) if (!rport || fc_remote_port_chkready(rport)) return -ENXIO; - hd = shost_priv(sdev->host); - ioc = hd->ioc; + hd = (MPT_SCSI_HOST *)sdev->host->hostdata; - vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdevice) { + vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", - ioc->name, sizeof(VirtDevice)); + hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - sdev->hostdata = vdevice; + sdev->hostdata = vdev; vtarget = starget->hostdata; if (vtarget->num_luns == 0) { - vtarget->ioc_id = ioc->id; + vtarget->ioc_id = hd->ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; } - vdevice->vtarget = vtarget; - vdevice->lun = sdev->lun; + vdev->vtarget = vtarget; + vdev->lun = sdev->lun; vtarget->num_luns++; - mptfc_dump_lun_info(ioc, rport, sdev, vtarget); + mptfc_dump_lun_info(hd->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 *vdevice = SCpnt->device->hostdata; + VirtDevice *vdev = SCpnt->device->hostdata; - if (!vdevice || !vdevice->vtarget) { + if (!vdev || !vdev->vtarget) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; @@ -674,50 +674,6 @@ mptfc_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) return mptscsih_qcmd(SCpnt,done); } -/* - * 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 @@ -817,7 +773,6 @@ 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); @@ -1067,18 +1022,6 @@ 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) { @@ -1220,7 +1163,6 @@ 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); @@ -1276,21 +1218,20 @@ mptfc_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_unlock_irqrestore(&ioc->FreeQlock, flags); - hd = shost_priv(sh); + hd = (MPT_SCSI_HOST *) sh->hostdata; hd->ioc = ioc; /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); - if (!ioc->ScsiLookup) { + hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!hd->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, ioc->ScsiLookup)); + ioc->name, hd->ScsiLookup)); /* Clear the TM flags */ @@ -1321,8 +1262,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(MYIOC_s_ERR_FMT - "scsi_add_host failed\n", ioc->name)); + dprintk(ioc, printk(KERN_ERR MYNAM + "scsi_add_host failed\n")); goto out_mptfc_probe; } @@ -1384,7 +1325,7 @@ mptfc_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) ioc->name, event)); if (ioc->sh == NULL || - ((hd = shost_priv(ioc->sh)) == NULL)) + ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) return 1; switch (event) { @@ -1396,14 +1337,6 @@ 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/trunk/drivers/message/fusion/mptlan.c b/trunk/drivers/message/fusion/mptlan.c index 7950fc678ed1..3da4c37846ec 100644 --- a/trunk/drivers/message/fusion/mptlan.c +++ b/trunk/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 Fibre Channel PCI chip/adapters - * running LSI Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Logic Fibre Channel PCI chip/adapters + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 2000-2007 LSI Corporation + * Copyright (c) 2000-2007 LSI Logic 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 u8 LanCtx = MPT_MAX_PROTOCOL_DRIVERS; +static int LanCtx = -1; static u32 max_buckets_out = 127; static u32 tx_max_out_p = 127 - 16; @@ -164,6 +164,12 @@ static struct NAA_Hosed *mpt_bad_naa = NULL; 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. @@ -1224,8 +1230,6 @@ 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; @@ -1347,11 +1351,10 @@ 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; - struct mpt_lan_priv *priv; + struct net_device *dev = alloc_fcdev(sizeof(struct mpt_lan_priv)); + struct mpt_lan_priv *priv = NULL; u8 HWaddr[FC_ALEN], *a; - dev = alloc_fcdev(sizeof(struct mpt_lan_priv)); if (!dev) return NULL; @@ -1363,6 +1366,7 @@ 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; @@ -1387,6 +1391,8 @@ 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; @@ -1502,6 +1508,9 @@ 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)) { @@ -1522,9 +1531,10 @@ static void __exit mpt_lan_exit(void) mpt_device_driver_deregister(MPTLAN_DRIVER); mpt_reset_deregister(LanCtx); - if (LanCtx) { + if (LanCtx >= 0) { mpt_deregister(LanCtx); - LanCtx = MPT_MAX_PROTOCOL_DRIVERS; + LanCtx = -1; + mpt_lan_index = 0; } } diff --git a/trunk/drivers/message/fusion/mptlan.h b/trunk/drivers/message/fusion/mptlan.h index bafb67fc8181..8d08c2bed24a 100644 --- a/trunk/drivers/message/fusion/mptlan.h +++ b/trunk/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 Fibre Channel PCI chip/adapters - * running LSI Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Logic Fibre Channel PCI chip/adapters + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 2000-2007 LSI Corporation + * Copyright (c) 2000-2007 LSI Logic Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -75,7 +75,7 @@ #include /* Override mptbase.h by pre-defining these! */ -#define MODULEAUTHOR "LSI Corporation" +#define MODULEAUTHOR "LSI Logic Corporation" #include "mptbase.h" diff --git a/trunk/drivers/message/fusion/mptsas.c b/trunk/drivers/message/fusion/mptsas.c index e4c94f93de16..b9c69bff218c 100644 --- a/trunk/drivers/message/fusion/mptsas.c +++ b/trunk/drivers/message/fusion/mptsas.c @@ -1,10 +1,11 @@ /* * linux/drivers/message/fusion/mptsas.c - * For use with LSI PCI chip/adapter(s) - * running LSI Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic Corporation * (mailto:DL-MPTFusionLinux@lsi.com) + * Copyright (c) 2005-2007 Dell */ /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ /* @@ -60,7 +61,6 @@ #include "mptbase.h" #include "mptscsih.h" -#include "mptsas.h" #define my_NAME "Fusion MPT SAS Host driver" @@ -89,35 +89,134 @@ static int max_lun = MPTSAS_MAX_LUN; module_param(max_lun, int, 0); MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); -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 int mptsasDoneCtx = -1; +static int mptsasTaskCtx = -1; +static int mptsasInternalCtx = -1; /* Used only for internal commands */ +static int mptsasMgmtCtx = -1; 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(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))); + 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))); } static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0) @@ -126,41 +225,27 @@ static void mptsas_print_phy_pg0(MPT_ADAPTER *ioc, SasPhyPage0_t *pg0) memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); - 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))); + 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))); } static void mptsas_print_phy_pg1(MPT_ADAPTER *ioc, SasPhyPage1_t *pg1) { - 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)); + 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)); } static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0) @@ -169,53 +254,37 @@ static void mptsas_print_device_pg0(MPT_ADAPTER *ioc, SasDevicePage0_t *pg0) memcpy(&sas_address, &pg0->SASAddress, sizeof(__le64)); - 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)); + 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)); } static void mptsas_print_expander_pg1(MPT_ADAPTER *ioc, SasExpanderPage1_t *pg1) { - 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))); + 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))); } static inline MPT_ADAPTER *phy_to_ioc(struct sas_phy *phy) @@ -285,8 +354,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(MYIOC_s_DEBUG_FMT "%s: [%p]: num_phys=%02d " - "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, port_details, + dsaswideprintk(ioc, printk(KERN_DEBUG "%s: [%p]: num_phys=%02d " + "bitmask=0x%016llX\n", __FUNCTION__, port_details, port_details->num_phys, (unsigned long long) port_details->phy_bitmask)); @@ -313,15 +382,14 @@ 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(MYIOC_s_DEBUG_FMT "sas_rphy_add: rphy=%p\n", - ioc->name, rphy)); + dsaswideprintk(ioc, printk(KERN_DEBUG "sas_rphy_add: rphy=%p\n", rphy)); } if (rphy) { dsaswideprintk(ioc, dev_printk(KERN_DEBUG, - &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)); + &rphy->dev, "add:")); + dsaswideprintk(ioc, printk(KERN_DEBUG "rphy=%p release=%p\n", + rphy, rphy->dev.release)); } } @@ -342,9 +410,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, MYIOC_s_FMT "add:", ioc->name)); - dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "port=%p release=%p\n", - ioc->name, port, port->dev.release)); + &port->dev, "add:")); + dsaswideprintk(ioc, printk(KERN_DEBUG "port=%p release=%p\n", + port, port->dev.release)); } } @@ -395,9 +463,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(MYIOC_s_DEBUG_FMT - "%s: [%p]: deleting phy = %d\n", - ioc->name, __FUNCTION__, port_details, i)); + dsaswideprintk(ioc, printk(KERN_DEBUG + "%s: [%p]: deleting phy = %d\n", + __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)); @@ -411,8 +479,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(MYIOC_s_DEBUG_FMT "phy_id=%d sas_address=0x%018llX\n", - ioc->name, i, (unsigned long long)sas_address)); + dsaswideprintk(ioc, printk(KERN_DEBUG "phy_id=%d sas_address=0x%018llX\n", + i, (unsigned long long)sas_address)); if (!sas_address) continue; port_details = phy_info->port_details; @@ -430,9 +498,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(MYIOC_s_DEBUG_FMT "\t\tForming port\n\t\t" + dsaswideprintk(ioc, printk(KERN_DEBUG "\t\tForming port\n\t\t" "phy_id=%d sas_address=0x%018llX\n", - ioc->name, i, (unsigned long long)sas_address)); + i, (unsigned long long)sas_address)); phy_info->port_details = port_details; } @@ -447,9 +515,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(MYIOC_s_DEBUG_FMT + dsaswideprintk(ioc, printk(KERN_DEBUG "\t\tphy_id=%d sas_address=0x%018llX\n", - ioc->name, j, (unsigned long long) + j, (unsigned long long) phy_info_cmp->attached.sas_address)); if (phy_info_cmp->port_details) { port_details->rphy = @@ -481,15 +549,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(MYIOC_s_DEBUG_FMT + dsaswideprintk(ioc, printk(KERN_DEBUG "%s: [%p]: phy_id=%02d num_phys=%02d " - "bitmask=0x%016llX\n", ioc->name, __FUNCTION__, + "bitmask=0x%016llX\n", __FUNCTION__, port_details, i, port_details->num_phys, (unsigned long long)port_details->phy_bitmask)); - 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"\t\tport = %p rphy=%p\n", + port_details->port, port_details->rphy)); } - dsaswideprintk(ioc, printk("\n")); + dsaswideprintk(ioc, printk(KERN_DEBUG"\n")); mutex_unlock(&ioc->sas_topology_mutex); } @@ -505,15 +573,15 @@ static VirtTarget * mptsas_find_vtarget(MPT_ADAPTER *ioc, u8 channel, u8 id) { struct scsi_device *sdev; - VirtDevice *vdevice; + VirtDevice *vdev; VirtTarget *vtarget = NULL; shost_for_each_device(sdev, ioc->sh) { - if ((vdevice = sdev->hostdata) == NULL) + if ((vdev = sdev->hostdata) == NULL) continue; - if (vdevice->vtarget->id == id && - vdevice->vtarget->channel == channel) - vtarget = vdevice->vtarget; + if (vdev->vtarget->id == id && + vdev->vtarget->channel == channel) + vtarget = vdev->vtarget; } return vtarget; } @@ -555,7 +623,13 @@ mptsas_target_reset(MPT_ADAPTER *ioc, u8 channel, u8 id) DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)mf); - mpt_put_msg_frame_hi_pri(ioc->TaskCtx, ioc, 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; + } return 1; } @@ -575,7 +649,7 @@ static void mptsas_target_reset_queue(MPT_ADAPTER *ioc, EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *sas_event_data) { - MPT_SCSI_HOST *hd = shost_priv(ioc->sh); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; VirtTarget *vtarget = NULL; struct mptsas_target_reset_event *target_reset_list; u8 id, channel; @@ -622,7 +696,7 @@ mptsas_target_reset_queue(MPT_ADAPTER *ioc, static void mptsas_dev_reset_complete(MPT_ADAPTER *ioc) { - MPT_SCSI_HOST *hd = shost_priv(ioc->sh); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; struct list_head *head = &hd->target_reset_list; struct mptsas_target_reset_event *target_reset_list; struct mptsas_hotplug_event *ev; @@ -739,7 +813,7 @@ mptsas_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) if (!ioc->sh || !ioc->sh->hostdata) goto out; - hd = shost_priv(ioc->sh); + hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; if (!hd->ioc) goto out; @@ -839,20 +913,19 @@ static int mptsas_target_alloc(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(&starget->dev); - MPT_SCSI_HOST *hd = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; 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 = ioc->id; + vtarget->ioc_id = hd->ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; id = starget->id; channel = 0; @@ -861,15 +934,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 < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) - if (id == ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID) - channel = ioc->raid_data.pIocPg2->RaidVolume[i].VolumeBus; + 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; goto out; } rphy = dev_to_rphy(starget->dev.parent); - mutex_lock(&ioc->sas_topology_mutex); - list_for_each_entry(p, &ioc->sas_topology, list) { + mutex_lock(&hd->ioc->sas_topology_mutex); + list_for_each_entry(p, &hd->ioc->sas_topology, list) { for (i = 0; i < p->num_phys; i++) { if (p->phy_info[i].attached.sas_address != rphy->identify.sas_address) @@ -881,18 +954,18 @@ mptsas_target_alloc(struct scsi_target *starget) /* * Exposing hidden raid components */ - if (mptscsih_is_phys_disk(ioc, channel, id)) { - id = mptscsih_raid_id_to_num(ioc, + if (mptscsih_is_phys_disk(hd->ioc, channel, id)) { + id = mptscsih_raid_id_to_num(hd->ioc, channel, id); vtarget->tflags |= MPT_TARGET_FLAGS_RAID_COMPONENT; p->phy_info[i].attached.phys_disk_num = id; } - mutex_unlock(&ioc->sas_topology_mutex); + mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; } } - mutex_unlock(&ioc->sas_topology_mutex); + mutex_unlock(&hd->ioc->sas_topology_mutex); kfree(vtarget); return -ENXIO; @@ -908,11 +981,10 @@ static void mptsas_target_destroy(struct scsi_target *starget) { struct Scsi_Host *host = dev_to_shost(&starget->dev); - MPT_SCSI_HOST *hd = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; struct sas_rphy *rphy; struct mptsas_portinfo *p; int i; - MPT_ADAPTER *ioc = hd->ioc; if (!starget->hostdata) return; @@ -921,7 +993,7 @@ mptsas_target_destroy(struct scsi_target *starget) goto out; rphy = dev_to_rphy(starget->dev.parent); - list_for_each_entry(p, &ioc->sas_topology, list) { + list_for_each_entry(p, &hd->ioc->sas_topology, list) { for (i = 0; i < p->num_phys; i++) { if (p->phy_info[i].attached.sas_address != rphy->identify.sas_address) @@ -941,62 +1013,61 @@ static int mptsas_slave_alloc(struct scsi_device *sdev) { struct Scsi_Host *host = sdev->host; - MPT_SCSI_HOST *hd = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; struct sas_rphy *rphy; struct mptsas_portinfo *p; - VirtDevice *vdevice; + VirtDevice *vdev; struct scsi_target *starget; int i; - MPT_ADAPTER *ioc = hd->ioc; - vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdevice) { + vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { printk(MYIOC_s_ERR_FMT "slave_alloc kzalloc(%zd) FAILED!\n", - ioc->name, sizeof(VirtDevice)); + hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } starget = scsi_target(sdev); - vdevice->vtarget = starget->hostdata; + vdev->vtarget = starget->hostdata; if (sdev->channel == MPTSAS_RAID_CHANNEL) goto out; rphy = dev_to_rphy(sdev->sdev_target->dev.parent); - mutex_lock(&ioc->sas_topology_mutex); - list_for_each_entry(p, &ioc->sas_topology, list) { + mutex_lock(&hd->ioc->sas_topology_mutex); + list_for_each_entry(p, &hd->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; - vdevice->lun = sdev->lun; + vdev->lun = sdev->lun; /* * Exposing hidden raid components */ - if (mptscsih_is_phys_disk(ioc, + if (mptscsih_is_phys_disk(hd->ioc, p->phy_info[i].attached.channel, p->phy_info[i].attached.id)) sdev->no_uld_attach = 1; - mutex_unlock(&ioc->sas_topology_mutex); + mutex_unlock(&hd->ioc->sas_topology_mutex); goto out; } } - mutex_unlock(&ioc->sas_topology_mutex); + mutex_unlock(&hd->ioc->sas_topology_mutex); - kfree(vdevice); + kfree(vdev); return -ENXIO; out: - vdevice->vtarget->num_luns++; - sdev->hostdata = vdevice; + vdev->vtarget->num_luns++; + sdev->hostdata = vdev; return 0; } static int mptsas_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) { - VirtDevice *vdevice = SCpnt->device->hostdata; + VirtDevice *vdev = SCpnt->device->hostdata; - if (!vdevice || !vdevice->vtarget || vdevice->vtarget->deleted) { + if (!vdev || !vdev->vtarget || vdev->vtarget->deleted) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; @@ -1168,8 +1239,10 @@ 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(MYIOC_s_INFO_FMT "%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", - ioc->name, __FUNCTION__, reply->IOCStatus, reply->IOCLogInfo); + printk("%s: IOCStatus=0x%X IOCLogInfo=0x%X\n", + __FUNCTION__, + reply->IOCStatus, + reply->IOCLogInfo); error = -ENXIO; goto out_unlock; } @@ -1255,16 +1328,16 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, u64 sas_address = 0; if (!rsp) { - printk(MYIOC_s_ERR_FMT "%s: the smp response space is missing\n", - ioc->name, __FUNCTION__); + printk(KERN_ERR "%s: the smp response space is missing\n", + __FUNCTION__); return -EINVAL; } /* do we need to support multiple segments? */ if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { - 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); + 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); return -EINVAL; } @@ -1329,7 +1402,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(MYIOC_s_ERR_FMT "%s: smp timeout!\n", ioc->name, __FUNCTION__); + printk(KERN_ERR "%s: smp timeout!\n", __FUNCTION__); /* On timeout reset the board */ mpt_HardResetHandler(ioc, CAN_SLEEP); ret = -ETIMEDOUT; @@ -1344,8 +1417,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(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n", - ioc->name, __FUNCTION__); + printk(KERN_ERR "%s: smp passthru reply failed to be returned\n", + __FUNCTION__); ret = -ENXIO; } unmap: @@ -1989,12 +2062,12 @@ static int mptsas_probe_one_phy(struct device *dev, goto out; } mptsas_set_port(ioc, phy_info, port); - dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT + dsaswideprintk(ioc, printk(KERN_DEBUG "sas_port_alloc: port=%p dev=%p port_id=%d\n", - ioc->name, port, dev, port->port_identifier)); + port, dev, port->port_identifier)); } - dsaswideprintk(ioc, printk(MYIOC_s_DEBUG_FMT "sas_port_add_phy: phy_id=%d\n", - ioc->name, phy_info->phy_id)); + dsaswideprintk(ioc, printk(KERN_DEBUG "sas_port_add_phy: phy_id=%d\n", + phy_info->phy_id)); sas_port_add_phy(port, phy_info->phy); phy_info->sas_port_add_phy = 0; } @@ -2296,9 +2369,8 @@ mptsas_delete_expander_phys(MPT_ADAPTER *ioc) expander_sas_address) continue; dsaswideprintk(ioc, - dev_printk(KERN_DEBUG, &port->dev, - MYIOC_s_FMT "delete port (%d)\n", ioc->name, - port->port_identifier)); + dev_printk(KERN_DEBUG, &port->dev, + "delete port (%d)\n", port->port_identifier)); sas_port_delete(port); mptsas_port_delete(ioc, phy_info->port_details); } @@ -2541,7 +2613,7 @@ mptsas_adding_inactive_raid_components(MPT_ADAPTER *ioc, u8 channel, u8 id) ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { - printk(MYIOC_s_WARN_FMT "mptsas: lost hotplug event\n", ioc->name); + printk(KERN_WARNING "mptsas: lost hotplug event\n"); goto out; } @@ -2682,8 +2754,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, MYIOC_s_FMT - "delete port (%d)\n", ioc->name, port->port_identifier); + dev_printk(KERN_DEBUG, &port->dev, + "delete port (%d)\n", port->port_identifier); sas_port_delete(port); mptsas_port_delete(ioc, phy_info->port_details); break; @@ -2724,8 +2796,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; } /* @@ -2858,7 +2930,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(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name); + printk(KERN_WARNING "mptsas: lost hotplug event\n"); break; } @@ -2917,7 +2989,7 @@ mptsas_send_raid_event(MPT_ADAPTER *ioc, ev = kzalloc(sizeof(*ev), GFP_ATOMIC); if (!ev) { - printk(MYIOC_s_WARN_FMT "lost hotplug event\n", ioc->name); + printk(KERN_WARNING "mptsas: lost hotplug event\n"); return; } @@ -3216,22 +3288,20 @@ mptsas_probe(struct pci_dev *pdev, const struct pci_device_id *id) sh->sg_tablesize = numSGE; } - hd = shost_priv(sh); + hd = (MPT_SCSI_HOST *) sh->hostdata; hd->ioc = ioc; /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); - if (!ioc->ScsiLookup) { + hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!hd->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, ioc->ScsiLookup)); + ioc->name, hd->ScsiLookup)); /* Clear the TM flags */ @@ -3270,8 +3340,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(MYIOC_s_ERR_FMT - "scsi_add_host failed\n", ioc->name)); + dprintk(ioc, printk(KERN_ERR MYNAM + "scsi_add_host failed\n")); goto out_mptsas_probe; } diff --git a/trunk/drivers/message/fusion/mptsas.h b/trunk/drivers/message/fusion/mptsas.h deleted file mode 100644 index 7c150f50629a..000000000000 --- a/trunk/drivers/message/fusion/mptsas.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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/trunk/drivers/message/fusion/mptscsih.c b/trunk/drivers/message/fusion/mptscsih.c index bdff950a54a1..5431529741ad 100644 --- a/trunk/drivers/message/fusion/mptscsih.c +++ b/trunk/drivers/message/fusion/mptscsih.c @@ -1,9 +1,9 @@ /* * linux/drivers/message/fusion/mptscsih.c - * For use with LSI PCI chip/adapter(s) - * running LSI Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ @@ -80,10 +80,6 @@ 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); @@ -94,6 +90,7 @@ 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); @@ -195,7 +192,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; @@ -206,14 +203,13 @@ 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_ERR_FMT "getFreeChainBuffer failed\n", - ioc->name)); + dfailprintk(ioc, printk(MYIOC_s_DEBUG_FMT "getFreeChainBuffer failed\n", + ioc->name)); } spin_unlock_irqrestore(&ioc->FreeQlock, flags); @@ -423,8 +419,8 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, * out the Address and Flags fields. */ chainSge = (char *) psge; - dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Current buff @ %p (index 0x%x)", - ioc->name, psge, req_idx)); + dsgprintk(ioc, printk(KERN_DEBUG " Current buff @ %p (index 0x%x)", + psge, req_idx)); /* Start the SGE for the next buffer */ @@ -432,8 +428,8 @@ mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt, sgeOffset = 0; sg_done = 0; - dsgprintk(ioc, printk(MYIOC_s_DEBUG_FMT " Chain buff @ %p (index 0x%x)\n", - ioc->name, psge, chain_idx)); + dsgprintk(ioc, printk(KERN_DEBUG " Chain buff @ %p (index 0x%x)\n", + psge, chain_idx)); /* Start the SGE for the next buffer */ @@ -592,17 +588,18 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc } scsi_print_command(sc); - 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), + 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), le32_to_cpu(pScsiReply->TransferCount), sc->result); - printk(MYIOC_s_DEBUG_FMT "\tiocstatus = %s (0x%04x), " + + printk(KERN_DEBUG "\tiocstatus = %s (0x%04x), " "scsi_status = %s (0x%02x), scsi_state = (0x%02x)\n", - ioc->name, desc, ioc_status, desc1, pScsiReply->SCSIStatus, + desc, ioc_status, + desc1, pScsiReply->SCSIStatus, pScsiReply->SCSIState); if (pScsiReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_VALID) { @@ -610,8 +607,9 @@ mptscsih_info_scsiio(MPT_ADAPTER *ioc, struct scsi_cmnd *sc, SCSIIOReply_t * pSc asc = sc->sense_buffer[12]; ascq = sc->sense_buffer[13]; - printk(MYIOC_s_DEBUG_FMT "\t[sense_key,asc,ascq]: " - "[0x%02x,0x%02x,0x%02x]\n", ioc->name, skey, asc, ascq); + printk(KERN_DEBUG "\t[sense_key,asc,ascq]: " + "[0x%02x,0x%02x,0x%02x]\n", + skey, asc, ascq); } /* @@ -619,8 +617,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(MYIOC_s_DEBUG_FMT "response_info = %08xh\n", - ioc->name, le32_to_cpu(pScsiReply->ResponseInfo)); + printk(KERN_DEBUG "response_info = %08xh\n", + le32_to_cpu(pScsiReply->ResponseInfo)); } #endif @@ -647,10 +645,11 @@ 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 *vdevice; + VirtDevice *vdev; VirtTarget *vtarget; - hd = shost_priv(ioc->sh); + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; + 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; @@ -661,11 +660,12 @@ 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, - mptscsih_get_scsi_lookup(ioc, req_idx_MR)); + hd->ScsiLookup[req_idx_MR]); return 0; } - sc = mptscsih_getclear_scsi_lookup(ioc, req_idx); + sc = hd->ScsiLookup[req_idx]; + hd->ScsiLookup[req_idx] = NULL; 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(MYIOC_s_NOTE_FMT "[%d:%d:%d:%d] " - "FCP_ResponseInfo=%08xh\n", ioc->name, + printk(KERN_NOTICE "[%d:%d:%d:%d] " + "FCP_ResponseInfo=%08xh\n", 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]++; - vdevice = sc->device->hostdata; - if (!vdevice) + vdev = sc->device->hostdata; + if (!vdev) break; - vtarget = vdevice->vtarget; + vtarget = vdev->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(MYIOC_s_DEBUG_FMT + dreplyprintk(ioc, printk(KERN_DEBUG "RESIDUAL_MISMATCH: result=%x on channel=%d id=%d\n", - ioc->name, sc->result, sc->device->channel, sc->device->id)); + sc->result, sc->device->channel, sc->device->id)); break; case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: /* 0x0045 */ @@ -858,11 +858,9 @@ mptscsih_io_done(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) } - 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)); + 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)); /* Report Queue Full */ @@ -971,32 +969,48 @@ static void mptscsih_flush_running_cmds(MPT_SCSI_HOST *hd) { MPT_ADAPTER *ioc = hd->ioc; - struct scsi_cmnd *sc; - SCSIIORequest_t *mf = NULL; + struct scsi_cmnd *SCpnt; + MPT_FRAME_HDR *mf; int ii; - int channel, id; + int max = ioc->req_depth; - 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); + 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; + + SCpnt->scsi_done(SCpnt); /* Issue the command callback */ + } } + + return; } /* @@ -1018,16 +1032,17 @@ 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; - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - for (ii = 0; ii < ioc->req_depth; ii++) { - if ((sc = ioc->ScsiLookup[ii]) != NULL) { + 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) { - mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(ioc, ii); + mf = (SCSIIORequest_t *)MPT_INDEX_2_MFPTR(hd->ioc, ii); if (mf == NULL) continue; /* If the device is a hidden raid component, then its @@ -1044,23 +1059,22 @@ 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, MYIOC_s_FMT "completing cmds: fw_channel %d," - "fw_id %d, sc=%p, mf = %p, idx=%x\n", ioc->name, vdevice->vtarget->channel, + sdev_printk(KERN_INFO, sc->device, "completing cmds: fw_channel %d," + "fw_id %d, sc=%p, mf = %p, idx=%x\n", 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; } @@ -1083,18 +1097,17 @@ 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 = shost_priv(sc->device->host)) == NULL) + if ((hd = (MPT_SCSI_HOST *)sc->device->host->hostdata) == NULL) return; - ioc = hd->ioc; + if (time - hd->last_queue_full > 10 * HZ) { - dprintk(ioc, printk(MYIOC_s_WARN_FMT "Device (%d:%d:%d) reported QUEUE_FULL!\n", - ioc->name, 0, sc->device->id, sc->device->lun)); + 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)); hd->last_queue_full = time; } } @@ -1121,28 +1134,28 @@ mptscsih_remove(struct pci_dev *pdev) scsi_remove_host(host); - if((hd = shost_priv(host)) == NULL) + if((hd = (MPT_SCSI_HOST *)host->hostdata) == NULL) return; mptscsih_shutdown(pdev); sz1=0; - if (ioc->ScsiLookup != NULL) { - sz1 = ioc->req_depth * sizeof(void *); - kfree(ioc->ScsiLookup); - ioc->ScsiLookup = NULL; + if (hd->ScsiLookup != NULL) { + sz1 = hd->ioc->req_depth * sizeof(void *); + kfree(hd->ScsiLookup); + hd->ScsiLookup = NULL; } - dprintk(ioc, printk(MYIOC_s_DEBUG_FMT + dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Free'd ScsiLookup (%d) memory\n", - ioc->name, sz1)); + hd->ioc->name, sz1)); kfree(hd->info_kbuf); /* NULL the Scsi_Host pointer */ - ioc->sh = NULL; + hd->ioc->sh = NULL; scsi_host_put(host); @@ -1158,6 +1171,15 @@ 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 @@ -1203,7 +1225,7 @@ mptscsih_info(struct Scsi_Host *SChost) MPT_SCSI_HOST *h; int size = 0; - h = shost_priv(SChost); + h = (MPT_SCSI_HOST *)SChost->hostdata; if (h) { if (h->info_kbuf == NULL) @@ -1297,7 +1319,7 @@ int mptscsih_proc_info(struct Scsi_Host *host, char *buffer, char **start, off_t offset, int length, int func) { - MPT_SCSI_HOST *hd = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; int size = 0; @@ -1336,7 +1358,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) MPT_SCSI_HOST *hd; MPT_FRAME_HDR *mf; SCSIIORequest_t *pScsiReq; - VirtDevice *vdevice = SCpnt->device->hostdata; + VirtDevice *vdev = SCpnt->device->hostdata; int lun; u32 datalen; u32 scsictl; @@ -1346,7 +1368,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) int ii; MPT_ADAPTER *ioc; - hd = shost_priv(SCpnt->device->host); + hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; ioc = hd->ioc; lun = SCpnt->device->lun; SCpnt->scsi_done = done; @@ -1363,7 +1385,7 @@ mptscsih_qcmd(struct scsi_cmnd *SCpnt, void (*done)(struct scsi_cmnd *)) /* * Put together a MPT SCSI request... */ - if ((mf = mpt_get_msg_frame(ioc->DoneCtx, ioc)) == NULL) { + if ((mf = mpt_get_msg_frame(hd->ioc->DoneCtx, hd->ioc)) == NULL) { dprintk(ioc, printk(MYIOC_s_WARN_FMT "QueueCmd, no msg frames!!\n", ioc->name)); return SCSI_MLQUEUE_HOST_BUSY; @@ -1393,8 +1415,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 (vdevice - && (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) + if (vdev + && (vdev->vtarget->tflags & MPT_TARGET_FLAGS_Q_YES) && (SCpnt->device->tagged_supported)) { scsictl = scsidir | MPI_SCSIIO_CONTROL_SIMPLEQ; } else { @@ -1403,10 +1425,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) vdevice->vtarget->id; - pScsiReq->Bus = vdevice->vtarget->channel; + pScsiReq->TargetID = (u8) vdev->vtarget->id; + pScsiReq->Bus = vdev->vtarget->channel; pScsiReq->ChainOffset = 0; - if (vdevice->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) + if (vdev->vtarget->tflags & MPT_TARGET_FLAGS_RAID_COMPONENT) pScsiReq->Function = MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; else pScsiReq->Function = MPI_FUNCTION_SCSI_IO_REQUEST; @@ -1431,7 +1453,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(ioc->sense_buf_low_dma + pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma + (my_idx * MPT_SENSE_BUFFER_ALLOC)); /* Now add the SG list @@ -1443,22 +1465,23 @@ 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(ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) + if (mptscsih_AddSGE(hd->ioc, SCpnt, pScsiReq, my_idx) != SUCCESS) goto fail; } SCpnt->host_scribble = (unsigned char *)mf; - mptscsih_set_scsi_lookup(ioc, my_idx, SCpnt); + hd->ScsiLookup[my_idx] = SCpnt; - mpt_put_msg_frame(ioc->DoneCtx, ioc, mf); + mpt_put_msg_frame(hd->ioc->DoneCtx, hd->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: - mptscsih_freeChainBuffers(ioc, my_idx); - mpt_free_msg_frame(ioc, mf); + hd->ScsiLookup[my_idx] = NULL; + mptscsih_freeChainBuffers(hd->ioc, my_idx); + mpt_free_msg_frame(hd->ioc, mf); return SCSI_MLQUEUE_HOST_BUSY; } @@ -1567,38 +1590,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(MYIOC_s_DEBUG_FMT "TMHandler abort: " + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: 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(MYIOC_s_DEBUG_FMT "TMHandler target " + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: 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(MYIOC_s_DEBUG_FMT "TMHandler bus reset: " + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: TMHandler bus reset: " "Timed out waiting for last TM (%d) to complete! \n", ioc->name, hd->tmPending)); return FAILED; } } else { - spin_lock_irqsave(&ioc->FreeQlock, flags); + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); hd->tmPending |= (1 << type); - spin_unlock_irqrestore(&ioc->FreeQlock, flags); + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); } - ioc_raw_state = mpt_GetIocState(ioc, 0); + ioc_raw_state = mpt_GetIocState(hd->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(MYIOC_s_WARN_FMT " Issuing HardReset!!\n", ioc->name); + printk(KERN_WARNING " Issuing HardReset!!\n"); if (mpt_HardResetHandler(ioc, CAN_SLEEP) < 0) - printk(MYIOC_s_WARN_FMT "TMHandler: HardReset " - "FAILED!!\n", ioc->name); + printk((KERN_WARNING "TMHandler: HardReset " + "FAILED!!\n")); return FAILED; } @@ -1657,17 +1680,16 @@ 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(ioc->TaskCtx, ioc)) == NULL) { - dfailprintk(ioc, printk(MYIOC_s_ERR_FMT "IssueTaskMgmt, no msg frames!!\n", - ioc->name)); + 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)); return FAILED; } - dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", - ioc->name, mf)); + dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt request @ %p\n", + hd->ioc->name, mf)); /* Format the Request */ @@ -1690,34 +1712,28 @@ mptscsih_IssueTaskMgmt(MPT_SCSI_HOST *hd, u8 type, u8 channel, u8 id, int lun, i pScsiTm->TaskMsgContext = ctx2abort; - dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " - "type=%d\n", ioc->name, ctx2abort, type)); + dtmprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "IssueTaskMgmt: ctx2abort (0x%08x) " + "type=%d\n", hd->ioc->name, ctx2abort, type)); DBG_DUMP_TM_REQUEST_FRAME(ioc, (u32 *)pScsiTm); - 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 ((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(mptscsih_tm_wait_for_completion(hd, timeout) == FAILED) { - 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)); + 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)); goto fail_out; } @@ -1738,7 +1754,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(ioc, mf); + mpt_free_msg_frame(hd->ioc, mf); hd->tmPending = 0; hd->tmState = TM_STATE_NONE; return FAILED; @@ -1781,11 +1797,11 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* If we can't locate our host adapter structure, return FAILED status. */ - if ((hd = shost_priv(SCpnt->device->host)) == NULL) { + if ((hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata) == NULL) { SCpnt->result = DID_RESET << 16; SCpnt->scsi_done(SCpnt); - printk(KERN_ERR MYNAM ": task abort: " - "can't locate host! (sc=%p)\n", SCpnt); + printk(KERN_DEBUG MYNAM ": mptscsih_abort: Can't locate " + "host! (sc=%p)\n", SCpnt); return FAILED; } @@ -1796,9 +1812,8 @@ 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; @@ -1808,9 +1823,8 @@ 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; @@ -1818,12 +1832,12 @@ mptscsih_abort(struct scsi_cmnd * SCpnt) /* Find this command */ - if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(ioc, SCpnt)) < 0) { + if ((scpnt_idx = SCPNT_TO_LOOKUP_IDX(SCpnt)) < 0) { /* Cmd not found in ScsiLookup. * Do OS callback. */ SCpnt->result = DID_RESET << 16; - dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "task abort: " + dtmprintk(ioc, printk(KERN_DEBUG MYNAM ": %s: mptscsih_abort: " "Command not in the active list! (sc=%p)\n", ioc->name, SCpnt)); retval = 0; @@ -1845,7 +1859,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(ioc, scpnt_idx); + mf = MPT_INDEX_2_MFPTR(hd->ioc, scpnt_idx); ctx2abort = mf->u.frame.hwhdr.msgctxu.MsgContext; hd->abortSCpnt = SCpnt; @@ -1854,7 +1868,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(ioc, SCpnt) == scpnt_idx && + if (SCPNT_TO_LOOKUP_IDX(SCpnt) == scpnt_idx && SCpnt->serial_number == sn) retval = FAILED; @@ -1887,9 +1901,9 @@ mptscsih_dev_reset(struct scsi_cmnd * SCpnt) /* If we can't locate our host adapter structure, return FAILED status. */ - if ((hd = shost_priv(SCpnt->device->host)) == NULL){ - printk(KERN_ERR MYNAM ": target reset: " - "Can't locate host! (sc=%p)\n", SCpnt); + 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); return FAILED; } @@ -1945,14 +1959,14 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) { MPT_SCSI_HOST *hd; int retval; - VirtDevice *vdevice; + VirtDevice *vdev; MPT_ADAPTER *ioc; /* If we can't locate our host adapter structure, return FAILED status. */ - if ((hd = shost_priv(SCpnt->device->host)) == NULL){ - printk(KERN_ERR MYNAM ": bus reset: " - "Can't locate host! (sc=%p)\n", SCpnt); + 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 ); return FAILED; } @@ -1964,9 +1978,9 @@ mptscsih_bus_reset(struct scsi_cmnd * SCpnt) if (hd->timeouts < -1) hd->timeouts++; - vdevice = SCpnt->device->hostdata; + vdev = SCpnt->device->hostdata; retval = mptscsih_TMHandler(hd, MPI_SCSITASKMGMT_TASKTYPE_RESET_BUS, - vdevice->vtarget->channel, 0, 0, 0, mptscsih_get_tm_timeout(ioc)); + vdev->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); @@ -1994,9 +2008,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 = shost_priv(SCpnt->device->host)) == NULL){ - printk(KERN_ERR MYNAM ": host reset: " - "Can't locate host! (sc=%p)\n", SCpnt); + 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); return FAILED; } @@ -2007,7 +2021,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(ioc, CAN_SLEEP) < 0) { + if (mpt_HardResetHandler(hd->ioc, CAN_SLEEP) < 0) { retval = FAILED; } else { /* Make sure TM pending is cleared and TM state is set to @@ -2037,18 +2051,17 @@ 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(&ioc->FreeQlock, flags); + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); if (hd->tmState == TM_STATE_NONE) { hd->tmState = TM_STATE_IN_PROGRESS; hd->tmPending = 1; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); status = SUCCESS; break; } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); msleep(250); } while (--loop_count); @@ -2069,16 +2082,15 @@ 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(&ioc->FreeQlock, flags); + spin_lock_irqsave(&hd->ioc->FreeQlock, flags); if(hd->tmPending == 0) { status = SUCCESS; - spin_unlock_irqrestore(&ioc->FreeQlock, flags); + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); break; } - spin_unlock_irqrestore(&ioc->FreeQlock, flags); + spin_unlock_irqrestore(&hd->ioc->FreeQlock, flags); msleep(250); } while (--loop_count); @@ -2160,7 +2172,7 @@ mptscsih_taskmgmt_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *m return 1; } - hd = shost_priv(ioc->sh); + hd = (MPT_SCSI_HOST *)ioc->sh->hostdata; pScsiTmReply = (SCSITaskMgmtReply_t*)mr; pScsiTmReq = (SCSITaskMgmt_t*)mf; tmType = pScsiTmReq->TaskType; @@ -2211,7 +2223,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(MYIOC_s_WARN_FMT " Firmware Reload FAILED!!\n", ioc->name); + printk((KERN_WARNING " Firmware Reload FAILED!!\n")); break; case MPI_SCSITASKMGMT_TASKTYPE_TARGET_RESET: @@ -2354,7 +2366,7 @@ void mptscsih_slave_destroy(struct scsi_device *sdev) { struct Scsi_Host *host = sdev->host; - MPT_SCSI_HOST *hd = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; VirtTarget *vtarget; VirtDevice *vdevice; struct scsi_target *starget; @@ -2381,17 +2393,16 @@ mptscsih_slave_destroy(struct scsi_device *sdev) int mptscsih_change_queue_depth(struct scsi_device *sdev, int qdepth) { - MPT_SCSI_HOST *hd = shost_priv(sdev->host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; VirtTarget *vtarget; struct scsi_target *starget; int max_depth; int tagged; - MPT_ADAPTER *ioc = hd->ioc; starget = scsi_target(sdev); vtarget = starget->hostdata; - if (ioc->bus_type == SPI) { + if (hd->ioc->bus_type == SPI) { if (!(vtarget->tflags & MPT_TARGET_FLAGS_Q_YES)) max_depth = 1; else if (sdev->type == TYPE_DISK && @@ -2426,20 +2437,19 @@ mptscsih_slave_configure(struct scsi_device *sdev) VirtTarget *vtarget; VirtDevice *vdevice; struct scsi_target *starget; - MPT_SCSI_HOST *hd = shost_priv(sh); - MPT_ADAPTER *ioc = hd->ioc; + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sh->hostdata; starget = scsi_target(sdev); vtarget = starget->hostdata; vdevice = sdev->hostdata; - dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "device @ %p, channel=%d, id=%d, lun=%d\n", - ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); - if (ioc->bus_type == SPI) - dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT + hd->ioc->name, sdev, sdev->channel, sdev->id, sdev->lun)); + if (hd->ioc->bus_type == SPI) + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "sdtr %d wdtr %d ppr %d inq length=%d\n", - ioc->name, sdev->sdtr, sdev->wdtr, + hd->ioc->name, sdev->sdtr, sdev->wdtr, sdev->ppr, sdev->inquiry_len)); if (sdev->id > sh->max_id) { @@ -2451,21 +2461,21 @@ mptscsih_slave_configure(struct scsi_device *sdev) vdevice->configured_lun = 1; mptscsih_change_queue_depth(sdev, MPT_SCSI_CMD_PER_DEV_HIGH); - dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Queue depth=%d, tflags=%x\n", - ioc->name, sdev->queue_depth, vtarget->tflags)); + hd->ioc->name, sdev->queue_depth, vtarget->tflags)); - if (ioc->bus_type == SPI) - dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT + if (hd->ioc->bus_type == SPI) + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "negoFlags=%x, maxOffset=%x, SyncFactor=%x\n", - ioc->name, vtarget->negoFlags, vtarget->maxOffset, + hd->ioc->name, vtarget->negoFlags, vtarget->maxOffset, vtarget->minSyncFactor)); slave_configure_exit: - dsprintk(ioc, printk(MYIOC_s_DEBUG_FMT + dsprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "tagged %d, simple %d, ordered %d\n", - ioc->name,sdev->tagged_supported, sdev->simple_tags, + hd->ioc->name,sdev->tagged_supported, sdev->simple_tags, sdev->ordered_tags)); return 0; @@ -2484,15 +2494,14 @@ mptscsih_slave_configure(struct scsi_device *sdev) static void mptscsih_copy_sense_data(struct scsi_cmnd *sc, MPT_SCSI_HOST *hd, MPT_FRAME_HDR *mf, SCSIIOReply_t *pScsiReply) { - VirtDevice *vdevice; + VirtDevice *vdev; SCSIIORequest_t *pReq; u32 sense_count = le32_to_cpu(pScsiReply->SenseCount); - MPT_ADAPTER *ioc = hd->ioc; /* Get target structure */ pReq = (SCSIIORequest_t *) mf; - vdevice = sc->device->hostdata; + vdev = sc->device->hostdata; if (sense_count) { u8 *sense_data; @@ -2500,14 +2509,15 @@ 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 *)ioc->sense_buf_pool + (req_index * MPT_SENSE_BUFFER_ALLOC)); + sense_data = ((u8 *)hd->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 ((ioc->events) && (ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { - if ((sense_data[12] == 0x5D) && (vdevice->vtarget->raidVolume == 0)) { + if ((hd->ioc->events) && (hd->ioc->eventTypes & (1 << MPI_EVENT_SCSI_DEVICE_STATUS_CHANGE))) { + if ((sense_data[12] == 0x5D) && (vdev->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; @@ -2520,116 +2530,36 @@ 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 (ioc->pcidev->vendor == + if (hd->ioc->pcidev->vendor == PCI_VENDOR_ID_IBM) { - mptscsih_issue_sep_command(ioc, - vdevice->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); - vdevice->vtarget->tflags |= + mptscsih_issue_sep_command(hd->ioc, + vdev->vtarget, MPI_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); + vdev->vtarget->tflags |= MPT_TARGET_FLAGS_LED_ON; } } } } else { - dprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n", - ioc->name)); + dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Hmmm... SenseData len=0! (?)\n", + hd->ioc->name)); } } -/** - * 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) -{ - unsigned long flags; - struct scsi_cmnd *scmd; - - 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; -} - -/** - * 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) +SCPNT_TO_LOOKUP_IDX(struct scsi_cmnd *sc) { - unsigned long flags; - int i, index=-1; + MPT_SCSI_HOST *hd; + int i; - 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; + hd = (MPT_SCSI_HOST *) sc->device->host->hostdata; + + for (i = 0; i < hd->ioc->req_depth; i++) { + if (hd->ScsiLookup[i] == sc) { + return i; } } - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return index; + return -1; } /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/ @@ -2638,20 +2568,21 @@ mptscsih_ioc_reset(MPT_ADAPTER *ioc, int reset_phase) { MPT_SCSI_HOST *hd; unsigned long flags; + int ii; - 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"))); + 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"))); /* 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 || shost_priv(ioc->sh) == NULL) + if ((ioc->sh == NULL) || (ioc->sh->hostdata == NULL)) return 0; else - hd = shost_priv(ioc->sh); + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; if (reset_phase == MPT_IOC_SETUP_RESET) { dtmprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Setup-Diag Reset\n", ioc->name)); @@ -2693,6 +2624,11 @@ 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 */ @@ -2739,7 +2675,7 @@ mptscsih_event_process(MPT_ADAPTER *ioc, EventNotificationReply_t *pEvReply) ioc->name, event)); if (ioc->sh == NULL || - ((hd = shost_priv(ioc->sh)) == NULL)) + ((hd = (MPT_SCSI_HOST *)ioc->sh->hostdata) == NULL)) return 1; switch (event) { @@ -2777,8 +2713,7 @@ 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(MYIOC_s_DEBUG_FMT ": Ignoring event (=%02Xh)\n", - ioc->name, event)); + dprintk(ioc, printk(KERN_DEBUG MYNAM ": Ignoring event (=%02Xh)\n", event)); break; } @@ -2818,7 +2753,7 @@ mptscsih_scandv_complete(MPT_ADAPTER *ioc, MPT_FRAME_HDR *mf, MPT_FRAME_HDR *mr) int completionCode; u16 req_idx; - hd = shost_priv(ioc->sh); + hd = (MPT_SCSI_HOST *) ioc->sh->hostdata; if ((mf == NULL) || (mf >= MPT_INDEX_2_MFPTR(ioc, ioc->req_depth))) { @@ -2830,17 +2765,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); - mptscsih_set_scsi_lookup(ioc, req_idx, NULL); + hd->ScsiLookup[req_idx] = NULL; pReq = (SCSIIORequest_t *) mf; if (mf != hd->cmdPtr) { printk(MYIOC_s_WARN_FMT "ScanDvComplete (mf=%p, cmdPtr=%p, idx=%d)\n", - ioc->name, (void *)mf, (void *) hd->cmdPtr, req_idx); + hd->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", - ioc->name, mf, mr, req_idx)); + hd->ioc->name, mf, mr, req_idx)); hd->pLocal = &hd->localReply; hd->pLocal->scsiStatus = 0; @@ -2904,15 +2839,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 *)ioc->sense_buf_pool + + sense_data = ((u8 *)hd->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(MYIOC_s_DEBUG_FMT " Check Condition, sense ptr %p\n", - ioc->name, sense_data)); + ddvprintk(ioc, printk(KERN_DEBUG " Check Condition, sense ptr %p\n", + sense_data)); } else if (pReply->SCSIState & MPI_SCSI_STATE_AUTOSENSE_FAILED) { if (pReq->CDB[0] == INQUIRY) completionCode = MPT_SCANDV_ISSUE_SENSE; @@ -2971,9 +2906,8 @@ void mptscsih_timer_expired(unsigned long data) { MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) data; - MPT_ADAPTER *ioc = hd->ioc; - ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", ioc->name, hd->cmdPtr)); + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired! Cmd %p\n", hd->ioc->name, hd->cmdPtr)); if (hd->cmdPtr) { MPIHeader_t *cmd = (MPIHeader_t *)hd->cmdPtr; @@ -2987,13 +2921,13 @@ mptscsih_timer_expired(unsigned long data) */ } else { /* Perform a FW reload */ - if (mpt_HardResetHandler(ioc, NO_SLEEP) < 0) { - printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", ioc->name); + if (mpt_HardResetHandler(hd->ioc, NO_SLEEP) < 0) { + printk(MYIOC_s_WARN_FMT "Firmware Reload FAILED!\n", hd->ioc->name); } } } else { /* This should NEVER happen */ - printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", ioc->name); + printk(MYIOC_s_WARN_FMT "Null cmdPtr!!!!\n", hd->ioc->name); } /* No more processing. @@ -3001,7 +2935,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(ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", ioc->name)); + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Timer Expired Complete!\n", hd->ioc->name)); return; } @@ -3039,12 +2973,11 @@ 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(ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n", - ioc->name)); + dprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Internal SCSI IO request not allowed in ISR context!\n", + hd->ioc->name)); return -EPERM; } @@ -3145,9 +3078,9 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) /* Get and Populate a free Frame */ - if ((mf = mpt_get_msg_frame(ioc->InternalCtx, ioc)) == NULL) { - dfailprintk(ioc, printk(MYIOC_s_WARN_FMT "No msg frames!\n", - ioc->name)); + 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)); return -EBUSY; } @@ -3186,19 +3119,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(ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n", - ioc->name, cmd)); + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "Untagged! 0x%2x\n", + hd->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(ioc->sense_buf_low_dma + pScsiReq->SenseBufferLowAddr = cpu_to_le32(hd->ioc->sense_buf_low_dma + (my_idx * MPT_SENSE_BUFFER_ALLOC)); - 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)); + 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)); if (dir == MPI_SCSIIO_CONTROL_READ) { mpt_add_sge((char *) &pScsiReq->SGL, @@ -3233,7 +3166,7 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) hd->cmdPtr = mf; add_timer(&hd->timer); - mpt_put_msg_frame(ioc->InternalCtx, ioc, mf); + mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); wait_event(hd->scandv_waitq, hd->scandv_wait_done); if (hd->pLocal) { @@ -3249,8 +3182,8 @@ mptscsih_do_cmd(MPT_SCSI_HOST *hd, INTERNAL_CMD *io) } else { rc = -EFAULT; /* This should never happen. */ - ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n", - ioc->name)); + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "_do_cmd: Null pLocal!!!\n", + hd->ioc->name)); } return rc; @@ -3302,7 +3235,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", @@ -3317,7 +3250,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02x.%02x.%02x.%02x\n", @@ -3332,7 +3265,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%03x\n", ioc->facts.MsgVersion); @@ -3343,7 +3276,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%s\n", ioc->prod_name); @@ -3355,7 +3288,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02xh\n", @@ -3368,7 +3301,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02xh\n",ioc->nvdata_version_default); @@ -3380,7 +3313,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_name); @@ -3391,7 +3324,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_assembly); @@ -3403,7 +3336,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%s\n", ioc->board_tracer); @@ -3415,7 +3348,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); @@ -3427,7 +3360,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); @@ -3439,7 +3372,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->debug_level); @@ -3449,7 +3382,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 = shost_priv(host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)host->hostdata; MPT_ADAPTER *ioc = hd->ioc; int val = 0; diff --git a/trunk/drivers/message/fusion/mptscsih.h b/trunk/drivers/message/fusion/mptscsih.h index d289e97cfe8b..67b088db2f10 100644 --- a/trunk/drivers/message/fusion/mptscsih.h +++ b/trunk/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 Fusion MPT (Message Passing Technology) firmware. + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic Corporation * (mailto:DL-MPTFusionLinux@lsi.com) * */ diff --git a/trunk/drivers/message/fusion/mptspi.c b/trunk/drivers/message/fusion/mptspi.c index 25bcfcf36f2e..8c98420640a5 100644 --- a/trunk/drivers/message/fusion/mptspi.c +++ b/trunk/drivers/message/fusion/mptspi.c @@ -1,9 +1,9 @@ /* * linux/drivers/message/fusion/mptspi.c - * For use with LSI PCI chip/adapter(s) - * running LSI Fusion MPT (Message Passing Technology) firmware. + * For use with LSI Logic PCI chip/adapter(s) + * running LSI Logic Fusion MPT (Message Passing Technology) firmware. * - * Copyright (c) 1999-2007 LSI Corporation + * Copyright (c) 1999-2007 LSI Logic 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 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 */ +static int mptspiDoneCtx = -1; +static int mptspiTaskCtx = -1; +static int mptspiInternalCtx = -1; /* Used only for internal commands */ /** * mptspi_setTargetNegoParms - Update the target negotiation parameters @@ -107,8 +107,7 @@ static void mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, struct scsi_device *sdev) { - MPT_ADAPTER *ioc = hd->ioc; - SpiCfgData *pspi_data = &ioc->spi_data; + SpiCfgData *pspi_data = &hd->ioc->spi_data; int id = (int) target->id; int nvram; u8 width = MPT_NARROW; @@ -139,10 +138,9 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, else { factor = MPT_ULTRA320; if (scsi_device_qas(sdev)) { - ddvprintk(ioc, - printk(MYIOC_s_DEBUG_FMT "Enabling QAS due to " - "byte56=%02x on id=%d!\n", ioc->name, - scsi_device_qas(sdev), id)); + ddvprintk(hd->ioc, + printk(KERN_DEBUG "Enabling QAS due to " + "byte56=%02x on id=%d!\n", scsi_device_qas(sdev), id)); noQas = 0; } if (sdev->type == TYPE_TAPE && @@ -229,8 +227,8 @@ mptspi_setTargetNegoParms(MPT_SCSI_HOST *hd, VirtTarget *target, /* Disable QAS in a mixed configuration case */ - ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "Disabling QAS due to noQas=%02x on id=%d!\n", ioc->name, noQas, id)); + ddvprintk(hd->ioc, printk(KERN_DEBUG + "Disabling QAS due to noQas=%02x on id=%d!\n", noQas, id)); } } @@ -304,7 +302,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); @@ -376,15 +374,14 @@ static int mptspi_is_raid(struct _MPT_SCSI_HOST *hd, u32 id) { int i, rc = 0; - MPT_ADAPTER *ioc = hd->ioc; - if (!ioc->raid_data.pIocPg2) + if (!hd->ioc->raid_data.pIocPg2) goto out; - if (!ioc->raid_data.pIocPg2->NumActiveVolumes) + if (!hd->ioc->raid_data.pIocPg2->NumActiveVolumes) goto out; - for (i=0; i < ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { - if (ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) { + for (i=0; i < hd->ioc->raid_data.pIocPg2->NumActiveVolumes; i++) { + if (hd->ioc->raid_data.pIocPg2->RaidVolume[i].VolumeID == id) { rc = 1; goto out; } @@ -397,19 +394,17 @@ 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 = shost_priv(shost); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; 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 = ioc->id; + vtarget->ioc_id = hd->ioc->id; vtarget->tflags = MPT_TARGET_FLAGS_Q_YES; vtarget->id = (u8)starget->id; vtarget->channel = (u8)starget->channel; @@ -417,34 +412,34 @@ static int mptspi_target_alloc(struct scsi_target *starget) starget->hostdata = vtarget; if (starget->channel == 1) { - if (mptscsih_is_phys_disk(ioc, 0, starget->id) == 0) + if (mptscsih_is_phys_disk(hd->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(ioc, 0, + vtarget->id = mptscsih_raid_id_to_num(hd->ioc, 0, starget->id); } if (starget->channel == 0 && mptspi_is_raid(hd, starget->id)) { vtarget->raidVolume = 1; - ddvprintk(ioc, printk(MYIOC_s_DEBUG_FMT - "RAID Volume @ channel=%d id=%d\n", ioc->name, starget->channel, + ddvprintk(hd->ioc, printk(KERN_DEBUG + "RAID Volume @ channel=%d id=%d\n", starget->channel, 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]; + 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]; 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) = ioc->spi_data.minSyncFactor; - spi_max_width(starget) = ioc->spi_data.maxBusWidth; + spi_min_period(starget) = hd->ioc->spi_data.minSyncFactor; + spi_max_width(starget) = hd->ioc->spi_data.maxBusWidth; } - spi_max_offset(starget) = ioc->spi_data.maxSyncOffset; + spi_max_offset(starget) = hd->ioc->spi_data.maxSyncOffset; spi_offset(starget) = 0; mptspi_write_width(starget, 0); @@ -514,10 +509,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 = shost_priv(shost); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; struct _MPT_ADAPTER *ioc = hd->ioc; - struct _CONFIG_PAGE_SCSI_DEVICE_0 *spi_dev_pg0; - dma_addr_t spi_dev_pg0_dma; + struct _CONFIG_PAGE_SCSI_DEVICE_0 *pg0; + dma_addr_t pg0_dma; int size; struct _x_config_parms cfg; struct _CONFIG_PAGE_HEADER hdr; @@ -535,10 +530,9 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, size += 2048; */ - 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); + 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"); return -EINVAL; } @@ -552,22 +546,22 @@ static int mptspi_read_spi_device_pg0(struct scsi_target *starget, memset(&cfg, 0, sizeof(cfg)); cfg.cfghdr.hdr = &hdr; - cfg.physAddr = spi_dev_pg0_dma; + cfg.physAddr = 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, MYIOC_s_FMT "mpt_config failed\n", ioc->name); + starget_printk(KERN_ERR, starget, "mpt_config failed\n"); goto out_free; } err = 0; - memcpy(pass_pg0, spi_dev_pg0, size); + memcpy(pass_pg0, pg0, size); - mptspi_print_read_nego(hd, starget, le32_to_cpu(spi_dev_pg0->NegotiatedParameters)); + mptspi_print_read_nego(hd, starget, le32_to_cpu(pg0->NegotiatedParameters)); out_free: - dma_free_coherent(&ioc->pcidev->dev, size, spi_dev_pg0, spi_dev_pg0_dma); + dma_free_coherent(&ioc->pcidev->dev, size, pg0, pg0_dma); return err; } @@ -594,11 +588,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 spi_dev_pg0; + struct _CONFIG_PAGE_SCSI_DEVICE_0 pg0; - mptspi_read_spi_device_pg0(starget, &spi_dev_pg0); + mptspi_read_spi_device_pg0(starget, &pg0); - nego = le32_to_cpu(spi_dev_pg0.NegotiatedParameters); + nego = le32_to_cpu(pg0.NegotiatedParameters); spi_iu(starget) = (nego & MPI_SCSIDEVPAGE0_NP_IU) ? 1 : 0; spi_dt(starget) = (nego & MPI_SCSIDEVPAGE0_NP_DT) ? 1 : 0; @@ -618,13 +612,12 @@ 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(ioc->InternalCtx, ioc)) == NULL) { - ddvprintk(ioc, printk(MYIOC_s_WARN_FMT "_do_raid: no msg frames!\n", - ioc->name)); + 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)); return -EAGAIN; } pReq = (MpiRaidActionRequest_t *)mf; @@ -645,8 +638,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(ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", - ioc->name, pReq->Action, channel, id)); + ddvprintk(hd->ioc, printk(MYIOC_s_DEBUG_FMT "RAID Volume action=%x channel=%d id=%d\n", + hd->ioc->name, pReq->Action, channel, id)); hd->pLocal = NULL; hd->timer.expires = jiffies + HZ*10; /* 10 second timeout */ @@ -658,7 +651,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(ioc->InternalCtx, ioc, mf); + mpt_put_msg_frame(hd->ioc->InternalCtx, hd->ioc, mf); wait_event(hd->scandv_waitq, hd->scandv_wait_done); if ((hd->pLocal == NULL) || (hd->pLocal->completion != 0)) @@ -671,7 +664,6 @@ 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 && @@ -681,8 +673,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), MYIOC_s_FMT - "Integrated RAID quiesce failed\n", ioc->name); + starget_printk(KERN_ERR, scsi_target(sdev), + "Integrated RAID quiesce failed\n"); return; } @@ -692,8 +684,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), MYIOC_s_FMT - "Integrated RAID resume failed\n", ioc->name); + starget_printk(KERN_ERR, scsi_target(sdev), + "Integrated RAID resume failed\n"); mptspi_read_parameters(sdev->sdev_target); spi_display_xfer_agreement(sdev->sdev_target); @@ -702,29 +694,28 @@ static void mptspi_dv_device(struct _MPT_SCSI_HOST *hd, static int mptspi_slave_alloc(struct scsi_device *sdev) { - MPT_SCSI_HOST *hd = shost_priv(sdev->host); + MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *)sdev->host->hostdata; VirtTarget *vtarget; - VirtDevice *vdevice; + VirtDevice *vdev; struct scsi_target *starget; - MPT_ADAPTER *ioc = hd->ioc; if (sdev->channel == 1 && - mptscsih_is_phys_disk(ioc, 0, sdev->id) == 0) + mptscsih_is_phys_disk(hd->ioc, 0, sdev->id) == 0) return -ENXIO; - vdevice = kzalloc(sizeof(VirtDevice), GFP_KERNEL); - if (!vdevice) { + vdev = kzalloc(sizeof(VirtDevice), GFP_KERNEL); + if (!vdev) { printk(MYIOC_s_ERR_FMT "slave_alloc kmalloc(%zd) FAILED!\n", - ioc->name, sizeof(VirtDevice)); + hd->ioc->name, sizeof(VirtDevice)); return -ENOMEM; } - vdevice->lun = sdev->lun; - sdev->hostdata = vdevice; + vdev->lun = sdev->lun; + sdev->hostdata = vdev; starget = scsi_target(sdev); vtarget = starget->hostdata; - vdevice->vtarget = vtarget; + vdev->vtarget = vtarget; vtarget->num_luns++; if (sdev->channel == 1) @@ -735,7 +726,8 @@ static int mptspi_slave_alloc(struct scsi_device *sdev) static int mptspi_slave_configure(struct scsi_device *sdev) { - struct _MPT_SCSI_HOST *hd = shost_priv(sdev->host); + struct _MPT_SCSI_HOST *hd = + (struct _MPT_SCSI_HOST *)sdev->host->hostdata; VirtTarget *vtarget = scsi_target(sdev)->hostdata; int ret; @@ -763,25 +755,24 @@ 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 = shost_priv(SCpnt->device->host); - VirtDevice *vdevice = SCpnt->device->hostdata; - MPT_ADAPTER *ioc = hd->ioc; + struct _MPT_SCSI_HOST *hd = (MPT_SCSI_HOST *) SCpnt->device->host->hostdata; + VirtDevice *vdev = SCpnt->device->hostdata; - if (!vdevice || !vdevice->vtarget) { + if (!vdev || !vdev->vtarget) { SCpnt->result = DID_NO_CONNECT << 16; done(SCpnt); return 0; } if (SCpnt->device->channel == 1 && - mptscsih_is_phys_disk(ioc, 0, SCpnt->device->id) == 0) { + mptscsih_is_phys_disk(hd->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(ioc, scsi_print_command(SCpnt)); + ddvprintk(hd->ioc, scsi_print_command(SCpnt)); return mptscsih_qcmd(SCpnt,done); } @@ -838,7 +829,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 = shost_priv(shost); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; struct _MPT_ADAPTER *ioc = hd->ioc; struct _CONFIG_PAGE_SCSI_DEVICE_1 *pg1; dma_addr_t pg1_dma; @@ -856,8 +847,7 @@ 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, MYIOC_s_FMT - "dma_alloc_coherent for parameters failed\n", ioc->name); + starget_printk(KERN_ERR, starget, "dma_alloc_coherent for parameters failed\n"); return -EINVAL; } @@ -886,8 +876,7 @@ 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, MYIOC_s_FMT - "mpt_config failed\n", ioc->name); + starget_printk(KERN_ERR, starget, "mpt_config failed\n"); goto out_free; } err = 0; @@ -1026,7 +1015,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 = shost_priv(shost); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)shost->hostdata; VirtTarget *vtarget = starget->hostdata; u32 nego; @@ -1078,16 +1067,15 @@ 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; - MPT_ADAPTER *ioc = hd->ioc; - struct Scsi_Host *shost = ioc->sh; + struct Scsi_Host *shost = hd->ioc->sh; struct scsi_device *sdev; int disk = wqw->disk; struct _CONFIG_PAGE_IOC_3 *pg3; kfree(wqw); - mpt_findImVolumes(ioc); - pg3 = ioc->raid_data.pIocPg3; + mpt_findImVolumes(hd->ioc); + pg3 = hd->ioc->raid_data.pIocPg3; if (!pg3) return; @@ -1104,25 +1092,24 @@ static void mpt_work_wrapper(struct work_struct *work) if(vtarget->id != disk) continue; - starget_printk(KERN_INFO, vtarget->starget, MYIOC_s_FMT - "Integrated RAID requests DV of new device\n", ioc->name); + starget_printk(KERN_INFO, vtarget->starget, + "Integrated RAID requests DV of new device\n"); mptspi_dv_device(hd, sdev); } - 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); + 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); } 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, ioc->sh, MYIOC_s_FMT - "Failed to act on RAID event for physical disk %d\n", - ioc->name, disk); + shost_printk(KERN_ERR, hd->ioc->sh, + "Failed to act on RAID event for physical disk %d\n", + disk); return; } INIT_WORK(&wqw->work, mpt_work_wrapper); @@ -1136,7 +1123,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 = shost_priv(ioc->sh); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; if (hd && event == MPI_EVENT_INTEGRATED_RAID) { int reason @@ -1203,8 +1190,6 @@ 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 */ @@ -1225,12 +1210,11 @@ 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, ioc->sh) { + shost_for_each_device(sdev, hd->ioc->sh) { if (hd->spi_pending & (1 << sdev->id)) continue; starget = scsi_target(sdev); @@ -1241,7 +1225,7 @@ mptspi_dv_renegotiate_work(struct work_struct *work) mptspi_write_spi_device_pg1(starget, &pg1); } } else { - shost_for_each_device(sdev, ioc->sh) + shost_for_each_device(sdev, hd->ioc->sh) mptspi_dv_device(hd, sdev); } } @@ -1266,7 +1250,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 = shost_priv(ioc->sh); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; int rc; rc = mptscsih_ioc_reset(ioc, reset_phase); @@ -1285,7 +1269,7 @@ static int mptspi_resume(struct pci_dev *pdev) { MPT_ADAPTER *ioc = pci_get_drvdata(pdev); - struct _MPT_SCSI_HOST *hd = shost_priv(ioc->sh); + struct _MPT_SCSI_HOST *hd = (struct _MPT_SCSI_HOST *)ioc->sh->hostdata; int rc; rc = mptscsih_resume(pdev); @@ -1432,7 +1416,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_DEBUG_FMT + dprintk(ioc, printk(MYIOC_s_INFO_FMT "Resetting sg_tablesize to %d from %d\n", ioc->name, numSGE, sh->sg_tablesize)); sh->sg_tablesize = numSGE; @@ -1440,21 +1424,20 @@ mptspi_probe(struct pci_dev *pdev, const struct pci_device_id *id) spin_unlock_irqrestore(&ioc->FreeQlock, flags); - hd = shost_priv(sh); + hd = (MPT_SCSI_HOST *) sh->hostdata; hd->ioc = ioc; /* SCSI needs scsi_cmnd lookup table! * (with size equal to req_depth*PtrSz!) */ - ioc->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); - if (!ioc->ScsiLookup) { + hd->ScsiLookup = kcalloc(ioc->req_depth, sizeof(void *), GFP_ATOMIC); + if (!hd->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, ioc->ScsiLookup)); + ioc->name, hd->ScsiLookup)); /* Clear the TM flags */ @@ -1494,13 +1477,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 (ioc->spi_data.sdp0length != 0) + if (hd->ioc->spi_data.sdp0length != 0) sh->transportt = mptspi_transport_template; error = scsi_add_host (sh, &ioc->pcidev->dev); if(error) { - dprintk(ioc, printk(MYIOC_s_ERR_FMT - "scsi_add_host failed\n", ioc->name)); + dprintk(ioc, printk(KERN_ERR MYNAM + "scsi_add_host failed\n")); goto out_mptspi_probe; } diff --git a/trunk/drivers/s390/scsi/zfcp_aux.c b/trunk/drivers/s390/scsi/zfcp_aux.c index 7507067351bd..90aa53fc4f3e 100644 --- a/trunk/drivers/s390/scsi/zfcp_aux.c +++ b/trunk/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,10 +1038,6 @@ 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); @@ -1062,6 +1058,7 @@ 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)) @@ -1088,8 +1085,6 @@ 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: @@ -1135,8 +1130,6 @@ 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/trunk/drivers/s390/scsi/zfcp_ccw.c b/trunk/drivers/s390/scsi/zfcp_ccw.c index e01cbf152a81..c0d1c0eb3209 100644 --- a/trunk/drivers/s390/scsi/zfcp_ccw.c +++ b/trunk/drivers/s390/scsi/zfcp_ccw.c @@ -148,12 +148,15 @@ 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; + goto out_erp_thread; } retval = zfcp_adapter_scsi_register(adapter); @@ -172,6 +175,8 @@ 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; @@ -194,6 +199,7 @@ 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/trunk/drivers/s390/scsi/zfcp_def.h b/trunk/drivers/s390/scsi/zfcp_def.h index 16e5563e0c65..b36dfc40d9fa 100644 --- a/trunk/drivers/s390/scsi/zfcp_def.h +++ b/trunk/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/trunk/drivers/s390/scsi/zfcp_erp.c b/trunk/drivers/s390/scsi/zfcp_erp.c index a6475a2bb8a7..16b4418ab257 100644 --- a/trunk/drivers/s390/scsi/zfcp_erp.c +++ b/trunk/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: - /* Nothing to do if status == ZFCP_ERP_SUCCEEDED */ - if (status != ZFCP_ERP_SUCCEEDED) + if (status == ZFCP_ERP_SUCCEEDED) ; /* no further action */ + else 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); + ret = zfcp_fsf_exchange_port_data(erp_action, adapter, NULL); 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/trunk/drivers/s390/scsi/zfcp_ext.h b/trunk/drivers/s390/scsi/zfcp_ext.h index 8534cf09546c..991d45667a44 100644 --- a/trunk/drivers/s390/scsi/zfcp_ext.h +++ b/trunk/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,11 +82,9 @@ 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_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_exchange_port_data(struct zfcp_erp_action *, + 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/trunk/drivers/s390/scsi/zfcp_fsf.c b/trunk/drivers/s390/scsi/zfcp_fsf.c index ff866ebd44ac..99299976e891 100644 --- a/trunk/drivers/s390/scsi/zfcp_fsf.c +++ b/trunk/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,28 +1941,25 @@ 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; + int retval = 0; /* setup new FSF request */ - retval = zfcp_fsf_req_create(adapter, + retval = zfcp_fsf_req_create(erp_action->adapter, FSF_QTCB_EXCHANGE_CONFIG_DATA, ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp, + erp_action->adapter->pool.fsf_req_erp, &lock_flags, &fsf_req); - if (retval) { + if (retval < 0) { 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; + zfcp_get_busid_by_adapter(erp_action->adapter)); + goto out; } 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 | @@ -1974,71 +1971,23 @@ 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(adapter)); + 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_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)); - - return retval; -} - -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; + ZFCP_LOG_DEBUG("exchange configuration data request initiated " + "(adapter %s)\n", + zfcp_get_busid_by_adapter(erp_action->adapter)); - 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, + out: + write_unlock_irqrestore(&erp_action->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; } @@ -2067,17 +2016,11 @@ 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) = @@ -2110,8 +2053,7 @@ 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" @@ -2148,7 +2090,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 @@ -2183,7 +2125,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 " @@ -2196,8 +2138,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 " @@ -2237,8 +2179,7 @@ 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); @@ -2246,7 +2187,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; } @@ -2256,118 +2197,74 @@ 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) +zfcp_fsf_exchange_port_data(struct zfcp_erp_action *erp_action, + struct zfcp_adapter *adapter, + struct fsf_qtcb_bottom_port *data) { volatile struct qdio_buffer_element *sbale; - struct zfcp_fsf_req *fsf_req; - struct zfcp_adapter *adapter = erp_action->adapter; + struct zfcp_fsf_req *fsf_req; unsigned long lock_flags; - int retval; + int retval = 0; 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, - ZFCP_REQ_AUTO_CLEANUP, - adapter->pool.fsf_req_erp, - &lock_flags, &fsf_req); - if (retval) { + erp_action ? ZFCP_REQ_AUTO_CLEANUP : 0, + NULL, &lock_flags, &fsf_req); + if (retval < 0) { 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; - erp_action->fsf_req = fsf_req; - fsf_req->erp_action = erp_action; - zfcp_erp_start_timer(fsf_req); + 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); 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); - 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)); + if (erp_action) + erp_action->fsf_req = NULL; 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 (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 + if (!erp_action) { 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; } @@ -2380,16 +2277,18 @@ static void zfcp_fsf_exchange_port_evaluate(struct zfcp_fsf_req *fsf_req, int xchg_ok) { struct zfcp_adapter *adapter; - struct fsf_qtcb_bottom_port *bottom; + struct fsf_qtcb *qtcb; + struct fsf_qtcb_bottom_port *bottom, *data; struct Scsi_Host *shost; adapter = fsf_req->adapter; - bottom = &fsf_req->qtcb->bottom.port; + qtcb = fsf_req->qtcb; + bottom = &qtcb->bottom.port; shost = adapter->scsi_host; - if (fsf_req->data) - memcpy((struct fsf_qtcb_bottom_port*) fsf_req->data, bottom, - sizeof(struct fsf_qtcb_bottom_port)); + data = (struct fsf_qtcb_bottom_port*) fsf_req->data; + if (data) + memcpy(data, bottom, sizeof(struct fsf_qtcb_bottom_port)); if (adapter->connection_features & FSF_FEATURE_NPIV_MODE) fc_host_permanent_port_name(shost) = bottom->wwpn; @@ -2437,10 +2336,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) @@ -2501,7 +2400,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) @@ -3103,7 +3002,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) @@ -3366,7 +3265,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 @@ -3687,17 +3586,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; } @@ -3828,7 +3727,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) @@ -4065,7 +3964,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) @@ -4293,7 +4192,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) @@ -4736,7 +4635,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/trunk/drivers/s390/scsi/zfcp_fsf.h b/trunk/drivers/s390/scsi/zfcp_fsf.h index 8cce5cc11d50..71186618947c 100644 --- a/trunk/drivers/s390/scsi/zfcp_fsf.h +++ b/trunk/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/trunk/drivers/s390/scsi/zfcp_qdio.c b/trunk/drivers/s390/scsi/zfcp_qdio.c index 3f105fdcf239..c6899efdc8f6 100644 --- a/trunk/drivers/s390/scsi/zfcp_qdio.c +++ b/trunk/drivers/s390/scsi/zfcp_qdio.c @@ -174,9 +174,10 @@ 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/trunk/drivers/s390/scsi/zfcp_scsi.c b/trunk/drivers/s390/scsi/zfcp_scsi.c index abae2027f7e5..ad7eb4a9261c 100644 --- a/trunk/drivers/s390/scsi/zfcp_scsi.c +++ b/trunk/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,12 +189,13 @@ 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 @@ -360,11 +361,12 @@ 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; @@ -372,7 +374,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 @@ -731,7 +733,7 @@ zfcp_get_fc_host_stats(struct Scsi_Host *shost) if (!data) return NULL; - ret = zfcp_fsf_exchange_port_data_sync(adapter, data); + ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); if (ret) { kfree(data); return NULL; /* XXX return zeroed fc_stats? */ @@ -761,7 +763,7 @@ zfcp_reset_fc_host_stats(struct Scsi_Host *shost) if (!data) return; - ret = zfcp_fsf_exchange_port_data_sync(adapter, data); + ret = zfcp_fsf_exchange_port_data(NULL, adapter, data); if (ret) { kfree(data); } else { @@ -800,7 +802,6 @@ 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/trunk/drivers/s390/scsi/zfcp_sysfs_unit.c b/trunk/drivers/s390/scsi/zfcp_sysfs_unit.c index 63f75ee95c33..81a484175863 100644 --- a/trunk/drivers/s390/scsi/zfcp_sysfs_unit.c +++ b/trunk/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/trunk/drivers/scsi/Kconfig b/trunk/drivers/scsi/Kconfig index 30905cebefbb..6f2c71ef47ee 100644 --- a/trunk/drivers/scsi/Kconfig +++ b/trunk/drivers/scsi/Kconfig @@ -272,13 +272,6 @@ 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 @@ -296,20 +289,6 @@ 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 @@ -523,6 +502,7 @@ 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 @@ -544,32 +524,19 @@ config SCSI_IN2000 module will be called in2000. config SCSI_ARCMSR - tristate "ARECA (ARC11xx/12xx/13xx/16xx) SATA/SAS RAID Host Adapter" + tristate "ARECA ARC11X0[PCI-X]/ARC12X0[PCI-EXPRESS] SATA-RAID support" depends on PCI && SCSI help - This driver supports all of ARECA's SATA/SAS RAID controller cards. + This driver supports all of ARECA's SATA RAID controller cards. This is an ARECA-maintained driver by Erich Chen. - If you have any problems, please mail to: . + If you have any problems, please mail to: < erich@areca.com.tw > Areca supports Linux RAID config tools. - 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 . - To enable this function, choose Y here. - source "drivers/scsi/megaraid/Kconfig.megaraid" config SCSI_HPTIOP @@ -869,7 +836,6 @@ 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 @@ -878,7 +844,7 @@ config SCSI_IBMVSCSI config SCSI_IBMVSCSIS tristate "IBM Virtual SCSI Server support" - depends on PPC_PSERIES && SCSI_SRP && SCSI_SRP_TGT_ATTRS + depends on PPC_PSERIES && SCSI_TGT && SCSI_SRP help This is the SRP target driver for IBM pSeries virtual environments. diff --git a/trunk/drivers/scsi/Makefile b/trunk/drivers/scsi/Makefile index 6141389dcdb2..86a7ba7bad63 100644 --- a/trunk/drivers/scsi/Makefile +++ b/trunk/drivers/scsi/Makefile @@ -34,7 +34,6 @@ 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/trunk/drivers/scsi/NCR5380.c b/trunk/drivers/scsi/NCR5380.c index 988f0bc5eda5..f8e449a98d29 100644 --- a/trunk/drivers/scsi/NCR5380.c +++ b/trunk/drivers/scsi/NCR5380.c @@ -1542,7 +1542,9 @@ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) hostdata->connected = cmd; hostdata->busy[cmd->device->id] |= (1 << cmd->device->lun); - initialize_SCp(cmd); + if (cmd->SCp.ptr != (char *)cmd->sense_buffer) { + initialize_SCp(cmd); + } return 0; @@ -2131,7 +2133,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->scsi_done(cmd); + cmd->done(cmd); return; #endif /* @@ -2194,7 +2196,7 @@ static void NCR5380_information_transfer(struct Scsi_Host *instance) { sink = 1; do_abort(instance); cmd->result = DID_ERROR << 16; - cmd->scsi_done(cmd); + cmd->done(cmd); /* XXX - need to source or sink data here, as appropriate */ } else cmd->SCp.this_residual -= transfersize - len; @@ -2278,16 +2280,19 @@ 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 *) @@ -2735,7 +2740,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->scsi_done(tmp); + tmp->done(tmp); return SUCCESS; } #if (NDEBUG & NDEBUG_ABORT) @@ -2800,7 +2805,7 @@ static int NCR5380_abort(Scsi_Cmnd * cmd) { *prev = (Scsi_Cmnd *) tmp->host_scribble; tmp->host_scribble = NULL; tmp->result = DID_ABORT << 16; - tmp->scsi_done(tmp); + tmp->done(tmp); return SUCCESS; } } diff --git a/trunk/drivers/scsi/NCR5380.h b/trunk/drivers/scsi/NCR5380.h index bdc468c9e1d9..bccf13f71532 100644 --- a/trunk/drivers/scsi/NCR5380.h +++ b/trunk/drivers/scsi/NCR5380.h @@ -30,10 +30,6 @@ #include -#ifdef AUTOSENSE -#include -#endif - #define NCR5380_PUBLIC_RELEASE 7 #define NCR53C400_PUBLIC_RELEASE 2 @@ -285,9 +281,6 @@ struct NCR5380_hostdata { unsigned pendingr; unsigned pendingw; #endif -#ifdef AUTOSENSE - struct scsi_eh_save ses; -#endif }; #ifdef __KERNEL__ diff --git a/trunk/drivers/scsi/NCR53C9x.c b/trunk/drivers/scsi/NCR53C9x.c index 96e8e29aa05d..79b4df158140 100644 --- a/trunk/drivers/scsi/NCR53C9x.c +++ b/trunk/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->scsi_done(this); + this->done(this); if(don) esp->dma_ints_on(esp); return SUCCESS; diff --git a/trunk/drivers/scsi/NCR_D700.c b/trunk/drivers/scsi/NCR_D700.c index 9e64b21ef637..3a8089705feb 100644 --- a/trunk/drivers/scsi/NCR_D700.c +++ b/trunk/drivers/scsi/NCR_D700.c @@ -97,6 +97,7 @@ #include #include #include +#include #include #include #include @@ -313,10 +314,10 @@ NCR_D700_probe(struct device *dev) break; } - p = kzalloc(sizeof(*p), GFP_KERNEL); + p = kmalloc(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/trunk/drivers/scsi/a4000t.c b/trunk/drivers/scsi/a4000t.c index d4bda2017746..0c758d1452ba 100644 --- a/trunk/drivers/scsi/a4000t.c +++ b/trunk/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; + struct Scsi_Host * host = NULL; struct NCR_700_Host_Parameters *hostdata; if (!(MACH_IS_AMIGA && AMIGAHW_PRESENT(A4000_SCSI))) @@ -47,11 +47,12 @@ static int __devinit a4000t_probe(struct device *dev) "A4000T builtin SCSI")) goto out; - hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); - if (!hostdata) { + hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + if (hostdata == NULL) { 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/trunk/drivers/scsi/aacraid/aachba.c b/trunk/drivers/scsi/aacraid/aachba.c index 80e448d0f3db..6800e578e4b1 100644 --- a/trunk/drivers/scsi/aacraid/aachba.c +++ b/trunk/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 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 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 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 (!aac_check_reset || + if (!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/trunk/drivers/scsi/aacraid/aacraid.h b/trunk/drivers/scsi/aacraid/aacraid.h index 03b51025a8f4..94727b9375ec 100644 --- a/trunk/drivers/scsi/aacraid/aacraid.h +++ b/trunk/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 aac_check_reset; +extern int check_reset; diff --git a/trunk/drivers/scsi/aacraid/commsup.c b/trunk/drivers/scsi/aacraid/commsup.c index 240a0bb8986f..bb870906b4cf 100644 --- a/trunk/drivers/scsi/aacraid/commsup.c +++ b/trunk/drivers/scsi/aacraid/commsup.c @@ -1372,9 +1372,8 @@ int aac_check_health(struct aac_dev * aac) printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED); - if (!aac_check_reset || - (aac->supplement_adapter_info.SupportedOptions2 & - le32_to_cpu(AAC_OPTION_IGNORE_RESET))) + if (!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/trunk/drivers/scsi/advansys.c b/trunk/drivers/scsi/advansys.c index 9dd3952516c5..79c0b6e37a3b 100644 --- a/trunk/drivers/scsi/advansys.c +++ b/trunk/drivers/scsi/advansys.c @@ -1,27 +1,765 @@ -#define DRV_NAME "advansys" -#define ASC_VERSION "3.4" /* AdvanSys Driver Version */ +#define ASC_VERSION "3.3K" /* 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 * All Rights Reserved. * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. + * 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. + * */ /* - * 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 + + 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 wrote the AdvanSys SCSI driver + and maintained it up to 3.3F. He continues to answer questions + and help maintain the driver. + + Nathan Hartwell provided the directions and + basis for the Linux v1.3.X changes which were included in the + 1.2 release. + + Thomas E Zerucha pointed out a bug + in advansys_biosparam() which was fixed in the 1.3 release. + + Erik Ratcliffe has done testing of the + AdvanSys driver in the Caldera releases. + + Rik van Riel provided a patch to + AscWaitTixISRDone() which he found necessary to make the + driver work with a SCSI-1 disk. + + Mark Moran has helped test Ultra-Wide + support in the 3.1A driver. + + Doug Gilbert has made changes and + suggestions to improve the driver and done a lot of testing. + + Ken Mort reported a DEBUG compile bug fixed + in 3.2K. + + Tom Rini provided the CONFIG_ISA + patch and helped with PowerPC wide and narrow board support. + + Philip Blundell provided an + advansys_interrupts_enabled patch. + + Dave Jones reported the compiler + warnings generated when CONFIG_PROC_FS was not defined in + the 3.2M driver. + + Jerry Quinn fixed PowerPC support (endian + problems) for wide cards. + + Bryan Henderson helped debug narrow + card error handling. + + Manuel Veloso worked hard on PowerPC narrow + board support and fixed a bug in AscGetEEPConfig(). + + Arnaldo Carvalho de Melo made + save_flags/restore_flags changes. + + Andy Kellner 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 */ #include + +#if defined(CONFIG_X86) && !defined(CONFIG_ISA) +#define CONFIG_ISA +#endif /* CONFIG_X86 && !CONFIG_ISA */ + #include #include #include @@ -33,9 +771,7 @@ #include #include #include -#include -#include -#include +#include #include #include @@ -43,38 +779,49 @@ #include #include +/* 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 #include #include #include #include +#ifdef CONFIG_PCI +#include +#endif /* CONFIG_PCI */ -/* 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 +/* + * --- Driver Options */ -#warning this driver is still not properly converted to the DMA API + +/* Enable driver assertions. */ +#define ADVANSYS_ASSERT /* Enable driver /proc statistics. */ #define ADVANSYS_STATS /* Enable driver tracing. */ -#undef ADVANSYS_DEBUG +/* #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 /* * Portable Data Types @@ -90,6 +837,17 @@ #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 @@ -99,9 +857,29 @@ 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 @@ -120,7 +898,7 @@ typedef unsigned char uchar; #define CC_VERY_LONG_SG_LIST 0 #define ASC_SRB2SCSIQ(srb_ptr) (srb_ptr) -#define PortAddr unsigned int /* port address size */ +#define PortAddr unsigned short /* port address size */ #define inp(port) inb(port) #define outp(port, byte) outb((byte), (port)) @@ -140,10 +918,11 @@ 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) @@ -162,9 +941,16 @@ 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 @@ -175,17 +961,82 @@ 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 + /* - * Narrow boards only support 12-byte commands, while wide boards - * extend to 16-byte commands. + * Inquiry SPC-2 SPI Byte 1 EVPD (Enable Vital Product Data) + * and CmdDt (Command Support Data) field bit definitions. */ -#define ASC_MAX_CDB_LEN 12 -#define ADV_MAX_CDB_LEN 16 - +#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 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 @@ -364,9 +1215,22 @@ typedef struct asc_sg_head { ushort queue_cnt; ushort entry_to_copy; ushort res; - ASC_SG_LIST sg_list[0]; + ASC_SG_LIST sg_list[ASC_MAX_SG_LIST]; } 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; @@ -423,12 +1287,45 @@ 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'. @@ -441,51 +1338,84 @@ 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/ADV}_DVC_VAR 'err_code'. + * Error code values are set in ASC_DVC_VAR 'err_code'. */ -#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_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_DEF_MAX_TOTAL_QNG (0xF0) #define ASC_MIN_TAG_Q_PER_DVC (0x04) -#define ASC_MIN_FREE_Q (0x02) +#define ASC_DEF_TAG_Q_PER_DVC (0x04) +#define ASC_MIN_FREE_Q ASC_MIN_REMAIN_Q #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 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 -}; +#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 typedef struct ext_msg { uchar msg_type; @@ -526,16 +1456,22 @@ 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 @@ -548,39 +1484,43 @@ 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]; - const uchar *sdtr_period_tbl; + uchar sdtr_period_tbl[ASC_MAX_SYN_XFER_NO]; ASC_DVC_CFG *cfg; ASC_SCSI_BIT_ID_TYPE pci_fix_asyn_xfer_always; char redo_scam; @@ -589,11 +1529,9 @@ 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; @@ -630,7 +1568,12 @@ 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 @@ -666,10 +1609,17 @@ 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) @@ -846,9 +1796,16 @@ 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 @@ -871,10 +1828,11 @@ 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 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 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) @@ -929,6 +1887,125 @@ 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 * @@ -967,6 +2044,12 @@ typedef struct asc_mc_saved { #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 @@ -975,14 +2058,28 @@ typedef struct asc_mc_saved { * 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 maximum number of scatter-gather elements per request. + * Define Adv Library required maximum number of scatter-gather + * elements per request. */ #define ADV_MAX_SG_LIST 255 -#define NO_OF_SG_PER_BLOCK 15 + +/* 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 ADV_EEP_DVC_CFG_BEGIN (0x00) #define ADV_EEP_DVC_CFG_END (0x15) @@ -1288,6 +2385,10 @@ 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 @@ -1304,8 +2405,10 @@ 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 @@ -1315,6 +2418,8 @@ 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'. @@ -1444,6 +2549,8 @@ 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 @@ -1483,6 +2590,8 @@ 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) @@ -1635,11 +2744,14 @@ 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) @@ -1650,11 +2762,30 @@ 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. */ @@ -1771,7 +2902,8 @@ 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)) + (PAGE_SIZE - 1))/PAGE_SIZE) + (((ADV_CARRIER_COUNT * sizeof(ADV_CARR_T)) + \ + (ADV_PAGE_SIZE - 1))/ADV_PAGE_SIZE) #define ADV_CARRIER_BUFSIZE \ ((ADV_CARRIER_COUNT + ADV_CARRIER_NUM_PAGE_CROSSING) * sizeof(ADV_CARR_T)) @@ -1805,17 +2937,80 @@ 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; @@ -1873,83 +3068,6 @@ typedef struct adv_scsi_req_q { uchar pad[2]; /* Pad out to a word boundary. */ } 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 */ @@ -1974,8 +3092,10 @@ typedef struct adv_dvc_var { /* * 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. */ @@ -1985,6 +3105,53 @@ typedef struct adv_dvc_var { #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))) @@ -2152,6 +3319,23 @@ 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) @@ -2169,10 +3353,92 @@ do { \ (sizeof(ADV_SG_BLOCK) * \ ((ADV_MAX_SG_LIST + (NO_OF_SG_PER_BLOCK - 1))/NO_OF_SG_PER_BLOCK)) -/* struct asc_board flags */ -#define ASC_IS_WIDE_BOARD 0x04 /* AdvanSys Wide Board */ +/* + * 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 +#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 */ @@ -2207,14 +3473,82 @@ do { \ #define HOST_BYTE(byte) ((byte) << 16) #define DRIVER_BYTE(byte) ((byte) << 24) -#define ASC_STATS(shost, counter) ASC_STATS_ADD(shost, counter, 1) +/* + * 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. */ + #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) \ - (((struct asc_board *) shost_priv(shost))->asc_stats.counter += (count)) + (ASC_BOARDP(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))) ? \ @@ -2255,8 +3589,13 @@ do { \ #ifndef ADVANSYS_DEBUG -#define ASC_DBG(lvl, s...) +#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_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) @@ -2275,11 +3614,40 @@ do { \ * 2-N: Verbose Tracing */ -#define ASC_DBG(lvl, format, arg...) { \ - if (asc_dbglvl >= (lvl)) \ - printk(KERN_DEBUG "%s: %s: " format, DRV_NAME, \ - __FUNCTION__ , ## arg); \ -} +#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_PRT_SCSI_HOST(lvl, s) \ { \ @@ -2288,6 +3656,13 @@ do { \ } \ } +#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)) { \ @@ -2326,6 +3701,24 @@ do { \ 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 */ @@ -2346,23 +3739,72 @@ struct asc_stats { ADV_DCNT exe_error; /* # ASC_ERROR returns. */ ADV_DCNT exe_unknown; /* # unknown returns. */ /* Data Transfer Statistics */ - ADV_DCNT xfer_cnt; /* # I/O requests received */ - ADV_DCNT xfer_elem; /* # scatter-gather elements */ - ADV_DCNT xfer_sect; /* # 512-byte blocks */ + 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 */ }; #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_host_alloc() at the end + * This structure is allocated by scsi_register() at the end * of the 'Scsi_Host' structure starting at the 'hostdata' * field. It is guaranteed to be allocated from DMA-able memory. */ -struct asc_board { - struct device *dev; +typedef struct asc_board { + int id; /* Board Id */ uint flags; /* Board flags */ - unsigned int irq; union { ASC_DVC_VAR asc_dvc_var; /* Narrow board */ ADV_DVC_VAR adv_dvc_var; /* Wide board */ @@ -2372,7 +3814,11 @@ 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 */ @@ -2383,413 +3829,415 @@ 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. */ -}; - -#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 int asc_dbglvl = 3; +} asc_board_t; /* - * asc_prt_asc_dvc_var() + * PCI configuration structures */ -static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h) -{ - printk("ASC_DVC_VAR at addr 0x%lx\n", (ulong)h); - - 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); - - printk(" bus_type %d, init_sdtr 0x%x,\n", h->bus_type, - (unsigned)h->init_sdtr); - - 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); - - 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); - - 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); - - 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); - - printk(" cfg 0x%lx\n", (ulong)h->cfg); -} +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; /* - * asc_prt_asc_dvc_cfg() + * --- Driver Data */ -static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) -{ - printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h); - 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); +/* Note: All driver global data should be initialized. */ - 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); +/* Number of boards detected in system. */ +static int asc_board_count = 0; +static struct Scsi_Host *asc_host[ASC_NUM_BOARD_SUPPORTED] = { NULL }; - printk(" mcode_date 0x%x, mcode_version %d\n", - h->mcode_date, h->mcode_version); -} +/* Overrun buffer used by all narrow boards. */ +static uchar overrun_buf[ASC_OVERRUN_BSIZE] = { 0 }; /* - * asc_prt_adv_dvc_var() - * - * Display an ADV_DVC_VAR structure. + * Global structures required to issue a command. */ -static void asc_prt_adv_dvc_var(ADV_DVC_VAR *h) -{ - printk(" ADV_DVC_VAR at addr 0x%lx\n", (ulong)h); - - 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); - - printk(" sdtr_able 0x%x, wdtr_able 0x%x\n", - (unsigned)h->sdtr_able, (unsigned)h->wdtr_able); - - printk(" start_motor 0x%x, scsi_reset_wait 0x%x\n", - (unsigned)h->start_motor, (unsigned)h->scsi_reset_wait); +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, +}; - 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); +static int asc_iopflag = ASC_FALSE; +static int asc_ioport[ASC_NUM_IOPORT_PROBE] = { 0, 0, 0, 0 }; - printk(" icq_sp 0x%lx, irq_sp 0x%lx\n", - (ulong)h->icq_sp, (ulong)h->irq_sp); +#ifdef ADVANSYS_DEBUG +static char *asc_bus_name[ASC_NUM_BUS] = { + "ASC_IS_ISA", + "ASC_IS_VL", + "ASC_IS_EISA", + "ASC_IS_PCI", +}; - printk(" no_scam 0x%x, tagqng_able 0x%x\n", - (unsigned)h->no_scam, (unsigned)h->tagqng_able); +static int asc_dbglvl = 3; +#endif /* ADVANSYS_DEBUG */ - printk(" chip_scsi_id 0x%x, cfg 0x%lx\n", - (unsigned)h->chip_scsi_id, (ulong)h->cfg); -} +/* Declaration for Asc Library internal data referenced by driver. */ +static PortAddr _asc_def_iop_base[]; /* - * asc_prt_adv_dvc_cfg() + * --- Driver Function Prototypes * - * 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); - - printk(" disc_enable 0x%x, termination 0x%x\n", - h->disc_enable, h->termination); - - printk(" chip_version 0x%x, mcode_date 0x%x\n", - h->chip_version, h->mcode_date); - - printk(" mcode_version 0x%x, control_flag 0x%x\n", - h->mcode_version, h->control_flag); -} - -/* - * asc_prt_scsi_host() + * advansys.h contains function prototypes for functions global to Linux. */ -static void asc_prt_scsi_host(struct Scsi_Host *s) -{ - struct asc_board *boardp = shost_priv(s); - - 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); - printk(" base 0x%lx, io_port 0x%lx, irq %d,\n", - (ulong)s->base, (ulong)s->io_port, boardp->irq); +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 */ - printk(" dma_channel %d, this_id %d, can_queue %d,\n", - s->dma_channel, s->this_id, s->can_queue); +/* Declaration for Asc Library internal functions referenced by driver. */ +static int AscFindSignature(PortAddr); +static ushort AscGetEEPConfig(PortAddr, ASCEEP_CONFIG *, ushort); - printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", - s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); +/* 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 */ - 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); - } -} +/* 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 /* - * asc_prt_hex() + * advansys_proc_info() - /proc/scsi/advansys/[0-(ASC_NUM_BOARD_SUPPORTED-1)] * - * Print hexadecimal output in 4 byte groupings 32 bytes - * or 8 double-words per line. + * *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 void asc_prt_hex(char *f, uchar *s, int l) +static int +advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, + off_t offset, int length, int inout) { + struct Scsi_Host *shp; + asc_board_t *boardp; int i; - int j; - int k; - int m; + char *cp; + int cplen; + int cnt; + int totcnt; + int leftlen; + char *curbuf; + off_t advoffset; +#ifdef ADVANSYS_STATS + int tgt_id; +#endif /* ADVANSYS_STATS */ - printk("%s: (%d bytes)\n", f, l); + ASC_DBG(1, "advansys_proc_info: begin\n"); - for (i = 0; i < l; i += 32) { + /* + * User write not supported. + */ + if (inout == TRUE) { + return (-ENOSYS); + } - /* Display a maximum of 8 double-words per line. */ - if ((k = (l - i) / 4) >= 8) { - k = 8; - m = 0; - } else { - m = (l - i) % 4; - } + /* + * User read of /proc/scsi/advansys/[0...] file. + */ - 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]); + /* 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); + } - 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; - } - - printk("\n"); - } -} + shp = asc_host[i]; + boardp = ASC_BOARDP(shp); -/* - * asc_prt_asc_scsi_q() - */ -static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q) -{ - ASC_SG_HEAD *sgp; - int i; - - printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q); - - 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); - - 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); + /* Copy read data starting at the beginning of the buffer. */ + *start = buffer; + curbuf = buffer; + advoffset = 0; + totcnt = 0; + leftlen = length; - 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); + /* + * 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; - 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)); + /* + * 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; } -} - -/* - * 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); -} - -/* - * asc_prt_adv_sgblock() - * - * Display an ADV_SG_BLOCK structure. - */ -static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) -{ - int i; - 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); + /* + * 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; } -} - -/* - * 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; - - printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q); - - 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); - - 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); - - 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); + advoffset += cplen; + curbuf += cnt; - 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); + /* + * 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; - printk(" sg_working_ix 0x%x, target_cmd %u\n", - q->sg_working_ix, q->target_cmd); + /* + * 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(" 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); +#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; - /* 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; - } - sg_blk_cnt++; + /* + * 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_DEBUG */ - -/* - * 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. - */ -#define BAD_SRB 0 -static u32 advansys_ptr_to_srb(struct asc_dvc_var *asc_dvc, void *ptr) -{ - int i; - void **new_ptr; +#endif /* ADVANSYS_STATS */ - for (i = 0; i < asc_dvc->ptr_map_count; i++) { - if (!asc_dvc->ptr_map[i]) - goto out; + /* + * 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; - if (asc_dvc->ptr_map_count == 0) - asc_dvc->ptr_map_count = 1; - else - asc_dvc->ptr_map_count *= 2; - - 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; -} - -static void * advansys_srb_to_ptr(struct asc_dvc_var *asc_dvc, u32 srb) -{ - void *ptr; + ASC_DBG1(1, "advansys_proc_info: totcnt %d\n", totcnt); - srb--; - if (srb >= asc_dvc->ptr_map_count) { - printk("advansys: bad SRB %u, max %u\n", srb, - asc_dvc->ptr_map_count); - return NULL; - } - 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 totcnt; } +#endif /* CONFIG_PROC_FS */ /* * advansys_info() @@ -2803,15 +4251,17 @@ static void * advansys_srb_to_ptr(struct asc_dvc_var *asc_dvc, u32 srb) static const char *advansys_info(struct Scsi_Host *shost) { static char info[ASC_INFO_SIZE]; - struct asc_board *boardp = shost_priv(shost); + asc_board_t *boardp; ASC_DVC_VAR *asc_dvc_varp; ADV_DVC_VAR *adv_dvc_varp; char *busname; + int iolen; char *widename = NULL; + boardp = ASC_BOARDP(shost); if (ASC_NARROW_BOARD(boardp)) { asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - ASC_DBG(1, "begin\n"); + 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) { @@ -2819,12 +4269,13 @@ static const char *advansys_info(struct Scsi_Host *shost) } 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 + ASC_IOADR_GAP - 1, - boardp->irq, shost->dma_channel); + (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"; @@ -2839,15 +4290,18 @@ static const char *advansys_info(struct Scsi_Host *shost) } } else { busname = "?"; - shost_printk(KERN_ERR, shost, "unknown bus " - "type %d\n", asc_dvc_varp->bus_type); + 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 + ASC_IOADR_GAP - 1, - boardp->irq); - } + ASC_VERSION, busname, + (ulong)shost->io_port, + (ulong)shost->io_port + boardp->asc_n_io_port - + 1, shost->irq); + } } else { /* * Wide Adapter Information @@ -2858,5759 +4312,4237 @@ static const char *advansys_info(struct Scsi_Host *shost) */ 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 + boardp->asc_n_io_port - 1, boardp->irq); + (ulong)adv_dvc_varp->iop_base + iolen - 1, shost->irq); } - BUG_ON(strlen(info) >= ASC_INFO_SIZE); - ASC_DBG(1, "end\n"); + ASC_ASSERT(strlen(info) < ASC_INFO_SIZE); + ASC_DBG(1, "advansys_info: end\n"); return info; } -#ifdef CONFIG_PROC_FS /* - * asc_prt_line() - * - * If 'cp' is NULL print to the console, otherwise print to a buffer. - * - * Return 0 if printing to the console, otherwise return the number of - * bytes written to the buffer. + * advansys_queuecommand() - interrupt-driven I/O entrypoint. * - * 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. + * This function always returns 0. Command return status is saved + * in the 'scp' result field. */ -static int asc_prt_line(char *buf, int buflen, char *fmt, ...) +static int +advansys_queuecommand(struct scsi_cmnd *scp, void (*done) (struct scsi_cmnd *)) { - va_list args; - int ret; - char s[ASC_PRTLINE_SIZE]; - - 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; -} + struct Scsi_Host *shost; + asc_board_t *boardp; + ulong flags; + struct scsi_cmnd *done_scp; -/* - * asc_prt_board_devices() - * - * Print driver information for devices attached to the board. - * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). - * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. - */ -static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen) -{ - struct asc_board *boardp = shost_priv(shost); - int leftlen; - int totlen; - int len; - int chip_scsi_id; - int i; + shost = scp->device->host; + boardp = ASC_BOARDP(shost); + ASC_STATS(shost, queuecommand); - leftlen = cplen; - totlen = len = 0; + /* host_lock taken by mid-level prior to call but need to protect */ + /* against own ISR */ + spin_lock_irqsave(&boardp->lock, flags); - len = asc_prt_line(cp, leftlen, - "\nDevice Information for AdvanSys SCSI Host %d:\n", - shost->host_no); - ASC_PRT_NEXT(); + /* + * 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); - 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; + /* + * 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; } - len = asc_prt_line(cp, leftlen, "Target IDs Detected:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) { - len = asc_prt_line(cp, leftlen, " %X,", i); - ASC_PRT_NEXT(); - } + /* + * 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); } - len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id); - ASC_PRT_NEXT(); - - return totlen; -} - -/* - * Display Wide Board BIOS Information. - */ -static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen) -{ - struct asc_board *boardp = shost_priv(shost); - int leftlen; - int totlen; - int len; - ushort major, minor, letter; - - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: "); - ASC_PRT_NEXT(); /* - * If the BIOS saved a valid signature, then fill in - * the BIOS code segment base address. + * 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. */ - if (boardp->bios_signature != 0x55AA) { - len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, - "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, - "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n"); - ASC_PRT_NEXT(); - } else { - major = (boardp->bios_version >> 12) & 0xF; - minor = (boardp->bios_version >> 8) & 0xF; - letter = (boardp->bios_version & 0xFF); - - len = asc_prt_line(cp, leftlen, "%d.%d%c\n", - major, minor, - letter >= 26 ? '?' : letter + 'A'); - ASC_PRT_NEXT(); - - /* - * Current available ROM BIOS release is 3.1I for UW - * and 3.2I for U2W. This code doesn't differentiate - * UW and U2W boards. - */ - if (major < 3 || (major <= 3 && minor < 1) || - (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) { - len = asc_prt_line(cp, leftlen, - "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n"); - ASC_PRT_NEXT(); - len = asc_prt_line(cp, leftlen, - "ftp://ftp.connectcom.net/pub\n"); - ASC_PRT_NEXT(); - } + 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); - return totlen; + return 0; } /* - * Add serial number to information bar if signature AAh - * is found in at bit 15-9 (7 bits) of word 1. - * - * Serial Number consists fo 12 alpha-numeric digits. - * - * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits) - * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits) - * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits) - * 5 - Product revision (A-J) Word0: " " - * - * Signature Word1: 15-9 (7 bits) - * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit) - * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits) - * - * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits) - * - * Note 1: Only production cards will have a serial number. + * advansys_reset() * - * Note 2: Signature is most significant 7 bits (0xFE). + * Reset the bus associated with the command 'scp'. * - * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE. + * 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 asc_get_eeprom_string(ushort *serialnum, uchar *cp) +static int advansys_reset(struct scsi_cmnd *scp) { - ushort w, num; + 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; - if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) { - return ASC_FALSE; - } else { - /* - * First word - 6 digits. - */ - w = serialnum[0]; + ASC_DBG1(1, "advansys_reset: 0x%lx\n", (ulong)scp); - /* Product type - 1st digit. */ - if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') { - /* Product type is P=Prototype */ - *cp += 0x8; - } - cp++; +#ifdef ADVANSYS_STATS + if (scp->device->host != NULL) { + ASC_STATS(scp->device->host, reset); + } +#endif /* ADVANSYS_STATS */ - /* Manufacturing location - 2nd digit. */ - *cp++ = 'A' + ((w & 0x1C00) >> 10); + if ((shost = scp->device->host) == NULL) { + scp->result = HOST_BYTE(DID_ERROR); + return FAILED; + } - /* Product ID - 3rd, 4th digits. */ - num = w & 0x3FF; - *cp++ = '0' + (num / 100); - num %= 100; - *cp++ = '0' + (num / 10); + boardp = ASC_BOARDP(shost); - /* Product revision - 5th digit. */ - *cp++ = 'A' + (num % 10); + 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)) { /* - * Second word + * Narrow Board */ - w = serialnum[1]; + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; /* - * Year - 6th digit. - * - * If bit 15 of third word is set, then the - * last digit of the year is greater than 7. + * Reset the chip and SCSI bus. */ - if (serialnum[2] & 0x8000) { - *cp++ = '8' + ((w & 0x1C0) >> 6); + 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 { - *cp++ = '0' + ((w & 0x1C0) >> 6); + ASC_PRINT1 + ("advansys_reset: board %d: SCSI bus reset successful.\n", + boardp->id); } - /* Week of year - 7th, 8th digits. */ - num = w & 0x003F; - *cp++ = '0' + num / 10; - num %= 10; - *cp++ = '0' + num; + ASC_DBG(1, "advansys_reset: after AscInitAsc1000Driver()\n"); + spin_lock_irqsave(&boardp->lock, flags); + } else { /* - * Third word + * Wide Board + * + * If the suggest reset bus flags are set, then reset the bus. + * Otherwise only reset the device. */ - w = serialnum[2] & 0x7FFF; + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - /* Serial number - 9th digit. */ - *cp++ = 'A' + (w / 1000); + /* + * 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. */ - /* 10th, 11th, 12th digits. */ - num = w % 1000; - *cp++ = '0' + num / 100; - num %= 100; - *cp++ = '0' + num / 10; - num %= 10; - *cp++ = '0' + num; + /* + * 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); - *cp = '\0'; /* Null Terminate the string. */ - return ASC_TRUE; + /* + * 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; + } + } + + /* Save the time of the most recently completed reset. */ + boardp->last_reset = jiffies; + + /* Clear reset flag. */ + boardp->flags &= ~ASC_HOST_IN_RESET; + spin_unlock_irqrestore(&boardp->lock, flags); + + /* + * Complete all the 'done_scp' requests. + */ + if (done_scp != NULL) { + asc_scsi_done_list(done_scp); } + + ASC_DBG1(1, "advansys_reset: ret %d\n", ret); + + return ret; } /* - * asc_prt_asc_board_eeprom() + * advansys_biosparam() * - * Print board EEPROM configuration. + * Translate disk drive geometry if the "BIOS greater than 1 GB" + * support is enabled for a drive. * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). + * 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; + + 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; +} + +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. * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. + * '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. */ -static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) +static irqreturn_t advansys_interrupt(int irq, void *dev_id) { - struct asc_board *boardp = shost_priv(shost); - ASC_DVC_VAR *asc_dvc_varp; - int leftlen; - int totlen; - int len; - ASCEEP_CONFIG *ep; + ulong flags; int i; -#ifdef CONFIG_ISA - int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 }; -#endif /* CONFIG_ISA */ - uchar serialstr[13]; + asc_board_t *boardp; + struct scsi_cmnd *done_scp = NULL, *last_scp = NULL; + struct scsi_cmnd *new_last_scp; + struct Scsi_Host *shost; - asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - ep = &boardp->eep_config.asc_eep; + ASC_DBG(1, "advansys_interrupt: begin\n"); - leftlen = cplen; - totlen = len = 0; + /* + * 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); + } + } - len = asc_prt_line(cp, leftlen, - "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", - shost->host_no); - ASC_PRT_NEXT(); + /* + * 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); + } - if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr) - == ASC_TRUE) { - len = - asc_prt_line(cp, leftlen, " Serial Number: %s\n", - serialstr); - ASC_PRT_NEXT(); - } else { - if (ep->adapter_info[5] == 0xBB) { - len = asc_prt_line(cp, leftlen, - " Default Settings Used for EEPROM-less Adapter.\n"); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - " Serial Number Signature Not Present.\n"); - ASC_PRT_NEXT(); + /* + * 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); } - len = asc_prt_line(cp, leftlen, - " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng, - ep->max_tag_qng); - ASC_PRT_NEXT(); + /* + * If interrupts were enabled on entry, then they + * are now enabled here. + * + * Complete all requests on the done list. + */ - len = asc_prt_line(cp, leftlen, - " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam); - ASC_PRT_NEXT(); + asc_scsi_done_list(done_scp); - len = asc_prt_line(cp, leftlen, " Target ID: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %d", i); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + ASC_DBG(1, "advansys_interrupt: end\n"); + return IRQ_HANDLED; +} - len = asc_prt_line(cp, leftlen, " Disconnects: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep-> - disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : - 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); +/* + * 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; - len = asc_prt_line(cp, leftlen, " Command Queuing: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep-> - use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : - 'N'); - ASC_PRT_NEXT(); + 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); } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + 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; +} - len = asc_prt_line(cp, leftlen, " Start Motor: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep-> - start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : - 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); +/* + * Complete all requests on the singly linked list pointed + * to by 'scp'. + * + * Interrupts can be enabled on entry. + */ +static void asc_scsi_done_list(struct scsi_cmnd *scp) +{ + struct scsi_cmnd *tscp; - len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep-> - init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : - 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + ASC_DBG(2, "asc_scsi_done_list: begin\n"); + while (scp != NULL) { + asc_board_t *boardp; + struct device *dev; -#ifdef CONFIG_ISA - if (asc_dvc_varp->bus_type & ASC_IS_ISA) { - len = asc_prt_line(cp, leftlen, - " Host ISA DMA speed: %d MB/S\n", - isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]); - ASC_PRT_NEXT(); - } -#endif /* CONFIG_ISA */ + ASC_DBG1(3, "asc_scsi_done_list: scp 0x%lx\n", (ulong)scp); + tscp = REQPNEXT(scp); + scp->host_scribble = NULL; - return totlen; + 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; + + 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); + + ASC_STATS(scp->device->host, done); + ASC_ASSERT(scp->scsi_done != NULL); + + scp->scsi_done(scp); + + scp = tscp; + } + ASC_DBG(2, "asc_scsi_done_list: done\n"); + return; } /* - * asc_prt_adv_board_eeprom() + * Execute a single 'Scsi_Cmnd'. * - * Print board EEPROM configuration. + * The function 'done' is called when the request has been completed. * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). + * Scsi_Cmnd: * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. + * 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. + * + * If ASC_BUSY is returned the request will be enqueued by the + * caller on the target's waiting queue and re-tried later. */ -static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) +static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) { - struct asc_board *boardp = shost_priv(shost); + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; ADV_DVC_VAR *adv_dvc_varp; - int leftlen; - int totlen; - int len; - int i; - char *termstr; - uchar serialstr[13]; - ADVEEP_3550_CONFIG *ep_3550 = NULL; - ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL; - ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL; - ushort word; - ushort *wordp; - ushort sdtr_speed = 0; + ADV_SCSI_REQ_Q *adv_scsiqp; + struct scsi_device *device; + int ret; - 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; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; - } else { - ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; - } + ASC_DBG2(1, "asc_execute_scsi_cmnd: scp 0x%lx, done 0x%lx\n", + (ulong)scp, (ulong)scp->scsi_done); - leftlen = cplen; - totlen = len = 0; + boardp = ASC_BOARDP(scp->device->host); + device = boardp->device[scp->device->id]; - len = asc_prt_line(cp, leftlen, - "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", - shost->host_no); - ASC_PRT_NEXT(); + if (ASC_NARROW_BOARD(boardp)) { + /* + * Build and execute Narrow Board request. + */ - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - wordp = &ep_3550->serial_number_word1; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - wordp = &ep_38C0800->serial_number_word1; - } else { - wordp = &ep_38C1600->serial_number_word1; - } + asc_dvc_varp = &boardp->dvc_var.asc_dvc_var; - if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) { - len = - asc_prt_line(cp, leftlen, " Serial Number: %s\n", - serialstr); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - " Serial Number Signature Not Present.\n"); - ASC_PRT_NEXT(); - } + /* + * 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; + } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - len = asc_prt_line(cp, leftlen, - " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_3550->adapter_scsi_id, - ep_3550->max_host_qng, ep_3550->max_dvc_qng); - ASC_PRT_NEXT(); - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - len = asc_prt_line(cp, leftlen, - " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_38C0800->adapter_scsi_id, - ep_38C0800->max_host_qng, - ep_38C0800->max_dvc_qng); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", - ep_38C1600->adapter_scsi_id, - ep_38C1600->max_host_qng, - ep_38C1600->max_dvc_qng); - ASC_PRT_NEXT(); - } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - word = ep_3550->termination; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - word = ep_38C0800->termination_lvd; + /* + * 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; + } } else { - word = ep_38C1600->termination_lvd; - } - switch (word) { - case 1: - termstr = "Low Off/High Off"; - break; - case 2: - termstr = "Low Off/High On"; - break; - case 3: - termstr = "Low On/High On"; - break; - default: - case 0: - termstr = "Automatic"; - break; - } + /* + * Build and execute Wide Board request. + */ + adv_dvc_varp = &boardp->dvc_var.adv_dvc_var; - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - len = asc_prt_line(cp, leftlen, - " termination: %u (%s), bios_ctrl: 0x%x\n", - ep_3550->termination, termstr, - ep_3550->bios_ctrl); - ASC_PRT_NEXT(); - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - len = asc_prt_line(cp, leftlen, - " termination: %u (%s), bios_ctrl: 0x%x\n", - ep_38C0800->termination_lvd, termstr, - ep_38C0800->bios_ctrl); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - " termination: %u (%s), bios_ctrl: 0x%x\n", - ep_38C1600->termination_lvd, termstr, - ep_38C1600->bios_ctrl); - ASC_PRT_NEXT(); - } + /* + * 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. + */ + default: + ASC_DBG(1, + "asc_execute_scsi_cmnd: adv_build_req ASC_ERROR\n"); + ASC_STATS(scp->device->host, build_error); + return ASC_ERROR; + } - len = asc_prt_line(cp, leftlen, " Target ID: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %X", i); - ASC_PRT_NEXT(); + /* + * 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); + 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); + 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); + break; + } } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - word = ep_3550->disc_enable; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - word = ep_38C0800->disc_enable; - } else { - word = ep_38C1600->disc_enable; - } - len = asc_prt_line(cp, leftlen, " Disconnects: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); + 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; } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + 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 (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - word = ep_3550->tagqng_able; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - word = ep_38C0800->tagqng_able; + /* + * 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 { - word = ep_38C1600->tagqng_able; - } - len = asc_prt_line(cp, leftlen, " Command Queuing: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); + asc_scsi_q.q2.tag_code = MSG_SIMPLE_TAG; } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - word = ep_3550->start_motor; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - word = ep_38C0800->start_motor; + /* + * 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 { - word = ep_38C1600->start_motor; - } - len = asc_prt_line(cp, leftlen, " Start Motor: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + /* + * CDB scatter-gather request list. + */ + int sgcnt; + int use_sg; + struct scatterlist *slp; - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep_3550-> - sdtr_able & ADV_TID_TO_TIDMASK(i)) ? - 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - } + slp = (struct scatterlist *)scp->request_buffer; + use_sg = + dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - len = asc_prt_line(cp, leftlen, " Ultra Transfer: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (ep_3550-> - ultra_able & ADV_TID_TO_TIDMASK(i)) - ? 'Y' : 'N'); - ASC_PRT_NEXT(); + 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; } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - } - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { - word = ep_3550->wdtr_able; - } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { - word = ep_38C0800->wdtr_able; - } else { - word = ep_38C1600->wdtr_able; - } - len = asc_prt_line(cp, leftlen, " Wide Transfer: "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - len = asc_prt_line(cp, leftlen, " %c", - (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + ASC_STATS(scp->device->host, sg_cnt); - if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 || - adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) { - len = asc_prt_line(cp, leftlen, - " Synchronous Transfer Speed (Mhz):\n "); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - char *speed_str; + /* + * 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)); - if (i == 0) { - sdtr_speed = adv_dvc_varp->sdtr_speed1; - } else if (i == 4) { - sdtr_speed = adv_dvc_varp->sdtr_speed2; - } else if (i == 8) { - sdtr_speed = adv_dvc_varp->sdtr_speed3; - } else if (i == 12) { - sdtr_speed = adv_dvc_varp->sdtr_speed4; - } - switch (sdtr_speed & ADV_MAX_TID) { - case 0: - speed_str = "Off"; - break; - case 1: - speed_str = " 5"; - break; - case 2: - speed_str = " 10"; - break; - case 3: - speed_str = " 20"; - break; - case 4: - speed_str = " 40"; - break; - case 5: - speed_str = " 80"; - break; - default: - speed_str = "Unk"; - break; - } - len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str); - ASC_PRT_NEXT(); - if (i == 7) { - len = asc_prt_line(cp, leftlen, "\n "); - ASC_PRT_NEXT(); - } - sdtr_speed >>= 4; + 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)); } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); } - return totlen; + ASC_DBG_PRT_ASC_SCSI_Q(2, &asc_scsi_q); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + + return ASC_NOERROR; } /* - * asc_prt_driver_conf() + * Build a request structure for the Adv Library (Wide Board). * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). + * 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. * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. + * 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 asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen) +static int +adv_build_req(asc_board_t *boardp, struct scsi_cmnd *scp, + ADV_SCSI_REQ_Q **adv_scsiqpp) { - struct asc_board *boardp = shost_priv(shost); - int leftlen; - int totlen; - int len; - int chip_scsi_id; - - leftlen = cplen; - totlen = len = 0; + adv_req_t *reqp; + ADV_SCSI_REQ_Q *scsiqp; + int i; + int ret; + struct device *dev = boardp->dvc_cfg.adv_dvc_cfg.dev; - len = asc_prt_line(cp, leftlen, - "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n", - shost->host_no); - ASC_PRT_NEXT(); + /* + * 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; + } - len = asc_prt_line(cp, leftlen, - " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n", - shost->host_busy, shost->last_reset, shost->max_id, - shost->max_lun, shost->max_channel); - ASC_PRT_NEXT(); + /* + * Get 32-byte aligned ADV_SCSI_REQ_Q and ADV_SG_BLOCK pointers. + */ + scsiqp = (ADV_SCSI_REQ_Q *)ADV_32BALIGN(&reqp->scsi_req_q); - len = asc_prt_line(cp, leftlen, - " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", - shost->unique_id, shost->can_queue, shost->this_id, - shost->sg_tablesize, shost->cmd_per_lun); - ASC_PRT_NEXT(); + /* + * Initialize the structure. + */ + scsiqp->cntl = scsiqp->scsi_cntl = scsiqp->done_status = 0; - len = asc_prt_line(cp, leftlen, - " unchecked_isa_dma %d, use_clustering %d\n", - shost->unchecked_isa_dma, shost->use_clustering); - ASC_PRT_NEXT(); + /* + * Set the ADV_SCSI_REQ_Q 'srb_ptr' to point to the adv_req_t structure. + */ + scsiqp->srb_ptr = ASC_VADDR_TO_U32(reqp); - len = asc_prt_line(cp, leftlen, - " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n", - boardp->flags, boardp->last_reset, jiffies, - boardp->asc_n_io_port); - ASC_PRT_NEXT(); + /* + * Set the adv_req_t 'cmndp' to point to the struct scsi_cmnd structure. + */ + reqp->cmndp = scp; - len = asc_prt_line(cp, leftlen, " io_port 0x%x\n", shost->io_port); - ASC_PRT_NEXT(); + /* + * Build the ADV_SCSI_REQ_Q request. + */ - 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; + /* + * 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]; } - return totlen; -} + scsiqp->target_id = scp->device->id; + scsiqp->target_lun = scp->device->lun; -/* - * asc_prt_asc_board_info() - * - * Print dynamic board configuration information. - * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). - * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. - */ -static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen) -{ - struct asc_board *boardp = shost_priv(shost); - int chip_scsi_id; - int leftlen; - int totlen; - int len; - ASC_DVC_VAR *v; - ASC_DVC_CFG *c; - int i; - int renegotiate = 0; + scsiqp->sense_addr = cpu_to_le32(virt_to_bus(&scp->sense_buffer[0])); + scsiqp->sense_len = sizeof(scp->sense_buffer); - v = &boardp->dvc_var.asc_dvc_var; - c = &boardp->dvc_cfg.asc_dvc_cfg; - chip_scsi_id = c->chip_scsi_id; + /* + * Build ADV_SCSI_REQ_Q for a contiguous buffer or a scatter-gather + * buffer command. + */ - leftlen = cplen; - totlen = len = 0; - - len = asc_prt_line(cp, leftlen, - "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", - shost->host_no); - ASC_PRT_NEXT(); - - 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. */ - len = asc_prt_line(cp, leftlen, - " Total Command Pending: %d\n", v->cur_total_qng); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, " Command Queuing:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%c", - i, - (v-> - use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? - 'Y' : 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + 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)); - /* Current number of commands waiting for a device. */ - len = asc_prt_line(cp, leftlen, " Command Queue Pending:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - /* Current limit on number of commands that can be sent to a device. */ - len = asc_prt_line(cp, leftlen, " Command Queue Limit:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - /* Indicate whether the device has returned queue full status. */ - len = asc_prt_line(cp, leftlen, " Command Queue Full:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } - if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) { - len = asc_prt_line(cp, leftlen, " %X:Y-%d", - i, boardp->queue_full_cnt[i]); + 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 { - len = asc_prt_line(cp, leftlen, " %X:N", i); - } - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ASC_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; + scsiqp->vdata_addr = NULL; + scp->SCp.dma_handle = 0; } - len = asc_prt_line(cp, leftlen, " %X:%c", - i, - (v-> - sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : - 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + 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; - for (i = 0; i <= ASC_MAX_TID; i++) { - uchar syn_period_ix; + slp = (struct scatterlist *)scp->request_buffer; + use_sg = + dma_map_sg(dev, slp, scp->use_sg, scp->sc_data_direction); - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || - ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } + 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); - len = asc_prt_line(cp, leftlen, " %X:", i); - ASC_PRT_NEXT(); + /* + * 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; - if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) { - len = asc_prt_line(cp, leftlen, " Asynchronous"); - ASC_PRT_NEXT(); - } else { - syn_period_ix = - (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - - 1); + return ASC_ERROR; + } - len = asc_prt_line(cp, leftlen, - " Transfer Period Factor: %d (%d.%d Mhz),", - v->sdtr_period_tbl[syn_period_ix], - 250 / - v->sdtr_period_tbl[syn_period_ix], - ASC_TENTHS(250, - v-> - sdtr_period_tbl - [syn_period_ix])); - ASC_PRT_NEXT(); + 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; - len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", - boardp-> - sdtr_data[i] & ASC_SYN_MAX_OFFSET); - ASC_PRT_NEXT(); + return ret; } - if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*\n"); - renegotiate = 1; - } else { - len = asc_prt_line(cp, leftlen, "\n"); - } - ASC_PRT_NEXT(); + ASC_STATS(scp->device->host, sg_cnt); + ASC_STATS_ADD(scp->device->host, sg_elem, use_sg); } - if (renegotiate) { - len = asc_prt_line(cp, leftlen, - " * = Re-negotiation pending before next command.\n"); - ASC_PRT_NEXT(); - } + ASC_DBG_PRT_ADV_SCSI_REQ_Q(2, scsiqp); + ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); - return totlen; + *adv_scsiqpp = scsiqp; + + return ASC_NOERROR; } /* - * asc_prt_adv_board_info() - * - * Print dynamic board configuration information. + * Build scatter-gather list for Adv Library (Wide Board). * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). + * 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 the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. + * Return: + * ADV_SUCCESS(1) - SG List successfully created + * ADV_ERROR(-1) - SG List creation failed */ -static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen) +static int +adv_get_sglist(asc_board_t *boardp, adv_req_t *reqp, struct scsi_cmnd *scp, + int use_sg) { - struct asc_board *boardp = shost_priv(shost); - int leftlen; - int totlen; - int len; + 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; - ADV_DVC_VAR *v; - ADV_DVC_CFG *c; - AdvPortAddr iop_base; - ushort chip_scsi_id; - ushort lramword; - uchar lrambyte; - ushort tagqng_able; - ushort sdtr_able, wdtr_able; - ushort wdtr_done, sdtr_done; - ushort period = 0; - int renegotiate = 0; - v = &boardp->dvc_var.adv_dvc_var; - c = &boardp->dvc_cfg.adv_dvc_cfg; - iop_base = v->iop_base; - chip_scsi_id = v->chip_scsi_id; + 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; - leftlen = cplen; - totlen = len = 0; + 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); - len = asc_prt_line(cp, leftlen, - "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", - shost->host_no); - ASC_PRT_NEXT(); + /* + * 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; - len = asc_prt_line(cp, leftlen, - " iop_base 0x%lx, cable_detect: %X, err_code %u\n", - v->iop_base, - AdvReadWordRegister(iop_base, - IOPW_SCSI_CFG1) & CABLE_DETECT, - v->err_code); - ASC_PRT_NEXT(); + /* 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; - 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(); + /* + * 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); - AdvReadWordLram(iop_base, ASC_MC_TAGQNG_ABLE, tagqng_able); - len = asc_prt_line(cp, leftlen, " Queuing Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } + /* + * 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; - len = asc_prt_line(cp, leftlen, " %X:%c", - i, - (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : - 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + /* + * 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; - len = asc_prt_line(cp, leftlen, " Queue Limit:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; + /* + * 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); + } } - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, - lrambyte); - - len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + 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)); - len = asc_prt_line(cp, leftlen, " Command Pending:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; + 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++; } - - AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, - lrambyte); - - len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); - ASC_PRT_NEXT(); + sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; + prev_sg_block = sg_block; } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); - len = asc_prt_line(cp, leftlen, " Wide Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } + while (1); + /* NOTREACHED */ +} - len = asc_prt_line(cp, leftlen, " %X:%c", - i, - (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : - 'N'); - ASC_PRT_NEXT(); - } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); +/* + * 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) +{ + asc_board_t *boardp; + struct scsi_cmnd *scp; + struct Scsi_Host *shost; + int i; - AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done); - len = asc_prt_line(cp, leftlen, " Transfer Bit Width:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } + 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); - AdvReadWordLram(iop_base, - ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), - lramword); + /* + * 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); - len = asc_prt_line(cp, leftlen, " %X:%d", - i, (lramword & 0x8000) ? 16 : 8); - ASC_PRT_NEXT(); + if (scp == NULL) { + ASC_PRINT("asc_isr_callback: scp is NULL\n"); + return; + } + ASC_DBG_PRT_CDB(2, scp->cmnd, scp->cmd_len); - if ((wdtr_able & ADV_TID_TO_TIDMASK(i)) && - (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*"); - ASC_PRT_NEXT(); - renegotiate = 1; + /* + * 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; } } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); + 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; + } - AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); - len = asc_prt_line(cp, leftlen, " Synchronous Enabled:"); - ASC_PRT_NEXT(); - for (i = 0; i <= ADV_MAX_TID; i++) { - if ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; - } + ASC_STATS(shost, callback); + ASC_DBG1(1, "asc_isr_callback: shost 0x%lx\n", (ulong)shost); - len = asc_prt_line(cp, leftlen, " %X:%c", - i, - (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : - 'N'); - ASC_PRT_NEXT(); + /* + * 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; } - len = asc_prt_line(cp, leftlen, "\n"); - ASC_PRT_NEXT(); - AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done); - for (i = 0; i <= ADV_MAX_TID; i++) { - - AdvReadWordLram(iop_base, - ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), - lramword); - lramword &= ~0x8000; + /* + * '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 ((chip_scsi_id == i) || - ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || - ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) { - continue; + /* + * 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); } - len = asc_prt_line(cp, leftlen, " %X:", i); - ASC_PRT_NEXT(); - - if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */ - len = asc_prt_line(cp, leftlen, " Asynchronous"); - ASC_PRT_NEXT(); - } else { - len = - asc_prt_line(cp, leftlen, - " Transfer Period Factor: "); - ASC_PRT_NEXT(); - - if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */ - len = - asc_prt_line(cp, leftlen, "9 (80.0 Mhz),"); - ASC_PRT_NEXT(); - } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */ - len = - asc_prt_line(cp, leftlen, "10 (40.0 Mhz),"); - ASC_PRT_NEXT(); - } else { /* 20 Mhz or below. */ - - period = (((lramword >> 8) * 25) + 50) / 4; + /* + * 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; - if (period == 0) { /* Should never happen. */ - len = - asc_prt_line(cp, leftlen, - "%d (? Mhz), "); - ASC_PRT_NEXT(); - } else { - len = asc_prt_line(cp, leftlen, - "%d (%d.%d Mhz),", - period, 250 / period, - ASC_TENTHS(250, - period)); - ASC_PRT_NEXT(); - } + 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; - len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", - lramword & 0x1F); - ASC_PRT_NEXT(); + 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; - if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { - len = asc_prt_line(cp, leftlen, "*\n"); - renegotiate = 1; - } else { - len = asc_prt_line(cp, leftlen, "\n"); - } - ASC_PRT_NEXT(); + 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 (renegotiate) { - len = asc_prt_line(cp, leftlen, - " * = Re-negotiation pending before next command.\n"); - ASC_PRT_NEXT(); + /* + * 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); } - return totlen; -} - -/* - * asc_proc_copy() - * - * Copy proc information to a read buffer taking into account the current - * read offset in the file and the remaining space in the read buffer. - */ -static int -asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, - char *cp, int cplen) -{ - int cnt = 0; + /* + * 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); - 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_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) { - /* Read offset within current range, partial copy. */ - cnt = (advoffset + cplen) - offset; - cp = (cp + cplen) - cnt; - cnt = min(cnt, leftlen); - ASC_DBG(2, "curbuf 0x%lx, cp 0x%lx, cnt %d\n", - (ulong)curbuf, (ulong)cp, cnt); - memcpy(curbuf, cp, cnt); - } - return cnt; + return; } -#ifdef ADVANSYS_STATS /* - * asc_prt_board_stats() - * - * Note: no single line should be greater than ASC_PRTLINE_SIZE, - * cf. asc_prt_line(). + * adv_isr_callback() - Second Level Interrupt Handler called by AdvISR(). * - * Return the number of characters copied into 'cp'. No more than - * 'cplen' characters will be copied to 'cp'. + * Callback function for the Wide SCSI Adv Library. */ -static int asc_prt_board_stats(struct Scsi_Host *shost, char *cp, int cplen) +static void adv_isr_callback(ADV_DVC_VAR *adv_dvc_varp, ADV_SCSI_REQ_Q *scsiqp) { - 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(); + 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; - 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(); + 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); /* - * Display data transfer statistics. + * 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. */ - 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(); + 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; } - return totlen; -} -#endif /* ADVANSYS_STATS */ - -/* - * advansys_proc_info() - /proc/scsi/advansys/{0,1,2,3,...} - * - * *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 -advansys_proc_info(struct Scsi_Host *shost, char *buffer, char **start, - off_t offset, int length, int inout) -{ - struct asc_board *boardp = shost_priv(shost); - char *cp; - int cplen; - int cnt; - int totcnt; - int leftlen; - char *curbuf; - off_t advoffset; - - ASC_DBG(1, "begin\n"); - /* - * User write not supported. + * 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. */ - if (inout == TRUE) - return -ENOSYS; + 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); /* - * User read of /proc/scsi/advansys/[0...] file. + * 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; + } - /* Copy read data starting at the beginning of the buffer. */ - *start = buffer; - curbuf = buffer; - advoffset = 0; - totcnt = 0; - leftlen = length; + ASC_STATS(shost, callback); + ASC_DBG1(1, "adv_isr_callback: shost 0x%lx\n", (ulong)shost); /* - * Get board configuration information. + * 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. * - * advansys_info() returns the board string from its own static buffer. + * 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. */ - 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; + 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; } - advoffset += cplen; - curbuf += cnt; /* - * Display Wide Board BIOS Information. + * 'done_status' contains the command's ending status. */ - 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; + switch (scsiqp->done_status) { + case QD_NO_ERROR: + ASC_DBG(2, "adv_isr_callback: 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 (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; } - advoffset += cplen; - curbuf += cnt; + break; + + 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); + } + 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; + } + 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; } /* - * Display driver information for each device attached to the board. + * 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. */ - 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; + 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); } - advoffset += cplen; - curbuf += cnt; /* - * Display EEPROM configuration for the board. + * 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(). */ - cp = boardp->prtbuf; - if (ASC_NARROW_BOARD(boardp)) { - cplen = asc_prt_asc_board_eeprom(shost, cp, ASC_PRTBUF_SIZE); - } else { - cplen = asc_prt_adv_board_eeprom(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_enqueue(&boardp->done, scp, ASC_BACK); /* - * Display driver configuration and information for the board. + * Free all 'adv_sgblk_t' structures allocated for the request. */ - 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; + while ((sgblkp = reqp->sgblkp) != NULL) { + /* Remove 'sgblkp' from the request list. */ + reqp->sgblkp = sgblkp->next_sgblkp; -#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; + /* Add 'sgblkp' to the board free list. */ + sgblkp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgblkp; } - advoffset += cplen; - curbuf += cnt; -#endif /* ADVANSYS_STATS */ /* - * Display Asc Library dynamic configuration information - * for the board. + * Free the adv_req_t structure used with the command by adding + * it back to the board free list. */ - 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; + reqp->next_reqp = boardp->adv_reqp; + boardp->adv_reqp = reqp; - ASC_DBG(1, "totcnt %d\n", totcnt); + ASC_DBG(1, "adv_isr_callback: done\n"); - return totcnt; + return; } -#endif /* CONFIG_PROC_FS */ -static void asc_scsi_done(struct scsi_cmnd *scp) +/* + * adv_async_callback() - Adv Library asynchronous event callback function. + */ +static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) { - scsi_dma_unmap(scp); - ASC_STATS(scp->device->host, done); - scp->scsi_done(scp); -} + 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; -static void AscSetBank(PortAddr iop_base, uchar bank) -{ - uchar val; + 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; - 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; + 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; + + default: + ASC_DBG1(0, "DvcAsyncCallBack: unknown code 0x%x\n", code); + break; } - AscSetChipControl(iop_base, val); } -static void AscSetChipIH(PortAddr iop_base, ushort ins_code) +/* + * 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) { - AscSetBank(iop_base, 1); - AscWriteChipIH(iop_base, ins_code); - AscSetBank(iop_base, 0); + 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; } -static int AscStartChip(PortAddr iop_base) +/* + * 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) { - AscSetChipControl(iop_base, 0); - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - return (0); + 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 */ } - return (1); + ASC_DBG1(3, "asc_dequeue: reqp 0x%lx\n", (ulong)reqp); + return reqp; } -static int AscStopChip(PortAddr iop_base) +/* + * 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. + * + * 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. + * + * Unfortunately collecting queuing time statistics adds overhead to + * the function that isn't inherent to the function's algorithm. + */ +static REQP asc_dequeue_list(asc_queue_t *ascq, REQP *lastpp, int tid) { - uchar cc_val; + REQP firstp, lastp; + int i; - 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); -} + 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 int AscIsChipHalted(PortAddr iop_base) -{ - if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { - if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { - return (1); + /* + * 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); + } + } +#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]; + } else { + ASC_ASSERT(lastp != NULL); + lastp->host_scribble = + (unsigned char *)ascq->q_first[i]; + lastp = ascq->q_last[i]; + } + 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); + } } +#endif /* ADVANSYS_STATS */ } - return (0); + if (lastpp) { + *lastpp = lastp; + } + ASC_DBG1(3, "asc_dequeue_list: firstp 0x%lx\n", (ulong)firstp); + return firstp; } -static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc) +/* + * 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) { - PortAddr iop_base; - int i = 10; + REQP currp, prevp; + int tid; + int ret = ASC_FALSE; - 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)); -} + ASC_DBG2(3, "asc_rmqueue: ascq 0x%lx, reqp 0x%lx\n", + (ulong)ascq, (ulong)reqp); + ASC_ASSERT(reqp != NULL); -static int AscFindSignature(PortAddr iop_base) -{ - ushort sig_word; + tid = REQPTID(reqp); + ASC_ASSERT(tid >= 0 && tid <= ADV_MAX_TID); - 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); + /* + * 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); + /* + * 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. + * + * Set 'prevp' to the first entry, 'currp' to the second entry, + * and search for 'reqp'. + */ + 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; + } } } - return (0); +#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; } -static void AscEnableInterrupt(PortAddr iop_base) +/* + * Execute as many queued requests as possible for the specified queue. + * + * Calls asc_execute_scsi_cmnd() to execute a REQP/struct scsi_cmnd. + */ +static void asc_execute_queue(asc_queue_t *ascq) { - ushort cfg; + ADV_SCSI_BIT_ID_TYPE scan_tidmask; + REQP reqp; + int i; - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); + 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; } -static void AscDisableInterrupt(PortAddr iop_base) +#ifdef CONFIG_PROC_FS +/* + * asc_prt_board_devices() + * + * Print driver information for devices attached to the board. + * + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). + * + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. + */ +static int asc_prt_board_devices(struct Scsi_Host *shost, char *cp, int cplen) { - ushort cfg; + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + int chip_scsi_id; + int i; - cfg = AscGetChipCfgLsw(iop_base); - AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); -} + boardp = ASC_BOARDP(shost); + leftlen = cplen; + totlen = len = 0; -static uchar AscReadLramByte(PortAddr iop_base, ushort addr) -{ - unsigned char byte_data; - unsigned short word_data; + len = asc_prt_line(cp, leftlen, + "\nDevice Information for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); - if (isodd_word(addr)) { - AscSetChipLramAddr(iop_base, addr - 1); - word_data = AscGetChipLramData(iop_base); - byte_data = (word_data >> 8) & 0xFF; + if (ASC_NARROW_BOARD(boardp)) { + chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; } else { - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - byte_data = word_data & 0xFF; + chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; } - return byte_data; -} -static ushort AscReadLramWord(PortAddr iop_base, ushort addr) -{ - ushort word_data; + len = asc_prt_line(cp, leftlen, "Target IDs Detected:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if (boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) { + len = asc_prt_line(cp, leftlen, " %X,", i); + ASC_PRT_NEXT(); + } + } + len = asc_prt_line(cp, leftlen, " (%X=Host Adapter)\n", chip_scsi_id); + ASC_PRT_NEXT(); - AscSetChipLramAddr(iop_base, addr); - word_data = AscGetChipLramData(iop_base); - return (word_data); + return totlen; } -#if CC_VERY_LONG_SG_LIST -static ASC_DCNT AscReadLramDWord(PortAddr iop_base, ushort addr) +/* + * Display Wide Board BIOS Information. + */ +static int asc_prt_adv_bios(struct Scsi_Host *shost, char *cp, int cplen) { - 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 */ + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + ushort major, minor, letter; -static void -AscMemWordSetLram(PortAddr iop_base, ushort s_addr, ushort set_wval, int words) -{ - int i; + boardp = ASC_BOARDP(shost); + leftlen = cplen; + totlen = len = 0; - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < words; i++) { - AscSetChipLramData(iop_base, set_wval); - } -} + len = asc_prt_line(cp, leftlen, "\nROM BIOS Version: "); + ASC_PRT_NEXT(); -static void AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val) -{ - AscSetChipLramAddr(iop_base, addr); - AscSetChipLramData(iop_base, word_val); -} + /* + * If the BIOS saved a valid signature, then fill in + * the BIOS code segment base address. + */ + if (boardp->bios_signature != 0x55AA) { + len = asc_prt_line(cp, leftlen, "Disabled or Pre-3.1\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "BIOS either disabled or Pre-3.1. If it is pre-3.1, then a newer version\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "can be found at the ConnectCom FTP site: ftp://ftp.connectcom.net/pub\n"); + ASC_PRT_NEXT(); + } else { + major = (boardp->bios_version >> 12) & 0xF; + minor = (boardp->bios_version >> 8) & 0xF; + letter = (boardp->bios_version & 0xFF); -static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val) -{ - ushort word_data; + len = asc_prt_line(cp, leftlen, "%d.%d%c\n", + major, minor, + letter >= 26 ? '?' : letter + 'A'); + ASC_PRT_NEXT(); - 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); + /* + * Current available ROM BIOS release is 3.1I for UW + * and 3.2I for U2W. This code doesn't differentiate + * UW and U2W boards. + */ + if (major < 3 || (major <= 3 && minor < 1) || + (major <= 3 && minor <= 1 && letter < ('I' - 'A'))) { + len = asc_prt_line(cp, leftlen, + "Newer version of ROM BIOS is available at the ConnectCom FTP site:\n"); + ASC_PRT_NEXT(); + len = asc_prt_line(cp, leftlen, + "ftp://ftp.connectcom.net/pub\n"); + ASC_PRT_NEXT(); + } } - AscWriteLramWord(iop_base, addr, word_data); + + return totlen; } /* - * Copy 2 bytes to LRAM. + * Add serial number to information bar if signature AAh + * is found in at bit 15-9 (7 bits) of word 1. * - * The source data is assumed to be in little-endian order in memory - * and is maintained in little-endian order when written to LRAM. + * Serial Number consists fo 12 alpha-numeric digits. + * + * 1 - Product type (A,B,C,D..) Word0: 15-13 (3 bits) + * 2 - MFG Location (A,B,C,D..) Word0: 12-10 (3 bits) + * 3-4 - Product ID (0-99) Word0: 9-0 (10 bits) + * 5 - Product revision (A-J) Word0: " " + * + * Signature Word1: 15-9 (7 bits) + * 6 - Year (0-9) Word1: 8-6 (3 bits) & Word2: 15 (1 bit) + * 7-8 - Week of the year (1-52) Word1: 5-0 (6 bits) + * + * 9-12 - Serial Number (A001-Z999) Word2: 14-0 (15 bits) + * + * Note 1: Only production cards will have a serial number. + * + * Note 2: Signature is most significant 7 bits (0xFE). + * + * Returns ASC_TRUE if serial number found, otherwise returns ASC_FALSE. */ -static void -AscMemWordCopyPtrToLram(PortAddr iop_base, - ushort s_addr, uchar *s_buffer, int words) +static int asc_get_eeprom_string(ushort *serialnum, uchar *cp) { - int i; + ushort w, num; - AscSetChipLramAddr(iop_base, s_addr); - for (i = 0; i < 2 * words; i += 2) { + if ((serialnum[1] & 0xFE00) != ((ushort)0xAA << 8)) { + return ASC_FALSE; + } else { /* - * 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. + * First word - 6 digits. */ - outpw(iop_base + IOP_RAM_DATA, - ((ushort)s_buffer[i + 1] << 8) | s_buffer[i]); - } -} + w = serialnum[0]; -/* - * 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; + /* Product type - 1st digit. */ + if ((*cp = 'A' + ((w & 0xE000) >> 13)) == 'H') { + /* Product type is P=Prototype */ + *cp += 0x8; + } + cp++; - 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 */ + /* Manufacturing location - 2nd digit. */ + *cp++ = 'A' + ((w & 0x1C00) >> 10); + + /* Product ID - 3rd, 4th digits. */ + num = w & 0x3FF; + *cp++ = '0' + (num / 100); + num %= 100; + *cp++ = '0' + (num / 10); + + /* Product revision - 5th digit. */ + *cp++ = 'A' + (num % 10); + + /* + * Second word + */ + w = serialnum[1]; + + /* + * Year - 6th digit. + * + * If bit 15 of third word is set, then the + * last digit of the year is greater than 7. + */ + if (serialnum[2] & 0x8000) { + *cp++ = '8' + ((w & 0x1C0) >> 6); + } else { + *cp++ = '0' + ((w & 0x1C0) >> 6); + } + + /* Week of year - 7th, 8th digits. */ + num = w & 0x003F; + *cp++ = '0' + num / 10; + num %= 10; + *cp++ = '0' + num; + + /* + * Third word + */ + w = serialnum[2] & 0x7FFF; + + /* Serial number - 9th digit. */ + *cp++ = 'A' + (w / 1000); + + /* 10th, 11th, 12th digits. */ + num = w % 1000; + *cp++ = '0' + num / 100; + num %= 100; + *cp++ = '0' + num / 10; + num %= 10; + *cp++ = '0' + num; + + *cp = '\0'; /* Null Terminate the string. */ + return ASC_TRUE; } } /* - * Copy 2 bytes from LRAM. + * asc_prt_asc_board_eeprom() * - * The source data is assumed to be in little-endian order in LRAM - * and is maintained in little-endian order when written to memory. + * Print board EEPROM configuration. + * + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). + * + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. */ -static void -AscMemWordCopyPtrFromLram(PortAddr iop_base, - ushort s_addr, uchar *d_buffer, int words) +static int asc_prt_asc_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) { + asc_board_t *boardp; + ASC_DVC_VAR *asc_dvc_varp; + int leftlen; + int totlen; + int len; + ASCEEP_CONFIG *ep; int i; - ushort word; - - 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; +#ifdef CONFIG_ISA + int isa_dma_speed[] = { 10, 8, 7, 6, 5, 4, 3, 2 }; +#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; + + leftlen = cplen; + totlen = len = 0; + + len = asc_prt_line(cp, leftlen, + "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); + + if (asc_get_eeprom_string((ushort *)&ep->adapter_info[0], serialstr) + == ASC_TRUE) { + len = + asc_prt_line(cp, leftlen, " Serial Number: %s\n", + serialstr); + ASC_PRT_NEXT(); + } else { + if (ep->adapter_info[5] == 0xBB) { + len = asc_prt_line(cp, leftlen, + " Default Settings Used for EEPROM-less Adapter.\n"); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Serial Number Signature Not Present.\n"); + ASC_PRT_NEXT(); + } } -} -static ASC_DCNT AscMemSumLramWord(PortAddr iop_base, ushort s_addr, int words) -{ - ASC_DCNT sum; - int i; + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ASC_EEP_GET_CHIP_ID(ep), ep->max_total_qng, + ep->max_tag_qng); + ASC_PRT_NEXT(); - sum = 0L; - for (i = 0; i < words; i++, s_addr += 2) { - sum += AscReadLramWord(iop_base, s_addr); + len = asc_prt_line(cp, leftlen, + " cntl 0x%x, no_scam 0x%x\n", ep->cntl, ep->no_scam); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Target ID: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %d", i); + ASC_PRT_NEXT(); } - return (sum); -} + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); -static ushort AscInitLram(ASC_DVC_VAR *asc_dvc) -{ - uchar i; - ushort s_addr; - PortAddr iop_base; - ushort warn_code; + len = asc_prt_line(cp, leftlen, " Disconnects: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + disc_enable & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - 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); + len = asc_prt_line(cp, leftlen, " Command Queuing: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + use_cmd_qng & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); } - 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); + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Start Motor: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + start_motor & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); } - return warn_code; + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep-> + init_sdtr & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + +#ifdef CONFIG_ISA + if (asc_dvc_varp->bus_type & ASC_IS_ISA) { + len = asc_prt_line(cp, leftlen, + " Host ISA DMA speed: %d MB/S\n", + isa_dma_speed[ASC_EEP_GET_DMA_SPD(ep)]); + ASC_PRT_NEXT(); + } +#endif /* CONFIG_ISA */ + + return totlen; } -static ASC_DCNT -AscLoadMicroCode(PortAddr iop_base, - ushort s_addr, uchar *mcode_buf, ushort mcode_size) +/* + * asc_prt_adv_board_eeprom() + * + * Print board EEPROM configuration. + * + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). + * + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. + */ +static int asc_prt_adv_board_eeprom(struct Scsi_Host *shost, char *cp, int cplen) { - ASC_DCNT chksum; - ushort mcode_word_size; - ushort mcode_chksum; + asc_board_t *boardp; + ADV_DVC_VAR *adv_dvc_varp; + int leftlen; + int totlen; + int len; + int i; + char *termstr; + uchar serialstr[13]; + ADVEEP_3550_CONFIG *ep_3550 = NULL; + ADVEEP_38C0800_CONFIG *ep_38C0800 = NULL; + ADVEEP_38C1600_CONFIG *ep_38C1600 = NULL; + ushort word; + ushort *wordp; + ushort sdtr_speed = 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); + 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; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + ep_38C0800 = &boardp->eep_config.adv_38C0800_eep; + } else { + ep_38C1600 = &boardp->eep_config.adv_38C1600_eep; + } - 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; -} + leftlen = cplen; + totlen = len = 0; -/* 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, -}; + len = asc_prt_line(cp, leftlen, + "\nEEPROM Settings for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); -static unsigned short _asc_mcode_size = sizeof(_asc_mcode_buf); -static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + wordp = &ep_3550->serial_number_word1; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + wordp = &ep_38C0800->serial_number_word1; + } else { + wordp = &ep_38C1600->serial_number_word1; + } -/* 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, -}; + if (asc_get_eeprom_string(wordp, serialstr) == ASC_TRUE) { + len = + asc_prt_line(cp, leftlen, " Serial Number: %s\n", + serialstr); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Serial Number Signature Not Present.\n"); + ASC_PRT_NEXT(); + } -static unsigned short _adv_asc3550_size = sizeof(_adv_asc3550_buf); /* 0x13AD */ -static ADV_DCNT _adv_asc3550_chksum = 0x04D52DDDUL; /* Expanded little-endian checksum. */ + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_3550->adapter_scsi_id, + ep_3550->max_host_qng, ep_3550->max_dvc_qng); + ASC_PRT_NEXT(); + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_38C0800->adapter_scsi_id, + ep_38C0800->max_host_qng, + ep_38C0800->max_dvc_qng); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " Host SCSI ID: %u, Host Queue Size: %u, Device Queue Size: %u\n", + ep_38C1600->adapter_scsi_id, + ep_38C1600->max_host_qng, + ep_38C1600->max_dvc_qng); + ASC_PRT_NEXT(); + } + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->termination; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->termination_lvd; + } else { + word = ep_38C1600->termination_lvd; + } + switch (word) { + case 1: + termstr = "Low Off/High Off"; + break; + case 2: + termstr = "Low Off/High On"; + break; + case 3: + termstr = "Low On/High On"; + break; + default: + case 0: + termstr = "Automatic"; + break; + } -/* 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. */ + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_3550->termination, termstr, + ep_3550->bios_ctrl); + ASC_PRT_NEXT(); + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_38C0800->termination_lvd, termstr, + ep_38C0800->bios_ctrl); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + " termination: %u (%s), bios_ctrl: 0x%x\n", + ep_38C1600->termination_lvd, termstr, + ep_38C1600->bios_ctrl); + ASC_PRT_NEXT(); + } -/* 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, -}; + len = asc_prt_line(cp, leftlen, " Target ID: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %X", i); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); -static unsigned short _adv_asc38C1600_size = sizeof(_adv_asc38C1600_buf); /* 0x1673 */ -static ADV_DCNT _adv_asc38C1600_chksum = 0x0604EF77UL; /* Expanded little-endian checksum. */ + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->disc_enable; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->disc_enable; + } else { + word = ep_38C1600->disc_enable; + } + len = asc_prt_line(cp, leftlen, " Disconnects: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); -static void AscInitQLinkVar(ASC_DVC_VAR *asc_dvc) -{ - PortAddr iop_base; - int i; - ushort lram_addr; + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->tagqng_able; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->tagqng_able; + } else { + word = ep_38C1600->tagqng_able; + } + len = asc_prt_line(cp, leftlen, " Command Queuing: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - 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); + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->start_motor; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->start_motor; + } else { + word = ep_38C1600->start_motor; } -} - -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); - - 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]); + len = asc_prt_line(cp, leftlen, " Start Motor: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - 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); + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep_3550-> + sdtr_able & ADV_TID_TO_TIDMASK(i)) ? + 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + } - 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); + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + len = asc_prt_line(cp, leftlen, " Ultra Transfer: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (ep_3550-> + ultra_able & ADV_TID_TO_TIDMASK(i)) + ? 'Y' : 'N'); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); + } - 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 (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) { + word = ep_3550->wdtr_able; + } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) { + word = ep_38C0800->wdtr_able; + } else { + word = ep_38C1600->wdtr_able; } - if (AscStartChip(iop_base) != 1) { - asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; - return warn_code; + len = asc_prt_line(cp, leftlen, " Wide Transfer: "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + len = asc_prt_line(cp, leftlen, " %c", + (word & ADV_TID_TO_TIDMASK(i)) ? 'Y' : 'N'); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - return warn_code; -} - -static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) -{ - ushort warn_code; - PortAddr iop_base; + if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800 || + adv_dvc_varp->chip_type == ADV_CHIP_ASC38C1600) { + len = asc_prt_line(cp, leftlen, + " Synchronous Transfer Speed (Mhz):\n "); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + char *speed_str; - 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; + if (i == 0) { + sdtr_speed = adv_dvc_varp->sdtr_speed1; + } else if (i == 4) { + sdtr_speed = adv_dvc_varp->sdtr_speed2; + } else if (i == 8) { + sdtr_speed = adv_dvc_varp->sdtr_speed3; + } else if (i == 12) { + sdtr_speed = adv_dvc_varp->sdtr_speed4; + } + switch (sdtr_speed & ADV_MAX_TID) { + case 0: + speed_str = "Off"; + break; + case 1: + speed_str = " 5"; + break; + case 2: + speed_str = " 10"; + break; + case 3: + speed_str = " 20"; + break; + case 4: + speed_str = " 40"; + break; + case 5: + speed_str = " 80"; + break; + default: + speed_str = "Unk"; + break; + } + len = asc_prt_line(cp, leftlen, "%X:%s ", i, speed_str); + ASC_PRT_NEXT(); + if (i == 7) { + len = asc_prt_line(cp, leftlen, "\n "); + ASC_PRT_NEXT(); + } + sdtr_speed >>= 4; + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); } - warn_code |= AscInitMicroCodeVar(asc_dvc); - asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; - AscEnableInterrupt(iop_base); - return warn_code; + + return totlen; } /* - * Load the Microcode - * - * Write the microcode image to RISC memory starting at address 0. - * - * The microcode is stored compressed in the following format: - * - * 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. + * asc_prt_driver_conf() * - * 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. + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). * - * Returns 0 or an error if the checksum doesn't match + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. */ -static int AdvLoadMicrocode(AdvPortAddr iop_base, unsigned char *buf, int size, - int memsize, int chksum) +static int asc_prt_driver_conf(struct Scsi_Host *shost, char *cp, int cplen) { - int i, j, end, len = 0; - ADV_DCNT sum; - - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + asc_board_t *boardp; + int leftlen; + int totlen; + int len; + int chip_scsi_id; - 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; - } - } + boardp = ASC_BOARDP(shost); - end = len; + leftlen = cplen; + totlen = len = 0; - while (len < memsize) { - AdvWriteWordAutoIncLram(iop_base, 0); - len += 2; - } + len = asc_prt_line(cp, leftlen, + "\nLinux Driver Configuration and Information for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); - /* Verify the microcode checksum. */ - sum = 0; - AdvWriteWordRegister(iop_base, IOPW_RAM_ADDR, 0); + len = asc_prt_line(cp, leftlen, + " host_busy %u, last_reset %u, max_id %u, max_lun %u, max_channel %u\n", + shost->host_busy, shost->last_reset, shost->max_id, + shost->max_lun, shost->max_channel); + ASC_PRT_NEXT(); - for (len = 0; len < end; len += 2) { - sum += AdvReadWordAutoIncLram(iop_base); - } + len = asc_prt_line(cp, leftlen, + " unique_id %d, can_queue %d, this_id %d, sg_tablesize %u, cmd_per_lun %u\n", + shost->unique_id, shost->can_queue, shost->this_id, + shost->sg_tablesize, shost->cmd_per_lun); + ASC_PRT_NEXT(); - if (sum != chksum) - return ASC_IERR_MCODE_CHKSUM; + len = asc_prt_line(cp, leftlen, + " unchecked_isa_dma %d, use_clustering %d\n", + shost->unchecked_isa_dma, shost->use_clustering); + ASC_PRT_NEXT(); - return 0; -} + len = asc_prt_line(cp, leftlen, + " flags 0x%x, last_reset 0x%x, jiffies 0x%x, asc_n_io_port 0x%x\n", + boardp->flags, boardp->last_reset, jiffies, + boardp->asc_n_io_port); + ASC_PRT_NEXT(); -static void AdvBuildCarrierFreelist(struct adv_dvc_var *asc_dvc) -{ - ADV_CARR_T *carrp; - ADV_SDCNT buf_size; - ADV_PADDR carr_paddr; + /* '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); + ASC_PRT_NEXT(); - 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; + if (ASC_NARROW_BOARD(boardp)) { + chip_scsi_id = boardp->dvc_cfg.asc_dvc_cfg.chip_scsi_id; } else { - buf_size = ADV_CARRIER_BUFSIZE - sizeof(ADV_CARR_T); + chip_scsi_id = boardp->dvc_var.adv_dvc_var.chip_scsi_id; } - 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); -} + return totlen; +} /* - * Send an idle command to the chip and wait for completion. + * asc_prt_asc_board_info() * - * Command completion is polled for once per microsecond. + * Print dynamic board configuration information. * - * 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. + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). * - * Return Values: - * ADV_TRUE - command completed successfully - * ADV_FALSE - command failed - * ADV_ERROR - command timed out + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. */ -static int -AdvSendIdleCmd(ADV_DVC_VAR *asc_dvc, - ushort idle_cmd, ADV_DCNT idle_cmd_parameter) +static int asc_prt_asc_board_info(struct Scsi_Host *shost, char *cp, int cplen) { - int result; - ADV_DCNT i, j; - AdvPortAddr iop_base; + asc_board_t *boardp; + int chip_scsi_id; + int leftlen; + int totlen; + int len; + ASC_DVC_VAR *v; + ASC_DVC_CFG *c; + int i; + int renegotiate = 0; - iop_base = asc_dvc->iop_base; + 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; - /* - * 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); + leftlen = cplen; + totlen = len = 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); + len = asc_prt_line(cp, leftlen, + "\nAsc Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); - /* - * 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); + 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); + ASC_PRT_NEXT(); + + /* Current number of commands waiting for the host. */ + len = asc_prt_line(cp, leftlen, + " Total Command Pending: %d\n", v->cur_total_qng); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " Command Queuing:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (v-> + use_tagged_qng & ADV_TID_TO_TIDMASK(i)) ? + 'Y' : 'N'); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - /* 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); + /* Current number of commands waiting for a device. */ + len = asc_prt_line(cp, leftlen, " Command Queue Pending:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; } + len = asc_prt_line(cp, leftlen, " %X:%u", i, v->cur_dvc_qng[i]); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - BUG(); /* The idle command should never timeout. */ - return ADV_ERROR; -} + /* Current limit on number of commands that can be sent to a device. */ + len = asc_prt_line(cp, leftlen, " Command Queue Limit:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%u", i, v->max_dvc_qng[i]); + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); -/* - * 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; + /* Indicate whether the device has returned queue full status. */ + len = asc_prt_line(cp, leftlen, " Command Queue Full:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + if (boardp->queue_full & ADV_TID_TO_TIDMASK(i)) { + len = asc_prt_line(cp, leftlen, " %X:Y-%d", + i, boardp->queue_full_cnt[i]); + } else { + len = asc_prt_line(cp, leftlen, " %X:N", i); + } + ASC_PRT_NEXT(); + } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - /* - * 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; + len = asc_prt_line(cp, leftlen, " Synchronous Transfer:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ASC_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (v-> + sdtr_done & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - /* - * 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); + for (i = 0; i <= ASC_MAX_TID; i++) { + uchar syn_period_ix; - /* - * 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; + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || + ((v->init_sdtr & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:", i); + ASC_PRT_NEXT(); + + if ((boardp->sdtr_data[i] & ASC_SYN_MAX_OFFSET) == 0) { + len = asc_prt_line(cp, leftlen, " Asynchronous"); + ASC_PRT_NEXT(); + } else { + syn_period_ix = + (boardp->sdtr_data[i] >> 4) & (v->max_sdtr_index - + 1); + + len = asc_prt_line(cp, leftlen, + " Transfer Period Factor: %d (%d.%d Mhz),", + v->sdtr_period_tbl[syn_period_ix], + 250 / + v->sdtr_period_tbl[syn_period_ix], + ASC_TENTHS(250, + v-> + sdtr_period_tbl + [syn_period_ix])); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", + boardp-> + sdtr_data[i] & ASC_SYN_MAX_OFFSET); + ASC_PRT_NEXT(); + } + + if ((v->sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*\n"); + renegotiate = 1; + } else { + len = asc_prt_line(cp, leftlen, "\n"); + } + ASC_PRT_NEXT(); } - mdelay(asc_dvc->scsi_reset_wait * 1000); /* XXX: msleep? */ + if (renegotiate) { + len = asc_prt_line(cp, leftlen, + " * = Re-negotiation pending before next command.\n"); + ASC_PRT_NEXT(); + } - return status; + return totlen; } /* - * Initialize the ASC-3550. + * asc_prt_adv_board_info() * - * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. + * Print dynamic board configuration information. * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). * - * Needed after initialization for error recovery. + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. */ -static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) +static int asc_prt_adv_board_info(struct Scsi_Host *shost, char *cp, int cplen) { - AdvPortAddr iop_base; - ushort warn_code; - int begin_addr; - int end_addr; - ushort code_sum; - int word; + asc_board_t *boardp; + int leftlen; + int totlen; + int len; 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]; + ADV_DVC_VAR *v; + ADV_DVC_CFG *c; + AdvPortAddr iop_base; + ushort chip_scsi_id; + ushort lramword; + uchar lrambyte; + ushort tagqng_able; + ushort sdtr_able, wdtr_able; + ushort wdtr_done, sdtr_done; + ushort period = 0; + int renegotiate = 0; - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) - return ADV_ERROR; + boardp = ASC_BOARDP(shost); + v = &boardp->dvc_var.adv_dvc_var; + c = &boardp->dvc_cfg.adv_dvc_cfg; + iop_base = v->iop_base; + chip_scsi_id = v->chip_scsi_id; - /* - * 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; - } + leftlen = cplen; + totlen = len = 0; - warn_code = 0; - iop_base = asc_dvc->iop_base; + len = asc_prt_line(cp, leftlen, + "\nAdv Library Configuration and Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + 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, + " iop_base 0x%lx, cable_detect: %X, err_code %u\n", + v->iop_base, + AdvReadWordRegister(iop_base, + IOPW_SCSI_CFG1) & CABLE_DETECT, + v->err_code); + 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, + " 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); + 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]); + len = asc_prt_line(cp, leftlen, " Queuing Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } + + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (tagqng_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - 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; + len = asc_prt_line(cp, leftlen, " Queue Limit:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } - /* - * 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]); - } + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_MAX_CMD + i, + lrambyte); - /* - * 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); + len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); + ASC_PRT_NEXT(); } - AdvWriteWordLram(iop_base, ASC_MC_CODE_CHK_SUM, code_sum); + len = asc_prt_line(cp, leftlen, "\n"); + 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); + len = asc_prt_line(cp, leftlen, " Command Pending:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } - /* - * Set the chip type to indicate the ASC3550. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC3550); + AdvReadByteLram(iop_base, ASC_MC_NUMBER_OF_QUEUED_CMD + i, + lrambyte); - /* - * 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); + len = asc_prt_line(cp, leftlen, " %X:%d", i, lrambyte); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - /* - * 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); + AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, wdtr_able); + len = asc_prt_line(cp, leftlen, " Wide Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } - /* - * 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, " %X:%c", + i, + (wdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + 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))); + AdvReadWordLram(iop_base, ASC_MC_WDTR_DONE, wdtr_done); + len = asc_prt_line(cp, leftlen, " Transfer Bit Width:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; } - 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. - */ + AdvReadWordLram(iop_base, + ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), + lramword); - /* Read current SCSI_CFG1 Register value. */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + len = asc_prt_line(cp, leftlen, " %X:%d", + i, (lramword & 0x8000) ? 16 : 8); + ASC_PRT_NEXT(); - /* - * 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 ((wdtr_able & ADV_TID_TO_TIDMASK(i)) && + (wdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*"); + ASC_PRT_NEXT(); + renegotiate = 1; + } } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - /* - * 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; - } + AdvReadWordLram(iop_base, ASC_MC_SDTR_ABLE, sdtr_able); + len = asc_prt_line(cp, leftlen, " Synchronous Enabled:"); + ASC_PRT_NEXT(); + for (i = 0; i <= ADV_MAX_TID; i++) { + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; + } - /* - * 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; + len = asc_prt_line(cp, leftlen, " %X:%c", + i, + (sdtr_able & ADV_TID_TO_TIDMASK(i)) ? 'Y' : + 'N'); + ASC_PRT_NEXT(); } + len = asc_prt_line(cp, leftlen, "\n"); + ASC_PRT_NEXT(); - /* - * 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; + AdvReadWordLram(iop_base, ASC_MC_SDTR_DONE, sdtr_done); + for (i = 0; i <= ADV_MAX_TID; i++) { - /* 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; + AdvReadWordLram(iop_base, + ASC_MC_DEVICE_HSHK_CFG_TABLE + (2 * i), + lramword); + lramword &= ~0x8000; - /* TERM_CTL_H: off, TERM_CTL_L: off */ - case 0x2: - case 0x6: - break; + if ((chip_scsi_id == i) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(i)) == 0) || + ((sdtr_able & ADV_TID_TO_TIDMASK(i)) == 0)) { + continue; } - } - /* - * 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)); + len = asc_prt_line(cp, leftlen, " %X:", i); + ASC_PRT_NEXT(); - /* - * 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); + if ((lramword & 0x1F) == 0) { /* Check for REQ/ACK Offset 0. */ + len = asc_prt_line(cp, leftlen, " Asynchronous"); + ASC_PRT_NEXT(); + } else { + len = + asc_prt_line(cp, leftlen, + " Transfer Period Factor: "); + ASC_PRT_NEXT(); - /* - * 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); + if ((lramword & 0x1F00) == 0x1100) { /* 80 Mhz */ + len = + asc_prt_line(cp, leftlen, "9 (80.0 Mhz),"); + ASC_PRT_NEXT(); + } else if ((lramword & 0x1F00) == 0x1000) { /* 40 Mhz */ + len = + asc_prt_line(cp, leftlen, "10 (40.0 Mhz),"); + ASC_PRT_NEXT(); + } else { /* 20 Mhz or below. */ - /* - * 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)); + period = (((lramword >> 8) * 25) + 50) / 4; - AdvBuildCarrierFreelist(asc_dvc); + if (period == 0) { /* Should never happen. */ + len = + asc_prt_line(cp, leftlen, + "%d (? Mhz), "); + ASC_PRT_NEXT(); + } else { + len = asc_prt_line(cp, leftlen, + "%d (%d.%d Mhz),", + period, 250 / period, + ASC_TENTHS(250, + period)); + ASC_PRT_NEXT(); + } + } - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ + len = asc_prt_line(cp, leftlen, " REQ/ACK Offset: %d", + lramword & 0x1F); + ASC_PRT_NEXT(); + } - if ((asc_dvc->icq_sp = asc_dvc->carr_freelist) == NULL) { - asc_dvc->err_code |= ASC_IERR_NO_CARRIER; - return ADV_ERROR; + if ((sdtr_done & ADV_TID_TO_TIDMASK(i)) == 0) { + len = asc_prt_line(cp, leftlen, "*\n"); + renegotiate = 1; + } else { + len = asc_prt_line(cp, leftlen, "\n"); + } + ASC_PRT_NEXT(); } - 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; + if (renegotiate) { + len = asc_prt_line(cp, leftlen, + " * = Re-negotiation pending before next command.\n"); + ASC_PRT_NEXT(); } - 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; + return totlen; +} - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | - ADV_INTR_ENABLE_GLOBAL_INTR)); +/* + * asc_proc_copy() + * + * Copy proc information to a read buffer taking into account the current + * read offset in the file and the remaining space in the read buffer. + */ +static int +asc_proc_copy(off_t advoffset, off_t offset, char *curbuf, int leftlen, + char *cp, int cplen) +{ + int cnt = 0; - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); + ASC_DBG3(2, "asc_proc_copy: 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", + (ulong)curbuf, (ulong)cp, cnt); + memcpy(curbuf, cp, cnt); + } else if (offset < advoffset + cplen) { + /* Read offset within current range, partial copy. */ + 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", + (ulong)curbuf, (ulong)cp, cnt); + memcpy(curbuf, cp, cnt); + } + return cnt; +} - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); +/* + * asc_prt_line() + * + * If 'cp' is NULL print to the console, otherwise print to a buffer. + * + * 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 int asc_prt_line(char *buf, int buflen, char *fmt, ...) +{ + va_list args; + int ret; + char s[ASC_PRTLINE_SIZE]; - /* - * 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; - } - } + va_start(args, fmt); + ret = vsprintf(s, fmt, args); + ASC_ASSERT(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; +} +#endif /* CONFIG_PROC_FS */ - return warn_code; +/* + * --- Functions Required by the Asc Library + */ + +/* + * 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) +{ + ASC_DBG1(4, "DvcSleepMilliSecond: %lu\n", (ulong)n); + mdelay(n); } /* - * Initialize the ASC-38C0800. - * - * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. + * Currently and inline noop but leave as a placeholder. + * Leave DvcEnterCritical() as a noop placeholder. + */ +static inline ulong DvcEnterCritical(void) +{ + return 0; +} + +/* + * Critical sections are all protected by the board spinlock. + * Leave DvcLeaveCritical() as a noop placeholder. + */ +static inline void DvcLeaveCritical(ulong flags) +{ + return; +} + +/* + * void + * DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. + * Calling/Exit State: + * none * - * Needed after initialization for error recovery. + * Description: + * Output an ASC_SCSI_Q structure to the chip */ -static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) +static void +DvcPutScsiQ(PortAddr iop_base, ushort s_addr, uchar *outbuf, int words) { - 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]; - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) - return ADV_ERROR; + 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]); + } +} - /* - * 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; +/* + * 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); +} - warn_code = 0; - iop_base = asc_dvc->iop_base; +/* + * Read a PCI configuration byte. + */ +static uchar __init DvcReadPCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset) +{ +#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) */ +} + +/* + * Write a PCI configuration byte. + */ +static void __init +DvcWritePCIConfigByte(ASC_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) +{ +#ifdef CONFIG_PCI + pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); +#endif /* CONFIG_PCI */ +} + +/* + * 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) +{ + ushort cfg_lsw; + ushort bios_addr; /* - * 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. + * 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. */ - for (i = 0; i < ASC_MC_BIOSLEN / 2; i++) { - AdvReadWordLram(iop_base, ASC_MC_BIOSMEM + (2 * i), - bios_mem[i]); + if (bus_type & ASC_IS_PCI) { + return (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); /* - * Save current per TID negotiated values. + * ISA PnP uses the top bit as the 32K BIOS flag */ - 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]); + if (bus_type == ASC_IS_ISAPNP) { + cfg_lsw &= 0x7FFF; } + /* if */ + bios_addr = (ushort)(((cfg_lsw >> 12) * ASC_BIOS_BANK_SIZE) + + ASC_BIOS_MIN_ADDR); + return (bios_addr); +} - /* - * 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. - */ +/* + * --- Functions Required by the Adv Library + */ - /* - * 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; - } +/* + * DvcGetPhyAddr() + * + * 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. + * + * Note: Because Linux currently doesn't page the kernel and all + * kernel buffers are physically contiguous, leave '*lenp' unchanged. + */ +ADV_PADDR +DvcGetPhyAddr(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq, + uchar *vaddr, ADV_SDCNT *lenp, int flag) +{ + ADV_PADDR paddr; - 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; - } - } + paddr = virt_to_bus(vaddr); - /* - * 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_DBG4(4, + "DvcGetPhyAddr: vaddr 0x%lx, lenp 0x%lx *lenp %lu, paddr 0x%lx\n", + (ulong)vaddr, (ulong)lenp, (ulong)*((ulong *)lenp), + (ulong)paddr); - 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; - } + return paddr; +} - /* We need to reset back to normal mode after LRAM test passes. */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); +/* + * Read a PCI configuration byte. + */ +static uchar __init DvcAdvReadPCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset) +{ +#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 */ +} - 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; +/* + * Write a PCI configuration byte. + */ +static void __init +DvcAdvWritePCIConfigByte(ADV_DVC_VAR *asc_dvc, ushort offset, uchar byte_data) +{ +#ifdef CONFIG_PCI + pci_write_config_byte(to_pci_dev(asc_dvc->cfg->dev), offset, byte_data); +#else /* CONFIG_PCI */ + return; +#endif /* CONFIG_PCI */ +} - /* - * 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]); - } +/* + * --- Tracing and Debugging Functions + */ - /* - * 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); +#ifdef ADVANSYS_STATS +#ifdef CONFIG_PROC_FS +/* + * asc_prt_board_stats() + * + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). + * + * 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) +{ + int leftlen; + int totlen; + int len; + struct asc_stats *s; + asc_board_t *boardp; - /* - * 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); + leftlen = cplen; + totlen = len = 0; - /* - * Set the chip type to indicate the ASC38C0800. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C0800); + boardp = ASC_BOARDP(shost); + s = &boardp->asc_stats; - /* - * 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); + len = asc_prt_line(cp, leftlen, + "\nLinux Driver Statistics for AdvanSys SCSI Host %d:\n", + shost->host_no); + ASC_PRT_NEXT(); - /* - * 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); - } + 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(); - /* - * 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); + 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(); /* - * 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. + * Display data transfer statistics. */ - 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); + if (s->cont_cnt > 0) { + len = asc_prt_line(cp, leftlen, " cont_cnt %lu, ", s->cont_cnt); + ASC_PRT_NEXT(); + + len = asc_prt_line(cp, leftlen, "cont_xfer %lu.%01lu kb ", + s->cont_xfer / 2, + ASC_TENTHS(s->cont_xfer, 2)); + ASC_PRT_NEXT(); + + /* 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(); } - /* - * 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); + if (s->sg_cnt > 0) { - /* - * 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, " sg_cnt %lu, sg_elem %lu, ", + s->sg_cnt, s->sg_elem); + 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. - */ + 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(); - /* Read current SCSI_CFG1 Register value. */ - scsi_cfg1 = AdvReadWordRegister(iop_base, IOPW_SCSI_CFG1); + /* 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(); - /* - * 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; - } + 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(); - /* - * 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; + 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(); } /* - * 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. + * Display request queuing statistics. */ - 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; + len = asc_prt_line(cp, leftlen, + " Active and Waiting Request Queues (Time Unit: %d HZ):\n", + HZ); + ASC_PRT_NEXT(); - /* TERM_SE_HI: on, TERM_SE_LO: off */ - case 0x0: - asc_dvc->cfg->termination |= TERM_SE_HI; - break; - } - } + return totlen; +} - 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; +/* + * asc_prt_target_stats() + * + * Note: no single line should be greater than ASC_PRTLINE_SIZE, + * cf. asc_prt_line(). + * + * This is separated from asc_prt_board_stats because a full set + * of targets will overflow ASC_PRTBUF_SIZE. + * + * Return the number of characters copied into 'cp'. No more than + * 'cplen' characters will be copied to 'cp'. + */ +static int +asc_prt_target_stats(struct Scsi_Host *shost, int tgt_id, char *cp, int cplen) +{ + 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; - /* TERM_LVD_HI: off, TERM_LVD_LO: off */ - case 0x0: - break; - } + leftlen = cplen; + totlen = len = 0; + + boardp = ASC_BOARDP(shost); + s = &boardp->asc_stats; + + active = &ASC_BOARDP(shost)->active; + waiting = &ASC_BOARDP(shost)->waiting; + + 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; } - /* - * Clear any set TERM_SE and TERM_LVD bits. - */ - scsi_cfg1 &= (~TERM_SE & ~TERM_LVD); + if ((chip_scsi_id == tgt_id) || + ((boardp->init_tidmask & ADV_TID_TO_TIDMASK(tgt_id)) == 0)) { + return 0; + } - /* - * Invert the TERM_SE and TERM_LVD bits and then set 'scsi_cfg1'. - */ - scsi_cfg1 |= (~asc_dvc->cfg->termination & 0xF0); + 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(); - /* - * 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); + 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(); - /* - * 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); + 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(); + } + } while (0); - /* - * 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); + return totlen; +} +#endif /* CONFIG_PROC_FS */ +#endif /* ADVANSYS_STATS */ - /* - * 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)); +#ifdef ADVANSYS_DEBUG +/* + * asc_prt_scsi_host() + */ +static void asc_prt_scsi_host(struct Scsi_Host *s) +{ + asc_board_t *boardp; - AdvBuildCarrierFreelist(asc_dvc); + boardp = ASC_BOARDP(s); - /* - * Set-up the Host->RISC Initiator Command Queue (ICQ). - */ + 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); - 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(" 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); - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + printk(" dma_channel %d, this_id %d, can_queue %d,\n", + s->dma_channel, s->this_id, s->can_queue); - /* - * 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); + printk(" cmd_per_lun %d, sg_tablesize %d, unchecked_isa_dma %d\n", + s->cmd_per_lun, s->sg_tablesize, s->unchecked_isa_dma); - /* - * 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; + 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); } - 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); +/* + * 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); - /* - * 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; + 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); - AdvWriteByteRegister(iop_base, IOPB_INTR_ENABLES, - (ADV_INTR_ENABLE_HOST_INTR | - ADV_INTR_ENABLE_GLOBAL_INTR)); + asc_prt_hex(" CDB", s->cmnd, s->cmd_len); - AdvReadWordLram(iop_base, ASC_MC_CODE_BEGIN_ADDR, word); - AdvWriteWordRegister(iop_base, IOPW_PC, word); + printk("sc_data_direction %u, resid %d\n", + s->sc_data_direction, s->resid); - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + printk(" use_sg %u, sglist_len %u\n", s->use_sg, s->sglist_len); - /* - * 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; - } - } - } + printk(" serial_number 0x%x, retries %d, allowed %d\n", + (unsigned)s->serial_number, s->retries, s->allowed); - return warn_code; + printk(" timeout_per_command %d\n", s->timeout_per_command); + + 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); + + printk(" tag %u, pid %u\n", (unsigned)s->tag, (unsigned)s->pid); } /* - * 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. + * asc_prt_asc_dvc_var() */ -static int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) +static void asc_prt_asc_dvc_var(ASC_DVC_VAR *h) { - 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_DVC_VAR at addr 0x%lx\n", (ulong)h); - /* If there is already an error, don't continue. */ - if (asc_dvc->err_code != 0) { - return ADV_ERROR; - } + 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); - /* - * 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 + (" 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); - warn_code = 0; - iop_base = asc_dvc->iop_base; + 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); - /* - * 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]); - } + 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); - /* - * 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]); - } + 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); - /* - * 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. - */ + 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); - /* - * 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; - } + printk(" cfg 0x%lx, irq_no 0x%x\n", (ulong)h->cfg, (unsigned)h->irq_no); +} - 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_dvc_cfg() + */ +static void asc_prt_asc_dvc_cfg(ASC_DVC_CFG *h) +{ + printk("ASC_DVC_CFG at addr 0x%lx\n", (ulong)h); - /* - * 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. */ + 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); - 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 + (" 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); - /* We need to reset back to normal mode after LRAM test passes. */ - AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + 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); - 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(" mcode_version %d, overrun_buf 0x%lx\n", + h->mcode_version, (ulong)h->overrun_buf); +} - /* - * 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]); - } +/* + * asc_prt_asc_scsi_q() + */ +static void asc_prt_asc_scsi_q(ASC_SCSI_Q *q) +{ + ASC_SG_HEAD *sgp; + int 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); + printk("ASC_SCSI_Q at addr 0x%lx\n", (ulong)q); - /* - * 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 + (" 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); - /* - * Set the chip type to indicate the ASC38C1600. - */ - AdvWriteWordLram(iop_base, ASC_MC_CHIP_TYPE, ADV_CHIP_ASC38C1600); + 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); - /* - * 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); + 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); - /* - * 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 (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)); + } - /* - * 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); +/* + * 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); +} - /* - * 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_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); - /* - * 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(" iop_base 0x%lx, err_code 0x%x, ultra_able 0x%x\n", + (ulong)h->iop_base, h->err_code, (unsigned)h->ultra_able); - /* - * 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; - } + 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); - /* - * 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(" 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); - /* - * 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(" 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); - 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(" icq_sp 0x%lx, irq_sp 0x%lx\n", + (ulong)h->icq_sp, (ulong)h->irq_sp); - /* - * Clear any set TERM_SE bits. - */ - scsi_cfg1 &= ~TERM_SE; + printk(" no_scam 0x%x, tagqng_able 0x%x\n", + (unsigned)h->no_scam, (unsigned)h->tagqng_able); - /* - * Invert the TERM_SE bits and then set 'scsi_cfg1'. - */ - scsi_cfg1 |= (~asc_dvc->cfg->termination & TERM_SE); + printk(" chip_scsi_id 0x%x, cfg 0x%lx\n", + (unsigned)h->chip_scsi_id, (ulong)h->cfg); +} - /* - * 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); +/* + * 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); - /* - * 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); + printk(" disc_enable 0x%x, termination 0x%x\n", + h->disc_enable, h->termination); - /* - * 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); + printk(" chip_version 0x%x, mcode_date 0x%x\n", + h->chip_version, h->mcode_date); - /* - * 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(" 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); - AdvBuildCarrierFreelist(asc_dvc); + printk(" control_flag 0x%x, pci_slot_info 0x%x\n", + h->control_flag, h->pci_slot_info); +} - /* - * 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)); +/* + * 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; - /* - * The first command issued will be placed in the stopper carrier. - */ - asc_dvc->icq_sp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); + printk("ADV_SCSI_REQ_Q at addr 0x%lx\n", (ulong)q); - /* - * 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)); + 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); - /* - * 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)); + 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); - /* - * 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); + 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); - /* - * 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; + 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); - 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); + printk(" sg_working_ix 0x%x, target_cmd %u\n", + q->sg_working_ix, q->target_cmd); - /* finally, finally, gentlemen, start your engine */ - AdvWriteWordRegister(iop_base, IOPW_RISC_CSR, ADV_RISC_CSR_RUN); + 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); - /* - * 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) { + /* Display the request's ADV_SG_BLOCK structures. */ + if (q->sg_list_ptr != NULL) { + sg_blk_cnt = 0; + while (1) { /* - * Restore per TID negotiated values. + * '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. */ - 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_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; } + sg_blk_cnt++; } } - - return warn_code; } /* - * Reset chip and SCSI Bus. + * asc_prt_adv_sgblock() * - * Return Value: - * ADV_TRUE(1) - Chip re-initialization and SCSI Bus Reset successful. - * ADV_FALSE(0) - Chip re-initialization and SCSI Bus Reset failure. + * Display an ADV_SG_BLOCK structure. */ -static int AdvResetChipAndSB(ADV_DVC_VAR *asc_dvc) +static void asc_prt_adv_sgblock(int sgblockno, ADV_SG_BLOCK *b) { - 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; - - iop_base = asc_dvc->iop_base; + int 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); - if (asc_dvc->chip_type == ADV_CHIP_ASC38C1600) { - AdvReadWordLram(iop_base, ASC_MC_PPR_ABLE, ppr_able); + 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); } - 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 (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); } +} - /* - * 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); +/* + * 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; - /* - * 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); + printk("%s: (%d bytes)\n", f, l); - /* - * 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 (i = 0; i < l; i += 32) { - /* Translate initialization return value to status value. */ - if (status == 0) { - status = ADV_TRUE; - } else { - status = ADV_FALSE; - } + /* Display a maximum of 8 double-words per line. */ + if ((k = (l - i) / 4) >= 8) { + k = 8; + m = 0; + } else { + m = (l - i) % 4; + } - /* - * Restore the BIOS signature word. - */ - AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + 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]); + } - /* - * 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]); - } + 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; + } - return status; + printk("\n"); + } } +#endif /* ADVANSYS_DEBUG */ /* - * adv_async_callback() - Adv Library asynchronous event callback function. + * --- Asc Library Functions */ -static void adv_async_callback(ADV_DVC_VAR *adv_dvc_varp, uchar code) + +static ushort __init AscGetEisaChipCfg(PortAddr iop_base) { - 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; + PortAddr 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; + eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | + (PortAddr) (ASC_EISA_CFG_IOP_MASK); + return (inpw(eisa_cfg_iop)); +} - case ADV_HOST_SCSI_BUS_RESET: - /* - * Host generated SCSI bus reset occurred. - */ - ASC_DBG(0, "ADV_HOST_SCSI_BUS_RESET\n"); - break; +static uchar __init AscSetChipScsiID(PortAddr iop_base, uchar new_host_id) +{ + ushort cfg_lsw; - default: - ASC_DBG(0, "unknown code 0x%x\n", code); - break; + if (AscGetChipScsiID(iop_base) == new_host_id) { + return (new_host_id); } + 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)); } -/* - * 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) +static uchar __init AscGetChipScsiCtrl(PortAddr iop_base) { - struct asc_board *boardp; - adv_req_t *reqp; - adv_sgblk_t *sgblkp; - struct scsi_cmnd *scp; - struct Scsi_Host *shost; - ADV_DCNT resid_cnt; + uchar 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); + AscSetBank(iop_base, 1); + sc = inp(iop_base + IOP_REG_SC); + AscSetBank(iop_base, 0); + return (sc); +} - /* - * 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; +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)); } + return (AscGetChipVerNo(iop_base)); +} - /* - * 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; +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); } - 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); + 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); + } + return (ASC_IS_ISA); + } else if ((chip_ver >= ASC_CHIP_MIN_VER_PCI) && + (chip_ver <= ASC_CHIP_MAX_VER_PCI)) { + return (ASC_IS_PCI); + } + return (0); +} - boardp = shost_priv(shost); - BUG_ON(adv_dvc_varp != &boardp->dvc_var.adv_dvc_var); +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; - /* - * '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; + /* 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); - /* - * 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); - } - break; + 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); +} - 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; +static int AscFindSignature(PortAddr iop_base) +{ + ushort sig_word; - 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; + 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); } - 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; - } - - /* - * 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); } + return (0); +} - asc_scsi_done(scp); +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 +}; - /* - * 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; +#ifdef CONFIG_ISA +static uchar _isa_pnp_inited __initdata = 0; - /* Add 'sgblkp' to the board free list. */ - sgblkp->next_sgblkp = boardp->adv_sgblkp; - boardp->adv_sgblkp = sgblkp; +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); + } + } + return (0); + } + 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); + } + } + return (0); + } + if (bus_type & ASC_IS_EISA) { + if ((iop_beg = AscSearchIOPortAddrEISA(iop_beg)) != 0) { + return (iop_beg); + } + return (0); } + return (0); +} - /* - * 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; +static PortAddr __init AscSearchIOPortAddr11(PortAddr s_addr) +{ + int i; + PortAddr iop_base; - ASC_DBG(1, "done\n"); + for (i = 0; i < ASC_IOADR_TABLE_MAX_IX; i++) { + if (_asc_def_iop_base[i] > s_addr) { + 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); + } + } + return (0); } -/* - * 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) +static void __init AscSetISAPNPWaitForKey(void) { - AdvPortAddr iop_base; - uchar int_stat; - ushort target_bit; - ADV_CARR_T *free_carrp; - ADV_VADDR irq_next_vpa; - ADV_SCSI_REQ_Q *scsiq; + outp(ASC_ISA_PNP_PORT_ADDR, 0x02); + outp(ASC_ISA_PNP_PORT_WRITE, 0x02); + return; +} +#endif /* CONFIG_ISA */ - iop_base = asc_dvc->iop_base; +static void __init AscToggleIRQAct(PortAddr iop_base) +{ + AscSetChipStatus(iop_base, CIW_IRQ_ACT); + AscSetChipStatus(iop_base, 0); + return; +} - /* Reading the register clears the interrupt. */ - int_stat = AdvReadByteRegister(iop_base, IOPB_INTR_STATUS_REG); +static uchar __init AscGetChipIRQ(PortAddr iop_base, ushort bus_type) +{ + ushort cfg_lsw; + uchar chip_irq; - if ((int_stat & (ADV_INTR_STATUS_INTRA | ADV_INTR_STATUS_INTRB | - ADV_INTR_STATUS_INTRC)) == 0) { - return ADV_FALSE; + 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)); +} - /* - * 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; - - AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); +static uchar __init +AscSetChipIRQ(PortAddr iop_base, uchar irq_no, ushort bus_type) +{ + ushort cfg_lsw; - 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 ((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)); } } + 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)); + } + return (0); +} - adv_async_callback(asc_dvc, intrb_code); +#ifdef CONFIG_ISA +static void __init AscEnableIsaDma(uchar dma_channel) +{ + 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; +} +#endif /* CONFIG_ISA */ - /* - * 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)); +static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) +{ + EXT_MSG ext_msg; + EXT_MSG out_msg; + ushort halt_q_addr; + int sdtr_accept; + ushort int_halt_code; + ASC_SCSI_BIT_ID_TYPE scsi_busy; + ASC_SCSI_BIT_ID_TYPE target_id; + PortAddr iop_base; + uchar tag_code; + uchar q_status; + uchar halt_qp; + uchar sdtr_data; + uchar target_ix; + uchar q_cntl, tid_no; + uchar cur_dvc_qng; + uchar asyn_sdtr; + uchar scsi_status; + asc_board_t *boardp; - /* - * 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; - } + ASC_ASSERT(asc_dvc->drv_ptr != NULL); + boardp = asc_dvc->drv_ptr; - /* - * 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... - */ - } - 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 err_code; -} - -static void AscAckInterrupt(PortAddr iop_base) -{ - uchar host_flag; - uchar risc_flag; - ushort loop; - - 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; - } - } - AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); -} - -static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) -{ - 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); - } -} - -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; - - 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 -AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset) -{ - uchar byte; - uchar sdtr_period_ix; - - 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 int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data) -{ - ASC_SCSI_BIT_ID_TYPE org_id; - int i; - int sta = TRUE; - - 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; - } - } else { - sta = FALSE; - } - AscSetBank(iop_base, 1); - AscWriteChipDvcID(iop_base, org_id); - AscSetBank(iop_base, 0); - return (sta); -} - -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); -} - -static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) -{ - EXT_MSG ext_msg; - EXT_MSG out_msg; - ushort halt_q_addr; - int sdtr_accept; - ushort int_halt_code; - ASC_SCSI_BIT_ID_TYPE scsi_busy; - ASC_SCSI_BIT_ID_TYPE target_id; - PortAddr iop_base; - uchar tag_code; - uchar q_status; - uchar halt_qp; - uchar sdtr_data; - uchar target_ix; - uchar q_cntl, tid_no; - uchar cur_dvc_qng; - uchar asyn_sdtr; - uchar scsi_status; - struct asc_board *boardp; - - BUG_ON(!asc_dvc->drv_ptr); - boardp = asc_dvc->drv_ptr; - - iop_base = asc_dvc->iop_base; - int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); + iop_base = asc_dvc->iop_base; + int_halt_code = AscReadLramWord(iop_base, ASCV_HALTCODE_W); halt_qp = AscReadLramByte(iop_base, ASCV_CURCDB_B); halt_q_addr = ASC_QNO_TO_QADDR(halt_qp); 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); @@ -8634,13 +8566,14 @@ 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 == EXTENDED_MESSAGE && - ext_msg.msg_req == EXTENDED_SDTR && + if (ext_msg.msg_type == MS_EXTEND && + ext_msg.msg_req == MS_SDTR_CODE && ext_msg.msg_len == MS_SDTR_LEN) { sdtr_accept = TRUE; if ((ext_msg.req_ack_offset > ASC_SYN_MAX_OFFSET)) { @@ -8649,14 +8582,15 @@ 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->min_sdtr_index]) + asc_dvc->sdtr_period_tbl[asc_dvc-> + host_init_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-> - min_sdtr_index]; + host_init_sdtr_index]; } if (sdtr_accept) { sdtr_data = @@ -8680,6 +8614,7 @@ 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; @@ -8694,6 +8629,7 @@ 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, @@ -8719,8 +8655,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 == EXTENDED_MESSAGE && - ext_msg.msg_req == EXTENDED_WDTR && + } else if (ext_msg.msg_type == MS_EXTEND && + ext_msg.msg_req == MS_WDTR_CODE && ext_msg.msg_len == MS_WDTR_LEN) { ext_msg.wdtr_width = 0; @@ -8813,9 +8749,9 @@ static int AscIsrChipHalted(ASC_DVC_VAR *asc_dvc) (uchar *)&out_msg, sizeof(EXT_MSG) >> 1); - if ((out_msg.msg_type == EXTENDED_MESSAGE) && + if ((out_msg.msg_type == MS_EXTEND) && (out_msg.msg_len == MS_SDTR_LEN) && - (out_msg.msg_req == EXTENDED_SDTR)) { + (out_msg.msg_req == MS_SDTR_CODE)) { asc_dvc->init_sdtr &= ~target_id; asc_dvc->sdtr_done &= ~target_id; @@ -8861,9 +8797,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] = @@ -8889,8 +8825,9 @@ 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); @@ -8942,8 +8879,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 { @@ -9034,34 +8971,6 @@ 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, @@ -9105,146 +9014,31 @@ _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) +static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) { - 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) -{ - uchar next_qp; - uchar n_q_used; - uchar sg_list_qp; - uchar sg_queue_cnt; - uchar q_cnt; - uchar done_q_tail; - uchar tid_no; - ASC_SCSI_BIT_ID_TYPE scsi_busy; - ASC_SCSI_BIT_ID_TYPE target_id; - PortAddr iop_base; - ushort q_addr; - ushort sg_q_addr; - uchar cur_target_qng; - ASC_QDONE_INFO scsiq_buf; - ASC_QDONE_INFO *scsiq; - int false_overrun; + uchar next_qp; + uchar n_q_used; + uchar sg_list_qp; + uchar sg_queue_cnt; + uchar q_cnt; + uchar done_q_tail; + uchar tid_no; + ASC_SCSI_BIT_ID_TYPE scsi_busy; + ASC_SCSI_BIT_ID_TYPE target_id; + PortAddr iop_base; + ushort q_addr; + ushort sg_q_addr; + uchar cur_target_qng; + 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); @@ -9347,7 +9141,7 @@ static int AscIsrQDone(ASC_DVC_VAR *asc_dvc) AscSetChipControl(iop_base, (uchar)(CC_SCSI_RESET | CC_HALT)); - udelay(60); + DvcDelayNanoSecond(asc_dvc, 60000); AscSetChipControl(iop_base, CC_HALT); AscSetChipStatus(iop_base, CIW_CLR_SCSI_RESET_INT); @@ -9356,7 +9150,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) @@ -9374,7 +9168,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); } @@ -9396,19 +9190,22 @@ 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) { - return ERR; + if (((asc_dvc->init_state & ASC_INIT_STATE_END_LOAD_MC) == 0) + || (asc_dvc->isr_callback == 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); @@ -9423,7 +9220,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)) { - mdelay(100); + DvcSleepMilliSecond(100); } AscSetChipControl(iop_base, (CC_CHIP_RESET | CC_HALT)); AscSetChipControl(iop_base, CC_HALT); @@ -9438,7 +9235,9 @@ 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)) { @@ -9469,1745 +9268,1590 @@ 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); } -/* - * 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; - - ASC_DBG(1, "0x%p\n", scp); - - ASC_STATS(shost, reset); +/* 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, +}; - scmd_printk(KERN_INFO, scp, "SCSI bus reset started...\n"); +static ushort _asc_mcode_size = sizeof(_asc_mcode_buf); +static ADV_DCNT _asc_mcode_chksum = 0x012C453FUL; - if (ASC_NARROW_BOARD(boardp)) { - ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; +#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 +}; - /* Reset the chip and SCSI bus. */ - ASC_DBG(1, "before AscInitAsc1000Driver()\n"); - status = AscInitAsc1000Driver(asc_dvc); +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; - /* 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"); + 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); } - - 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; + } + 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); + } + 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); } - spin_lock_irqsave(shost->host_lock, flags); - AdvISR(adv_dvc); +#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); + } +#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; } - - /* 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; + 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 { - ip[0] = 64; - ip[1] = 32; + data_cnt = le32_to_cpu(scsiq->q1.data_cnt); } - } 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; + 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; + } + } + } } } - 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 (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 { + scsiq->q2.tag_code &= 0x27; + } + 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--; + if (asc_exe_callback != 0) { + (*asc_exe_callback) (asc_dvc, scsiq); + } + DvcLeaveCritical(last_int_level); + return (sta); + } } } else { - ASC_DBG(1, "before AdvISR()\n"); - if (AdvISR(&boardp->dvc_var.adv_dvc_var)) { - result = IRQ_HANDLED; - ASC_STATS(shost, interrupt); + 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--; + if (asc_exe_callback != 0) { + (*asc_exe_callback) (asc_dvc, scsiq); + } + DvcLeaveCritical(last_int_level); + return (sta); + } } } - spin_unlock(shost->host_lock); - - ASC_DBG(1, "end\n"); - return result; + asc_dvc->in_critical_cnt--; + DvcLeaveCritical(last_int_level); + return (sta); } -static int AscHostReqRiscHalt(PortAddr iop_base) +static int +AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required) { - int count = 0; - int sta = 0; - uchar saved_stop_code; + PortAddr iop_base; + uchar free_q_head; + uchar next_qp; + uchar tid_no; + uchar target_ix; + int sta; - 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; + 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); } - mdelay(100); - } while (count++ < 20); - AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); + } 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); + } + } return (sta); } -static int -AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data) +static int AscSgListToQueue(int sg_list) { - int sta = FALSE; + int n_sg_list_qs; - if (AscHostReqRiscHalt(iop_base)) { - sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); - AscStartChip(iop_base); - } - return sta; + 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); } -static void AscAsyncFix(ASC_DVC_VAR *asc_dvc, struct scsi_device *sdev) +static uint +AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) { - 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; + uint cur_used_qs; + uint cur_free_qs; + ASC_SCSI_BIT_ID_TYPE target_id; + uchar tid_no; - 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 { - asc_dvc->init_sdtr &= ~tid_bit; - } - - if (orig_init_sdtr != asc_dvc->init_sdtr) - AscAsyncFix(asc_dvc, sdev); + target_id = ASC_TIX_TO_TARGET_ID(target_ix); + 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); } - - 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]); - } + if (n_qs == 1) { + cur_used_qs = (uint) asc_dvc->cur_total_qng + + (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q; } else { - if (sdev->lun == 0) { - asc_dvc->cfg->can_tagged_qng &= ~tid_bit; - asc_dvc->use_tagged_qng &= ~tid_bit; + cur_used_qs = (uint) asc_dvc->cur_total_qng + + (uint) ASC_MIN_FREE_Q; + } + if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { + 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); } - scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + return (cur_free_qs); } - - 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]); + if (n_qs > 1) { + if ((n_qs > asc_dvc->last_q_shortage) + && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { + asc_dvc->last_q_shortage = n_qs; + } } + return (0); } -/* - * 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) +static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) { - unsigned short cfg_word; - AdvReadWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); - if ((cfg_word & tidmask) != 0) - return; + ushort q_addr; + uchar tid_no; + uchar sdtr_data; + uchar syn_period_ix; + uchar syn_offset; + PortAddr iop_base; - cfg_word |= tidmask; - AdvWriteWordLram(iop_base, ASC_MC_WDTR_ABLE, cfg_word); + iop_base = asc_dvc->iop_base; + if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && + ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { + tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); + sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); + syn_period_ix = + (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); + syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; + AscMsgOutSDTR(asc_dvc, + asc_dvc->sdtr_period_tbl[syn_period_ix], + syn_offset); + scsiq->q1.cntl |= QC_MSG_OUT; + } + q_addr = ASC_QNO_TO_QADDR(q_no); + if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { + scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; + } + scsiq->q1.status = QS_FREE; + AscMemWordCopyPtrToLram(iop_base, + q_addr + ASC_SCSIQ_CDB_BEG, + (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1); - /* - * 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); + DvcPutScsiQ(iop_base, + q_addr + ASC_SCSIQ_CPY_BEG, + (uchar *)&scsiq->q1.cntl, + ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1); + AscWriteLramWord(iop_base, + (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS), + (ushort)(((ushort)scsiq->q1. + q_no << 8) | (ushort)QS_READY)); + return (1); } -/* - * 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) +static int +AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) { - 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); + int sta; + int i; + ASC_SG_HEAD *sg_head; + ASC_SG_LIST_Q scsi_sg_q; + ASC_DCNT saved_data_addr; + ASC_DCNT saved_data_cnt; + PortAddr iop_base; + ushort sg_list_dwords; + ushort sg_index; + ushort sg_entry_cnt; + ushort q_addr; + uchar next_qp; + iop_base = asc_dvc->iop_base; + sg_head = scsiq->sg_head; + saved_data_addr = scsiq->q1.data_addr; + saved_data_cnt = scsiq->q1.data_cnt; + scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr; + scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes; +#if CC_VERY_LONG_SG_LIST /* - * Clear the microcode "SDTR negotiation" done indicator for the - * target to cause it to negotiate with the new setting set above. + * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST + * then not all SG elements will fit in the allocated queues. + * The rest of the SG elements will be copied when the RISC + * completes the SG elements that fit and halts. */ - 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) { + if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { /* - * 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. + * Set sg_entry_cnt to be the number of SG elements that + * will fit in the allocated SG queues. It is minus 1, because + * the first SG element is handled above. ASC_MAX_SG_LIST is + * already inflated by 1 to account for this. For example it + * may be 50 which is 1 + 7 queues * 7 SG elements. */ - - 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); + sg_entry_cnt = ASC_MAX_SG_LIST - 1; /* - * 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. + * Keep track of remaining number of SG elements that will + * need to be handled from a_isr.c. */ - 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); - } + scsiq->remain_sg_entry_cnt = + sg_head->entry_cnt - ASC_MAX_SG_LIST; + } else { +#endif /* CC_VERY_LONG_SG_LIST */ + /* + * Set sg_entry_cnt to be the number of SG elements that + * will fit in the allocated SG queues. It is minus 1, because + * the first SG element is handled above. + */ + sg_entry_cnt = sg_head->entry_cnt - 1; +#if CC_VERY_LONG_SG_LIST } - - if ((adv_dvc->tagqng_able & tidmask) && sdev->tagged_supported) { - scsi_adjust_queue_depth(sdev, MSG_ORDERED_TAG, - adv_dvc->max_dvc_qng); +#endif /* CC_VERY_LONG_SG_LIST */ + if (sg_entry_cnt != 0) { + scsiq->q1.cntl |= QC_SG_HEAD; + q_addr = ASC_QNO_TO_QADDR(q_no); + sg_index = 1; + scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; + scsi_sg_q.sg_head_qp = q_no; + scsi_sg_q.cntl = QCSG_SG_XFER_LIST; + for (i = 0; i < sg_head->queue_cnt; i++) { + scsi_sg_q.seq_no = i + 1; + if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { + sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); + sg_entry_cnt -= ASC_SG_LIST_PER_Q; + if (i == 0) { + scsi_sg_q.sg_list_cnt = + ASC_SG_LIST_PER_Q; + scsi_sg_q.sg_cur_list_cnt = + ASC_SG_LIST_PER_Q; + } else { + scsi_sg_q.sg_list_cnt = + ASC_SG_LIST_PER_Q - 1; + scsi_sg_q.sg_cur_list_cnt = + ASC_SG_LIST_PER_Q - 1; + } + } else { +#if CC_VERY_LONG_SG_LIST + /* + * This is the last SG queue in the list of + * allocated SG queues. If there are more + * SG elements than will fit in the allocated + * queues, then set the QCSG_SG_XFER_MORE flag. + */ + if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { + scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; + } else { +#endif /* CC_VERY_LONG_SG_LIST */ + scsi_sg_q.cntl |= QCSG_SG_XFER_END; +#if CC_VERY_LONG_SG_LIST + } +#endif /* CC_VERY_LONG_SG_LIST */ + sg_list_dwords = sg_entry_cnt << 1; + if (i == 0) { + scsi_sg_q.sg_list_cnt = sg_entry_cnt; + scsi_sg_q.sg_cur_list_cnt = + sg_entry_cnt; + } else { + scsi_sg_q.sg_list_cnt = + sg_entry_cnt - 1; + scsi_sg_q.sg_cur_list_cnt = + sg_entry_cnt - 1; + } + sg_entry_cnt = 0; + } + next_qp = AscReadLramByte(iop_base, + (ushort)(q_addr + + ASC_SCSIQ_B_FWD)); + scsi_sg_q.q_no = next_qp; + q_addr = ASC_QNO_TO_QADDR(next_qp); + AscMemWordCopyPtrToLram(iop_base, + q_addr + ASC_SCSIQ_SGHD_CPY_BEG, + (uchar *)&scsi_sg_q, + sizeof(ASC_SG_LIST_Q) >> 1); + AscMemDWordCopyPtrToLram(iop_base, + q_addr + ASC_SGQ_LIST_BEG, + (uchar *)&sg_head-> + sg_list[sg_index], + sg_list_dwords); + sg_index += ASC_SG_LIST_PER_Q; + scsiq->next_sg_index = sg_index; + } } else { - scsi_adjust_queue_depth(sdev, 0, sdev->host->cmd_per_lun); + scsiq->q1.cntl &= ~QC_SG_HEAD; } + sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); + scsiq->q1.data_addr = saved_data_addr; + scsiq->q1.data_cnt = saved_data_cnt; + return (sta); } -/* - * Set the number of commands to queue per device for the - * specified host adapter. - */ -static int advansys_slave_configure(struct scsi_device *sdev) +static int +AscSetRunChipSynRegAtID(PortAddr iop_base, uchar tid_no, uchar sdtr_data) { - 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); + int sta = FALSE; - return 0; + if (AscHostReqRiscHalt(iop_base)) { + sta = AscSetChipSynRegAtID(iop_base, tid_no, sdtr_data); + AscStartChip(iop_base); + return (sta); + } + return (sta); } -static __le32 advansys_get_sense_buffer_dma(struct scsi_cmnd *scp) +static int AscSetChipSynRegAtID(PortAddr iop_base, uchar id, uchar sdtr_data) { - 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); + ASC_SCSI_BIT_ID_TYPE org_id; + int i; + int sta = TRUE; + + 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; + } + } else { + sta = FALSE; + } + AscSetBank(iop_base, 1); + AscWriteChipDvcID(iop_base, org_id); + AscSetBank(iop_base, 0); + return (sta); } -static int asc_build_req(struct asc_board *boardp, struct scsi_cmnd *scp, - struct asc_scsi_q *asc_scsi_q) +static ushort AscInitLram(ASC_DVC_VAR *asc_dvc) { - struct asc_dvc_var *asc_dvc = &boardp->dvc_var.asc_dvc_var; - int use_sg; - - memset(asc_scsi_q, 0, sizeof(*asc_scsi_q)); + uchar i; + ushort s_addr; + PortAddr iop_base; + ushort warn_code; - /* - * 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; + 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); +} - /* - * 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); +static ushort AscInitQLinkVar(ASC_DVC_VAR *asc_dvc) +{ + PortAddr iop_base; + int i; + ushort lram_addr; - /* - * 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; + 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); +} - /* 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; - } +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 (err_code); +} - 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; - } +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; - 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); + 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 { - /* - * Convert scatter-gather list into ASC_SG_HEAD 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)); - } + sdtr_buf.req_ack_offset = 0; + AscMemWordCopyPtrToLram(iop_base, + ASCV_MSGOUT_BEG, + (uchar *)&sdtr_buf, + sizeof(EXT_MSG) >> 1); + return (0); } +} - ASC_STATS(scp->device->host, xfer_cnt); +static uchar +AscCalSDTRData(ASC_DVC_VAR *asc_dvc, uchar sdtr_period, uchar syn_offset) +{ + uchar byte; + uchar sdtr_period_ix; - ASC_DBG_PRT_ASC_SCSI_Q(2, asc_scsi_q); - ASC_DBG_PRT_CDB(1, scp->cmnd, scp->cmd_len); + 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); +} - return ASC_NOERROR; +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; } -/* - * 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) +static uchar AscGetSynPeriodIndex(ASC_DVC_VAR *asc_dvc, uchar syn_time) { - 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; + uchar *period_table; + int max_index; + int min_index; 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; + 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); } - return ASC_BUSY; } + return ((uchar)max_index); + } else { + return ((uchar)(max_index + 1)); + } +} - /* 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); +static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head) +{ + ushort q_addr; + uchar next_qp; + uchar q_status; - /* - * 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; + 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); +} - /* - * 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; +static uchar +AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q) +{ + uchar i; - /* - * 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); - } - - 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++; + 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); } - sg_block->sg_cnt = NO_OF_SG_PER_BLOCK; - prev_sg_block = sg_block; } + return (free_q_head); } -/* - * 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 -adv_build_req(struct asc_board *boardp, struct scsi_cmnd *scp, - ADV_SCSI_REQ_Q **adv_scsiqpp) +static int AscHostReqRiscHalt(PortAddr iop_base) { - adv_req_t *reqp; - ADV_SCSI_REQ_Q *scsiqp; - int i; - int ret; - int use_sg; - - /* - * 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; + int count = 0; + int sta = 0; + uchar saved_stop_code; - return ASC_ERROR; + 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; } + DvcSleepMilliSecond(100); + } while (count++ < 20); + AscWriteLramByte(iop_base, ASCV_STOP_CODE_B, saved_stop_code); + 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; - } +static int AscStopQueueExe(PortAddr iop_base) +{ + int count = 0; - ASC_STATS_ADD(scp->device->host, xfer_elem, use_sg); + 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); } + return (0); +} - 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 void DvcDelayMicroSecond(ADV_DVC_VAR *asc_dvc, ushort micro_sec) +{ + udelay(micro_sec); } -static int AscSgListToQueue(int sg_list) +static void DvcDelayNanoSecond(ASC_DVC_VAR *asc_dvc, ASC_DCNT nano_sec) { - int n_sg_list_qs; + udelay((nano_sec + 999) / 1000); +} - 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; +#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); } -static uint -AscGetNumOfFreeQueue(ASC_DVC_VAR *asc_dvc, uchar target_ix, uchar n_qs) +static PortAddr __init AscSearchIOPortAddrEISA(PortAddr iop_base) { - uint cur_used_qs; - uint cur_free_qs; - ASC_SCSI_BIT_ID_TYPE target_id; - uchar tid_no; + ASC_DCNT eisa_product_id; - target_id = ASC_TIX_TO_TARGET_ID(target_ix); - 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; - } - if (n_qs == 1) { - cur_used_qs = (uint) asc_dvc->cur_total_qng + - (uint) asc_dvc->last_q_shortage + (uint) ASC_MIN_FREE_Q; + if (iop_base == 0) { + iop_base = ASC_EISA_MIN_IOP_ADDR; } else { - cur_used_qs = (uint) asc_dvc->cur_total_qng + - (uint) ASC_MIN_FREE_Q; - } - if ((uint) (cur_used_qs + n_qs) <= (uint) asc_dvc->max_total_qng) { - 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; + 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; } - return cur_free_qs; } - if (n_qs > 1) { - if ((n_qs > asc_dvc->last_q_shortage) - && (n_qs <= (asc_dvc->max_total_qng - ASC_MIN_FREE_Q))) { - asc_dvc->last_q_shortage = n_qs; + 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; } } - return 0; + return (0); } +#endif /* CONFIG_ISA */ -static uchar AscAllocFreeQueue(PortAddr iop_base, uchar free_q_head) +static int AscStartChip(PortAddr iop_base) { - 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; + AscSetChipControl(iop_base, 0); + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + return (0); + } + return (1); } -static uchar -AscAllocMultipleFreeQueue(PortAddr iop_base, uchar free_q_head, uchar n_free_q) +static int AscStopChip(PortAddr iop_base) { - uchar i; + uchar cc_val; - 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; + 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 free_q_head; + return (1); } -/* - * 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) +static int AscIsChipHalted(PortAddr iop_base) { - 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; + if ((AscGetChipStatus(iop_base) & CSW_HALTED) != 0) { + if ((AscGetChipControl(iop_base) & CC_HALT) != 0) { + return (1); } - outpw(iop_base + IOP_RAM_DATA, - ((ushort)outbuf[i + 1] << 8) | outbuf[i]); } + return (0); } -static int AscPutReadyQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) +static void AscSetChipIH(PortAddr iop_base, ushort ins_code) { - ushort q_addr; - uchar tid_no; - uchar sdtr_data; - uchar syn_period_ix; - uchar syn_offset; - PortAddr iop_base; + AscSetBank(iop_base, 1); + AscWriteChipIH(iop_base, ins_code); + AscSetBank(iop_base, 0); + return; +} - iop_base = asc_dvc->iop_base; - if (((asc_dvc->init_sdtr & scsiq->q1.target_id) != 0) && - ((asc_dvc->sdtr_done & scsiq->q1.target_id) == 0)) { - tid_no = ASC_TIX_TO_TID(scsiq->q2.target_ix); - sdtr_data = AscGetMCodeInitSDTRAtID(iop_base, tid_no); - syn_period_ix = - (sdtr_data >> 4) & (asc_dvc->max_sdtr_index - 1); - syn_offset = sdtr_data & ASC_SYN_MAX_OFFSET; - AscMsgOutSDTR(asc_dvc, - asc_dvc->sdtr_period_tbl[syn_period_ix], - syn_offset); - scsiq->q1.cntl |= QC_MSG_OUT; - } - q_addr = ASC_QNO_TO_QADDR(q_no); - if ((scsiq->q1.target_id & asc_dvc->use_tagged_qng) == 0) { - scsiq->q2.tag_code &= ~MSG_SIMPLE_TAG; +static void AscAckInterrupt(PortAddr iop_base) +{ + uchar host_flag; + uchar risc_flag; + ushort loop; + + 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; + } } - scsiq->q1.status = QS_FREE; - AscMemWordCopyPtrToLram(iop_base, - q_addr + ASC_SCSIQ_CDB_BEG, - (uchar *)scsiq->cdbptr, scsiq->q2.cdb_len >> 1); + AscWriteLramByte(iop_base, ASCV_HOST_FLAG_B, host_flag); + return; +} - DvcPutScsiQ(iop_base, - q_addr + ASC_SCSIQ_CPY_BEG, - (uchar *)&scsiq->q1.cntl, - ((sizeof(ASC_SCSIQ_1) + sizeof(ASC_SCSIQ_2)) / 2) - 1); - AscWriteLramWord(iop_base, - (ushort)(q_addr + (ushort)ASC_SCSIQ_B_STATUS), - (ushort)(((ushort)scsiq->q1. - q_no << 8) | (ushort)QS_READY)); - return 1; +static void AscDisableInterrupt(PortAddr iop_base) +{ + ushort cfg; + + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg & (~ASC_CFG0_HOST_INT_ON)); + return; } -static int -AscPutReadySgListQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar q_no) +static void AscEnableInterrupt(PortAddr iop_base) { - int sta; - int i; - ASC_SG_HEAD *sg_head; - ASC_SG_LIST_Q scsi_sg_q; - ASC_DCNT saved_data_addr; - ASC_DCNT saved_data_cnt; - PortAddr iop_base; - ushort sg_list_dwords; - ushort sg_index; - ushort sg_entry_cnt; - ushort q_addr; - uchar next_qp; + ushort cfg; - iop_base = asc_dvc->iop_base; - sg_head = scsiq->sg_head; - saved_data_addr = scsiq->q1.data_addr; - saved_data_cnt = scsiq->q1.data_cnt; - scsiq->q1.data_addr = (ASC_PADDR) sg_head->sg_list[0].addr; - scsiq->q1.data_cnt = (ASC_DCNT) sg_head->sg_list[0].bytes; -#if CC_VERY_LONG_SG_LIST - /* - * If sg_head->entry_cnt is greater than ASC_MAX_SG_LIST - * then not all SG elements will fit in the allocated queues. - * The rest of the SG elements will be copied when the RISC - * completes the SG elements that fit and halts. - */ - if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { - /* - * Set sg_entry_cnt to be the number of SG elements that - * will fit in the allocated SG queues. It is minus 1, because - * the first SG element is handled above. ASC_MAX_SG_LIST is - * already inflated by 1 to account for this. For example it - * may be 50 which is 1 + 7 queues * 7 SG elements. - */ - sg_entry_cnt = ASC_MAX_SG_LIST - 1; + cfg = AscGetChipCfgLsw(iop_base); + AscSetChipCfgLsw(iop_base, cfg | ASC_CFG0_HOST_INT_ON); + return; +} - /* - * Keep track of remaining number of SG elements that will - * need to be handled from a_isr.c. - */ - scsiq->remain_sg_entry_cnt = - sg_head->entry_cnt - ASC_MAX_SG_LIST; - } else { -#endif /* CC_VERY_LONG_SG_LIST */ - /* - * Set sg_entry_cnt to be the number of SG elements that - * will fit in the allocated SG queues. It is minus 1, because - * the first SG element is handled above. - */ - sg_entry_cnt = sg_head->entry_cnt - 1; -#if CC_VERY_LONG_SG_LIST - } -#endif /* CC_VERY_LONG_SG_LIST */ - if (sg_entry_cnt != 0) { - scsiq->q1.cntl |= QC_SG_HEAD; - q_addr = ASC_QNO_TO_QADDR(q_no); - sg_index = 1; - scsiq->q1.sg_queue_cnt = sg_head->queue_cnt; - scsi_sg_q.sg_head_qp = q_no; - scsi_sg_q.cntl = QCSG_SG_XFER_LIST; - for (i = 0; i < sg_head->queue_cnt; i++) { - scsi_sg_q.seq_no = i + 1; - if (sg_entry_cnt > ASC_SG_LIST_PER_Q) { - sg_list_dwords = (uchar)(ASC_SG_LIST_PER_Q * 2); - sg_entry_cnt -= ASC_SG_LIST_PER_Q; - if (i == 0) { - scsi_sg_q.sg_list_cnt = - ASC_SG_LIST_PER_Q; - scsi_sg_q.sg_cur_list_cnt = - ASC_SG_LIST_PER_Q; - } else { - scsi_sg_q.sg_list_cnt = - ASC_SG_LIST_PER_Q - 1; - scsi_sg_q.sg_cur_list_cnt = - ASC_SG_LIST_PER_Q - 1; - } - } else { -#if CC_VERY_LONG_SG_LIST - /* - * This is the last SG queue in the list of - * allocated SG queues. If there are more - * SG elements than will fit in the allocated - * queues, then set the QCSG_SG_XFER_MORE flag. - */ - if (sg_head->entry_cnt > ASC_MAX_SG_LIST) { - scsi_sg_q.cntl |= QCSG_SG_XFER_MORE; - } else { -#endif /* CC_VERY_LONG_SG_LIST */ - scsi_sg_q.cntl |= QCSG_SG_XFER_END; -#if CC_VERY_LONG_SG_LIST - } -#endif /* CC_VERY_LONG_SG_LIST */ - sg_list_dwords = sg_entry_cnt << 1; - if (i == 0) { - scsi_sg_q.sg_list_cnt = sg_entry_cnt; - scsi_sg_q.sg_cur_list_cnt = - sg_entry_cnt; - } else { - scsi_sg_q.sg_list_cnt = - sg_entry_cnt - 1; - scsi_sg_q.sg_cur_list_cnt = - sg_entry_cnt - 1; - } - sg_entry_cnt = 0; - } - next_qp = AscReadLramByte(iop_base, - (ushort)(q_addr + - ASC_SCSIQ_B_FWD)); - scsi_sg_q.q_no = next_qp; - q_addr = ASC_QNO_TO_QADDR(next_qp); - AscMemWordCopyPtrToLram(iop_base, - q_addr + ASC_SCSIQ_SGHD_CPY_BEG, - (uchar *)&scsi_sg_q, - sizeof(ASC_SG_LIST_Q) >> 1); - AscMemDWordCopyPtrToLram(iop_base, - q_addr + ASC_SGQ_LIST_BEG, - (uchar *)&sg_head-> - sg_list[sg_index], - sg_list_dwords); - sg_index += ASC_SG_LIST_PER_Q; - scsiq->next_sg_index = sg_index; - } +static void AscSetBank(PortAddr iop_base, uchar bank) +{ + 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 { - scsiq->q1.cntl &= ~QC_SG_HEAD; + val &= ~CC_BANK_ONE; } - sta = AscPutReadyQueue(asc_dvc, scsiq, q_no); - scsiq->q1.data_addr = saved_data_addr; - scsiq->q1.data_cnt = saved_data_cnt; - return (sta); + AscSetChipControl(iop_base, val); + return; } -static int -AscSendScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq, uchar n_q_required) +static int AscResetChipAndScsiBus(ASC_DVC_VAR *asc_dvc) { PortAddr iop_base; - uchar free_q_head; - uchar next_qp; - uchar tid_no; - uchar target_ix; - int sta; + int i = 10; 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); - } - } - if (sta == 1) { - AscPutVarFreeQHead(iop_base, next_qp); - asc_dvc->cur_total_qng += n_q_required; - asc_dvc->cur_dvc_qng[tid_no]++; + while ((AscGetChipStatus(iop_base) & CSW_SCSI_RESET_ACTIVE) + && (i-- > 0)) { + DvcSleepMilliSecond(100); } - return sta; + 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)); } -#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 ASC_DCNT __init AscGetMaxDmaCount(ushort bus_type) +{ + if (bus_type & ASC_IS_ISA) + 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); +} -static int AscExeScsiQueue(ASC_DVC_VAR *asc_dvc, ASC_SCSI_Q *scsiq) +#ifdef CONFIG_ISA +static ushort __init AscGetIsaDmaChannel(PortAddr iop_base) +{ + ushort channel; + + channel = AscGetChipCfgLsw(iop_base) & 0x0003; + if (channel == 0x03) + return (0); + else if (channel == 0x00) + return (7); + return (channel + 4); +} + +static ushort __init AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) +{ + ushort cfg_lsw; + uchar value; + + if ((dma_channel >= 5) && (dma_channel <= 7)) { + if (dma_channel == 7) + value = 0x00; + else + value = dma_channel - 4; + cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; + cfg_lsw |= value; + 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)); +} + +static uchar __init AscGetIsaDmaSpeed(PortAddr iop_base) +{ + uchar speed_value; + + AscSetBank(iop_base, 1); + speed_value = AscReadChipDmaSpeed(iop_base); + speed_value &= 0x07; + AscSetBank(iop_base, 0); + return (speed_value); +} +#endif /* CONFIG_ISA */ + +static ushort __init +AscReadPCIConfigWord(ASC_DVC_VAR *asc_dvc, ushort pci_config_offset) +{ + 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; - int sta; - int n_q_required; - int disable_syn_offset_one_fix; - int i; - 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; + ushort PCIDeviceID; + ushort PCIVendorID; + uchar PCIRevisionID; + uchar prevCmdRegBits; + warn_code = 0; 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; - } - 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->init_state = ASC_INIT_STATE_BEG_GET_CFG; + if (asc_dvc->err_code != 0) { + return (UW_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); + 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; } - 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); + 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; } - } 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 ((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 (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 (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 { - scsiq->q2.tag_code &= 0x27; + asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; } - 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); - } - } + 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 { - 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->err_code = ASC_IERR_BAD_SIGNATURE; } - asc_dvc->in_critical_cnt--; - return (sta); + return (warn_code); } -/* - * 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) +static ushort __init AscInitFromAscDvcVar(ASC_DVC_VAR *asc_dvc) { - AdvPortAddr iop_base; - ADV_PADDR req_paddr; - ADV_CARR_T *new_carrp; - - /* - * 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; - } + PortAddr iop_base; + ushort cfg_msw; + ushort warn_code; + ushort pci_device_id = 0; iop_base = asc_dvc->iop_base; - - /* - * 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; +#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); } - 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_paddr = virt_to_bus(scsiq); - BUG_ON(req_paddr & 31); - /* 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; - - /* - * 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; - - /* - * 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); + 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; } - } 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; -} - -/* - * Execute a single 'Scsi_Cmnd'. - */ -static int asc_execute_scsi_cmnd(struct scsi_cmnd *scp) -{ - int ret, err_code; - struct asc_board *boardp = shost_priv(scp->device->host); - - ASC_DBG(1, "scp 0x%p\n", scp); - - if (ASC_NARROW_BOARD(boardp)) { - ASC_DVC_VAR *asc_dvc = &boardp->dvc_var.asc_dvc_var; - struct asc_scsi_q asc_scsi_q; - - /* 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; + 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; + } } - - 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; - - 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; + } 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; } - - ret = AdvExeScsiQueue(adv_dvc, adv_scsiqp); - err_code = adv_dvc->err_code; } - - 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; + 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; } - - ASC_DBG(1, "end\n"); - return ret; +#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); } -/* - * 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 *)) +static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) { - struct Scsi_Host *shost = scp->device->host; - int asc_res, result = 0; - - ASC_STATS(shost, queuecommand); - scp->scsi_done = done; - - asc_res = asc_execute_scsi_cmnd(scp); + ushort warn_code; + PortAddr iop_base; - 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 result; -} - -static ushort __devinit AscGetEisaChipCfg(PortAddr iop_base) -{ - PortAddr eisa_cfg_iop = (PortAddr) ASC_GET_EISA_SLOT(iop_base) | - (PortAddr) (ASC_EISA_CFG_IOP_MASK); - return inpw(eisa_cfg_iop); -} - -/* - * 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) -{ - unsigned short cfg_lsw; - unsigned short bios_addr; - - /* - * 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; - - 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; - } - - 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 uchar __devinit AscSetChipScsiID(PortAddr iop_base, uchar new_host_id) -{ - ushort cfg_lsw; - - if (AscGetChipScsiID(iop_base) == new_host_id) { - return (new_host_id); - } - 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 unsigned char __devinit AscGetChipScsiCtrl(PortAddr iop_base) -{ - unsigned char sc; - - AscSetBank(iop_base, 1); - sc = inp(iop_base + IOP_REG_SC); - AscSetBank(iop_base, 0); - return sc; -} - -static unsigned char __devinit -AscGetChipVersion(PortAddr iop_base, unsigned short bus_type) -{ - 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); -} - -#ifdef CONFIG_ISA -static void __devinit AscEnableIsaDma(uchar dma_channel) -{ - 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)); + 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)); } -} -#endif /* CONFIG_ISA */ - -static int AscStopQueueExe(PortAddr iop_base) -{ - int count = 0; - - 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); + 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); } - return (0); -} - -static ASC_DCNT __devinit AscGetMaxDmaCount(ushort bus_type) -{ - if (bus_type & ASC_IS_ISA) - 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; -} - -#ifdef CONFIG_ISA -static ushort __devinit AscGetIsaDmaChannel(PortAddr iop_base) -{ - ushort channel; - - channel = AscGetChipCfgLsw(iop_base) & 0x0003; - if (channel == 0x03) - return (0); - else if (channel == 0x00) - return (7); - return (channel + 4); -} - -static ushort __devinit AscSetIsaDmaChannel(PortAddr iop_base, ushort dma_channel) -{ - ushort cfg_lsw; - uchar value; - - if ((dma_channel >= 5) && (dma_channel <= 7)) { - if (dma_channel == 7) - value = 0x00; - else - value = dma_channel - 4; - cfg_lsw = AscGetChipCfgLsw(iop_base) & 0xFFFC; - cfg_lsw |= value; - AscSetChipCfgLsw(iop_base, cfg_lsw); - return (AscGetIsaDmaChannel(iop_base)); + 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); } - return 0; -} - -static uchar __devinit AscGetIsaDmaSpeed(PortAddr iop_base) -{ - uchar speed_value; - - AscSetBank(iop_base, 1); - speed_value = AscReadChipDmaSpeed(iop_base); - speed_value &= 0x07; - AscSetBank(iop_base, 0); - return speed_value; -} - -static uchar __devinit 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); + warn_code |= AscInitMicroCodeVar(asc_dvc); + asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; + AscEnableInterrupt(iop_base); + return (warn_code); } -#endif /* CONFIG_ISA */ -static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) +static ushort __init AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) { int i; PortAddr iop_base; @@ -11238,7 +10882,7 @@ static ushort __devinit AscInitAscDvcVar(ASC_DVC_VAR *asc_dvc) asc_dvc->queue_full_or_busy = 0; asc_dvc->redo_scam = 0; asc_dvc->res2 = 0; - asc_dvc->min_sdtr_index = 0; + asc_dvc->host_init_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; @@ -11250,14 +10894,39 @@ static ushort __devinit 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 = asc_syn_xfer_period; + 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->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 = asc_syn_ultra_xfer_period; + 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->max_sdtr_index = 15; if (chip_version == ASC_CHIP_VER_PCI_ULTRA_3150) { AscSetExtraControl(iop_base, @@ -11274,12 +10943,12 @@ static ushort __devinit 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); } @@ -11291,92 +10960,231 @@ static ushort __devinit 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 int __devinit AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg) +static ushort __init AscInitFromEEP(ASC_DVC_VAR *asc_dvc) { - int retry; + 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; - 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; + 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)); } - return 0; -} - -static void __devinit AscWaitEEPRead(void) -{ - mdelay(1); -} - -static ushort __devinit 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 __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; - - 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 (AscIsChipHalted(iop_base) == FALSE) { + 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; + 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); } - 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. */ + 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); } - /* - * 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 __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc) + 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; + } + + 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"); + } + } + return (warn_code); +} + +static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) +{ + 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] + ); + } + + 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)); + + /* 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); + + 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); +} + +static int __init AscTestExternalLram(ASC_DVC_VAR *asc_dvc) { PortAddr iop_base; ushort q_addr; @@ -11389,7 +11197,7 @@ static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc) saved_word = AscReadLramWord(iop_base, q_addr); AscSetChipLramAddr(iop_base, q_addr); AscSetChipLramData(iop_base, 0x55AA); - mdelay(10); + DvcSleepMilliSecond(10); AscSetChipLramAddr(iop_base, q_addr); if (AscGetChipLramData(iop_base) == 0x55AA) { sta = 1; @@ -11398,12 +11206,26 @@ static int __devinit AscTestExternalLram(ASC_DVC_VAR *asc_dvc) return (sta); } -static void __devinit AscWaitEEPWrite(void) +static int __init AscWriteEEPCmdReg(PortAddr iop_base, uchar cmd_reg) { - mdelay(20); + 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); + } + } } -static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) +static int __init AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) { ushort read_back; int retry; @@ -11411,7 +11233,7 @@ static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) retry = 0; while (TRUE) { AscSetChipEEPData(iop_base, data_reg); - mdelay(1); + DvcSleepMilliSecond(1); read_back = AscGetChipEEPData(iop_base); if (read_back == data_reg) { return (1); @@ -11422,7 +11244,34 @@ static int __devinit AscWriteEEPDataReg(PortAddr iop_base, ushort data_reg) } } -static ushort __devinit +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 AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val) { ushort read_wval; @@ -11443,7 +11292,54 @@ AscWriteEEPWord(PortAddr iop_base, uchar addr, ushort word_val) return (read_wval); } -static int __devinit +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 AscSetEEPConfigOnce(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { int n_error; @@ -11536,10 +11432,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 __devinit +static int __init AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) { int retry; @@ -11555,702 +11451,5416 @@ AscSetEEPConfig(PortAddr iop_base, ASCEEP_CONFIG *cfg_buf, ushort bus_type) break; } } - return n_error; + return (n_error); } -static ushort __devinit AscInitFromEEP(ASC_DVC_VAR *asc_dvc) +static void +AscAsyncFix(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq) { - 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; + 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; + } - 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); + if (asc_dvc->pci_fix_asyn_xfer & tid_bits) { + AscSetRunChipSynRegAtID(asc_dvc->iop_base, + tid_no, + ASYN_SDTR_DATA_FIX_PCI_REV_AB); } } } - 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; - } - } - 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; - } - 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; +} - 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"); - } +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 (warn_code); + return 1; } -static int __devinit AscInitGetConfig(struct Scsi_Host *shost) +static void +AscInquiryHandling(ASC_DVC_VAR *asc_dvc, uchar tid_no, ASC_SCSI_INQUIRY *inq) { - struct asc_board *board = shost_priv(shost); - ASC_DVC_VAR *asc_dvc = &board->dvc_var.asc_dvc_var; - unsigned short warn_code = 0; + 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; - asc_dvc->init_state = ASC_INIT_STATE_BEG_GET_CFG; - if (asc_dvc->err_code != 0) - return asc_dvc->err_code; + orig_init_sdtr = asc_dvc->init_sdtr; + orig_use_tagged_qng = asc_dvc->use_tagged_qng; - 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 { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - } + asc_dvc->init_sdtr &= ~tid_bit; + asc_dvc->cfg->can_tagged_qng &= ~tid_bit; + asc_dvc->use_tagged_qng &= ~tid_bit; - 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; + 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; + } + 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; + } + } } + 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); - 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); - - return asc_dvc->err_code; + 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 (orig_init_sdtr != asc_dvc->init_sdtr) { + AscAsyncFix(asc_dvc, tid_no, inq); + } + return; } -static int __devinit AscInitSetConfig(struct pci_dev *pdev, struct Scsi_Host *shost) +static int AscCompareString(uchar *str1, uchar *str2, int len) { - 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; - - 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; - } + int i; + int diff; - 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; - } -#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); + for (i = 0; i < len; i++) { + diff = (int)(str1[i] - str2[i]); + if (diff != 0) + return (diff); } -#endif /* CONFIG_ISA */ + return (0); +} - asc_dvc->init_state |= ASC_INIT_STATE_END_SET_CFG; +static uchar AscReadLramByte(PortAddr iop_base, ushort addr) +{ + uchar byte_data; + ushort word_data; - 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; + 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); } + return (byte_data); +} - 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 ushort AscReadLramWord(PortAddr iop_base, ushort addr) +{ + ushort word_data; - return asc_dvc->err_code; + AscSetChipLramAddr(iop_base, addr); + word_data = AscGetChipLramData(iop_base); + return (word_data); } -/* - * EEPROM Configuration. - * - * All drivers should use this structure to set the default EEPROM - * configuration. The BIOS now uses this structure when it is built. - * Additional structure information can be found in a_condor.h where - * the structure is defined. +#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 AscWriteLramWord(PortAddr iop_base, ushort addr, ushort word_val) +{ + AscSetChipLramAddr(iop_base, addr); + AscSetChipLramData(iop_base, word_val); + return; +} + +static void AscWriteLramByte(PortAddr iop_base, ushort addr, uchar byte_val) +{ + 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); + return; +} + +/* + * Copy 2 bytes to LRAM. * - * The *_Field_IsChar structs are needed to correct for endianness. - * These values are read from the board 16 bits at a time directly - * into the structs. Because some fields are char, the values will be - * in the wrong order. The *_Field_IsChar tells when to flip the - * bytes. Data read and written to PCI memory is automatically swapped - * on big-endian platforms so char fields read as words are actually being - * unswapped on big-endian platforms. + * 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 ADVEEP_3550_CONFIG Default_3550_EEPROM_Config __devinitdata = { - ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ - 0x0000, /* cfg_msw */ - 0xFFFF, /* disc_enable */ - 0xFFFF, /* wdtr_able */ - 0xFFFF, /* sdtr_able */ - 0xFFFF, /* start_motor */ - 0xFFFF, /* tagqng_able */ - 0xFFFF, /* bios_scan */ - 0, /* scam_tolerant */ - 7, /* adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* termination */ - 0, /* reserved1 */ - 0xFFE7, /* bios_ctrl */ - 0xFFFF, /* ultra_able */ - 0, /* reserved2 */ - ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* dvc_cntl */ - 0, /* bug_fix */ - 0, /* serial_number_word1 */ - 0, /* serial_number_word2 */ - 0, /* serial_number_word3 */ - 0, /* check_sum */ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - , /* oem_name[16] */ - 0, /* dvc_err_code */ - 0, /* adv_err_code */ - 0, /* adv_err_addr */ - 0, /* saved_dvc_err_code */ - 0, /* saved_adv_err_code */ - 0, /* saved_adv_err_addr */ - 0 /* num_of_err */ -}; +static void +AscMemWordCopyPtrToLram(PortAddr iop_base, + ushort s_addr, uchar *s_buffer, int words) +{ + int i; -static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __devinitdata = { - 0, /* cfg_lsw */ - 0, /* cfg_msw */ - 0, /* -disc_enable */ - 0, /* wdtr_able */ - 0, /* sdtr_able */ - 0, /* start_motor */ - 0, /* tagqng_able */ - 0, /* bios_scan */ - 0, /* scam_tolerant */ - 1, /* adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* termination */ - 1, /* reserved1 */ - 0, /* bios_ctrl */ - 0, /* ultra_able */ - 0, /* reserved2 */ - 1, /* max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* dvc_cntl */ - 0, /* bug_fix */ - 0, /* serial_number_word1 */ - 0, /* serial_number_word2 */ - 0, /* serial_number_word3 */ - 0, /* check_sum */ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} - , /* oem_name[16] */ - 0, /* dvc_err_code */ - 0, /* adv_err_code */ - 0, /* adv_err_addr */ - 0, /* saved_dvc_err_code */ - 0, /* saved_adv_err_code */ - 0, /* saved_adv_err_addr */ - 0 /* num_of_err */ -}; + 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]); + } + return; +} -static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __devinitdata = { - ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ - 0x0000, /* 01 cfg_msw */ - 0xFFFF, /* 02 disc_enable */ - 0xFFFF, /* 03 wdtr_able */ - 0x4444, /* 04 sdtr_speed1 */ - 0xFFFF, /* 05 start_motor */ - 0xFFFF, /* 06 tagqng_able */ - 0xFFFF, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 7, /* 09 adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* 10 scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* 11 termination_se */ - 0, /* termination_lvd */ - 0xFFE7, /* 12 bios_ctrl */ - 0x4444, /* 13 sdtr_speed2 */ - 0x4444, /* 14 sdtr_speed3 */ - ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0x4444, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - , /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - PCI_VENDOR_ID_ASP, /* 58 subsysvid */ - PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ -}; +/* + * 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; -static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __devinitdata = { - 0, /* 00 cfg_lsw */ - 0, /* 01 cfg_msw */ - 0, /* 02 disc_enable */ - 0, /* 03 wdtr_able */ - 0, /* 04 sdtr_speed1 */ - 0, /* 05 start_motor */ - 0, /* 06 tagqng_able */ - 0, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 1, /* 09 adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* 10 scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* 11 termination_se */ - 1, /* termination_lvd */ - 0, /* 12 bios_ctrl */ - 0, /* 13 sdtr_speed2 */ - 0, /* 14 sdtr_speed3 */ - 1, /* 15 max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} - , /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - 0, /* 58 subsysvid */ - 0, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ -}; + 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; +} -static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __devinitdata = { - ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ - 0x0000, /* 01 cfg_msw */ - 0xFFFF, /* 02 disc_enable */ - 0xFFFF, /* 03 wdtr_able */ - 0x5555, /* 04 sdtr_speed1 */ - 0xFFFF, /* 05 start_motor */ - 0xFFFF, /* 06 tagqng_able */ - 0xFFFF, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 7, /* 09 adapter_scsi_id */ - 0, /* bios_boot_delay */ - 3, /* 10 scsi_reset_delay */ - 0, /* bios_id_lun */ - 0, /* 11 termination_se */ - 0, /* termination_lvd */ - 0xFFE7, /* 12 bios_ctrl */ - 0x5555, /* 13 sdtr_speed2 */ - 0x5555, /* 14 sdtr_speed3 */ - ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ - ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0x5555, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} - , /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - PCI_VENDOR_ID_ASP, /* 58 subsysvid */ - PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +/* + * 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) +{ + int i; + ushort word; + + 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; + } + 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); + } + 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); + } + 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 ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __devinitdata = { - 0, /* 00 cfg_lsw */ - 0, /* 01 cfg_msw */ - 0, /* 02 disc_enable */ - 0, /* 03 wdtr_able */ - 0, /* 04 sdtr_speed1 */ - 0, /* 05 start_motor */ - 0, /* 06 tagqng_able */ - 0, /* 07 bios_scan */ - 0, /* 08 scam_tolerant */ - 1, /* 09 adapter_scsi_id */ - 1, /* bios_boot_delay */ - 1, /* 10 scsi_reset_delay */ - 1, /* bios_id_lun */ - 1, /* 11 termination_se */ - 1, /* termination_lvd */ - 0, /* 12 bios_ctrl */ - 0, /* 13 sdtr_speed2 */ - 0, /* 14 sdtr_speed3 */ - 1, /* 15 max_host_qng */ - 1, /* max_dvc_qng */ - 0, /* 16 dvc_cntl */ - 0, /* 17 sdtr_speed4 */ - 0, /* 18 serial_number_word1 */ - 0, /* 19 serial_number_word2 */ - 0, /* 20 serial_number_word3 */ - 0, /* 21 check_sum */ - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} - , /* 22-29 oem_name[16] */ - 0, /* 30 dvc_err_code */ - 0, /* 31 adv_err_code */ - 0, /* 32 adv_err_addr */ - 0, /* 33 saved_dvc_err_code */ - 0, /* 34 saved_adv_err_code */ - 0, /* 35 saved_adv_err_addr */ - 0, /* 36 reserved */ - 0, /* 37 reserved */ - 0, /* 38 reserved */ - 0, /* 39 reserved */ - 0, /* 40 reserved */ - 0, /* 41 reserved */ - 0, /* 42 reserved */ - 0, /* 43 reserved */ - 0, /* 44 reserved */ - 0, /* 45 reserved */ - 0, /* 46 reserved */ - 0, /* 47 reserved */ - 0, /* 48 reserved */ - 0, /* 49 reserved */ - 0, /* 50 reserved */ - 0, /* 51 reserved */ - 0, /* 52 reserved */ - 0, /* 53 reserved */ - 0, /* 54 reserved */ - 0, /* 55 reserved */ - 0, /* 56 cisptr_lsw */ - 0, /* 57 cisprt_msw */ - 0, /* 58 subsysvid */ - 0, /* 59 subsysid */ - 0, /* 60 reserved */ - 0, /* 61 reserved */ - 0, /* 62 reserved */ - 0 /* 63 reserved */ +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, }; -#ifdef CONFIG_PCI +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. */ + +/* a_init.c */ +/* + * EEPROM Configuration. + * + * All drivers should use this structure to set the default EEPROM + * configuration. The BIOS now uses this structure when it is built. + * Additional structure information can be found in a_condor.h where + * the structure is defined. + * + * The *_Field_IsChar structs are needed to correct for endianness. + * These values are read from the board 16 bits at a time directly + * into the structs. Because some fields are char, the values will be + * in the wrong order. The *_Field_IsChar tells when to flip the + * bytes. Data read and written to PCI memory is automatically swapped + * 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 = { + ADV_EEPROM_BIOS_ENABLE, /* cfg_lsw */ + 0x0000, /* cfg_msw */ + 0xFFFF, /* disc_enable */ + 0xFFFF, /* wdtr_able */ + 0xFFFF, /* sdtr_able */ + 0xFFFF, /* start_motor */ + 0xFFFF, /* tagqng_able */ + 0xFFFF, /* bios_scan */ + 0, /* scam_tolerant */ + 7, /* adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* termination */ + 0, /* reserved1 */ + 0xFFE7, /* bios_ctrl */ + 0xFFFF, /* ultra_able */ + 0, /* reserved2 */ + ASC_DEF_MAX_HOST_QNG, /* max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* dvc_cntl */ + 0, /* bug_fix */ + 0, /* serial_number_word1 */ + 0, /* serial_number_word2 */ + 0, /* serial_number_word3 */ + 0, /* check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* oem_name[16] */ + 0, /* dvc_err_code */ + 0, /* adv_err_code */ + 0, /* adv_err_addr */ + 0, /* saved_dvc_err_code */ + 0, /* saved_adv_err_code */ + 0, /* saved_adv_err_addr */ + 0 /* num_of_err */ +}; + +static ADVEEP_3550_CONFIG ADVEEP_3550_Config_Field_IsChar __initdata = { + 0, /* cfg_lsw */ + 0, /* cfg_msw */ + 0, /* -disc_enable */ + 0, /* wdtr_able */ + 0, /* sdtr_able */ + 0, /* start_motor */ + 0, /* tagqng_able */ + 0, /* bios_scan */ + 0, /* scam_tolerant */ + 1, /* adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* termination */ + 1, /* reserved1 */ + 0, /* bios_ctrl */ + 0, /* ultra_able */ + 0, /* reserved2 */ + 1, /* max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* dvc_cntl */ + 0, /* bug_fix */ + 0, /* serial_number_word1 */ + 0, /* serial_number_word2 */ + 0, /* serial_number_word3 */ + 0, /* check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* oem_name[16] */ + 0, /* dvc_err_code */ + 0, /* adv_err_code */ + 0, /* adv_err_addr */ + 0, /* saved_dvc_err_code */ + 0, /* saved_adv_err_code */ + 0, /* saved_adv_err_addr */ + 0 /* num_of_err */ +}; + +static ADVEEP_38C0800_CONFIG Default_38C0800_EEPROM_Config __initdata = { + ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ + 0x0000, /* 01 cfg_msw */ + 0xFFFF, /* 02 disc_enable */ + 0xFFFF, /* 03 wdtr_able */ + 0x4444, /* 04 sdtr_speed1 */ + 0xFFFF, /* 05 start_motor */ + 0xFFFF, /* 06 tagqng_able */ + 0xFFFF, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 7, /* 09 adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* 10 scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* 11 termination_se */ + 0, /* termination_lvd */ + 0xFFE7, /* 12 bios_ctrl */ + 0x4444, /* 13 sdtr_speed2 */ + 0x4444, /* 14 sdtr_speed3 */ + ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0x4444, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + PCI_VENDOR_ID_ASP, /* 58 subsysvid */ + PCI_DEVICE_ID_38C0800_REV1, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ +}; + +static ADVEEP_38C0800_CONFIG ADVEEP_38C0800_Config_Field_IsChar __initdata = { + 0, /* 00 cfg_lsw */ + 0, /* 01 cfg_msw */ + 0, /* 02 disc_enable */ + 0, /* 03 wdtr_able */ + 0, /* 04 sdtr_speed1 */ + 0, /* 05 start_motor */ + 0, /* 06 tagqng_able */ + 0, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 1, /* 09 adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* 10 scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* 11 termination_se */ + 1, /* termination_lvd */ + 0, /* 12 bios_ctrl */ + 0, /* 13 sdtr_speed2 */ + 0, /* 14 sdtr_speed3 */ + 1, /* 15 max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + 0, /* 58 subsysvid */ + 0, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ +}; + +static ADVEEP_38C1600_CONFIG Default_38C1600_EEPROM_Config __initdata = { + ADV_EEPROM_BIOS_ENABLE, /* 00 cfg_lsw */ + 0x0000, /* 01 cfg_msw */ + 0xFFFF, /* 02 disc_enable */ + 0xFFFF, /* 03 wdtr_able */ + 0x5555, /* 04 sdtr_speed1 */ + 0xFFFF, /* 05 start_motor */ + 0xFFFF, /* 06 tagqng_able */ + 0xFFFF, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 7, /* 09 adapter_scsi_id */ + 0, /* bios_boot_delay */ + 3, /* 10 scsi_reset_delay */ + 0, /* bios_id_lun */ + 0, /* 11 termination_se */ + 0, /* termination_lvd */ + 0xFFE7, /* 12 bios_ctrl */ + 0x5555, /* 13 sdtr_speed2 */ + 0x5555, /* 14 sdtr_speed3 */ + ASC_DEF_MAX_HOST_QNG, /* 15 max_host_qng */ + ASC_DEF_MAX_DVC_QNG, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0x5555, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + PCI_VENDOR_ID_ASP, /* 58 subsysvid */ + PCI_DEVICE_ID_38C1600_REV1, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ +}; + +static ADVEEP_38C1600_CONFIG ADVEEP_38C1600_Config_Field_IsChar __initdata = { + 0, /* 00 cfg_lsw */ + 0, /* 01 cfg_msw */ + 0, /* 02 disc_enable */ + 0, /* 03 wdtr_able */ + 0, /* 04 sdtr_speed1 */ + 0, /* 05 start_motor */ + 0, /* 06 tagqng_able */ + 0, /* 07 bios_scan */ + 0, /* 08 scam_tolerant */ + 1, /* 09 adapter_scsi_id */ + 1, /* bios_boot_delay */ + 1, /* 10 scsi_reset_delay */ + 1, /* bios_id_lun */ + 1, /* 11 termination_se */ + 1, /* termination_lvd */ + 0, /* 12 bios_ctrl */ + 0, /* 13 sdtr_speed2 */ + 0, /* 14 sdtr_speed3 */ + 1, /* 15 max_host_qng */ + 1, /* max_dvc_qng */ + 0, /* 16 dvc_cntl */ + 0, /* 17 sdtr_speed4 */ + 0, /* 18 serial_number_word1 */ + 0, /* 19 serial_number_word2 */ + 0, /* 20 serial_number_word3 */ + 0, /* 21 check_sum */ + {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1} + , /* 22-29 oem_name[16] */ + 0, /* 30 dvc_err_code */ + 0, /* 31 adv_err_code */ + 0, /* 32 adv_err_addr */ + 0, /* 33 saved_dvc_err_code */ + 0, /* 34 saved_adv_err_code */ + 0, /* 35 saved_adv_err_addr */ + 0, /* 36 reserved */ + 0, /* 37 reserved */ + 0, /* 38 reserved */ + 0, /* 39 reserved */ + 0, /* 40 reserved */ + 0, /* 41 reserved */ + 0, /* 42 reserved */ + 0, /* 43 reserved */ + 0, /* 44 reserved */ + 0, /* 45 reserved */ + 0, /* 46 reserved */ + 0, /* 47 reserved */ + 0, /* 48 reserved */ + 0, /* 49 reserved */ + 0, /* 50 reserved */ + 0, /* 51 reserved */ + 0, /* 52 reserved */ + 0, /* 53 reserved */ + 0, /* 54 reserved */ + 0, /* 55 reserved */ + 0, /* 56 cisptr_lsw */ + 0, /* 57 cisprt_msw */ + 0, /* 58 subsysvid */ + 0, /* 59 subsysid */ + 0, /* 60 reserved */ + 0, /* 61 reserved */ + 0, /* 62 reserved */ + 0 /* 63 reserved */ +}; + +/* + * 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. + */ +static int __init AdvInitGetConfig(ADV_DVC_VAR *asc_dvc) +{ + 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); + + 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; + } + } + warn_code |= status; + } + + return warn_code; +} + +/* + * 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. + */ +static int AdvInitAsc3550Driver(ADV_DVC_VAR *asc_dvc) +{ + 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; + } + + /* + * 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; + } + + 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. + */ + 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]); + } + + /* + * 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++; + } else { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc3550_buf[(_adv_asc3550_buf[i] * 2) + 1] << 8) | _adv_asc3550_buf[_adv_asc3550_buf[i] * 2])); + word++; + } + } + + /* + * 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. + */ + AdvWriteByteRegister(iop_base, IOPB_DMA_CFG0, + START_CTL_EMFU | 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 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. */ + } + } + + /* + * 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; + } + } + + /* + * 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)); + + /* + * Build 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 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); + + /* + * 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; + } + + 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; + } + 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; +} + +/* + * 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. + */ +static int AdvInitAsc38C0800Driver(ADV_DVC_VAR *asc_dvc) +{ + 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. */ + + 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; + } + + /* We need to reset back to normal mode after LRAM test passes. */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + + /* + * 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_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++; + } 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; + } + + 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; + } + 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; +} + +/* + * 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 int AdvInitAsc38C1600Driver(ADV_DVC_VAR *asc_dvc) +{ + 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. + */ + + /* + * 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. */ + + 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; + } + + /* We need to reset back to normal mode after LRAM test passes. */ + AdvWriteByteRegister(iop_base, IOPB_RAM_BIST, NORMAL_MODE); + + /* + * 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_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++; + } else { + AdvWriteWordAutoIncLram(iop_base, (((ushort) + _adv_asc38C1600_buf[(_adv_asc38C1600_buf[i] * 2) + 1] << 8) | _adv_asc38C1600_buf[_adv_asc38C1600_buf[i] * 2])); + word++; + } + } + + /* + * 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; + } + } + + /* + * 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)); + + 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; + } + + 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); + + /* + * 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; + } + } + } + + return warn_code; +} + +/* + * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and + * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while + * all of this is done. + * + * 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. + * + * Note: Chip is stopped on entry. + */ +static int __init 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; + + warn_code = 0; + + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; + + /* + * Set EEPROM default values. + */ + for (i = 0; i < sizeof(ADVEEP_3550_CONFIG); i++) { + *((uchar *)&eep_config + i) = + *((uchar *)&Default_3550_EEPROM_Config + i); + } + + /* + * 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); + + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); + + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); + + AdvSet3550EEPConfig(iop_base, &eep_config); + } + /* + * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_able = eep_config.sdtr_able; + asc_dvc->ultra_able = eep_config.ultra_able; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + asc_dvc->cfg->serial1 = eep_config.serial_number_word1; + asc_dvc->cfg->serial2 = eep_config.serial_number_word2; + asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } + + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } + + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } + + /* + * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ADV_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ADV_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination == 0) { + asc_dvc->cfg->termination = 0; /* auto termination */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination == 1) { + asc_dvc->cfg->termination = TERM_CTL_SEL; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination == 2) { + asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination == 3) { + asc_dvc->cfg->termination = + TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L; + } else { + /* + * The EEPROM 'termination' field contains a bad value. Use + * automatic termination instead. + */ + asc_dvc->cfg->termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } + + return warn_code; +} + +/* + * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and + * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while + * all of this is done. + * + * 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. + * + * Note: Chip is stopped on entry. + */ +static int __init 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; + + iop_base = asc_dvc->iop_base; + + warn_code = 0; + + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet38C0800EEPConfig(iop_base, &eep_config) != + eep_config.check_sum) { + warn_code |= ASC_WARN_EEPROM_CHKSUM; + + /* + * Set EEPROM default values. + */ + for (i = 0; i < sizeof(ADVEEP_38C0800_CONFIG); i++) { + *((uchar *)&eep_config + i) = + *((uchar *)&Default_38C0800_EEPROM_Config + i); + } + + /* + * 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); + + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); + + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); + + AdvSet38C0800EEPConfig(iop_base, &eep_config); + } + /* + * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; + asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; + asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; + asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + asc_dvc->cfg->serial1 = eep_config.serial_number_word1; + asc_dvc->cfg->serial2 = eep_config.serial_number_word2; + asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + + /* + * For every Target ID if any of its 'sdtr_speed[1234]' bits + * are set, then set an 'sdtr_able' bit for it. + */ + asc_dvc->sdtr_able = 0; + for (tid = 0; tid <= ADV_MAX_TID; tid++) { + if (tid == 0) { + sdtr_speed = asc_dvc->sdtr_speed1; + } else if (tid == 4) { + sdtr_speed = asc_dvc->sdtr_speed2; + } else if (tid == 8) { + sdtr_speed = asc_dvc->sdtr_speed3; + } else if (tid == 12) { + sdtr_speed = asc_dvc->sdtr_speed4; + } + if (sdtr_speed & ADV_MAX_TID) { + asc_dvc->sdtr_able |= (1 << tid); + } + sdtr_speed >>= 4; + } + + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } + + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } + + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } + + /* + * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ADV_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ADV_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination_se == 0) { + termination = 0; /* auto termination for SE */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_se == 1) { + termination = 0; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_se == 2) { + termination = TERM_SE_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_se == 3) { + termination = TERM_SE; + } else { + /* + * The EEPROM 'termination_se' field contains a bad value. + * Use automatic termination instead. + */ + termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } + + if (eep_config.termination_lvd == 0) { + asc_dvc->cfg->termination = termination; /* auto termination for LVD */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_lvd == 1) { + asc_dvc->cfg->termination = termination; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_lvd == 2) { + asc_dvc->cfg->termination = termination | TERM_LVD_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_lvd == 3) { + asc_dvc->cfg->termination = termination | TERM_LVD; + } else { + /* + * The EEPROM 'termination_lvd' field contains a bad value. + * Use automatic termination instead. + */ + asc_dvc->cfg->termination = termination; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } + + return warn_code; +} + +/* + * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and + * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while + * all of this is done. + * + * 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. + * + * Note: Chip is stopped on entry. + */ +static int __init 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; + + iop_base = asc_dvc->iop_base; + + warn_code = 0; + + /* + * Read the board's EEPROM configuration. + * + * Set default values if a bad checksum is found. + */ + if (AdvGet38C1600EEPConfig(iop_base, &eep_config) != + eep_config.check_sum) { + 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))); + + /* + * 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); + } + } + + /* + * 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); + + eep_config.serial_number_word2 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); + + eep_config.serial_number_word1 = + AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); + + AdvSet38C1600EEPConfig(iop_base, &eep_config); + } + + /* + * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the + * EEPROM configuration that was read. + * + * This is the mapping of EEPROM fields to Adv Library fields. + */ + asc_dvc->wdtr_able = eep_config.wdtr_able; + asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; + asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; + asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; + asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; + asc_dvc->ppr_able = 0; + asc_dvc->tagqng_able = eep_config.tagqng_able; + asc_dvc->cfg->disc_enable = eep_config.disc_enable; + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID); + asc_dvc->start_motor = eep_config.start_motor; + asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; + asc_dvc->bios_ctrl = eep_config.bios_ctrl; + asc_dvc->no_scam = eep_config.scam_tolerant; + + /* + * For every Target ID if any of its 'sdtr_speed[1234]' bits + * are set, then set an 'sdtr_able' bit for it. + */ + asc_dvc->sdtr_able = 0; + for (tid = 0; tid <= ASC_MAX_TID; tid++) { + if (tid == 0) { + sdtr_speed = asc_dvc->sdtr_speed1; + } else if (tid == 4) { + sdtr_speed = asc_dvc->sdtr_speed2; + } else if (tid == 8) { + sdtr_speed = asc_dvc->sdtr_speed3; + } else if (tid == 12) { + sdtr_speed = asc_dvc->sdtr_speed4; + } + if (sdtr_speed & ASC_MAX_TID) { + asc_dvc->sdtr_able |= (1 << tid); + } + sdtr_speed >>= 4; + } + + /* + * Set the host maximum queuing (max. 253, min. 16) and the per device + * maximum queuing (max. 63, min. 4). + */ + if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_host_qng == 0) { + eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; + } else { + eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; + } + } + + if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { + /* If the value is zero, assume it is uninitialized. */ + if (eep_config.max_dvc_qng == 0) { + eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; + } else { + eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; + } + } + + /* + * If 'max_dvc_qng' is greater than 'max_host_qng', then + * set 'max_dvc_qng' to 'max_host_qng'. + */ + if (eep_config.max_dvc_qng > eep_config.max_host_qng) { + eep_config.max_dvc_qng = eep_config.max_host_qng; + } + + /* + * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng' + * values based on possibly adjusted EEPROM values. + */ + asc_dvc->max_host_qng = eep_config.max_host_qng; + asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + + /* + * If the EEPROM 'termination' field is set to automatic (0), then set + * the ASC_DVC_CFG 'termination' field to automatic also. + * + * If the termination is specified with a non-zero 'termination' + * value check that a legal value is set and set the ASC_DVC_CFG + * 'termination' field appropriately. + */ + if (eep_config.termination_se == 0) { + termination = 0; /* auto termination for SE */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_se == 1) { + termination = 0; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_se == 2) { + termination = TERM_SE_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_se == 3) { + termination = TERM_SE; + } else { + /* + * The EEPROM 'termination_se' field contains a bad value. + * Use automatic termination instead. + */ + termination = 0; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } + + if (eep_config.termination_lvd == 0) { + asc_dvc->cfg->termination = termination; /* auto termination for LVD */ + } else { + /* Enable manual control with low off / high off. */ + if (eep_config.termination_lvd == 1) { + asc_dvc->cfg->termination = termination; + + /* Enable manual control with low off / high on. */ + } else if (eep_config.termination_lvd == 2) { + asc_dvc->cfg->termination = termination | TERM_LVD_HI; + + /* Enable manual control with low on / high on. */ + } else if (eep_config.termination_lvd == 3) { + asc_dvc->cfg->termination = termination | TERM_LVD; + } else { + /* + * The EEPROM 'termination_lvd' field contains a bad value. + * Use automatic termination instead. + */ + asc_dvc->cfg->termination = termination; + warn_code |= ASC_WARN_EEPROM_TERMINATION; + } + } + + return warn_code; +} + +/* + * 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; +} + /* - * Wait for EEPROM command to complete + * Read EEPROM configuration into the specified buffer. + * + * Return a checksum based on the EEPROM configuration read. */ -static void __devinit AdvWaitEEPCmd(AdvPortAddr iop_base) +static ushort __init +AdvGet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) { - int eep_delay_ms; + ushort wval, chksum; + ushort *wbuf; + int eep_addr; + ushort *charfields; - 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; + 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; } - mdelay(1); } - if ((AdvReadWordRegister(iop_base, IOPW_EE_CMD) & ASC_EEP_CMD_DONE) == - 0) - BUG(); + /* 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. + * + * 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 __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) +static ushort __init AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) { AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_READ | eep_word_addr); @@ -12258,10 +16868,31 @@ static ushort __devinit AdvReadEEPWord(AdvPortAddr iop_base, int eep_word_addr) 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'. */ -void __devinit +void __init AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) { ushort *wbuf; @@ -12292,7 +16923,7 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); AdvWaitEEPCmd(iop_base); - mdelay(ADV_EEP_DELAY_MS); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); } /* @@ -12323,12 +16954,13 @@ AdvSet3550EEPConfig(AdvPortAddr iop_base, ADVEEP_3550_CONFIG *cfg_buf) } AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); AdvWaitEEPCmd(iop_base); + return; } /* * Write the EEPROM from 'cfg_buf'. */ -void __devinit +void __init AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) { ushort *wbuf; @@ -12359,7 +16991,7 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); AdvWaitEEPCmd(iop_base); - mdelay(ADV_EEP_DELAY_MS); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); } /* @@ -12390,12 +17022,13 @@ AdvSet38C0800EEPConfig(AdvPortAddr iop_base, ADVEEP_38C0800_CONFIG *cfg_buf) } AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); AdvWaitEEPCmd(iop_base); + return; } /* * Write the EEPROM from 'cfg_buf'. */ -void __devinit +void __init AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) { ushort *wbuf; @@ -12426,7 +17059,7 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE | addr); AdvWaitEEPCmd(iop_base); - mdelay(ADV_EEP_DELAY_MS); + DvcSleepMilliSecond(ADV_EEP_DELAY_MS); } /* @@ -12446,997 +17079,826 @@ AdvSet38C1600EEPConfig(AdvPortAddr iop_base, ADVEEP_38C1600_CONFIG *cfg_buf) 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); -} - -/* - * Read EEPROM configuration into the specified buffer. - * - * Return a checksum based on the EEPROM configuration read. - */ -static ushort __devinit -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. - * - * 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; - - 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. - * - * 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; - - 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); + 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); } - return chksum; + AdvWriteWordRegister(iop_base, IOPW_EE_CMD, ASC_EEP_CMD_WRITE_DISABLE); + AdvWaitEEPCmd(iop_base); + return; } +/* a_advlib.c */ /* - * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and - * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while - * all of this is done. + * AdvExeScsiQueue() - Send a request to the RISC microcode program. * - * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. + * 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. * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. + * If 'done_status' is not set to QD_DO_RETRY, then 'error_retry' will be + * set to SCSI_MAX_RETRY. * - * Note: Chip is stopped on entry. + * 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 __devinit AdvInitFrom3550EEP(ADV_DVC_VAR *asc_dvc) +static int AdvExeScsiQueue(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) { + ulong last_int_level; AdvPortAddr iop_base; - ushort warn_code; - ADVEEP_3550_CONFIG eep_config; - - iop_base = asc_dvc->iop_base; + ADV_DCNT req_size; + ADV_PADDR req_paddr; + ADV_CARR_T *new_carrp; - warn_code = 0; + ASC_ASSERT(scsiq != NULL); /* 'scsiq' should never be NULL. */ /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. + * The ADV_SCSI_REQ_Q 'target_id' field should never exceed ADV_MAX_TID. */ - if (AdvGet3550EEPConfig(iop_base, &eep_config) != eep_config.check_sum) { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - - /* - * Set EEPROM default values. - */ - 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. - */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); + if (scsiq->target_id > ADV_MAX_TID) { + scsiq->host_status = QHSTA_M_INVALID_DEVICE; + scsiq->done_status = QD_WITH_ERROR; + return ADV_ERROR; + } - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); + iop_base = asc_dvc->iop_base; - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); + last_int_level = DvcEnterCritical(); - AdvSet3550EEPConfig(iop_base, &eep_config); + /* + * 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 ASC_DVC_VAR and ASC_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. + * 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. */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_able = eep_config.sdtr_able; - asc_dvc->ultra_able = eep_config.ultra_able; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; - asc_dvc->cfg->serial1 = eep_config.serial_number_word1; - asc_dvc->cfg->serial2 = eep_config.serial_number_word2; - asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + new_carrp->next_vpa = cpu_to_le32(ASC_CQ_STOPPER); /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). + * Clear the ADV_SCSI_REQ_Q done flag. */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } - } + scsiq->a_flag &= ~ADV_SCSIQ_DONE; - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } - } + 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)); /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. + * Every ADV_CARR_T.carr_pa is byte swapped to little-endian + * order during initialization. */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + scsiq->carr_pa = asc_dvc->icq_sp->carr_pa; /* - * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. + * 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->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + asc_dvc->icq_sp->areq_vpa = req_paddr; /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ADV_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ADV_DVC_CFG - * 'termination' field appropriately. + * 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. */ - if (eep_config.termination == 0) { - asc_dvc->cfg->termination = 0; /* auto termination */ - } else { - /* Enable manual control with low off / high off. */ - if (eep_config.termination == 1) { - asc_dvc->cfg->termination = TERM_CTL_SEL; + asc_dvc->icq_sp->next_vpa = new_carrp->carr_pa; - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination == 2) { - asc_dvc->cfg->termination = TERM_CTL_SEL | TERM_CTL_H; + /* + * Set the host adapter stopper pointer to point to the new carrier. + */ + asc_dvc->icq_sp = new_carrp; - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination == 3) { - asc_dvc->cfg->termination = - TERM_CTL_SEL | TERM_CTL_H | TERM_CTL_L; - } else { + 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) { /* - * The EEPROM 'termination' field contains a bad value. Use - * automatic termination instead. + * Clear the tickle value. In the ASC-3550 the RISC flag + * command 'clr_tickle_a' does not work unless the host + * value is cleared. */ - asc_dvc->cfg->termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; + 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)); } - return warn_code; + DvcLeaveCritical(last_int_level); + + return ADV_SUCCESS; } /* - * Read the board's EEPROM configuration. Set fields in ADV_DVC_VAR and - * ADV_DVC_CFG based on the EEPROM settings. The chip is stopped while - * all of this is done. - * - * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. + * Reset SCSI Bus and purge all outstanding requests. * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. + * 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. + */ + DvcDelayMicroSecond(asc_dvc, (ushort)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; + } + + DvcSleepMilliSecond((ADV_DCNT)asc_dvc->scsi_reset_wait * 1000); + + return status; +} + +/* + * Reset chip and SCSI Bus. * - * Note: Chip is stopped on entry. + * 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 __devinit AdvInitFrom38C0800EEP(ADV_DVC_VAR *asc_dvc) +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 warn_code; - ADVEEP_38C0800_CONFIG eep_config; - uchar tid, termination; - ushort sdtr_speed = 0; + ushort bios_sig; iop_base = asc_dvc->iop_base; - warn_code = 0; - /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. + * Save current per TID negotiated values. */ - if (AdvGet38C0800EEPConfig(iop_base, &eep_config) != - eep_config.check_sum) { - warn_code |= ASC_WARN_EEPROM_CHKSUM; - - /* - * Set EEPROM default values. - */ - 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. - */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - - AdvSet38C0800EEPConfig(iop_base, &eep_config); + 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]); } + /* - * Set ADV_DVC_VAR and ADV_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. + * 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. */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; - asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; - asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; - asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ADV_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; - asc_dvc->cfg->serial1 = eep_config.serial_number_word1; - asc_dvc->cfg->serial2 = eep_config.serial_number_word2; - asc_dvc->cfg->serial3 = eep_config.serial_number_word3; + AdvReadWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); + AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, 0); /* - * For every Target ID if any of its 'sdtr_speed[1234]' bits - * are set, then set an 'sdtr_able' bit for it. + * Stop chip and reset it. */ - asc_dvc->sdtr_able = 0; - for (tid = 0; tid <= ADV_MAX_TID; tid++) { - if (tid == 0) { - sdtr_speed = asc_dvc->sdtr_speed1; - } else if (tid == 4) { - sdtr_speed = asc_dvc->sdtr_speed2; - } else if (tid == 8) { - sdtr_speed = asc_dvc->sdtr_speed3; - } else if (tid == 12) { - sdtr_speed = asc_dvc->sdtr_speed4; - } - if (sdtr_speed & ADV_MAX_TID) { - asc_dvc->sdtr_able |= (1 << tid); - } - sdtr_speed >>= 4; - } + 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); /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). + * Reset Adv Library error code, if any, and try + * re-initializing the chip. */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } + 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); } - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } + /* Translate initialization return value to status value. */ + if (status == 0) { + status = ADV_TRUE; + } else { + status = ADV_FALSE; } /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. + * Restore the BIOS signature word. */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + AdvWriteWordLram(iop_base, ASC_MC_BIOS_SIGNATURE, bios_sig); /* - * Set ADV_DVC_VAR 'max_host_qng' and ADV_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. + * Restore per TID negotiated values. */ - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + 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]); + } - /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ADV_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ADV_DVC_CFG - * 'termination' field appropriately. - */ - if (eep_config.termination_se == 0) { - termination = 0; /* auto termination for SE */ - } else { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_se == 1) { - termination = 0; + return status; +} - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_se == 2) { - termination = TERM_SE_HI; +/* + * 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; - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_se == 3) { - termination = TERM_SE; - } else { - /* - * The EEPROM 'termination_se' field contains a bad value. - * Use automatic termination instead. - */ - termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } + flags = DvcEnterCritical(); + + 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) { + DvcLeaveCritical(flags); + return ADV_FALSE; } - if (eep_config.termination_lvd == 0) { - asc_dvc->cfg->termination = termination; /* auto termination for LVD */ - } else { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_lvd == 1) { - asc_dvc->cfg->termination = termination; + /* + * 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. + */ + if (int_stat & ADV_INTR_STATUS_INTRB) { + uchar intrb_code; - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_lvd == 2) { - asc_dvc->cfg->termination = termination | TERM_LVD_HI; + AdvReadByteLram(iop_base, ASC_MC_INTRB_CODE, intrb_code); - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_lvd == 3) { - asc_dvc->cfg->termination = termination | TERM_LVD; - } else { - /* - * The EEPROM 'termination_lvd' field contains a bad value. - * Use automatic termination instead. - */ - asc_dvc->cfg->termination = termination; - warn_code |= ASC_WARN_EEPROM_TERMINATION; + 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); } } - return warn_code; -} + /* + * 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)); -/* - * Read the board's EEPROM configuration. Set fields in ASC_DVC_VAR and - * ASC_DVC_CFG based on the EEPROM settings. The chip is stopped while - * all of this is done. - * - * 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. - * - * Note: Chip is stopped on entry. - */ -static int __devinit AdvInitFrom38C1600EEP(ADV_DVC_VAR *asc_dvc) -{ - AdvPortAddr iop_base; - ushort warn_code; - ADVEEP_38C1600_CONFIG eep_config; - uchar tid, termination; - ushort sdtr_speed = 0; + /* + * 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; + } - iop_base = asc_dvc->iop_base; + /* + * 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)); - warn_code = 0; + 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--; - /* - * Read the board's EEPROM configuration. - * - * Set default values if a bad checksum is found. - */ - 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; + ASC_ASSERT(scsiq != NULL); + target_bit = ADV_TID_TO_TIDMASK(scsiq->target_id); /* - * Set EEPROM default values. + * Clear request microcode control flag. */ - memcpy(&eep_config, &Default_38C1600_EEPROM_Config, - sizeof(ADVEEP_38C1600_CONFIG)); + scsiq->cntl = 0; - 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; + /* + * 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); } /* - * Assume the 6 byte board serial number that was read from - * EEPROM is correct even if the EEPROM checksum failed. + * 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... */ - eep_config.serial_number_word3 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 1); - eep_config.serial_number_word2 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 2); - eep_config.serial_number_word1 = - AdvReadEEPWord(iop_base, ADV_EEP_DVC_CFG_END - 3); - AdvSet38C1600EEPConfig(iop_base, &eep_config); + /* + * 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(); } + DvcLeaveCritical(flags); + return ADV_TRUE; +} - /* - * Set ASC_DVC_VAR and ASC_DVC_CFG variables from the - * EEPROM configuration that was read. - * - * This is the mapping of EEPROM fields to Adv Library fields. - */ - asc_dvc->wdtr_able = eep_config.wdtr_able; - asc_dvc->sdtr_speed1 = eep_config.sdtr_speed1; - asc_dvc->sdtr_speed2 = eep_config.sdtr_speed2; - asc_dvc->sdtr_speed3 = eep_config.sdtr_speed3; - asc_dvc->sdtr_speed4 = eep_config.sdtr_speed4; - asc_dvc->ppr_able = 0; - asc_dvc->tagqng_able = eep_config.tagqng_able; - asc_dvc->cfg->disc_enable = eep_config.disc_enable; - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; - asc_dvc->chip_scsi_id = (eep_config.adapter_scsi_id & ASC_MAX_TID); - asc_dvc->start_motor = eep_config.start_motor; - asc_dvc->scsi_reset_wait = eep_config.scsi_reset_delay; - asc_dvc->bios_ctrl = eep_config.bios_ctrl; - asc_dvc->no_scam = eep_config.scam_tolerant; - - /* - * For every Target ID if any of its 'sdtr_speed[1234]' bits - * are set, then set an 'sdtr_able' bit for it. - */ - asc_dvc->sdtr_able = 0; - for (tid = 0; tid <= ASC_MAX_TID; tid++) { - if (tid == 0) { - sdtr_speed = asc_dvc->sdtr_speed1; - } else if (tid == 4) { - sdtr_speed = asc_dvc->sdtr_speed2; - } else if (tid == 8) { - sdtr_speed = asc_dvc->sdtr_speed3; - } else if (tid == 12) { - sdtr_speed = asc_dvc->sdtr_speed4; - } - if (sdtr_speed & ASC_MAX_TID) { - asc_dvc->sdtr_able |= (1 << tid); - } - sdtr_speed >>= 4; - } +/* + * 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; - /* - * Set the host maximum queuing (max. 253, min. 16) and the per device - * maximum queuing (max. 63, min. 4). - */ - if (eep_config.max_host_qng > ASC_DEF_MAX_HOST_QNG) { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else if (eep_config.max_host_qng < ASC_DEF_MIN_HOST_QNG) { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_host_qng == 0) { - eep_config.max_host_qng = ASC_DEF_MAX_HOST_QNG; - } else { - eep_config.max_host_qng = ASC_DEF_MIN_HOST_QNG; - } - } + last_int_level = DvcEnterCritical(); - if (eep_config.max_dvc_qng > ASC_DEF_MAX_DVC_QNG) { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else if (eep_config.max_dvc_qng < ASC_DEF_MIN_DVC_QNG) { - /* If the value is zero, assume it is uninitialized. */ - if (eep_config.max_dvc_qng == 0) { - eep_config.max_dvc_qng = ASC_DEF_MAX_DVC_QNG; - } else { - eep_config.max_dvc_qng = ASC_DEF_MIN_DVC_QNG; - } - } + iop_base = asc_dvc->iop_base; /* - * If 'max_dvc_qng' is greater than 'max_host_qng', then - * set 'max_dvc_qng' to 'max_host_qng'. + * 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. */ - if (eep_config.max_dvc_qng > eep_config.max_host_qng) { - eep_config.max_dvc_qng = eep_config.max_host_qng; - } + AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD_STATUS, (ushort)0); /* - * Set ASC_DVC_VAR 'max_host_qng' and ASC_DVC_VAR 'max_dvc_qng' - * values based on possibly adjusted EEPROM values. + * 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. */ - asc_dvc->max_host_qng = eep_config.max_host_qng; - asc_dvc->max_dvc_qng = eep_config.max_dvc_qng; + AdvWriteDWordLramNoSwap(iop_base, ASC_MC_IDLE_CMD_PARAMETER, + cpu_to_le32(idle_cmd_parameter)); + AdvWriteWordLram(iop_base, ASC_MC_IDLE_CMD, idle_cmd); /* - * If the EEPROM 'termination' field is set to automatic (0), then set - * the ASC_DVC_CFG 'termination' field to automatic also. - * - * If the termination is specified with a non-zero 'termination' - * value check that a legal value is set and set the ASC_DVC_CFG - * 'termination' field appropriately. + * Tickle the RISC to tell it to process the idle command. */ - if (eep_config.termination_se == 0) { - termination = 0; /* auto termination for SE */ - } else { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_se == 1) { - termination = 0; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_se == 2) { - termination = TERM_SE_HI; - - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_se == 3) { - termination = TERM_SE; - } else { - /* - * The EEPROM 'termination_se' field contains a bad value. - * Use automatic termination instead. - */ - termination = 0; - warn_code |= ASC_WARN_EEPROM_TERMINATION; - } - } - - if (eep_config.termination_lvd == 0) { - asc_dvc->cfg->termination = termination; /* auto termination for LVD */ - } else { - /* Enable manual control with low off / high off. */ - if (eep_config.termination_lvd == 1) { - asc_dvc->cfg->termination = termination; - - /* Enable manual control with low off / high on. */ - } else if (eep_config.termination_lvd == 2) { - asc_dvc->cfg->termination = termination | TERM_LVD_HI; + 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); + } - /* Enable manual control with low on / high on. */ - } else if (eep_config.termination_lvd == 3) { - asc_dvc->cfg->termination = termination | TERM_LVD; - } else { - /* - * The EEPROM 'termination_lvd' field contains a bad value. - * Use automatic termination instead. - */ - asc_dvc->cfg->termination = termination; - warn_code |= ASC_WARN_EEPROM_TERMINATION; + /* 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); } } - return warn_code; + ASC_ASSERT(0); /* The idle command should never timeout. */ + DvcLeaveCritical(last_int_level); + return ADV_ERROR; } /* - * Initialize the ADV_DVC_VAR structure. - * - * On failure set the ADV_DVC_VAR field 'err_code' and return ADV_ERROR. + * Inquiry Information Byte 7 Handling * - * For a non-fatal error return a warning code. If there are no warnings - * then 0 is returned. + * Handle SCSI Inquiry Command information for a device by setting + * microcode operating variables that affect WDTR, SDTR, and Tag + * Queuing. */ -static int __devinit -AdvInitGetConfig(struct pci_dev *pdev, struct Scsi_Host *shost) +static void AdvInquiryHandling(ADV_DVC_VAR *asc_dvc, ADV_SCSI_REQ_Q *scsiq) { - 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; - - asc_dvc->err_code = 0; + AdvPortAddr iop_base; + uchar tid; + ADV_SCSI_INQUIRY *inq; + ushort tidmask; + ushort cfg_word; /* - * 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. + * 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. */ - 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; - asc_dvc->cfg->chip_version = - AdvGetChipVersion(iop_base, asc_dvc->bus_type); + if (scsiq->cdb[4] < 8 || + (scsiq->cdb[4] - le32_to_cpu(scsiq->data_cnt)) < 8) { + return; + } - 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); + iop_base = asc_dvc->iop_base; + tid = scsiq->target_id; - 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); + inq = (ADV_SCSI_INQUIRY *) scsiq->vdata_addr; /* - * Reset the chip to start and allow register writes. + * WDTR, SDTR, and Tag Queuing cannot be enabled for old devices. */ - if (AdvFindSignature(iop_base) == 0) { - asc_dvc->err_code = ASC_IERR_BAD_SIGNATURE; - return ADV_ERROR; + if (ADV_INQ_RESPONSE_FMT(inq) < 2 && ADV_INQ_ANSI_VER(inq) < 2) { + return; } else { /* - * The caller must set 'chip_type' to a valid setting. + * 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. */ - 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; - } + + tidmask = ADV_TID_TO_TIDMASK(tid); /* - * Reset Chip. + * 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. */ - 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 ((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); - 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 { - status = AdvInitFrom3550EEP(asc_dvc); + /* + * 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); + } } - warn_code |= status; - } - if (warn_code != 0) - shost_printk(KERN_WARNING, shost, "warning: 0x%x\n", warn_code); + /* + * 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 (asc_dvc->err_code) - shost_printk(KERN_ERR, shost, "error code 0x%x\n", - asc_dvc->err_code); + /* + * 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); - return asc_dvc->err_code; + AdvWriteByteLram(iop_base, + ASC_MC_NUMBER_OF_MAX_CMD + tid, + asc_dvc->max_dvc_qng); + } + } } -#endif -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, - /* - * 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. - */ - .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, -}; +MODULE_LICENSE("Dual BSD/GPL"); -static int __devinit advansys_wide_init_chip(struct Scsi_Host *shost) +static struct Scsi_Host *__devinit +advansys_board_found(int iop, struct device *dev, int bus_type) { - 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; + struct Scsi_Host *shost; + struct pci_dev *pdev = bus_type == ASC_IS_PCI ? to_pci_dev(dev) : NULL; + asc_board_t *boardp; + 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; /* - * Allocate buffer carrier structures. The total size - * is about 4 KB, so allocate all at once. - */ - adv_dvc->carrier_buf = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL); - ASC_DBG(1, "carrier_buf 0x%p\n", adv_dvc->carrier_buf); - - if (!adv_dvc->carrier_buf) - goto kmalloc_failed; - - /* - * 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->max_host_qng; req_cnt > 0; req_cnt--) { - reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL); - - ASC_DBG(1, "reqp 0x%p, req_cnt %d, bytes %lu\n", reqp, req_cnt, - (ulong)sizeof(adv_req_t) * req_cnt); - - if (reqp) - break; - } - - if (!reqp) - goto kmalloc_failed; - - adv_dvc->orig_reqp = reqp; - - /* - * Allocate up to ADV_TOT_SG_BLOCK request structures for - * the Wide board. Each structure is about 136 bytes. + * Adapter found. + * + * Register the adapter, get its configuration, and + * initialize it. */ - board->adv_sgblkp = NULL; - for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) { - sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL); - - if (!sgp) - break; + ASC_DBG(2, "advansys_board_found: scsi_register()\n"); + shost = scsi_register(&driver_template, sizeof(asc_board_t)); - sgp->next_sgblkp = board->adv_sgblkp; - board->adv_sgblkp = sgp; + if (!shost) + return NULL; - } + /* Save a pointer to the Scsi_Host of each board found. */ + asc_host[asc_board_count++] = shost; - ASC_DBG(1, "sg_cnt %d * %lu = %lu bytes\n", sg_cnt, sizeof(adv_sgblk_t), - sizeof(adv_sgblk_t) * sg_cnt); + /* Initialize private per board data */ + boardp = ASC_BOARDP(shost); + memset(boardp, 0, sizeof(asc_board_t)); + boardp->id = asc_board_count - 1; - if (!board->adv_sgblkp) - goto kmalloc_failed; + /* Initialize spinlock. */ + spin_lock_init(&boardp->lock); /* - * Point 'adv_reqp' to the request structures and - * link them together. + * 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. */ - 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]; - - 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); - } - err_code = adv_dvc->err_code; - - if (warn_code || err_code) { - shost_printk(KERN_WARNING, shost, "error: warn 0x%x, error " - "0x%x\n", warn_code, err_code); - } - - goto exit; - - kmalloc_failed: - shost_printk(KERN_ERR, shost, "error: kmalloc() failed\n"); - err_code = ADV_ERROR; - exit: - return err_code; -} - -static void advansys_wide_free_mem(struct asc_board *board) -{ - 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); +#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; } -} - -static int __devinit advansys_board_found(struct Scsi_Host *shost, - unsigned int iop, int bus_type) -{ - 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; - int share_irq, warn_code, ret; - - pdev = (bus_type == ASC_IS_PCI) ? to_pci_dev(boardp->dev) : NULL; +#endif /* CONFIG_PCI */ if (ASC_NARROW_BOARD(boardp)) { - ASC_DBG(1, "narrow board\n"); + ASC_DBG(1, "advansys_board_found: 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 { -#ifdef CONFIG_PCI + ASC_DBG(1, "advansys_board_found: wide board\n"); 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, "wide board ASC-3550\n"); + ASC_DBG(1, "advansys_board_found: ASC-3550\n"); adv_dvc_varp->chip_type = ADV_CHIP_ASC3550; } else if (pdev->device == PCI_DEVICE_ID_38C0800_REV1) { - ASC_DBG(1, "wide board ASC-38C0800\n"); + ASC_DBG(1, "advansys_board_found: ASC-38C0800\n"); adv_dvc_varp->chip_type = ADV_CHIP_ASC38C0800; } else { - ASC_DBG(1, "wide board ASC-38C1600\n"); + ASC_DBG(1, "advansys_board_found: ASC-38C1600\n"); adv_dvc_varp->chip_type = ADV_CHIP_ASC38C1600; } +#endif /* CONFIG_PCI */ - 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; + /* + * 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; } - adv_dvc_varp->iop_base = (AdvPortAddr)boardp->ioremap_addr; - ASC_DBG(1, "iop_base: 0x%p\n", adv_dvc_varp->iop_base); + 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 */ /* * Even though it isn't used to access wide boards, other @@ -13445,9 +17907,9 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, */ boardp->ioport = 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 */ + 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)); } #ifdef CONFIG_PROC_FS @@ -13455,16 +17917,18 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, * Allocate buffer for printing information from * /proc/scsi/advansys/[0...]. */ - 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; + 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; } #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(). @@ -13473,55 +17937,126 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, #ifdef CONFIG_ISA case ASC_IS_ISA: shost->unchecked_isa_dma = TRUE; - share_irq = 0; + share_irq = FALSE; break; case ASC_IS_VL: shost->unchecked_isa_dma = FALSE; - share_irq = 0; + share_irq = FALSE; break; case ASC_IS_EISA: shost->unchecked_isa_dma = FALSE; - share_irq = IRQF_SHARED; + share_irq = TRUE; 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 = IRQF_SHARED; + share_irq = TRUE; break; #endif /* CONFIG_PCI */ default: - shost_printk(KERN_ERR, shost, "unknown adapter type: " - "%d\n", asc_dvc_varp->bus_type); + ASC_PRINT2 + ("advansys_board_found: board %d: unknown adapter type: %d\n", + boardp->id, asc_dvc_varp->bus_type); shost->unchecked_isa_dma = TRUE; - share_irq = 0; + share_irq = FALSE; 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, "AscInitGetConfig()\n"); - ret = AscInitGetConfig(shost) ? -ENODEV : 0; + 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); + } } else { -#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"); - - ret = AdvInitGetConfig(pdev, shost) ? -ENODEV : 0; -#endif /* CONFIG_PCI */ + 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); + } } - if (ret) - goto err_free_proc; + if (err_code != 0) { +#ifdef CONFIG_PROC_FS + kfree(boardp->prtbuf); +#endif /* CONFIG_PROC_FS */ + scsi_unregister(shost); + asc_board_count--; + return NULL; + } /* * Save the EEPROM configuration so that it can be displayed @@ -13563,10 +18098,61 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, /* * Modify board configuration. */ - ASC_DBG(2, "AscInitSetConfig()\n"); - ret = AscInitSetConfig(pdev, shost) ? -ENODEV : 0; - if (ret) - goto err_free_proc; + 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; + } } else { ADVEEP_3550_CONFIG *ep_3550; ADVEEP_38C0800_CONFIG *ep_38C0800; @@ -13660,6 +18246,11 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, */ 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; } /* @@ -13671,7 +18262,6 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, 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; @@ -13682,7 +18272,6 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, } 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 @@ -13691,6 +18280,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, * PCI Memory Mapped I/O. */ shost->io_port = iop; + boardp->asc_n_io_port = iolen; shost->this_id = adv_dvc_varp->chip_scsi_id; @@ -13698,6 +18288,15 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, shost->can_queue = adv_dvc_varp->max_host_qng; } + /* + * '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. @@ -13744,12 +18343,14 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, shost->sg_tablesize = SG_ALL; } - ASC_DBG(1, "sg_tablesize: %d\n", shost->sg_tablesize); + ASC_DBG1(1, "advansys_board_found: sg_tablesize: %d\n", shost->sg_tablesize); /* BIOS start address. */ if (ASC_NARROW_BOARD(boardp)) { - shost->base = AscGetChipBiosAddress(asc_dvc_varp->iop_base, - asc_dvc_varp->bus_type); + shost->base = ((ulong) + AscGetChipBiosAddress(asc_dvc_varp-> + iop_base, + asc_dvc_varp->bus_type)); } else { /* * Fill-in BIOS board variables. The Wide BIOS saves @@ -13764,10 +18365,12 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, AdvReadWordLram(adv_dvc_varp->iop_base, BIOS_CODELEN, boardp->bios_codelen); - ASC_DBG(1, "bios_signature 0x%x, bios_version 0x%x\n", + ASC_DBG2(1, + "advansys_board_found: bios_signature 0x%x, bios_version 0x%x\n", boardp->bios_signature, boardp->bios_version); - ASC_DBG(1, "bios_codeseg 0x%x, bios_codelen 0x%x\n", + ASC_DBG2(1, + "advansys_board_found: bios_codeseg 0x%x, bios_codelen 0x%x\n", boardp->bios_codeseg, boardp->bios_codelen); /* @@ -13789,6 +18392,30 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, * 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 @@ -13796,12 +18423,19 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, /* 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; - 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; + 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; } AscEnableIsaDma(shost->dma_channel); } @@ -13809,392 +18443,573 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, #endif /* CONFIG_ISA */ /* Register IRQ Number. */ - 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) { + 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)) { if (ret == -EBUSY) { - shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x " - "already in use\n", boardp->irq); + ASC_PRINT2 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x already in use.\n", + boardp->id, shost->irq); } else if (ret == -EINVAL) { - shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x " - "not valid\n", boardp->irq); + ASC_PRINT2 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x not valid.\n", + boardp->id, shost->irq); } else { - shost_printk(KERN_ERR, shost, "request_irq(): IRQ 0x%x " - "failed with %d\n", boardp->irq, ret); + ASC_PRINT3 + ("advansys_board_found: board %d: request_irq(): IRQ 0x%x failed with %d\n", + boardp->id, shost->irq, ret); } - goto err_free_dma; + 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; } /* * Initialize board RISC chip and enable interrupts. */ if (ASC_NARROW_BOARD(boardp)) { - ASC_DBG(2, "AscInitAsc1000Driver()\n"); + ASC_DBG(2, "advansys_board_found: AscInitAsc1000Driver()\n"); warn_code = AscInitAsc1000Driver(asc_dvc_varp); + err_code = asc_dvc_varp->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; + 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); } } else { - if (advansys_wide_init_chip(shost)) - ret = -ENODEV; - } + ADV_CARR_T *carrp; + int req_cnt = 0; + adv_req_t *reqp = NULL; + int sg_cnt = 0; - if (ret) - goto err_free_wide_mem; + /* + * 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); - ASC_DBG_PRT_SCSI_HOST(2, shost); + if (carrp == NULL) { + goto kmalloc_error; + } - ret = scsi_add_host(shost, boardp->dev); - if (ret) - goto err_free_wide_mem; + /* + * 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--) { - scsi_scan_host(shost); - return 0; + reqp = (adv_req_t *) + kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC); - 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; -} + 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); -/* - * 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 (reqp != NULL) { + break; + } + } + if (reqp == NULL) { + goto kmalloc_error; + } -#define ASC_IOADR_TABLE_MAX_IX 11 + /* + * 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++) { -static PortAddr _asc_def_iop_base[ASC_IOADR_TABLE_MAX_IX] __devinitdata = { - 0x100, 0x0110, 0x120, 0x0130, 0x140, 0x0150, 0x0190, - 0x0210, 0x0230, 0x0250, 0x0330 -}; + sgp = (adv_sgblk_t *) + kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC); -/* - * 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 (sgp == NULL) { + break; + } -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; + sgp->next_sgblkp = boardp->adv_sgblkp; + boardp->adv_sgblkp = sgp; - 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; + } + 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)); - err = -ENOMEM; - shost = scsi_host_alloc(&advansys_template, sizeof(*board)); - if (!shost) - goto release_region; + /* + * 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 { - board = shost_priv(shost); - board->irq = advansys_isa_irq_no(iop_base); - board->dev = dev; + /* Save carrier buffer pointer. */ + boardp->orig_carrp = carrp; - err = advansys_board_found(shost, iop_base, ASC_IS_ISA); - if (err) - goto free_host; + /* + * Save original pointer for kfree() in case the + * driver is built as a module and can be unloaded. + */ + boardp->orig_reqp = reqp; - dev_set_drvdata(dev, shost); - return 0; + adv_dvc_varp->carrier_buf = carrp; - free_host: - scsi_host_put(shost); - release_region: - release_region(iop_base, ASC_IOADR_GAP); - return err; -} + /* + * 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; -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; -} + 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); + } + } + } -static struct isa_driver advansys_isa_driver = { - .probe = advansys_isa_probe, - .remove = __devexit_p(advansys_isa_remove), - .driver = { - .owner = THIS_MODULE, - .name = DRV_NAME, - }, -}; + 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); -/* - * 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 unsigned int __devinit advansys_vlb_irq_no(PortAddr iop_base) -{ - 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; - return chip_irq; + return shost; } -static int __devinit advansys_vlb_probe(struct device *dev, unsigned int id) +/* + * 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(). + */ +static int __init advansys_detect(struct scsi_host_template *tpnt) { - int err = -ENODEV; - PortAddr iop_base = _asc_def_iop_base[id]; - struct Scsi_Host *shost; - struct asc_board *board; + 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 (!request_region(iop_base, ASC_IOADR_GAP, DRV_NAME)) { - ASC_DBG(1, "I/O port 0x%x busy\n", iop_base); - return -ENODEV; + if (detect_called == ASC_FALSE) { + detect_called = ASC_TRUE; + } else { + printk + ("AdvanSys SCSI: advansys_detect() multiple calls ignored\n"); + return 0; } - ASC_DBG(1, "probing I/O port 0x%x\n", iop_base); - if (!AscFindSignature(iop_base)) - goto release_region; - /* - * 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 (AscGetChipVersion(iop_base, ASC_IS_VL) > ASC_CHIP_MAX_VER_VL) - goto release_region; - - err = -ENOMEM; - shost = scsi_host_alloc(&advansys_template, sizeof(*board)); - if (!shost) - goto release_region; - board = shost_priv(shost); - board->irq = advansys_vlb_irq_no(iop_base); - board->dev = dev; + ASC_DBG(1, "advansys_detect: begin\n"); - err = advansys_board_found(shost, iop_base, ASC_IS_VL); - if (err) - goto free_host; + asc_board_count = 0; - dev_set_drvdata(dev, shost); - return 0; + /* + * If I/O port probing has been modified, then verify and + * clean-up the 'asc_ioport' list. + */ + 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; + } - free_host: - scsi_host_put(shost); - release_region: - release_region(iop_base, ASC_IOADR_GAP); - return -ENODEV; -} + for (bus = 0; bus < ASC_NUM_BUS; bus++) { -static struct isa_driver advansys_vlb_driver = { - .probe = advansys_vlb_probe, - .remove = __devexit_p(advansys_isa_remove), - .driver = { - .owner = THIS_MODULE, - .name = "advansys_vlb", - }, -}; + ASC_DBG2(1, "advansys_detect: bus search type %d (%s)\n", + bus, asc_bus_name[bus]); + iop = 0; -static struct eisa_device_id advansys_eisa_table[] __devinitdata = { - { "ABP7401" }, - { "ABP7501" }, - { "" } -}; + while (asc_board_count < ASC_NUM_BOARD_SUPPORTED) { -MODULE_DEVICE_TABLE(eisa, advansys_eisa_table); + ASC_DBG1(2, "advansys_detect: asc_board_count %d\n", + asc_board_count); -/* - * 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]; -}; + 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; -/* - * 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; -} + case ASC_IS_EISA: +#ifdef CONFIG_ISA + iop = AscSearchIOPortAddr(iop, asc_bus[bus]); +#endif /* CONFIG_ISA */ + 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; + 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; + } + } + } - err = -ENOMEM; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - goto fail; - ioport = edev->base_addr + 0xc30; + /* + * 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; + } + } + } - 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; - } + pci_card_cnt = 0; + } else { + pci_card_cnt++; + } - /* - * 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 (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; - if (!irq) - irq = advansys_eisa_irq_no(edev); +#endif /* CONFIG_PCI */ + break; - err = -ENOMEM; - shost = scsi_host_alloc(&advansys_template, sizeof(*board)); - if (!shost) - goto release_region; + default: + ASC_PRINT1 + ("advansys_detect: unknown bus type: %d\n", + asc_bus[bus]); + break; + } + ASC_DBG1(1, "advansys_detect: iop 0x%x\n", iop); - board = shost_priv(shost); - board->irq = irq; - board->dev = dev; + /* + * Adapter not found, try next bus type. + */ + if (iop == 0) { + break; + } - err = advansys_board_found(shost, ioport, ASC_IS_EISA); - if (!err) { - data->host[i] = shost; - continue; + advansys_board_found(iop, dev, asc_bus[bus]); } - - scsi_host_put(shost); - release_region: - release_region(ioport, ASC_IOADR_GAP); - break; } - 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; + ASC_DBG1(1, "advansys_detect: done: asc_board_count %d\n", + asc_board_count); + return asc_board_count; } -static __devexit int advansys_eisa_remove(struct device *dev) +/* + * advansys_release() + * + * Release resources allocated for a single AdvanSys adapter. + */ +static int advansys_release(struct Scsi_Host *shost) { - int i; - struct eisa_scsi_data *data = dev_get_drvdata(dev); + asc_board_t *boardp; - 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); + 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); } + release_region(shost->io_port, boardp->asc_n_io_port); + if (ASC_WIDE_BOARD(boardp)) { + adv_sgblk_t *sgp = NULL; - kfree(data); + 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"); return 0; } -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), - } -}; - +#ifdef CONFIG_PCI /* PCI Devices supported by this driver */ static struct pci_device_id advansys_pci_tbl[] __devinitdata = { {PCI_VENDOR_ID_ASP, PCI_DEVICE_ID_ASP_1200A, @@ -14213,131 +19028,4 @@ static struct pci_device_id advansys_pci_tbl[] __devinitdata = { }; MODULE_DEVICE_TABLE(pci, advansys_pci_tbl); - -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"); +#endif /* CONFIG_PCI */ diff --git a/trunk/drivers/scsi/aha152x.c b/trunk/drivers/scsi/aha152x.c index f08e71e0205a..d30a30786dda 100644 --- a/trunk/drivers/scsi/aha152x.c +++ b/trunk/drivers/scsi/aha152x.c @@ -907,10 +907,9 @@ struct Scsi_Host *aha152x_probe_one(struct aha152x_setup *setup) void aha152x_release(struct Scsi_Host *shpnt) { - if (!shpnt) + if(!shpnt) return; - scsi_remove_host(shpnt); if (shpnt->irq) free_irq(shpnt->irq, shpnt); @@ -924,6 +923,7 @@ 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/trunk/drivers/scsi/aic7xxx_old.c b/trunk/drivers/scsi/aic7xxx_old.c index 1a71b0236c97..4998bb850c49 100644 --- a/trunk/drivers/scsi/aic7xxx_old.c +++ b/trunk/drivers/scsi/aic7xxx_old.c @@ -8416,9 +8416,10 @@ aic7xxx_alloc(struct scsi_host_template *sht, struct aic7xxx_host *temp) *p = *temp; p->host = host; - p->scb_data = kzalloc(sizeof(scb_data_type), GFP_ATOMIC); - if (!p->scb_data) + p->scb_data = kmalloc(sizeof(scb_data_type), GFP_ATOMIC); + if (p->scb_data != NULL) { + memset(p->scb_data, 0, sizeof(scb_data_type)); scbq_init (&p->scb_data->free_scbs); } else @@ -9195,9 +9196,10 @@ aic7xxx_detect(struct scsi_host_template *template) printk(KERN_INFO " this driver, we are ignoring it.\n"); } } - else if ( (temp_p = kzalloc(sizeof(struct aic7xxx_host), + else if ( (temp_p = kmalloc(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/trunk/drivers/scsi/aic94xx/aic94xx_hwi.h b/trunk/drivers/scsi/aic94xx/aic94xx_hwi.h index 491e5d8a98bc..c6c3d18222fa 100644 --- a/trunk/drivers/scsi/aic94xx/aic94xx_hwi.h +++ b/trunk/drivers/scsi/aic94xx/aic94xx_hwi.h @@ -40,6 +40,18 @@ #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/trunk/drivers/scsi/aic94xx/aic94xx_init.c b/trunk/drivers/scsi/aic94xx/aic94xx_init.c index b70d6e7f96e9..63bcde246447 100644 --- a/trunk/drivers/scsi/aic94xx/aic94xx_init.c +++ b/trunk/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_put; + goto Err; } asd_ha->pcidev = dev; asd_ha->sas_ha.dev = &asd_ha->pcidev->dev; @@ -600,12 +600,14 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, shost->max_cmd_len = 16; err = scsi_add_host(shost, &dev->dev); - if (err) + if (err) { + scsi_host_put(shost); goto Err_free; + } err = asd_dev->setup(asd_ha); if (err) - goto Err_remove; + goto Err_free; err = -ENODEV; if (!pci_set_dma_mask(dev, DMA_64BIT_MASK) @@ -616,14 +618,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_remove; + goto Err_free; } pci_set_drvdata(dev, asd_ha); err = asd_map_ha(asd_ha); if (err) - goto Err_remove; + goto Err_free; err = asd_create_ha_caches(asd_ha); if (err) @@ -690,12 +692,9 @@ static int __devinit asd_pci_probe(struct pci_dev *dev, asd_destroy_ha_caches(asd_ha); Err_unmap: asd_unmap_ha(asd_ha); -Err_remove: - scsi_remove_host(shost); Err_free: kfree(asd_ha); -Err_put: - scsi_host_put(shost); + scsi_remove_host(shost); Err: pci_disable_device(dev); return err; @@ -830,15 +829,22 @@ 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, 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}, + {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}, {} }; diff --git a/trunk/drivers/scsi/aic94xx/aic94xx_task.c b/trunk/drivers/scsi/aic94xx/aic94xx_task.c index f2b23e01401a..ab13824df856 100644 --- a/trunk/drivers/scsi/aic94xx/aic94xx_task.c +++ b/trunk/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), - iu->status); + ts->stat); } } } else { diff --git a/trunk/drivers/scsi/arcmsr/arcmsr.h b/trunk/drivers/scsi/arcmsr/arcmsr.h index ace7a15b413e..f0b8bf4534f0 100644 --- a/trunk/drivers/scsi/arcmsr/arcmsr.h +++ b/trunk/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: support@areca.com.tw +** E-mail: erich@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,26 +45,19 @@ #include struct class_device_attribute; -/*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_MAX_OUTSTANDING_CMD 256 +#define ARCMSR_MAX_FREECCB_NUM 288 +#define ARCMSR_DRIVER_VERSION "Driver Version 1.20.00.14" #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_HBB_POSTQUEUE 264 -/* -********************************************************************************** -** -********************************************************************************** -*/ -#define ARC_SUCCESS 0 -#define ARC_FAILURE 1 +#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 + /* ******************************************************************************* ** split 64bits dma addressing @@ -97,7 +90,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 */ @@ -170,27 +163,27 @@ struct QBUFFER }; /* ******************************************************************************* -** FIRMWARE INFO for Intel IOP R 80331 processor (Type A) +** FIRMWARE INFO ******************************************************************************* */ 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 @@ -210,60 +203,6 @@ 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) @@ -275,6 +214,7 @@ struct ARCMSR_CDB uint8_t TargetID; uint8_t LUN; uint8_t Function; + uint8_t CdbLength; uint8_t sgcount; uint8_t Flags; @@ -284,18 +224,20 @@ struct ARCMSR_CDB #define ARCMSR_CDB_FLAG_SIMPLEQ 0x00 #define ARCMSR_CDB_FLAG_HEADQ 0x08 #define ARCMSR_CDB_FLAG_ORDEREDQ 0x10 - 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 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]; + union { struct SG32ENTRY sg32entry[ARCMSR_MAX_SG_ENTRIES]; @@ -304,10 +246,10 @@ struct ARCMSR_CDB }; /* ******************************************************************************* -** Messaging Unit (MU) of the Intel R 80331 I/O processor(Type A) and Type B processor +** Messaging Unit (MU) of the Intel R 80331 I/O processor (80331) ******************************************************************************* */ -struct MessageUnit_A +struct MessageUnit { uint32_t resrved0[4]; /*0000 000F*/ uint32_t inbound_msgaddr0; /*0010 0013*/ @@ -332,30 +274,6 @@ struct MessageUnit_A 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 @@ -363,45 +281,37 @@ 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 * pmu; + struct MessageUnit __iomem * 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 */ @@ -443,7 +353,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; @@ -556,9 +466,7 @@ struct SENSE_DATA #define ARCMSR_MU_OUTBOUND_MESSAGE0_INTMASKENABLE 0x01 #define ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE 0x1F -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 void arcmsr_post_Qbuffer(struct AdapterControlBlock *acb); extern struct class_device_attribute *arcmsr_host_attrs[]; -extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *); +extern int arcmsr_alloc_sysfs_attr(struct AdapterControlBlock *acb); void arcmsr_free_sysfs_attr(struct AdapterControlBlock *acb); diff --git a/trunk/drivers/scsi/arcmsr/arcmsr_attr.c b/trunk/drivers/scsi/arcmsr/arcmsr_attr.c index d04d1aa28fa4..06c0dce3b839 100644 --- a/trunk/drivers/scsi/arcmsr/arcmsr_attr.c +++ b/trunk/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: support@areca.com.tw +** E-mail: erich@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,7 +49,6 @@ #include #include #include -#include #include #include @@ -59,14 +58,15 @@ struct class_device_attribute *arcmsr_host_attrs[]; -static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, - struct bin_attribute *bin, - char *buf, loff_t off, - size_t count) +static ssize_t +arcmsr_sysfs_iop_message_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + 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,13 +85,12 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, allxfer_len++; } if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { - struct QBUFFER *prbuffer; - uint8_t *iop_data; + 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; - 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); @@ -100,15 +99,16 @@ static ssize_t arcmsr_sysfs_iop_message_read(struct kobject *kobj, iop_data++; iop_len--; } - arcmsr_iop_message_read(acb); + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK, + ®->inbound_doorbell); } return (allxfer_len); } -static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, - struct bin_attribute *bin, - char *buf, loff_t off, - size_t count) +static ssize_t +arcmsr_sysfs_iop_message_write(struct kobject *kobj, + struct bin_attribute *bin_attr, + 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 @@ static ssize_t 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_ioctldata2iop(acb); + arcmsr_post_Qbuffer(acb); return 0; /*need retry*/ } else { my_empty_len = (wqbuf_firstindex-wqbuf_lastindex - 1) @@ -144,7 +144,7 @@ static ssize_t 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_ioctldata2iop(acb); + arcmsr_post_Qbuffer(acb); } return count; } else { @@ -153,14 +153,15 @@ static ssize_t arcmsr_sysfs_iop_message_write(struct kobject *kobj, } } -static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, - struct bin_attribute *bin, - char *buf, loff_t off, - size_t count) +static ssize_t +arcmsr_sysfs_iop_message_clear(struct kobject *kobj, + struct bin_attribute *bin_attr, + 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)) @@ -168,7 +169,8 @@ static ssize_t arcmsr_sysfs_iop_message_clear(struct kobject *kobj, if (acb->acb_flags & ACB_F_IOPDATA_OVERFLOW) { acb->acb_flags &= ~ACB_F_IOPDATA_OVERFLOW; - arcmsr_iop_message_read(acb); + writel(ARCMSR_INBOUND_DRIVER_DATA_READ_OK + , ®->inbound_doorbell); } acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED @@ -189,7 +191,6 @@ 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, @@ -199,7 +200,6 @@ 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,7 +209,6 @@ 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, @@ -220,26 +219,31 @@ 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; } @@ -248,9 +252,12 @@ 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/trunk/drivers/scsi/arcmsr/arcmsr_hba.c b/trunk/drivers/scsi/arcmsr/arcmsr_hba.c index cfcf40159eab..0ddfc21e9f7d 100644 --- a/trunk/drivers/scsi/arcmsr/arcmsr_hba.c +++ b/trunk/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: support@areca.com.tw +** E-mail: erich@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,34 +71,33 @@ #include #include "arcmsr.h" -MODULE_AUTHOR("Erich Chen "); +MODULE_AUTHOR("Erich Chen "); 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_confirm(struct AdapterControlBlock *acb); +static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, struct scsi_cmnd *cmd); 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_hba_cache(struct AdapterControlBlock *acb); -static void arcmsr_flush_hbb_cache(struct AdapterControlBlock *acb); +static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb); +static uint8_t arcmsr_wait_msgint_ready(struct AdapterControlBlock *acb); static const char *arcmsr_info(struct Scsi_Host *); static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb); -static int arcmsr_adjust_disk_queue_depth(struct scsi_device *sdev, - int queue_depth) +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) { if (queue_depth > ARCMSR_MAX_CMD_PERLUN) queue_depth = ARCMSR_MAX_CMD_PERLUN; @@ -124,25 +123,17 @@ 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)}, @@ -162,20 +153,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 = dev_id; + struct AdapterControlBlock *acb; + unsigned long flags; - spin_lock(acb->host->host_lock); - handle_state = arcmsr_interrupt(acb); - spin_unlock(acb->host->host_lock); + acb = (struct AdapterControlBlock *)dev_id; + spin_lock_irqsave(acb->host->host_lock, flags); + handle_state = arcmsr_interrupt(acb); + spin_unlock_irqrestore(acb->host->host_lock, flags); return handle_state; } @@ -207,159 +198,68 @@ static int arcmsr_bios_param(struct scsi_device *sdev, return 0; } -static void arcmsr_define_adapter_type(struct AdapterControlBlock *acb) -{ - struct pci_dev *pdev = acb->pdev; - 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) { + 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; - 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; - - 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)); - } - - 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_GONE; - - /* - ** 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; - - acb->dma_coherent = dma_coherent; - acb->dma_coherent_handle = dma_coherent_handle; + if (!dma_coherent) + return -ENOMEM; - 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)); - } + acb->dma_coherent = dma_coherent; + acb->dma_coherent_handle = dma_coherent_handle; - reg = (struct MessageUnit_B *)(dma_coherent + - ARCMSR_MAX_FREECCB_NUM * sizeof(struct CommandControlBlock)); + 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++; + } - 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; + 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; + /* + ** 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); } + + writel(readl(®->outbound_intmask) | + ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, + ®->outbound_intmask); return 0; } @@ -410,11 +310,16 @@ 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; - } - arcmsr_define_adapter_type(acb); + 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; + } acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); @@ -423,10 +328,10 @@ static int arcmsr_probe(struct pci_dev *pdev, error = arcmsr_alloc_ccb_pool(acb); if (error) - goto out_release_regions; + goto out_iounmap; error = request_irq(pdev->irq, arcmsr_do_interrupt, - IRQF_SHARED, "arcmsr", acb); + IRQF_DISABLED | IRQF_SHARED, "arcmsr", acb); if (error) goto out_free_ccb_pool; @@ -444,15 +349,14 @@ 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); @@ -464,84 +368,17 @@ static int arcmsr_probe(struct pci_dev *pdev, return error; } -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_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) +static void arcmsr_abort_allcmd(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit __iomem *reg = acb->pmu; writel(ARCMSR_INBOUND_MESG0_ABORT_CMD, ®->inbound_msgaddr0); - 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)) + if (arcmsr_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; @@ -563,239 +400,28 @@ 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); - arcmsr_disable_outbound_ints(acb); + writel(readl(®->outbound_intmask) | + ARCMSR_MU_OUTBOUND_ALL_INTMASKENABLE, + ®->outbound_intmask); acb->acb_flags |= ACB_F_SCSISTOPADAPTER; acb->acb_flags &= ~ACB_F_IOP_INITED; - for (poll_count = 0; poll_count < ARCMSR_MAX_OUTSTANDING_CMD; poll_count++) { + for (poll_count = 0; poll_count < 256; poll_count++) { if (!atomic_read(&acb->ccboutstandingcount)) break; - arcmsr_interrupt(acb);/* FIXME: need spinlock */ + arcmsr_interrupt(acb); msleep(25); } @@ -803,7 +429,8 @@ static void arcmsr_remove(struct pci_dev *pdev) int i; arcmsr_abort_allcmd(acb); - arcmsr_done4abort_postqueue(acb); + for (i = 0; i < ARCMSR_MAX_OUTSTANDING_CMD; i++) + readl(®->outbound_queueport); for (i = 0; i < ARCMSR_MAX_FREECCB_NUM; i++) { struct CommandControlBlock *ccb = acb->pccb_pool[i]; if (ccb->startdone == ARCMSR_CCB_START) { @@ -850,53 +477,96 @@ static void arcmsr_module_exit(void) module_init(arcmsr_module_init); module_exit(arcmsr_module_exit); -static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, \ - u32 intmask_org) +static u32 arcmsr_disable_outbound_ints(struct AdapterControlBlock *acb) { - u32 mask; + 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; +} - switch (acb->adapter_type) { +static void arcmsr_enable_outbound_ints(struct AdapterControlBlock *acb, + u32 orig_mask) +{ + struct MessageUnit __iomem *reg = acb->pmu; + u32 mask; - case ACB_ADAPTER_TYPE_A : { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; - mask = intmask_org & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | + mask = orig_mask & ~(ARCMSR_MU_OUTBOUND_POSTQUEUE_INTMASKENABLE | ARCMSR_MU_OUTBOUND_DOORBELL_INTMASKENABLE); - writel(mask, ®->outbound_intmask); - acb->outbound_int_enable = ~(intmask_org & mask) & 0x000000ff; - } - break; - - 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; - } - } + writel(mask, ®->outbound_intmask); } -static void arcmsr_build_ccb(struct AdapterControlBlock *acb, - struct CommandControlBlock *ccb, struct scsi_cmnd *pcmd) +static void arcmsr_flush_adapter_cache(struct AdapterControlBlock *acb) { - struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; - int8_t *psge = (int8_t *)&arcmsr_cdb->u; - uint32_t address_lo, address_hi; - int arccdbsize = 0x30; - int nseg; - - ccb->pcmd = pcmd; - memset(arcmsr_cdb, 0, sizeof(struct ARCMSR_CDB)); - arcmsr_cdb->Bus = 0; - arcmsr_cdb->TargetID = pcmd->device->id; - arcmsr_cdb->LUN = pcmd->device->lun; - arcmsr_cdb->Function = 1; - arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len; - arcmsr_cdb->Context = (unsigned long)arcmsr_cdb; - memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); + struct MessageUnit __iomem *reg = acb->pmu; - nseg = scsi_dma_map(pcmd); - BUG_ON(nseg < 0); + 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; + + 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 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) +{ + struct ARCMSR_CDB *arcmsr_cdb = (struct ARCMSR_CDB *)&ccb->arcmsr_cdb; + int8_t *psge = (int8_t *)&arcmsr_cdb->u; + uint32_t address_lo, address_hi; + int arccdbsize = 0x30; + int nseg; + + ccb->pcmd = pcmd; + memset(arcmsr_cdb, 0, sizeof (struct ARCMSR_CDB)); + arcmsr_cdb->Bus = 0; + arcmsr_cdb->TargetID = pcmd->device->id; + arcmsr_cdb->LUN = pcmd->device->lun; + arcmsr_cdb->Function = 1; + arcmsr_cdb->CdbLength = (uint8_t)pcmd->cmd_len; + arcmsr_cdb->Context = (unsigned long)arcmsr_cdb; + memcpy(arcmsr_cdb->Cdb, pcmd->cmnd, pcmd->cmd_len); + + nseg = scsi_dma_map(pcmd); + BUG_ON(nseg < 0); if (nseg) { int length, i, cdb_sgcount = 0; @@ -939,85 +609,52 @@ 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; - - 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, + 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); - } - } - break; - - case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; - uint32_t ending_index, index = reg->postq_index; - - 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]); - } - 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; - } + else + writel(cdb_shifted_phyaddr, ®->inbound_queueport); } -static void arcmsr_stop_hba_bgrb(struct AdapterControlBlock *acb) +void arcmsr_post_Qbuffer(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_STOP_BGRB, ®->inbound_msgaddr0); + 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; - if (arcmsr_hba_wait_msgint_ready(acb)) { - printk(KERN_NOTICE - "arcmsr%d: wait 'stop adapter background rebulid' timeout \n" - , acb->host->host_no); + 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++; + } + writel(allxfer_len, &pwbuffer->data_len); + writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK + , ®->inbound_doorbell); } } -static void arcmsr_stop_hbb_bgrb(struct AdapterControlBlock *acb) +static void arcmsr_stop_adapter_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); + struct MessageUnit __iomem *reg = acb->pmu; - if (arcmsr_hbb_wait_msgint_ready(acb)) { + acb->acb_flags &= ~ACB_F_MSG_START_BGRB; + writel(ARCMSR_INBOUND_MESG0_STOP_BGRB, ®->inbound_msgaddr0); + if (arcmsr_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) @@ -1028,260 +665,151 @@ static void arcmsr_free_ccb_pool(struct AdapterControlBlock *acb) acb->dma_coherent_handle); } -void arcmsr_iop_message_read(struct AdapterControlBlock *acb) +static irqreturn_t arcmsr_interrupt(struct AdapterControlBlock *acb) { - 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; + struct MessageUnit __iomem *reg = acb->pmu; + struct CommandControlBlock *ccb; + uint32_t flag_ccb, outbound_intstatus, outbound_doorbell; - case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; - writel(ARCMSR_DRV2IOP_DATA_READ_OK, reg->drv2iop_doorbell_reg); + 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; } - break; } -} - -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; - /* - ** push inbound doorbell tell iop, driver data write ok - ** and wait reply on next hwinterrupt for next Qbuffer post - */ - writel(ARCMSR_INBOUND_DRIVER_DATA_WRITE_OK, ®->inbound_doorbell); - } - break; - - case ACB_ADAPTER_TYPE_B: { - struct MessageUnit_B *reg = (struct MessageUnit_B *)acb->pmu; + if (outbound_intstatus & ARCMSR_MU_OUTBOUND_POSTQUEUE_INT) { + int id, lun; /* - ** push inbound doorbell tell iop, driver data write ok - ** and wait reply on next hwinterrupt for next Qbuffer post + **************************************************************** + ** areca cdb command done + **************************************************************** */ - 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; + 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*/ } + if (!(outbound_intstatus & ARCMSR_MU_OUTBOUND_HANDLE_INT)) + return IRQ_NONE; return IRQ_HANDLED; } @@ -1290,47 +818,16 @@ 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); } } } -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) +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; @@ -1339,7 +836,7 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ (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; @@ -1355,199 +852,194 @@ static int arcmsr_iop_message_xfer(struct AdapterControlBlock *acb, \ } 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; - - 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) { + unsigned long *ver_addr; + dma_addr_t buf_handle; + uint8_t *pQbuffer, *ptmpQbuffer; + int32_t allxfer_len = 0; - 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--; + ver_addr = pci_alloc_consistent(acb->pdev, 1032, &buf_handle); + if (!ver_addr) { + retvalue = ARCMSR_MESSAGE_FAIL; + goto message_out; } - 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); + 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); + } + 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) { - 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 */ + 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_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; - 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; + 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; } 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; - 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; + 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; } 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; - 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; + 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; } 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; } @@ -1617,7 +1109,8 @@ 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; @@ -1660,27 +1153,26 @@ 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_hba_config(struct AdapterControlBlock *acb) +static void arcmsr_get_firmware_spec(struct AdapterControlBlock *acb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit __iomem *reg = acb->pmu; char *acb_firm_model = acb->firm_model; char *acb_firm_version = acb->firm_version; - char *iop_firm_model = (char *) (®->message_rwbuffer[15]); - char *iop_firm_version = (char *) (®->message_rwbuffer[17]); + char __iomem *iop_firm_model = (char __iomem *) ®->message_rwbuffer[15]; + char __iomem *iop_firm_version = (char __iomem *) ®->message_rwbuffer[17]; int count; writel(ARCMSR_INBOUND_MESG0_GET_CONFIG, ®->inbound_msgaddr0); - if (arcmsr_hba_wait_msgint_ready(acb)) { - printk(KERN_NOTICE "arcmsr%d: wait 'get adapter firmware \ - miscellaneous data' timeout \n", acb->host->host_no); - } - + if (arcmsr_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); @@ -1688,7 +1180,6 @@ static void arcmsr_get_hba_config(struct AdapterControlBlock *acb) iop_firm_model++; count--; } - count = 16; while (count) { *acb_firm_version = readb(iop_firm_version); @@ -1696,93 +1187,28 @@ static void arcmsr_get_hba_config(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_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, +static void arcmsr_polling_ccbdone(struct AdapterControlBlock *acb, struct CommandControlBlock *poll_ccb) { - struct MessageUnit_A __iomem *reg = (struct MessageUnit_A *)acb->pmu; + struct MessageUnit __iomem *reg = acb->pmu; struct CommandControlBlock *ccb; uint32_t flag_ccb, outbound_intstatus, poll_ccb_done = 0, poll_count = 0; + int id, lun; - polling_hba_ccb_retry: + polling_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) { @@ -1792,14 +1218,17 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, msleep(25); if (poll_count > 100) break; - goto polling_hba_ccb_retry; + goto polling_ccb_retry; } } - 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'" + 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'" " poll command abort successfully \n" , acb->host->host_no , ccb->pcmd->device->id @@ -1810,280 +1239,176 @@ static void arcmsr_polling_hba_ccbdone(struct AdapterControlBlock *acb, poll_ccb_done = 1; continue; } - 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; - } - 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; + 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); } - } - 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; + 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); - continue; } - printk(KERN_NOTICE "arcmsr%d: polling get an illegal ccb" - " command done ccb = '0x%p'" - "ccboutstandingcount = %d \n" + 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 - , ccb - , atomic_read(&acb->ccboutstandingcount)); - continue; + , 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; } - 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 int arcmsr_iop_confirm(struct AdapterControlBlock *acb) +static void arcmsr_done4_abort_postqueue(struct AdapterControlBlock *acb) { - 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; + 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; } - arcmsr_enable_outbound_ints(acb, intmask_org); - } - } - break; - - case ACB_ADAPTER_TYPE_B: { - unsigned long post_queue_phyaddr; - uint32_t *rwbuffer; - - 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; - } - - 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; -} -static void arcmsr_wait_firmware_ready(struct AdapterControlBlock *acb) -{ - uint32_t firmware_state = 0; + 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; - switch (acb->adapter_type) { + case ARCMSR_DEV_ABORTED: - 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 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 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; - } -} + 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_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); + 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; + } } -} - -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); + found = 1; + } } -} - -static void arcmsr_start_adapter_bgrb(struct AdapterControlBlock *acb) -{ - 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; + if (found){ + outbound_intstatus = readl(®->outbound_intstatus) & \ + acb->outbound_int_enable; + writel(outbound_intstatus, ®->outbound_intstatus); + /*clear interrupt*/ } + return; } -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; - - 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; - } -} static void arcmsr_iop_init(struct AdapterControlBlock *acb) { - uint32_t intmask_org; + struct MessageUnit __iomem *reg = acb->pmu; + uint32_t intmask_org, mask, outbound_doorbell, firmware_state = 0; - arcmsr_wait_firmware_ready(acb); - arcmsr_iop_confirm(acb); - /* disable all outbound interrupt */ - intmask_org = arcmsr_disable_outbound_ints(acb); + 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); - /*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_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); + } + + 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; acb->acb_flags |= ACB_F_IOP_INITED; } @@ -2096,24 +1421,22 @@ 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*/ - ssleep(3); - + msleep_interruptible(3000); /* disable all outbound interrupt */ intmask_org = arcmsr_disable_outbound_ints(acb); /* clear all outbound posted Q */ - arcmsr_done4abort_postqueue(acb); + arcmsr_done4_abort_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) @@ -2127,7 +1450,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);/* FIXME: need spinlock */ + arcmsr_interrupt(acb); msleep(25); } arcmsr_iop_reset(acb); @@ -2145,7 +1468,7 @@ static void arcmsr_abort_one_cmd(struct AdapterControlBlock *acb, /* ** Wait for 3 sec for all command done. */ - ssleep(3); + msleep_interruptible(3000); intmask = arcmsr_disable_outbound_ints(acb); arcmsr_polling_ccbdone(acb, ccb); @@ -2192,8 +1515,6 @@ 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*/ @@ -2201,7 +1522,6 @@ 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: @@ -2224,82 +1544,287 @@ 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 = pci_get_drvdata(pdev); - struct AdapterControlBlock *acb = - (struct AdapterControlBlock *) host->hostdata; - uint32_t intmask_org; - int i, j; + struct Scsi_Host *host; + struct AdapterControlBlock *acb; + uint8_t bus, dev_fun; + int error; - if (pci_enable_device(pdev)) { + error = pci_enable_device(pdev); + if (error) return PCI_ERS_RESULT_DISCONNECT; - } pci_set_master(pdev); - intmask_org = arcmsr_disable_outbound_ints(acb); + + 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; + + 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); + return PCI_ERS_RESULT_DISCONNECT; + } acb->acb_flags |= (ACB_F_MESSAGE_WQBUFFER_CLEARED | ACB_F_MESSAGE_RQBUFFER_CLEARED | ACB_F_MESSAGE_WQBUFFER_READED); acb->acb_flags &= ~ACB_F_SCSISTOPADAPTER; - for (i = 0; i < ARCMSR_MAX_TARGETID; i++) - for (j = 0; j < ARCMSR_MAX_TARGETLUN; j++) - acb->devstate[i][j] = ARECA_RAID_GONE; + INIT_LIST_HEAD(&acb->ccb_free_list); - 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; + error = arcmsr_alloc_ccb_pool(acb); + if (error) + return PCI_ERS_RESULT_DISCONNECT; - pci_enable_pcie_error_reporting(pdev); + 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; + + error = arcmsr_alloc_sysfs_attr(acb); + if (error) + return PCI_ERS_RESULT_DISCONNECT; + + scsi_scan_host(host); 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 AdapterControlBlock *acb = (struct AdapterControlBlock *) host->hostdata; + struct MessageUnit __iomem *reg = acb->pmu; struct CommandControlBlock *ccb; - uint32_t intmask_org; - int i = 0; + /*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; + } - 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); + 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" + " 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; } } - /* enable all outbound interrupt */ - arcmsr_enable_outbound_ints(acb, intmask_org); - } - pci_disable_device(pdev); + if (found){ + outbound_intstatus = readl(®->outbound_intstatus) & + acb->outbound_int_enable; + writel(outbound_intstatus, ®->outbound_intstatus); + /*clear interrupt*/ + } + return; } + 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 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; + } - arcmsr_stop_adapter_bgrb(acb); - arcmsr_flush_adapter_cache(acb); + 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" + " 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; } static pci_ers_result_t arcmsr_pci_error_detected(struct pci_dev *pdev, @@ -2315,6 +1840,5 @@ 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/trunk/drivers/scsi/atari_NCR5380.c b/trunk/drivers/scsi/atari_NCR5380.c index 52d0b87e9aa4..03dbe60c264a 100644 --- a/trunk/drivers/scsi/atari_NCR5380.c +++ b/trunk/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->scsi_done(cmd); + cmd->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->scsi_done(cmd); + cmd->done(cmd); /* XXX - need to source or sink data here, as appropriate */ } else { #ifdef REAL_DMA @@ -2235,17 +2235,24 @@ 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/trunk/drivers/scsi/bvme6000_scsi.c b/trunk/drivers/scsi/bvme6000_scsi.c index d858f3d41274..cac354086737 100644 --- a/trunk/drivers/scsi/bvme6000_scsi.c +++ b/trunk/drivers/scsi/bvme6000_scsi.c @@ -36,18 +36,19 @@ static struct platform_device *bvme6000_scsi_device; static __devinit int bvme6000_probe(struct device *dev) { - struct Scsi_Host *host; + struct Scsi_Host * host = NULL; struct NCR_700_Host_Parameters *hostdata; if (!MACH_IS_BVME6000) goto out; - hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); - if (!hostdata) { + hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + if (hostdata == NULL) { 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/trunk/drivers/scsi/constants.c b/trunk/drivers/scsi/constants.c index 024553f9c247..2a458d66b6ff 100644 --- a/trunk/drivers/scsi/constants.c +++ b/trunk/drivers/scsi/constants.c @@ -1235,21 +1235,7 @@ 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) { @@ -1272,7 +1258,7 @@ scsi_decode_sense_buffer(const unsigned char *sense_buffer, int sense_len, } } -static void +void scsi_decode_sense_extras(const unsigned char *sense_buffer, int sense_len, struct scsi_sense_hdr *sshdr) { diff --git a/trunk/drivers/scsi/dc395x.c b/trunk/drivers/scsi/dc395x.c index 1591824cf4b3..7b8a3457b696 100644 --- a/trunk/drivers/scsi/dc395x.c +++ b/trunk/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->serial_number, dcb->target_id, dcb->target_lun, srb); + srb->cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun, srb); + srb->cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun, srb); + srb->cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun, srb); + srb->cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun, srb); + srb->cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun, srb); + srb->cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun, srb); + srb->cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun); + cmd->pid, 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->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->pid, 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->serial_number); + dprintkdbg(DBG_1, "queue_command: (pid#%li) done\n", cmd->pid); 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->serial_number, + srb, srb->cmd, srb->cmd->pid, 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->serial_number, cmd->device->id, cmd->device->lun, cmd); + cmd->pid, 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->serial_number, cmd->device->id, cmd->device->lun, cmd); + cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun, srb); + srb->cmd->pid, 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->serial_number, s_stat, s_stat2); + srb->cmd->pid, 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->serial_number, + srb->cmd->pid, acb->active_dcb->active_srb ? - acb->active_dcb->active_srb->cmd->serial_number : 0); + acb->active_dcb->active_srb->cmd->pid : 0); return 1; } if (DC395x_read16(acb, TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT) { dprintkdbg(DBG_KG, "start_scsi: (pid#%li) Failed (busy)\n", - srb->cmd->serial_number); + srb->cmd->pid); 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->serial_number, srb->cmd->device->id, + srb->cmd->pid, 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->serial_number, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun); + srb->cmd->pid, 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->serial_number); + dprintkdbg(DBG_0, "msgout_phase0: (pid#%li)\n", srb->cmd->pid); 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->serial_number); + dprintkdbg(DBG_0, "msgout_phase1: (pid#%li)\n", srb->cmd->pid); 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->serial_number); /* So what ? */ + srb->cmd->pid); /* So what ? */ } if (!srb->msg_count) { dprintkdbg(DBG_0, "msgout_phase1: (pid#%li) NOP msg\n", - srb->cmd->serial_number); + srb->cmd->pid); 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->serial_number); + dprintkdbg(DBG_0, "command_phase0: (pid#%li)\n", srb->cmd->pid); 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->serial_number); + dprintkdbg(DBG_0, "command_phase1: (pid#%li)\n", srb->cmd->pid); 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->serial_number, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->pid, 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->serial_number, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->pid, 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->serial_number, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->pid, 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->serial_number); + "Parity Error\n", srb->cmd->pid); 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->serial_number, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->pid, 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->serial_number, srb->cmd->device->id, srb->cmd->device->lun, + srb->cmd->pid, 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->serial_number, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->pid, 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->serial_number, srb->cmd->device->id, srb->cmd->device->lun); + srb->cmd->pid, 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->serial_number, tag, srb); + srb->cmd->pid, 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->serial_number, srb->dcb->target_id, srb->dcb->target_lun); + srb->cmd->pid, 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->serial_number); + dprintkdbg(DBG_0, "msgin_phase0: (pid#%li)\n", srb->cmd->pid); 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->serial_number, srb->total_xfer_length); + srb->cmd->pid, 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->serial_number, dcb->target_id, + srb->cmd->pid, 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->serial_number); + dprintkdbg(DBG_0, "msgin_phase1: (pid#%li)\n", srb->cmd->pid); 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->serial_number); + dprintkdbg(DBG_0, "disconnect: (pid#%li)\n", srb->cmd->pid); 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->serial_number); + srb->cmd->pid); 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->serial_number, + "<%02i-%i> SelTO\n", srb->cmd->pid, 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->serial_number); + srb->cmd->pid); 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->serial_number, dcb->target_id, + srb->cmd->pid, 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->serial_number, + dprintkdbg(DBG_1, "srb_done: (pid#%li) <%02i-%i>\n", srb->cmd->pid, 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->serial_number, cmd->device->id, cmd->device->lun, + cmd->pid, 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->serial_number, cmd->result); + cmd->pid, 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->serial_number, + printk("G:%li(%02i-%i) ", p->pid, 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->serial_number, p->device->id, + printk("W:%li<%02i-%i>", p->pid, 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->serial_number, cmd->device->id, cmd->device->lun); + cmd->pid, 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->serial_number, dcb->target_id, dcb->target_lun); + srb->cmd->pid, 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->serial_number); + SPRINTF(" %li", srb->cmd->pid); 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->serial_number); + SPRINTF(" %li", srb->cmd->pid); if (!list_empty(&dcb->srb_waiting_list) || !list_empty(&dcb->srb_going_list)) SPRINTF("\n"); } diff --git a/trunk/drivers/scsi/dpt_i2o.c b/trunk/drivers/scsi/dpt_i2o.c index bea9d659af15..502732ac270d 100644 --- a/trunk/drivers/scsi/dpt_i2o.c +++ b/trunk/drivers/scsi/dpt_i2o.c @@ -949,14 +949,16 @@ static int adpt_install_hba(struct pci_dev* pDev) } // Allocate and zero the data structure - pHba = kzalloc(sizeof(adpt_hba), GFP_KERNEL); - if (!pHba) { - if (msg_addr_virt != base_addr_virt) + pHba = kmalloc(sizeof(adpt_hba), GFP_KERNEL); + if( pHba == NULL) { + 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); @@ -2620,13 +2622,14 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) msg=(u32 __iomem *)(pHba->msg_addr_virt+m); - status = kzalloc(4, GFP_KERNEL|ADDR32); - if (!status) { + status = kmalloc(4,GFP_KERNEL|ADDR32); + if (status==NULL) { 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]); @@ -2665,11 +2668,12 @@ static s32 adpt_i2o_init_outbound_q(adpt_hba* pHba) kfree(pHba->reply_pool); - 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; + 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; } + 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++) { @@ -2880,11 +2884,12 @@ static int adpt_i2o_build_sys_table(void) kfree(sys_tbl); - sys_tbl = kzalloc(sys_tbl_len, GFP_KERNEL|ADDR32); - if (!sys_tbl) { + sys_tbl = kmalloc(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; @@ -3346,7 +3351,7 @@ static int __init adpt_init(void) return count > 0 ? 0 : -ENODEV; } -static void adpt_exit(void) +static void __exit adpt_exit(void) { while (hba_chain) adpt_release(hba_chain); diff --git a/trunk/drivers/scsi/dtc.c b/trunk/drivers/scsi/dtc.c index 2596165096d3..9d52e45c7d36 100644 --- a/trunk/drivers/scsi/dtc.c +++ b/trunk/drivers/scsi/dtc.c @@ -137,9 +137,11 @@ 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) @@ -174,7 +176,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) { @@ -231,7 +233,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(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address); + printk("scsi-dtc : probing address %08x\n", bases[current_base].address); #endif if (bases[current_base].noauto) continue; @@ -242,7 +244,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(KERN_DEBUG "scsi-dtc : detected board.\n"); + printk("scsi-dtc : detected board.\n"); #endif goto found; } @@ -251,7 +253,7 @@ static int __init dtc_detect(struct scsi_host_template * tpnt) } #if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) - printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr); + printk("scsi-dtc : base = %08x\n", addr); #endif if (!addr) diff --git a/trunk/drivers/scsi/eata.c b/trunk/drivers/scsi/eata.c index ec2233114bc9..a83e9f150b97 100644 --- a/trunk/drivers/scsi/eata.c +++ b/trunk/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->serial_number, SCpnt); + ha->board_name, SCpnt->pid, 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->serial_number); + "qcomm, mbox %d, pid %ld.\n", i, SCpnt->pid); 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->serial_number); + "qcomm, pid %ld, adapter busy.\n", SCpnt->pid); 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->serial_number); + "abort, pid %ld inactive.\n", SCarg->pid); return SUCCESS; } i = *(unsigned int *)SCarg->host_scribble; scmd_printk(KERN_WARNING, SCarg, - "abort, mbox %d, pid %ld.\n", i, SCarg->serial_number); + "abort, mbox %d, pid %ld.\n", i, SCarg->pid); 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->serial_number); + ha->board_name, i, SCarg->pid); 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->serial_number); + "reset, enter, pid %ld.\n", SCarg->pid); spin_lock_irq(shost->host_lock); if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->serial_number); + printk("%s: reset, pid %ld inactive.\n", ha->board_name, SCarg->pid); 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->serial_number); + ha->board_name, i, SCpnt->pid); } else { ha->cp_stat[i] = IN_RESET; printk("%s: reset, mbox %d in reset, pid %ld.\n", - ha->board_name, i, SCpnt->serial_number); + ha->board_name, i, SCpnt->pid); } 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->serial_number); + ha->board_name, i, SCpnt->pid); } 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->serial_number); + ha->board_name, i, SCpnt->pid); } 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->serial_number); + printk("%s: reset, exit, pid %ld done.\n", ha->board_name, SCarg->pid); 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->serial_number; + pl[n] = SCpnt->pid; 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->serial_number, k, flushcount, + SCpnt->pid, 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->serial_number, k); + SCpnt->pid, 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->serial_number, SCpnt); + i, SCpnt->pid, SCpnt); if (*(unsigned int *)SCpnt->host_scribble != i) panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n", - ha->board_name, i, SCpnt->serial_number, + ha->board_name, i, SCpnt->pid, *(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->serial_number, + SCpnt->device->lun, SCpnt->pid, spp->target_status, SCpnt->sense_buffer[2]); ha->target_to[SCpnt->device->id][SCpnt->device->channel] = 0; - if (ha->last_retried_pid == SCpnt->serial_number) + if (ha->last_retried_pid == SCpnt->pid) 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->serial_number; + ha->last_retried_pid = SCpnt->pid; } 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->serial_number, reg, ha->iocount); + SCpnt->pid, reg, ha->iocount); unmap_dma(i, ha); diff --git a/trunk/drivers/scsi/eata_pio.c b/trunk/drivers/scsi/eata_pio.c index 96180bb47e41..f33ad01064a9 100644 --- a/trunk/drivers/scsi/eata_pio.c +++ b/trunk/drivers/scsi/eata_pio.c @@ -107,44 +107,59 @@ 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) { - int len = 0; - off_t begin = 0, pos = 0; + static u8 buff[512]; + int size, len = 0; + off_t begin = 0, pos = 0; - if (rw) - return -ENOSYS; + if (rw) + return -ENOSYS; + if (offset == 0) + memset(buff, 0, sizeof(buff)); - len += sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: " + size = sprintf(buffer+len, "EATA (Extended Attachment) PIO driver version: " "%d.%d%s\n",VER_MAJOR, VER_MINOR, VER_SUB); - len += sprintf(buffer + len, "queued commands: %10ld\n" + len += size; pos = begin + len; + size = sprintf(buffer + len, "queued commands: %10ld\n" "processed interrupts:%10ld\n", queue_counter, int_counter); - len += sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n", + len += size; pos = begin + len; + + size = sprintf(buffer + len, "\nscsi%-2d: HBA %.10s\n", shost->host_no, SD(shost)->name); - len += sprintf(buffer + len, "Firmware revision: v%s\n", + len += size; + pos = begin + len; + size = sprintf(buffer + len, "Firmware revision: v%s\n", SD(shost)->revision); - 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", + 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", (SD(shost)->bustype == 'P')?"PCI ": (SD(shost)->bustype == 'E')?"EISA":"ISA "); - pos = begin + len; + len += size; + 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) @@ -375,7 +390,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->serial_number, y)); + cmd->pid, y)); cmd->scsi_done = (void *) done; @@ -420,10 +435,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->serial_number); + "returning DID_BUS_BUSY, done.\n", cmd->pid); done(cmd); cp->status = FREE; - return 0; + return (0); } /* FIXME: timeout */ while (!(inb(base + HA_RSTATUS) & HA_SDRQ)) @@ -435,9 +450,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->serial_number, y, sh->irq)); + "slot %d irq %d\n", sh->base, cmd->pid, y, sh->irq)); - return 0; + return (0); } static int eata_pio_abort(struct scsi_cmnd *cmd) @@ -446,7 +461,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->serial_number)); + cmd->pid)); while (inb(cmd->device->host->base + HA_RAUXSTAT) & HA_ABUSY) if (--loop == 0) { @@ -482,7 +497,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->serial_number)); + cmd->pid)); spin_lock_irq(host->host_lock); @@ -501,7 +516,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->serial_number); + printk(KERN_WARNING "eata_pio_reset: slot %d in reset, pid %ld.\n", x, sp->pid); if (sp == NULL) panic("eata_pio_reset: slot %d, sp==NULL.\n", x); @@ -574,28 +589,23 @@ 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)) - cpu_relax(); - + return (NULL); + while (!(inb(base + HA_RSTATUS) & HA_SDRQ)); 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) - cpu_relax(); - + while (inb(base + HA_RSTATUS) & HA_SBUSY); 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/trunk/drivers/scsi/esp_scsi.c b/trunk/drivers/scsi/esp_scsi.c index 4ed3a5297066..95cf7b6cd622 100644 --- a/trunk/drivers/scsi/esp_scsi.c +++ b/trunk/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 esp_get_revision(struct esp *esp) +static void __devinit esp_get_revision(struct esp *esp) { u8 val; @@ -2187,7 +2187,7 @@ static void esp_get_revision(struct esp *esp) } } -static void esp_init_swstate(struct esp *esp) +static void __devinit 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 esp_set_clock_params(struct esp *esp) +static void __devinit 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 scsi_esp_register(struct esp *esp, struct device *dev) +int __devinit scsi_esp_register(struct esp *esp, struct device *dev) { static int instance; int err; @@ -2346,7 +2346,7 @@ int scsi_esp_register(struct esp *esp, struct device *dev) } EXPORT_SYMBOL(scsi_esp_register); -void scsi_esp_unregister(struct esp *esp) +void __devexit scsi_esp_unregister(struct esp *esp) { scsi_remove_host(esp->host); } diff --git a/trunk/drivers/scsi/fdomain.c b/trunk/drivers/scsi/fdomain.c index 5d282e6a6ae1..36169d597e98 100644 --- a/trunk/drivers/scsi/fdomain.c +++ b/trunk/drivers/scsi/fdomain.c @@ -387,9 +387,7 @@ 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; @@ -1766,7 +1764,6 @@ 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, @@ -1774,7 +1771,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/trunk/drivers/scsi/g_NCR5380.c b/trunk/drivers/scsi/g_NCR5380.c index 607336f56d55..880f70d24e65 100644 --- a/trunk/drivers/scsi/g_NCR5380.c +++ b/trunk/drivers/scsi/g_NCR5380.c @@ -556,7 +556,7 @@ generic_NCR5380_biosparam(struct scsi_device *sdev, struct block_device *bdev, } #endif -#ifdef NCR53C400_PSEUDO_DMA +#if NCR53C400_PSEUDO_DMA /** * NCR5380_pread - pseudo DMA read diff --git a/trunk/drivers/scsi/gdth.c b/trunk/drivers/scsi/gdth.c index e8010a702e73..55e4d2dc2bbe 100644 --- a/trunk/drivers/scsi/gdth.c +++ b/trunk/drivers/scsi/gdth.c @@ -27,8 +27,280 @@ * along with this kernel; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * - * Linux kernel 2.6.x supported * + * Linux kernel 2.4.x, 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 + * 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. @@ -56,6 +328,8 @@ * 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, @@ -67,7 +341,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,hdr_channel:0, + * max_ids:127,rescan:N,virt_ctr: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". * @@ -78,22 +352,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 hdr_channel=0 shared_access=0 + * max_ids=127 rescan=0 virt_ctr=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: 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 + * 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 */ @@ -118,8 +392,12 @@ #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,6) #include -#include +#else +#define DMA_32BIT_MASK 0x00000000ffffffffULL +#define DMA_64BIT_MASK 0xffffffffffffffffULL +#endif #ifdef GDTH_RTC #include @@ -131,27 +409,29 @@ #include #include #include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) #include -#include +#else +#include +#include "sd.h" +#endif #include "scsi.h" #include +#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 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 int gdth_sync_event(int hanum,int service,unchar index,Scsi_Cmnd *scp); +static int gdth_async_event(int hanum); static void gdth_log_event(gdth_evt_data *dvr, char *buffer); -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 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 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); @@ -159,34 +439,42 @@ 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(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 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_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_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 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(gdth_ha_str *ha); +static void gdth_flush(int hanum); 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 @@ -283,17 +571,29 @@ static struct timer_list gdth_timer; #define GDTOFFSOF(a,b) (size_t)&(((a*)0)->b) #define INDEX_OK(i,t) ((i)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)) -#ifdef CONFIG_ISA +#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)) + 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 LIST_HEAD(gdth_instances); /* controller list */ +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 unchar gdth_write_through = FALSE; /* write through */ static gdth_evt_str ebuffer[MAX_EVENTS]; /* event buffer */ static int elastidx; @@ -345,6 +645,8 @@ 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 */ @@ -353,6 +655,7 @@ 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); @@ -361,9 +664,24 @@ 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"); @@ -374,47 +692,6 @@ 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" @@ -424,45 +701,6 @@ 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; icmndinfo[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) { @@ -472,62 +710,80 @@ static void gdth_delay(int milliseconds) } } +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) static void gdth_scsi_done(struct scsi_cmnd *scp) { - 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; + TRACE2(("gdth_scsi_done()\n")); - if (internal_command) - complete((struct completion *)scp->request); - else - scp->scsi_done(scp); + if (scp->request) + complete((struct completion *)scp->request); } 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 = kzalloc(sizeof(*scp), GFP_KERNEL); + scp = kmalloc(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; - 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->request_buffer = gdtcmd; scp->cmd_len = 12; memcpy(scp->cmnd, cmnd, 12); - cmndinfo.priority = IOCTL_PRI; - cmndinfo.internal_command = 1; + 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); +} - TRACE(("__gdth_execute() cmd 0x%x\n", scp->cmnd[0])); - __gdth_queuecommand(ha, scp, &cmndinfo); +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; + 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 = cmndinfo.status; + rval = scp->SCp.Status; if (info) - *info = cmndinfo.info; - kfree(scp); + *info = scp->SCp.Message; + + scsi_release_command(scp); return rval; } +#endif int gdth_execute(struct Scsi_Host *shost, gdth_cmd_str *gdtcmd, char *cmnd, int timeout, u32 *info) @@ -559,7 +815,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; @@ -576,9 +832,8 @@ 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; @@ -586,18 +841,14 @@ 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 = readl(addr); + id = gdth_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) { @@ -677,6 +928,7 @@ 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; @@ -713,9 +965,8 @@ 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; @@ -807,9 +1058,8 @@ 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; @@ -825,22 +1075,22 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) return 0; } dp2_ptr = ha->brd; - writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ + gdth_writeb(1, &dp2_ptr->io.memlock); /* switch off write protection */ /* reset interface area */ memset_io(&dp2_ptr->u, 0, sizeof(dp2_ptr->u)); - if (readl(&dp2_ptr->u) != 0) { + if (gdth_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 */ - 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); + 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); - irq_drq = readb(&dp2_ptr->io.rq); + irq_drq = gdth_readb(&dp2_ptr->io.rq); for (i=0; i<3; ++i) { if ((irq_drq & 1)==0) break; @@ -848,7 +1098,7 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) } ha->drq = gdth_drq_tab[i]; - irq_drq = readb(&dp2_ptr->io.rq) >> 3; + irq_drq = gdth_readb(&dp2_ptr->io.rq) >> 3; for (i=1; i<5; ++i) { if ((irq_drq & 1)==0) break; @@ -857,12 +1107,12 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) ha->irq = gdth_irq_tab[i]; /* deinitialize services */ - 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); + 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); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp2_ptr->u.ic.S_Status) != 0xff) { + while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-ISA: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -870,9 +1120,9 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)readl(&dp2_ptr->u.ic.S_Info[0]); - writeb(0, &dp2_ptr->u.ic.Status); - writeb(0xff, &dp2_ptr->io.irqdel); + 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); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-ISA: Illegal protocol version\n"); iounmap(ha->brd); @@ -886,15 +1136,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 */ - 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); + 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); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { + while (gdth_readb(&dp2_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-ISA: Initialization error\n"); iounmap(ha->brd); @@ -902,15 +1152,14 @@ static int __init gdth_init_isa(ulong32 bios_adr,gdth_ha_str *ha) } gdth_delay(1); } - writeb(0, &dp2_ptr->u.ic.Status); - writeb(0xff, &dp2_ptr->io.irqdel); + gdth_writeb(0, &dp2_ptr->u.ic.Status); + gdth_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; @@ -941,8 +1190,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } /* check and reset interface area */ dp6_ptr = ha->brd; - writel(DPMEM_MAGIC, &dp6_ptr->u); - if (readl(&dp6_ptr->u) != DPMEM_MAGIC) { + gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); + if (gdth_readl(&dp6_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; @@ -953,7 +1202,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 (readw(ha->brd) != 0xffff) { + if (gdth_readw(ha->brd) != 0xffff) { TRACE2(("init_pci_old() address 0x%x busy\n", i)); continue; } @@ -966,8 +1215,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) return 0; } dp6_ptr = ha->brd; - writel(DPMEM_MAGIC, &dp6_ptr->u); - if (readl(&dp6_ptr->u) == DPMEM_MAGIC) { + gdth_writel(DPMEM_MAGIC, &dp6_ptr->u); + if (gdth_readl(&dp6_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); found = TRUE; break; @@ -980,24 +1229,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 (readl(&dp6_ptr->u) != 0) { + if (gdth_readl(&dp6_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); iounmap(ha->brd); return 0; } /* disable board interrupts, deinit services */ - 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); + 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); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp6_ptr->u.ic.S_Status) != 0xff) { + while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1005,9 +1254,9 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - 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); + 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); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); iounmap(ha->brd); @@ -1018,15 +1267,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 */ - 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); + 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); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { + while (gdth_readb(&dp6_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); iounmap(ha->brd); @@ -1034,8 +1283,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - writeb(0, &dp6_ptr->u.ic.S_Status); - writeb(0xff, &dp6_ptr->io.irqdel); + gdth_writeb(0, &dp6_ptr->u.ic.S_Status); + gdth_writeb(0xff, &dp6_ptr->io.irqdel); ha->dma64_support = 0; @@ -1051,8 +1300,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } /* check and reset interface area */ dp6c_ptr = ha->brd; - writel(DPMEM_MAGIC, &dp6c_ptr->u); - if (readl(&dp6c_ptr->u) != DPMEM_MAGIC) { + gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); + if (gdth_readl(&dp6c_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; @@ -1063,7 +1312,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 (readw(ha->brd) != 0xffff) { + if (gdth_readw(ha->brd) != 0xffff) { TRACE2(("init_pci_plx() address 0x%x busy\n", i)); continue; } @@ -1076,8 +1325,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) return 0; } dp6c_ptr = ha->brd; - writel(DPMEM_MAGIC, &dp6c_ptr->u); - if (readl(&dp6c_ptr->u) == DPMEM_MAGIC) { + gdth_writel(DPMEM_MAGIC, &dp6c_ptr->u); + if (gdth_readl(&dp6c_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); found = TRUE; break; @@ -1090,7 +1339,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 (readl(&dp6c_ptr->u) != 0) { + if (gdth_readl(&dp6c_ptr->u) != 0) { printk("GDT-PCI: Initialization error (DPMEM write error)\n"); iounmap(ha->brd); return 0; @@ -1100,17 +1349,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)); - writeb(0x00, &dp6c_ptr->u.ic.S_Status); - writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); + gdth_writeb(0x00, &dp6c_ptr->u.ic.S_Status); + gdth_writeb(0x00, &dp6c_ptr->u.ic.Cmd_Index); - writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); - writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); + gdth_writel(pcistr->dpmem, &dp6c_ptr->u.ic.S_Info[0]); + gdth_writeb(0xff, &dp6c_ptr->u.ic.S_Cmd_Indx); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { + while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1118,8 +1367,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)readl(&dp6c_ptr->u.ic.S_Info[0]); - writeb(0, &dp6c_ptr->u.ic.Status); + prot_ver = (unchar)gdth_readl(&dp6c_ptr->u.ic.S_Info[0]); + gdth_writeb(0, &dp6c_ptr->u.ic.Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); iounmap(ha->brd); @@ -1130,17 +1379,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 */ - 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); + 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); outb(1,PTR2USHORT(&ha->plx->ldoor_reg)); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { + while (gdth_readb(&dp6c_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); iounmap(ha->brd); @@ -1148,7 +1397,7 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - writeb(0, &dp6c_ptr->u.ic.S_Status); + gdth_writeb(0, &dp6c_ptr->u.ic.S_Status); ha->dma64_support = 0; @@ -1176,12 +1425,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)readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 ) + while( ((int)gdth_readb(&dp6m_ptr->i960r.sema0_reg) ) & 3 ) gdth_delay(1); /* check and reset interface area */ - writel(DPMEM_MAGIC, &dp6m_ptr->u); - if (readl(&dp6m_ptr->u) != DPMEM_MAGIC) { + gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); + if (gdth_readl(&dp6m_ptr->u) != DPMEM_MAGIC) { printk("GDT-PCI: Cannot access DPMEM at 0x%lx (shadowed?)\n", pcistr->dpmem); found = FALSE; @@ -1192,7 +1441,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 (readw(ha->brd) != 0xffff) { + if (gdth_readw(ha->brd) != 0xffff) { TRACE2(("init_pci_mpr() address 0x%x busy\n", i)); continue; } @@ -1205,8 +1454,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) return 0; } dp6m_ptr = ha->brd; - writel(DPMEM_MAGIC, &dp6m_ptr->u); - if (readl(&dp6m_ptr->u) == DPMEM_MAGIC) { + gdth_writel(DPMEM_MAGIC, &dp6m_ptr->u); + if (gdth_readl(&dp6m_ptr->u) == DPMEM_MAGIC) { printk("GDT-PCI: Use free address at 0x%x\n", i); found = TRUE; break; @@ -1221,18 +1470,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 */ - writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) | 4, + gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) | 4, &dp6m_ptr->i960r.edoor_en_reg); - writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - writeb(0x00, &dp6m_ptr->u.ic.S_Status); - writeb(0x00, &dp6m_ptr->u.ic.Cmd_Index); + 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); - 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); + 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); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { + while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xff) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1240,8 +1489,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)readl(&dp6m_ptr->u.ic.S_Info[0]); - writeb(0, &dp6m_ptr->u.ic.S_Status); + prot_ver = (unchar)gdth_readl(&dp6m_ptr->u.ic.S_Info[0]); + gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); if (prot_ver != PROTOCOL_VERSION) { printk("GDT-PCI: Illegal protocol version\n"); iounmap(ha->brd); @@ -1252,15 +1501,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 */ - 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); + 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); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { + while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfe) { if (--retries == 0) { printk("GDT-PCI: Initialization error\n"); iounmap(ha->brd); @@ -1268,14 +1517,14 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - writeb(0, &dp6m_ptr->u.ic.S_Status); + gdth_writeb(0, &dp6m_ptr->u.ic.S_Status); /* read FW version to detect 64-bit DMA support */ - writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx); - writeb(1, &dp6m_ptr->i960r.ldoor_reg); + gdth_writeb(0xfd, &dp6m_ptr->u.ic.S_Cmd_Indx); + gdth_writeb(1, &dp6m_ptr->i960r.ldoor_reg); retries = INIT_RETRIES; gdth_delay(20); - while (readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) { + while (gdth_readb(&dp6m_ptr->u.ic.S_Status) != 0xfd) { if (--retries == 0) { printk("GDT-PCI: Initialization error (DEINIT failed)\n"); iounmap(ha->brd); @@ -1283,8 +1532,8 @@ static int __init gdth_init_pci(gdth_pci_str *pcistr,gdth_ha_str *ha) } gdth_delay(1); } - prot_ver = (unchar)(readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16); - writeb(0, &dp6m_ptr->u.ic.S_Status); + prot_ver = (unchar)(gdth_readl(&dp6m_ptr->u.ic.S_Info[0]) >> 16); + gdth_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 @@ -1293,18 +1542,20 @@ 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(gdth_ha_str *ha) +static void __init gdth_enable_int(int hanum) { + 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",ha->hanum)); + TRACE(("gdth_enable_int() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); if (ha->type == GDT_EISA) { @@ -1313,80 +1564,93 @@ static void __init gdth_enable_int(gdth_ha_str *ha) outb(0x01, ha->bmic + EINTENABREG); } else if (ha->type == GDT_ISA) { dp2_ptr = ha->brd; - writeb(1, &dp2_ptr->io.irqdel); - writeb(0, &dp2_ptr->u.ic.Cmd_Index); - writeb(1, &dp2_ptr->io.irqen); + gdth_writeb(1, &dp2_ptr->io.irqdel); + gdth_writeb(0, &dp2_ptr->u.ic.Cmd_Index); + gdth_writeb(1, &dp2_ptr->io.irqen); } else if (ha->type == GDT_PCI) { dp6_ptr = ha->brd; - writeb(1, &dp6_ptr->io.irqdel); - writeb(0, &dp6_ptr->u.ic.Cmd_Index); - writeb(1, &dp6_ptr->io.irqen); + gdth_writeb(1, &dp6_ptr->io.irqdel); + gdth_writeb(0, &dp6_ptr->u.ic.Cmd_Index); + gdth_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; - writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - writeb(readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4, + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(gdth_readb(&dp6m_ptr->i960r.edoor_en_reg) & ~4, &dp6m_ptr->i960r.edoor_en_reg); } spin_unlock_irqrestore(&ha->smp_lock, flags); } -/* return IStatus if interrupt was from this card else 0 */ -static unchar gdth_get_status(gdth_ha_str *ha, int irq) -{ - unchar IStatus = 0; - TRACE(("gdth_get_status() irq %d ctr_count %d\n", irq, gdth_ctr_count)); +static int gdth_get_status(unchar *pIStatus,int irq) +{ + register gdth_ha_str *ha; + int i; + TRACE(("gdth_get_status() irq %d ctr_count %d\n", + irq,gdth_ctr_count)); + + *pIStatus = 0; + for (i=0; iirq != (unchar)irq) /* check IRQ */ - return false; + continue; if (ha->type == GDT_EISA) - IStatus = inb((ushort)ha->bmic + EDOORREG); + *pIStatus = inb((ushort)ha->bmic + EDOORREG); else if (ha->type == GDT_ISA) - IStatus = - readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); + *pIStatus = + gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCI) - IStatus = - readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); + *pIStatus = + gdth_readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Cmd_Index); else if (ha->type == GDT_PCINEW) - IStatus = inb(PTR2USHORT(&ha->plx->edoor_reg)); + *pIStatus = inb(PTR2USHORT(&ha->plx->edoor_reg)); else if (ha->type == GDT_PCIMPR) - IStatus = - readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg); - - return IStatus; + *pIStatus = + gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.edoor_reg); + + if (*pIStatus) + return i; /* board found */ + } + return -1; } - -static int gdth_test_busy(gdth_ha_str *ha) + + +static int gdth_test_busy(int hanum) { + register gdth_ha_str *ha; register int gdtsema0 = 0; - TRACE(("gdth_test_busy() hanum %d\n", ha->hanum)); - + TRACE(("gdth_test_busy() hanum %d\n",hanum)); + + ha = HADATA(gdth_ctr_tab[hanum]); if (ha->type == GDT_EISA) gdtsema0 = (int)inb(ha->bmic + SEMA0REG); else if (ha->type == GDT_ISA) - gdtsema0 = (int)readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)gdth_readb(&((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); else if (ha->type == GDT_PCI) - gdtsema0 = (int)readb(&((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); + gdtsema0 = (int)gdth_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)readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); + (int)gdth_readb(&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); return (gdtsema0 & 1); } -static int gdth_get_cmd_index(gdth_ha_str *ha) +static int gdth_get_cmd_index(int hanum) { + register gdth_ha_str *ha; int i; - TRACE(("gdth_get_cmd_index() hanum %d\n", ha->hanum)); + TRACE(("gdth_get_cmd_index() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); for (i=0; icmd_tab[i].cmnd == UNUSED_CMND) { ha->cmd_tab[i].cmnd = ha->pccb->RequestBuffer; @@ -1399,26 +1663,30 @@ static int gdth_get_cmd_index(gdth_ha_str *ha) } -static void gdth_set_sema0(gdth_ha_str *ha) +static void gdth_set_sema0(int hanum) { - TRACE(("gdth_set_sema0() hanum %d\n", ha->hanum)); + register gdth_ha_str *ha; + 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) { - writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); + gdth_writeb(1, &((gdt2_dpram_str __iomem *)ha->brd)->u.ic.Sema0); } else if (ha->type == GDT_PCI) { - writeb(1, &((gdt6_dpram_str __iomem *)ha->brd)->u.ic.Sema0); + gdth_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) { - writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); + gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.sema0_reg); } } -static void gdth_copy_command(gdth_ha_str *ha) +static void gdth_copy_command(int hanum) { + 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; @@ -1426,8 +1694,9 @@ static void gdth_copy_command(gdth_ha_str *ha) gdt2_dpram_str __iomem *dp2_ptr; ushort cp_count,dp_offset,cmd_no; - TRACE(("gdth_copy_command() hanum %d\n", ha->hanum)); + TRACE(("gdth_copy_command() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); cp_count = ha->cmd_len; dp_offset= ha->cmd_offs_dpmem; cmd_no = ha->cmd_cnt; @@ -1446,39 +1715,42 @@ static void gdth_copy_command(gdth_ha_str *ha) /* set offset and service, copy command to DPMEM */ if (ha->type == GDT_ISA) { dp2_ptr = ha->brd; - writew(dp_offset + DPMEM_COMMAND_OFFSET, + gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp2_ptr->u.ic.comm_queue[cmd_no].offset); - writew((ushort)cmd_ptr->Service, + gdth_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; - writew(dp_offset + DPMEM_COMMAND_OFFSET, + gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6_ptr->u.ic.comm_queue[cmd_no].offset); - writew((ushort)cmd_ptr->Service, + gdth_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; - writew(dp_offset + DPMEM_COMMAND_OFFSET, + gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6c_ptr->u.ic.comm_queue[cmd_no].offset); - writew((ushort)cmd_ptr->Service, + gdth_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; - writew(dp_offset + DPMEM_COMMAND_OFFSET, + gdth_writew(dp_offset + DPMEM_COMMAND_OFFSET, &dp6m_ptr->u.ic.comm_queue[cmd_no].offset); - writew((ushort)cmd_ptr->Service, + gdth_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(gdth_ha_str *ha) +static void gdth_release_event(int hanum) { - TRACE(("gdth_release_event() hanum %d\n", ha->hanum)); + register gdth_ha_str *ha; + + TRACE(("gdth_release_event() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); #ifdef GDTH_STATISTICS { @@ -1502,50 +1774,56 @@ static void gdth_release_event(gdth_ha_str *ha) outl(ha->ccb_phys, ha->bmic + MAILBOXREG); outb(ha->pccb->Service, ha->bmic + LDOORREG); } else if (ha->type == GDT_ISA) { - writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event); + gdth_writeb(0, &((gdt2_dpram_str __iomem *)ha->brd)->io.event); } else if (ha->type == GDT_PCI) { - writeb(0, &((gdt6_dpram_str __iomem *)ha->brd)->io.event); + gdth_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) { - writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg); + gdth_writeb(1, &((gdt6m_dpram_str __iomem *)ha->brd)->i960r.ldoor_reg); } } -static int gdth_wait(gdth_ha_str *ha, int index, ulong32 time) + +static int gdth_wait(int hanum,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", ha->hanum, index, time)); + TRACE(("gdth_wait() hanum %d index %d time %d\n",hanum,index,time)); + ha = HADATA(gdth_ctr_tab[hanum]); if (index == 0) return 1; /* no wait required */ + gdth_from_wait = TRUE; do { - __gdth_interrupt(ha, (int)ha->irq, true, &wait_index); - if (wait_index == index) { + gdth_interrupt((int)ha->irq,ha); + if (wait_hanum==hanum && wait_index==index) { answer_found = TRUE; break; } gdth_delay(1); } while (--time); - - while (gdth_test_busy(ha)) + gdth_from_wait = FALSE; + + while (gdth_test_busy(hanum)) gdth_delay(0); return (answer_found); } -static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode, - ulong32 p1, ulong64 p2, ulong64 p3) +static int gdth_internal_cmd(int hanum,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)); @@ -1553,11 +1831,11 @@ static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode, for (retries = INIT_RETRIES;;) { cmd_ptr->Service = service; cmd_ptr->RequestBuffer = INTERNAL_CMND; - if (!(index=gdth_get_cmd_index(ha))) { + if (!(index=gdth_get_cmd_index(hanum))) { TRACE(("GDT: No free command index found\n")); return 0; } - gdth_set_sema0(ha); + gdth_set_sema0(hanum); cmd_ptr->OpCode = opcode; cmd_ptr->BoardNode = LOCALBOARD; if (service == CACHESERVICE) { @@ -1597,10 +1875,10 @@ static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode, ha->cmd_len = sizeof(gdth_cmd_str); ha->cmd_offs_dpmem = 0; ha->cmd_cnt = 0; - gdth_copy_command(ha); - gdth_release_event(ha); + gdth_copy_command(hanum); + gdth_release_event(hanum); gdth_delay(20); - if (!gdth_wait(ha, index, INIT_TIMEOUT)) { + if (!gdth_wait(hanum,index,INIT_TIMEOUT)) { printk("GDT: Initialization error (timeout service %d)\n",service); return 0; } @@ -1615,8 +1893,9 @@ static int gdth_internal_cmd(gdth_ha_str *ha, unchar service, ushort opcode, /* search for devices */ -static int __init gdth_search_drives(gdth_ha_str *ha) +static int __init gdth_search_drives(int hanum) { + register gdth_ha_str *ha; ushort cdev_cnt, i; int ok; ulong32 bus_no, drv_cnt, drv_no, j; @@ -1636,21 +1915,22 @@ static int __init gdth_search_drives(gdth_ha_str *ha) ulong flags; #endif - TRACE(("gdth_search_drives() hanum %d\n", ha->hanum)); + TRACE(("gdth_search_drives() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); ok = 0; /* initialize controller services, at first: screen service */ ha->screen_feat = 0; if (!force_dma32) { - ok = gdth_internal_cmd(ha, SCREENSERVICE, GDT_X_INIT_SCR, 0, 0, 0); + ok = gdth_internal_cmd(hanum,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(ha, SCREENSERVICE, GDT_INIT, 0, 0, 0); + ok = gdth_internal_cmd(hanum,SCREENSERVICE,GDT_INIT,0,0,0); if (!ok) { printk("GDT-HA %d: Initialization error screen service (code %d)\n", - ha->hanum, ha->status); + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): SCREENSERVICE initialized\n")); @@ -1674,26 +1954,25 @@ static int __init gdth_search_drives(gdth_ha_str *ha) 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(ha, SCREENSERVICE, GDT_REALTIME, *(ulong32 *)&rtc[0], + gdth_internal_cmd(hanum,SCREENSERVICE,GDT_REALTIME, *(ulong32 *)&rtc[0], *(ulong32 *)&rtc[4], *(ulong32 *)&rtc[8]); #endif /* unfreeze all IOs */ - gdth_internal_cmd(ha, CACHESERVICE, GDT_UNFREEZE_IO, 0, 0, 0); + gdth_internal_cmd(hanum,CACHESERVICE,GDT_UNFREEZE_IO,0,0,0); /* initialize cache service */ ha->cache_feat = 0; if (!force_dma32) { - ok = gdth_internal_cmd(ha, CACHESERVICE, GDT_X_INIT_HOST, LINUX_OS, - 0, 0); + ok = gdth_internal_cmd(hanum,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(ha, CACHESERVICE, GDT_INIT, LINUX_OS, 0, 0); + ok = gdth_internal_cmd(hanum,CACHESERVICE,GDT_INIT,LINUX_OS,0,0); if (!ok) { printk("GDT-HA %d: Initialization error cache service (code %d)\n", - ha->hanum, ha->status); + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): CACHESERVICE initialized\n")); @@ -1722,9 +2001,9 @@ static int __init gdth_search_drives(gdth_ha_str *ha) pmod->cmd_buff_size = 0; pmod->reserved1 = 0; pmod->reserved2 = 0; - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, SET_PERF_MODES, + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,SET_PERF_MODES, INVALID_CHANNEL,sizeof(gdth_perf_modes))) { - printk("GDT-HA %d: Interrupt coalescing activated\n", ha->hanum); + printk("GDT-HA %d: Interrupt coalescing activated\n", hanum); } } #endif @@ -1736,7 +2015,7 @@ static int __init gdth_search_drives(gdth_ha_str *ha) 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(ha, CACHESERVICE, GDT_IOCTL, IOCHAN_RAW_DESC, + if (gdth_internal_cmd(hanum,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; @@ -1751,13 +2030,13 @@ static int __init gdth_search_drives(gdth_ha_str *ha) chn = (gdth_getch_str *)ha->pscratch; for (bus_no = 0; bus_no < MAXBUS; ++bus_no) { chn->channel_no = bus_no; - if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, + if (!gdth_internal_cmd(hanum,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", - ha->hanum, ha->status); + hanum, ha->status); return 0; } break; @@ -1772,10 +2051,10 @@ static int __init gdth_search_drives(gdth_ha_str *ha) TRACE2(("gdth_search_drives() %d channels\n",ha->bus_cnt)); /* read cache configuration */ - if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_INFO, + if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_INFO, INVALID_CHANNEL,sizeof(gdth_cinfo_str))) { printk("GDT-HA %d: Initialization error cache service (code %d)\n", - ha->hanum, ha->status); + hanum, ha->status); return 0; } ha->cpar = ((gdth_cinfo_str *)ha->pscratch)->cpar; @@ -1785,11 +2064,11 @@ static int __init gdth_search_drives(gdth_ha_str *ha) /* read board info and features */ ha->more_proc = FALSE; - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, BOARD_INFO, + if (gdth_internal_cmd(hanum,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(ha, CACHESERVICE, GDT_IOCTL, BOARD_FEATURES, + if (gdth_internal_cmd(hanum,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; @@ -1797,7 +2076,7 @@ static int __init gdth_search_drives(gdth_ha_str *ha) } } else { TRACE2(("BOARD_INFO requires firmware >= 1.10/2.08\n")); - strcpy(ha->binfo.type_string, gdth_ctr_name(ha)); + strcpy(ha->binfo.type_string, gdth_ctr_name(hanum)); } TRACE2(("Controller name: %s\n",ha->binfo.type_string)); @@ -1810,7 +2089,7 @@ static int __init gdth_search_drives(gdth_ha_str *ha) 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(ha, CACHESERVICE, GDT_IOCTL, IOCHAN_DESC, + if (gdth_internal_cmd(hanum,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; @@ -1825,7 +2104,7 @@ static int __init gdth_search_drives(gdth_ha_str *ha) 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(ha, CACHESERVICE, GDT_IOCTL, + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, SCSI_CHAN_CNT | L_CTRL_PATTERN, ha->raw[bus_no].address | INVALID_CHANNEL, sizeof(gdth_getch_str))) { @@ -1837,7 +2116,7 @@ static int __init gdth_search_drives(gdth_ha_str *ha) 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(ha, CACHESERVICE, GDT_IOCTL, + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, SCSI_DR_LIST | L_CTRL_PATTERN, ha->raw[bus_no].address | INVALID_CHANNEL, sizeof(gdth_drlist_str))) { @@ -1850,10 +2129,10 @@ static int __init gdth_search_drives(gdth_ha_str *ha) } /* logical drives */ - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_DRV_CNT, + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL,CACHE_DRV_CNT, INVALID_CHANNEL,sizeof(ulong32))) { drv_cnt = *(ulong32 *)ha->pscratch; - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, CACHE_DRV_LIST, + if (gdth_internal_cmd(hanum,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]; @@ -1867,7 +2146,7 @@ static int __init gdth_search_drives(gdth_ha_str *ha) alst->entries_avail = MAX_LDRIVES; alst->first_entry = 0; alst->list_offset = GDTOFFSOF(gdth_arcdl_str, list[0]); - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, ARRAY_DRV_LIST2 | LA_CTRL_PATTERN, INVALID_CHANNEL, sizeof(gdth_arcdl_str) + (alst->entries_avail-1) * sizeof(gdth_alist_str))) { @@ -1878,7 +2157,7 @@ static int __init gdth_search_drives(gdth_ha_str *ha) 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(ha, CACHESERVICE, GDT_IOCTL, + } else if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_IOCTL, ARRAY_DRV_LIST | LA_CTRL_PATTERN, 0, 35 * sizeof(gdth_alist_str))) { for (j = 0; j < 35; ++j) { @@ -1896,24 +2175,24 @@ static int __init gdth_search_drives(gdth_ha_str *ha) /* initialize raw service */ ha->raw_feat = 0; if (!force_dma32) { - ok = gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_X_INIT_RAW, 0, 0, 0); + ok = gdth_internal_cmd(hanum,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(ha, SCSIRAWSERVICE, GDT_INIT, 0, 0, 0); + ok = gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_INIT,0,0,0); if (!ok) { printk("GDT-HA %d: Initialization error raw service (code %d)\n", - ha->hanum, ha->status); + hanum, ha->status); return 0; } TRACE2(("gdth_search_drives(): RAWSERVICE initialized\n")); /* set/get features raw service (scatter/gather) */ - if (gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_SET_FEAT, SCATTER_GATHER, - 0, 0)) { + if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_SET_FEAT,SCATTER_GATHER, + 0,0)) { TRACE2(("gdth_search_drives(): set features RAWSERVICE OK\n")); - if (gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_GET_FEAT, 0, 0, 0)) { + if (gdth_internal_cmd(hanum,SCSIRAWSERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat RAWSERVICE %d\n", ha->info)); ha->raw_feat |= (ushort)ha->info; @@ -1921,10 +2200,10 @@ static int __init gdth_search_drives(gdth_ha_str *ha) } /* set/get features cache service (equal to raw service) */ - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_SET_FEAT, 0, + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_SET_FEAT,0, SCATTER_GATHER,0)) { TRACE2(("gdth_search_drives(): set features CACHESERVICE OK\n")); - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_GET_FEAT, 0, 0, 0)) { + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_GET_FEAT,0,0,0)) { TRACE2(("gdth_search_dr(): get feat CACHESERV. %d\n", ha->info)); ha->cache_feat |= (ushort)ha->info; @@ -1933,22 +2212,22 @@ static int __init gdth_search_drives(gdth_ha_str *ha) /* reserve drives for raw service */ if (reserve_mode != 0) { - gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESERVE_ALL, + gdth_internal_cmd(hanum,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] == ha->hanum && reserve_list[i+1] < ha->bus_cnt && + if (reserve_list[i] == 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(ha, SCSIRAWSERVICE, GDT_RESERVE, 0, + if (!gdth_internal_cmd(hanum,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", - ha->hanum, ha->status); + hanum, ha->status); } } } @@ -1957,44 +2236,58 @@ static int __init gdth_search_drives(gdth_ha_str *ha) oemstr = (gdth_oem_str_ioctl *)ha->pscratch; oemstr->params.ctl_version = 0x01; oemstr->params.buffer_size = sizeof(oemstr->text); - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_IOCTL, + if (gdth_internal_cmd(hanum,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", - ha->hanum, oemstr->text.oem_company_name, ha->binfo.type_string); + 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", - ha->hanum, ha->binfo.type_string); + hanum,ha->binfo.type_string); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 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(ha, i); + gdth_analyse_hdrive(hanum,i); TRACE(("gdth_search_drives() OK\n")); return 1; } -static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive) +static int gdth_analyse_hdrive(int hanum,ushort hdrive) { + register gdth_ha_str *ha; ulong32 drv_cyls; int drv_hds, drv_secs; - TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n", ha->hanum, hdrive)); + TRACE(("gdth_analyse_hdrive() hanum %d drive %d\n",hanum,hdrive)); if (hdrive >= MAX_HDRIVES) return 0; + ha = HADATA(gdth_ctr_tab[hanum]); - if (!gdth_internal_cmd(ha, CACHESERVICE, GDT_INFO, hdrive, 0, 0)) + if (!gdth_internal_cmd(hanum,CACHESERVICE,GDT_INFO,hdrive,0,0)) return 0; ha->hdr[hdrive].present = TRUE; ha->hdr[hdrive].size = ha->info; @@ -2014,7 +2307,7 @@ static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive) ha->hdr[hdrive].size = drv_cyls * drv_hds * drv_secs; if (ha->cache_feat & GDT_64BIT) { - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_X_INFO, hdrive, 0, 0) + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_X_INFO,hdrive,0,0) && ha->info2 != 0) { ha->hdr[hdrive].size = ((ulong64)ha->info2 << 32) | ha->info; } @@ -2023,14 +2316,14 @@ static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive) hdrive,ha->hdr[hdrive].size,drv_hds,drv_secs)); /* get informations about device */ - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_DEVTYPE, hdrive, 0, 0)) { + if (gdth_internal_cmd(hanum,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(ha, CACHESERVICE, GDT_CLUST_INFO, hdrive, 0, 0)) { + if (gdth_internal_cmd(hanum,CACHESERVICE,GDT_CLUST_INFO,hdrive,0,0)) { TRACE2(("gdth_search_dr() cache drive %d cluster info %d\n", hdrive,ha->info)); if (!shared_access) @@ -2038,7 +2331,7 @@ static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive) } /* R/W attributes */ - if (gdth_internal_cmd(ha, CACHESERVICE, GDT_RW_ATTRIBS, hdrive, 0, 0)) { + if (gdth_internal_cmd(hanum,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; @@ -2050,26 +2343,27 @@ static int gdth_analyse_hdrive(gdth_ha_str *ha, ushort hdrive) /* command queueing/sending functions */ -static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority) +static void gdth_putq(int hanum,Scsi_Cmnd *scp,unchar priority) { - struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); + register gdth_ha_str *ha; 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 (!cmndinfo->internal_command) { - cmndinfo->priority = priority; - b = scp->device->channel; + if (scp->done != gdth_scsi_done) { + scp->SCp.this_residual = (int)priority; + b = virt_ctr ? NUMDATA(scp->device->host)->busnum: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 && thdr[t].lock)) { TRACE2(("gdth_putq(): locked IO ->update_timeout()\n")); - cmndinfo->timeout = gdth_update_timeout(scp, 0); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); } } } @@ -2081,7 +2375,7 @@ static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority) pscp = ha->req_first; nscp = (Scsi_Cmnd *)pscp->SCp.ptr; /* priority: 0-highest,..,0xff-lowest */ - while (nscp && gdth_cmnd_priv(nscp)->priority <= priority) { + while (nscp && (unchar)nscp->SCp.this_residual <= priority) { pscp = nscp; nscp = (Scsi_Cmnd *)pscp->SCp.ptr; } @@ -2101,8 +2395,9 @@ static void gdth_putq(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar priority) #endif } -static void gdth_next(gdth_ha_str *ha) +static void gdth_next(int hanum) { + register gdth_ha_str *ha; register Scsi_Cmnd *pscp; register Scsi_Cmnd *nscp; unchar b, t, l, firsttime; @@ -2110,7 +2405,8 @@ static void gdth_next(gdth_ha_str *ha) ulong flags = 0; int cmd_index; - TRACE(("gdth_next() hanum %d\n", ha->hanum)); + TRACE(("gdth_next() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); if (!gdth_polling) spin_lock_irqsave(&ha->smp_lock, flags); @@ -2120,14 +2416,14 @@ static void gdth_next(gdth_ha_str *ha) 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_cmndinfo->internal_command) { - b = nscp->device->channel; + if (nscp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(nscp->device->host)->busnum : nscp->device->channel; t = nscp->device->id; l = nscp->device->lun; - if (nscp_cmndinfo->priority >= DEFAULT_PRI) { + if (nscp->SCp.this_residual >= 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; @@ -2136,21 +2432,21 @@ static void gdth_next(gdth_ha_str *ha) b = t = l = 0; if (firsttime) { - if (gdth_test_busy(ha)) { /* controller busy ? */ - TRACE(("gdth_next() controller %d busy !\n", ha->hanum)); + if (gdth_test_busy(hanum)) { /* controller busy ? */ + TRACE(("gdth_next() controller %d busy !\n",hanum)); if (!gdth_polling) { spin_unlock_irqrestore(&ha->smp_lock, flags); return; } - while (gdth_test_busy(ha)) + while (gdth_test_busy(hanum)) gdth_delay(1); } firsttime = FALSE; } - if (!nscp_cmndinfo->internal_command) { - if (nscp_cmndinfo->phase == -1) { - nscp_cmndinfo->phase = CACHESERVICE; /* default: cache svc. */ + if (nscp->done != gdth_scsi_done) { + if (nscp->SCp.phase == -1) { + nscp->SCp.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)); @@ -2163,8 +2459,8 @@ static void gdth_next(gdth_ha_str *ha) } else if ((ha->scan_mode & 0x0f) == 1) { if (b == 0 && ((t == 0 && l == 1) || (t == 1 && l == 0))) { - nscp_cmndinfo->OpCode = GDT_SCAN_START; - nscp_cmndinfo->phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) + nscp->SCp.sent_command = GDT_SCAN_START; + nscp->SCp.phase = ((ha->scan_mode & 0x10 ? 1:0) << 8) | SCSIRAWSERVICE; ha->scan_mode = 0x12; TRACE2(("Scan mode: 0x%x (SCAN_START)\n", @@ -2175,8 +2471,8 @@ static void gdth_next(gdth_ha_str *ha) } } else if (ha->scan_mode == 0x12) { if (b == ha->bus_cnt && t == ha->tid_cnt-1) { - nscp_cmndinfo->phase = SCSIRAWSERVICE; - nscp_cmndinfo->OpCode = GDT_SCAN_END; + nscp->SCp.phase = SCSIRAWSERVICE; + nscp->SCp.sent_command = GDT_SCAN_END; ha->scan_mode &= 0x10; TRACE2(("Scan mode: 0x%x (SCAN_END)\n", ha->scan_mode)); @@ -2187,18 +2483,18 @@ static void gdth_next(gdth_ha_str *ha) nscp->cmnd[0] != READ_CAPACITY && nscp->cmnd[0] != MODE_SENSE && (ha->hdr[t].cluster_type & CLUSTER_DRIVE)) { /* always GDT_CLUST_INFO! */ - nscp_cmndinfo->OpCode = GDT_CLUST_INFO; + nscp->SCp.sent_command = GDT_CLUST_INFO; } } } - if (nscp_cmndinfo->OpCode != -1) { - if ((nscp_cmndinfo->phase & 0xff) == CACHESERVICE) { - if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t))) + if (nscp->SCp.sent_command != -1) { + if ((nscp->SCp.phase & 0xff) == CACHESERVICE) { + if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) this_cmd = FALSE; next_cmd = FALSE; - } else if ((nscp_cmndinfo->phase & 0xff) == SCSIRAWSERVICE) { - if (!(cmd_index=gdth_fill_raw_cmd(ha, nscp, BUS_L2P(ha, b)))) + } else if ((nscp->SCp.phase & 0xff) == SCSIRAWSERVICE) { + if (!(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) this_cmd = FALSE; next_cmd = FALSE; } else { @@ -2206,18 +2502,18 @@ static void gdth_next(gdth_ha_str *ha) nscp->sense_buffer[0] = 0x70; nscp->sense_buffer[2] = NOT_READY; nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - if (!nscp_cmndinfo->wait_for_completion) - nscp_cmndinfo->wait_for_completion++; + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; else - gdth_scsi_done(nscp); + nscp->scsi_done(nscp); } - } else if (gdth_cmnd_priv(nscp)->internal_command) { - if (!(cmd_index=gdth_special_cmd(ha, nscp))) + } else if (nscp->done == gdth_scsi_done) { + if (!(cmd_index=gdth_special_cmd(hanum,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(ha, nscp, BUS_L2P(ha, b)))) + !(cmd_index=gdth_fill_raw_cmd(hanum,nscp,BUS_L2P(ha,b)))) this_cmd = FALSE; else ha->raw[BUS_L2P(ha,b)].io_cnt[t]++; @@ -2225,10 +2521,10 @@ static void gdth_next(gdth_ha_str *ha) 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_cmndinfo->wait_for_completion) - nscp_cmndinfo->wait_for_completion++; + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; else - gdth_scsi_done(nscp); + nscp->scsi_done(nscp); } else { switch (nscp->cmnd[0]) { case TEST_UNIT_READY: @@ -2251,12 +2547,12 @@ static void gdth_next(gdth_ha_str *ha) nscp->sense_buffer[0] = 0x70; nscp->sense_buffer[2] = UNIT_ATTENTION; nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - if (!nscp_cmndinfo->wait_for_completion) - nscp_cmndinfo->wait_for_completion++; + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; else - gdth_scsi_done(nscp); - } else if (gdth_internal_cache_cmd(ha, nscp)) - gdth_scsi_done(nscp); + nscp->scsi_done(nscp); + } else if (gdth_internal_cache_cmd(hanum,nscp)) + nscp->scsi_done(nscp); break; case ALLOW_MEDIUM_REMOVAL: @@ -2267,15 +2563,15 @@ static void gdth_next(gdth_ha_str *ha) TRACE(("Prevent r. nonremov. drive->do nothing\n")); nscp->result = DID_OK << 16; nscp->sense_buffer[0] = 0; - if (!nscp_cmndinfo->wait_for_completion) - nscp_cmndinfo->wait_for_completion++; + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; else - gdth_scsi_done(nscp); + nscp->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(ha, nscp, t))) + if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) this_cmd = FALSE; } break; @@ -2284,7 +2580,7 @@ static void gdth_next(gdth_ha_str *ha) case RELEASE: TRACE2(("cache cmd %s\n",nscp->cmnd[0] == RESERVE ? "RESERVE" : "RELEASE")); - if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t))) + if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) this_cmd = FALSE; break; @@ -2303,11 +2599,11 @@ static void gdth_next(gdth_ha_str *ha) nscp->sense_buffer[0] = 0x70; nscp->sense_buffer[2] = UNIT_ATTENTION; nscp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); - if (!nscp_cmndinfo->wait_for_completion) - nscp_cmndinfo->wait_for_completion++; + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; else - gdth_scsi_done(nscp); - } else if (!(cmd_index=gdth_fill_cache_cmd(ha, nscp, t))) + nscp->scsi_done(nscp); + } else if (!(cmd_index=gdth_fill_cache_cmd(hanum,nscp,t))) this_cmd = FALSE; break; @@ -2316,12 +2612,12 @@ static void gdth_next(gdth_ha_str *ha) 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", - ha->hanum, nscp->cmnd[0]); + hanum, nscp->cmnd[0]); nscp->result = DID_ABORT << 16; - if (!nscp_cmndinfo->wait_for_completion) - nscp_cmndinfo->wait_for_completion++; + if (!nscp->SCp.have_data_in) + nscp->SCp.have_data_in++; else - gdth_scsi_done(nscp); + nscp->scsi_done(nscp); break; } } @@ -2337,77 +2633,79 @@ static void gdth_next(gdth_ha_str *ha) } if (ha->cmd_cnt > 0) { - gdth_release_event(ha); + gdth_release_event(hanum); } if (!gdth_polling) spin_unlock_irqrestore(&ha->smp_lock, flags); if (gdth_polling && ha->cmd_cnt > 0) { - if (!gdth_wait(ha, cmd_index, POLL_TIMEOUT)) + if (!gdth_wait(hanum,cmd_index,POLL_TIMEOUT)) printk("GDT-HA %d: Command %d timed out !\n", - ha->hanum, cmd_index); + hanum,cmd_index); } } - -/* - * 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) + +static void gdth_copy_internal_data(int hanum,Scsi_Cmnd *scp, + char *buffer,ushort count) { - ushort cpcount,i, max_sg = gdth_sg_count(scp); + ushort cpcount,i; ushort cpsum,cpnow; struct scatterlist *sl; + gdth_ha_str *ha; char *address; - cpcount = min_t(ushort, count, gdth_bufflen(scp)); + cpcount = count<=(ushort)scp->request_bufflen ? count:(ushort)scp->request_bufflen; + ha = HADATA(gdth_ctr_tab[hanum]); - if (cpcount) { - cpsum=0; - scsi_for_each_sg(scp, sl, max_sg, i) { + if (scp->use_sg) { + sl = (struct scatterlist *)scp->request_buffer; + for (i=0,cpsum=0; iuse_sg; ++i,++sl) { unsigned long flags; cpnow = (ushort)sl->length; TRACE(("copy_internal() now %d sum %d count %d %d\n", - cpnow, cpsum, cpcount, gdth_bufflen(scp))); + cpnow,cpsum,cpcount,(ushort)scp->bufflen)); 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", - ha->hanum); + 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; - if (to_buffer) - memcpy(buffer, address, cpnow); - else - memcpy(address, buffer, cpnow); + 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 if (count) { - printk("GDT-HA %d: SCSI command with no buffers but data transfer expected!\n", - ha->hanum); - WARN_ON(1); + } else { + TRACE(("copy_internal() count %d\n",cpcount)); + memcpy((char*)scp->request_buffer,buffer,cpcount); } } -static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) +static int gdth_internal_cache_cmd(int hanum,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)); @@ -2438,7 +2736,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) strcpy(inq.vendor,ha->oem_name); sprintf(inq.product,"Host Drive #%02d",t); strcpy(inq.revision," "); - gdth_copy_internal_data(ha, scp, (char*)&inq, sizeof(gdth_inq_data), 0); + gdth_copy_internal_data(hanum,scp,(char*)&inq,sizeof(gdth_inq_data)); break; case REQUEST_SENSE: @@ -2448,7 +2746,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) sd.key = NO_SENSE; sd.info = 0; sd.add_length= 0; - gdth_copy_internal_data(ha, scp, (char*)&sd, sizeof(gdth_sense_data), 0); + gdth_copy_internal_data(hanum,scp,(char*)&sd,sizeof(gdth_sense_data)); break; case MODE_SENSE: @@ -2460,7 +2758,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, 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(ha, scp, (char*)&mpd, sizeof(gdth_modep_data), 0); + gdth_copy_internal_data(hanum,scp,(char*)&mpd,sizeof(gdth_modep_data)); break; case READ_CAPACITY: @@ -2470,7 +2768,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, 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(ha, scp, (char*)&rdc, sizeof(gdth_rdcap_data), 0); + gdth_copy_internal_data(hanum,scp,(char*)&rdc,sizeof(gdth_rdcap_data)); break; case SERVICE_ACTION_IN: @@ -2481,8 +2779,7 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, 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(ha, scp, (char*)&rdc16, - sizeof(gdth_rdcap16_data), 0); + gdth_copy_internal_data(hanum,scp,(char*)&rdc16,sizeof(gdth_rdcap16_data)); } else { scp->result = DID_ABORT << 16; } @@ -2493,22 +2790,27 @@ static int gdth_internal_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) break; } - if (!cmndinfo->wait_for_completion) - cmndinfo->wait_for_completion++; + if (!scp->SCp.have_data_in) + scp->SCp.have_data_in++; else return 1; return 0; } - -static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) + +static int gdth_fill_cache_cmd(int hanum,Scsi_Cmnd *scp,ushort hdrive) { + register gdth_ha_str *ha; register gdth_cmd_str *cmdp; - struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); + struct scatterlist *sl; 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)); @@ -2524,18 +2826,18 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) cmdp->Service = CACHESERVICE; cmdp->RequestBuffer = scp; /* search free command index */ - if (!(cmd_index=gdth_get_cmd_index(ha))) { + if (!(cmd_index=gdth_get_cmd_index(hanum))) { 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(ha); + gdth_set_sema0(hanum); /* fill command */ read_write = 0; - if (cmndinfo->OpCode != -1) - cmdp->OpCode = cmndinfo->OpCode; /* special cache cmd. */ + if (scp->SCp.sent_command != -1) + cmdp->OpCode = scp->SCp.sent_command; /* special cache cmd. */ else if (scp->cmnd[0] == RESERVE) cmdp->OpCode = GDT_RESERVE_DRV; else if (scp->cmnd[0] == RELEASE) @@ -2596,17 +2898,17 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) cmdp->u.cache.BlockCnt = blockcnt; } - if (gdth_bufflen(scp)) { - cmndinfo->dma_dir = (read_write == 1 ? + 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 ? PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE); - sgcnt = pci_map_sg(ha->pdev, gdth_sglist(scp), gdth_sg_count(scp), - cmndinfo->dma_dir); + sgcnt = pci_map_sg(ha->pdev,sl,scp->use_sg,scp->SCp.Message); if (mode64) { - struct scatterlist *sl; - cmdp->u.cache64.DestAddr= (ulong64)-1; cmdp->u.cache64.sg_canz = sgcnt; - scsi_for_each_sg(scp, sl, sgcnt, i) { + for (i=0; iu.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) @@ -2617,11 +2919,9 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, 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; - scsi_for_each_sg(scp, sl, sgcnt, i) { + for (i=0; iu.cache.sg_lst[i].sg_ptr = sg_dma_address(sl); #ifdef GDTH_DMA_STATISTICS ha->dma32_cnt++; @@ -2637,6 +2937,38 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, 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 */ @@ -2672,21 +3004,23 @@ static int gdth_fill_cache_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, ushort hdrive) } /* copy command */ - gdth_copy_command(ha); + gdth_copy_command(hanum); return cmd_index; } -static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) +static int gdth_fill_raw_cmd(int hanum,Scsi_Cmnd *scp,unchar b) { + register gdth_ha_str *ha; register gdth_cmd_str *cmdp; + struct scatterlist *sl; ushort i; - dma_addr_t sense_paddr; + dma_addr_t phys_addr, 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; @@ -2701,27 +3035,26 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) cmdp->Service = SCSIRAWSERVICE; cmdp->RequestBuffer = scp; /* search free command index */ - if (!(cmd_index=gdth_get_cmd_index(ha))) { + if (!(cmd_index=gdth_get_cmd_index(hanum))) { 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(ha); + gdth_set_sema0(hanum); - cmndinfo = gdth_cmnd_priv(scp); /* fill command */ - if (cmndinfo->OpCode != -1) { - cmdp->OpCode = cmndinfo->OpCode; /* special raw cmd. */ + if (scp->SCp.sent_command != -1) { + cmdp->OpCode = scp->SCp.sent_command; /* special raw cmd. */ cmdp->BoardNode = LOCALBOARD; if (mode64) { - cmdp->u.raw64.direction = (cmndinfo->phase >> 8); + cmdp->u.raw64.direction = (scp->SCp.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 = (cmndinfo->phase >> 8); + cmdp->u.raw.direction = (scp->SCp.phase >> 8); TRACE2(("special raw cmd 0x%x param 0x%x\n", cmdp->OpCode, cmdp->u.raw.direction)); /* evaluate command size */ @@ -2733,8 +3066,9 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, 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); - - cmndinfo->sense_paddr = sense_paddr; + *(ulong32 *)&scp->SCp.buffer = (ulong32)sense_paddr; + /* high part, if 64bit */ + *(ulong32 *)&scp->host_scribble = (ulong32)((ulong64)sense_paddr >> 32); cmdp->OpCode = GDT_WRITE; /* always */ cmdp->BoardNode = LOCALBOARD; if (mode64) { @@ -2746,7 +3080,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) cmdp->u.raw64.lun = l; cmdp->u.raw64.bus = b; cmdp->u.raw64.priority = 0; - cmdp->u.raw64.sdlen = gdth_bufflen(scp); + cmdp->u.raw64.sdlen = scp->request_bufflen; cmdp->u.raw64.sense_len = 16; cmdp->u.raw64.sense_data = sense_paddr; cmdp->u.raw64.direction = @@ -2763,7 +3097,7 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, 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 = gdth_bufflen(scp); + cmdp->u.raw.sdlen = scp->request_bufflen; cmdp->u.raw.sense_len = 16; cmdp->u.raw.sense_data = sense_paddr; cmdp->u.raw.direction = @@ -2772,16 +3106,16 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) cmdp->u.raw.sg_ranz = 0; } - 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 (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 (mode64) { - struct scatterlist *sl; - cmdp->u.raw64.sdata = (ulong64)-1; cmdp->u.raw64.sg_ranz = sgcnt; - scsi_for_each_sg(scp, sl, sgcnt, i) { + for (i=0; iu.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) @@ -2792,11 +3126,9 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, 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; - scsi_for_each_sg(scp, sl, sgcnt, i) { + for (i=0; iu.raw.sg_lst[i].sg_ptr = sg_dma_address(sl); #ifdef GDTH_DMA_STATISTICS ha->dma32_cnt++; @@ -2812,6 +3144,38 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, 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", @@ -2845,33 +3209,35 @@ static int gdth_fill_raw_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp, unchar b) } /* copy command */ - gdth_copy_command(ha); + gdth_copy_command(hanum); return cmd_index; } -static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) +static int gdth_special_cmd(int hanum,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; - gdth_copy_internal_data(ha, scp, (char *)cmdp, sizeof(gdth_cmd_str), 1); + memcpy( cmdp, scp->request_buffer, sizeof(gdth_cmd_str)); cmdp->RequestBuffer = scp; /* search free command index */ - if (!(cmd_index=gdth_get_cmd_index(ha))) { + if (!(cmd_index=gdth_get_cmd_index(hanum))) { 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(ha); + gdth_set_sema0(hanum); /* evaluate command size, check space */ if (cmdp->OpCode == GDT_IOCTL) { @@ -2909,7 +3275,7 @@ static int gdth_special_cmd(gdth_ha_str *ha, Scsi_Cmnd *scp) } /* copy command */ - gdth_copy_command(ha); + gdth_copy_command(hanum); return cmd_index; } @@ -3036,14 +3402,15 @@ static void gdth_clear_events(void) /* SCSI interface functions */ -static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, - int gdth_from_wait, int* pIndex) +static irqreturn_t gdth_interrupt(int irq,void *dev_id) { + 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 rval, i; + int hanum, rval, i; unchar IStatus; ushort Service; ulong flags = 0; @@ -3064,15 +3431,17 @@ static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, } if (!gdth_polling) - spin_lock_irqsave(&ha->smp_lock, flags); + spin_lock_irqsave(&ha2->smp_lock, flags); + wait_index = 0; /* search controller */ - if (0 == (IStatus = gdth_get_status(ha, irq))) { + if ((hanum = gdth_get_status(&IStatus,irq)) == -1) { /* spurious interrupt */ if (!gdth_polling) - spin_unlock_irqrestore(&ha->smp_lock, flags); - return IRQ_HANDLED; + spin_unlock_irqrestore(&ha2->smp_lock, flags); + return IRQ_HANDLED; } + ha = HADATA(gdth_ctr_tab[hanum]); #ifdef GDTH_STATISTICS ++act_ints; @@ -3113,32 +3482,32 @@ static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, dp2_ptr = ha->brd; if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; - ha->status = readw(&dp2_ptr->u.ic.Status); + ha->status = gdth_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 = readl(&dp2_ptr->u.ic.Info[0]); - ha->service = readw(&dp2_ptr->u.ic.Service); - ha->info2 = readl(&dp2_ptr->u.ic.Info[1]); + 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]); - 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 */ + 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 */ } else if (ha->type == GDT_PCI) { dp6_ptr = ha->brd; if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; - ha->status = readw(&dp6_ptr->u.ic.Status); + ha->status = gdth_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 = readl(&dp6_ptr->u.ic.Info[0]); - ha->service = readw(&dp6_ptr->u.ic.Service); - ha->info2 = readl(&dp6_ptr->u.ic.Info[1]); + 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]); - 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 */ + 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 */ } else if (ha->type == GDT_PCINEW) { if (IStatus & 0x80) { /* error flag */ IStatus &= ~0x80; @@ -3161,7 +3530,7 @@ static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, ha->status = pcs->ext_status & 0xffff; else #endif - ha->status = readw(&dp6m_ptr->i960r.status); + ha->status = gdth_readw(&dp6m_ptr->i960r.status); TRACE2(("gdth_interrupt() error %d/%d\n",IStatus,ha->status)); } else /* no error */ ha->status = S_OK; @@ -3174,18 +3543,18 @@ static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, } else #endif { - ha->info = readl(&dp6m_ptr->i960r.info[0]); - ha->service = readw(&dp6m_ptr->i960r.service); - ha->info2 = readl(&dp6m_ptr->i960r.info[1]); + 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]); } /* event string */ if (IStatus == ASYNCINDEX) { if (ha->service != SCREENSERVICE && (ha->fw_vers & 0xff) >= 0x1a) { - ha->dvr.severity = readb + ha->dvr.severity = gdth_readb (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.severity); for (i = 0; i < 256; ++i) { - ha->dvr.event_string[i] = readb + ha->dvr.event_string[i] = gdth_readb (&((gdt6m_dpram_str __iomem *)ha->brd)->i960r.evt_str[i]); if (ha->dvr.event_string[i] == 0) break; @@ -3198,13 +3567,13 @@ static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, if (!coalesced) #endif { - writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - writeb(0, &dp6m_ptr->i960r.sema1_reg); + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); } } else { TRACE2(("gdth_interrupt() unknown controller type\n")); if (!gdth_polling) - spin_unlock_irqrestore(&ha->smp_lock, flags); + spin_unlock_irqrestore(&ha2->smp_lock, flags); return IRQ_HANDLED; } @@ -3212,25 +3581,26 @@ static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, IStatus,ha->status,ha->info)); if (gdth_from_wait) { - *pIndex = (int)IStatus; + wait_hanum = hanum; + wait_index = (int)IStatus; } if (IStatus == ASYNCINDEX) { TRACE2(("gdth_interrupt() async. event\n")); - gdth_async_event(ha); + gdth_async_event(hanum); if (!gdth_polling) - spin_unlock_irqrestore(&ha->smp_lock, flags); - gdth_next(ha); + spin_unlock_irqrestore(&ha2->smp_lock, flags); + gdth_next(hanum); 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 = ha->hanum; + ha->dvr.eu.driver.ionode = hanum; gdth_store_event(ha, ES_DRIVER, 4, &ha->dvr); if (!gdth_polling) - spin_unlock_irqrestore(&ha->smp_lock, flags); + spin_unlock_irqrestore(&ha2->smp_lock, flags); return IRQ_HANDLED; } scp = ha->cmd_tab[IStatus-2].cmnd; @@ -3239,28 +3609,28 @@ static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, 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 = ha->hanum; + ha->dvr.eu.driver.ionode = hanum; ha->dvr.eu.driver.index = IStatus; gdth_store_event(ha, ES_DRIVER, 1, &ha->dvr); if (!gdth_polling) - spin_unlock_irqrestore(&ha->smp_lock, flags); + spin_unlock_irqrestore(&ha2->smp_lock, flags); return IRQ_HANDLED; } if (scp == INTERNAL_CMND) { TRACE(("gdth_interrupt() answer to internal command\n")); if (!gdth_polling) - spin_unlock_irqrestore(&ha->smp_lock, flags); + spin_unlock_irqrestore(&ha2->smp_lock, flags); return IRQ_HANDLED; } TRACE(("gdth_interrupt() sync. status\n")); - rval = gdth_sync_event(ha,Service,IStatus,scp); + rval = gdth_sync_event(hanum,Service,IStatus,scp); if (!gdth_polling) - spin_unlock_irqrestore(&ha->smp_lock, flags); + spin_unlock_irqrestore(&ha2->smp_lock, flags); if (rval == 2) { - gdth_putq(ha, scp, gdth_cmnd_priv(scp)->priority); + gdth_putq(hanum,scp,scp->SCp.this_residual); } else if (rval == 1) { - gdth_scsi_done(scp); + scp->scsi_done(scp); } #ifdef INT_COAL @@ -3283,30 +3653,23 @@ static irqreturn_t __gdth_interrupt(gdth_ha_str *ha, int irq, /* coalescing only for new GDT_PCIMPR controllers available */ if (ha->type == GDT_PCIMPR && coalesced) { - writeb(0xff, &dp6m_ptr->i960r.edoor_reg); - writeb(0, &dp6m_ptr->i960r.sema1_reg); + gdth_writeb(0xff, &dp6m_ptr->i960r.edoor_reg); + gdth_writeb(0, &dp6m_ptr->i960r.sema1_reg); } #endif - gdth_next(ha); + gdth_next(hanum); return IRQ_HANDLED; } -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) +static int gdth_sync_event(int hanum,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)); @@ -3324,12 +3687,12 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, } if (msg->msg_ext && !msg->msg_answer) { - while (gdth_test_busy(ha)) + while (gdth_test_busy(hanum)) gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; - gdth_get_cmd_index(ha); - gdth_set_sema0(ha); + gdth_get_cmd_index(hanum); + gdth_set_sema0(hanum); cmdp->OpCode = GDT_READ; cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; @@ -3339,8 +3702,8 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) + sizeof(ulong64); ha->cmd_cnt = 0; - gdth_copy_command(ha); - gdth_release_event(ha); + gdth_copy_command(hanum); + gdth_release_event(hanum); return 0; } @@ -3358,12 +3721,12 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, } msg->msg_ext = 0; msg->msg_answer = 0; - while (gdth_test_busy(ha)) + while (gdth_test_busy(hanum)) gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; - gdth_get_cmd_index(ha); - gdth_set_sema0(ha); + gdth_get_cmd_index(hanum); + gdth_set_sema0(hanum); cmdp->OpCode = GDT_WRITE; cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; @@ -3373,67 +3736,74 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) + sizeof(ulong64); ha->cmd_cnt = 0; - gdth_copy_command(ha); - gdth_release_event(ha); + gdth_copy_command(hanum); + gdth_release_event(hanum); return 0; } printk("\n"); } else { - b = scp->device->channel; + b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; - if (cmndinfo->OpCode == -1 && b != ha->virt_bus) { + if (scp->SCp.sent_command == -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 (cmndinfo->OpCode == GDT_MOUNT) - cmndinfo->OpCode = GDT_CLUST_INFO; + if (scp->SCp.sent_command == GDT_MOUNT) + scp->SCp.sent_command = GDT_CLUST_INFO; /* retry */ return 2; } - 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 (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 (ha->status == S_OK) { - cmndinfo->status = S_OK; - cmndinfo->info = ha->info; - if (cmndinfo->OpCode != -1) { + scp->SCp.Status = S_OK; + scp->SCp.Message = ha->info; + if (scp->SCp.sent_command != -1) { TRACE2(("gdth_sync_event(): special cmd 0x%x OK\n", - cmndinfo->OpCode)); + scp->SCp.sent_command)); /* special commands GDT_CLUST_INFO/GDT_MOUNT ? */ - if (cmndinfo->OpCode == GDT_CLUST_INFO) { + if (scp->SCp.sent_command == GDT_CLUST_INFO) { ha->hdr[t].cluster_type = (unchar)ha->info; if (!(ha->hdr[t].cluster_type & CLUSTER_MOUNTED)) { /* NOT MOUNTED -> MOUNT */ - cmndinfo->OpCode = GDT_MOUNT; + scp->SCp.sent_command = GDT_MOUNT; if (ha->hdr[t].cluster_type & CLUSTER_RESERVED) { /* cluster drive RESERVED (on the other node) */ - cmndinfo->phase = -2; /* reservation conflict */ + scp->SCp.phase = -2; /* reservation conflict */ } } else { - cmndinfo->OpCode = -1; + scp->SCp.sent_command = -1; } } else { - if (cmndinfo->OpCode == GDT_MOUNT) { + if (scp->SCp.sent_command == GDT_MOUNT) { ha->hdr[t].cluster_type |= CLUSTER_MOUNTED; ha->hdr[t].media_changed = TRUE; - } else if (cmndinfo->OpCode == GDT_UNMOUNT) { + } else if (scp->SCp.sent_command == GDT_UNMOUNT) { ha->hdr[t].cluster_type &= ~CLUSTER_MOUNTED; ha->hdr[t].media_changed = TRUE; } - cmndinfo->OpCode = -1; + scp->SCp.sent_command = -1; } /* retry */ - cmndinfo->priority = HIGH_PRI; + scp->SCp.this_residual = HIGH_PRI; return 2; } else { /* RESERVE/RELEASE ? */ @@ -3446,17 +3816,17 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, scp->sense_buffer[0] = 0; } } else { - cmndinfo->status = ha->status; - cmndinfo->info = ha->info; + scp->SCp.Status = ha->status; + scp->SCp.Message = ha->info; - if (cmndinfo->OpCode != -1) { + if (scp->SCp.sent_command != -1) { TRACE2(("gdth_sync_event(): special cmd 0x%x error 0x%x\n", - cmndinfo->OpCode, ha->status)); - if (cmndinfo->OpCode == GDT_SCAN_START || - cmndinfo->OpCode == GDT_SCAN_END) { - cmndinfo->OpCode = -1; + 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; /* retry */ - cmndinfo->priority = HIGH_PRI; + scp->SCp.this_residual = HIGH_PRI; return 2; } memset((char*)scp->sense_buffer,0,16); @@ -3478,9 +3848,9 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, scp->sense_buffer[2] = NOT_READY; scp->result = (DID_OK << 16) | (CHECK_CONDITION << 1); } - if (!cmndinfo->internal_command) { + if (scp->done != gdth_scsi_done) { ha->dvr.size = sizeof(ha->dvr.eu.sync); - ha->dvr.eu.sync.ionode = ha->hanum; + ha->dvr.eu.sync.ionode = hanum; ha->dvr.eu.sync.service = service; ha->dvr.eu.sync.status = ha->status; ha->dvr.eu.sync.info = ha->info; @@ -3499,8 +3869,8 @@ static int gdth_sync_event(gdth_ha_str *ha, int service, unchar index, } } } - if (!cmndinfo->wait_for_completion) - cmndinfo->wait_for_completion++; + if (!scp->SCp.have_data_in) + scp->SCp.have_data_in++; else return 1; } @@ -3664,23 +4034,25 @@ static char *async_cache_tab[] = { }; -static int gdth_async_event(gdth_ha_str *ha) +static int gdth_async_event(int hanum) { + 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", - ha->hanum, ha->service)); + hanum,ha->service)); if (ha->service == SCREENSERVICE) { if (ha->status == MSG_REQUEST) { - while (gdth_test_busy(ha)) + while (gdth_test_busy(hanum)) gdth_delay(0); cmdp->Service = SCREENSERVICE; cmdp->RequestBuffer = SCREEN_CMND; - cmd_index = gdth_get_cmd_index(ha); - gdth_set_sema0(ha); + cmd_index = gdth_get_cmd_index(hanum); + gdth_set_sema0(hanum); cmdp->OpCode = GDT_READ; cmdp->BoardNode = LOCALBOARD; cmdp->u.screen.reserved = 0; @@ -3690,7 +4062,7 @@ static int gdth_async_event(gdth_ha_str *ha) ha->cmd_len = GDTOFFSOF(gdth_cmd_str,u.screen.su.msg.msg_addr) + sizeof(ulong64); ha->cmd_cnt = 0; - gdth_copy_command(ha); + gdth_copy_command(hanum); if (ha->type == GDT_EISA) printk("[EISA slot %d] ",(ushort)ha->brd_phys); else if (ha->type == GDT_ISA) @@ -3698,19 +4070,19 @@ static int gdth_async_event(gdth_ha_str *ha) else printk("[PCI %d/%d] ",(ushort)(ha->brd_phys>>8), (ushort)((ha->brd_phys>>3)&0x1f)); - gdth_release_event(ha); + gdth_release_event(hanum); } } else { if (ha->type == GDT_PCIMPR && (ha->fw_vers & 0xff) >= 0x1a) { ha->dvr.size = 0; - ha->dvr.eu.async.ionode = ha->hanum; + ha->dvr.eu.async.ionode = 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 = ha->hanum; + ha->dvr.eu.async.ionode = hanum; ha->dvr.eu.async.service = ha->service; ha->dvr.eu.async.status = ha->status; ha->dvr.eu.async.info = ha->info; @@ -3792,8 +4164,9 @@ static void gdth_timeout(ulong data) Scsi_Cmnd *nscp; gdth_ha_str *ha; ulong flags; + int hanum = 0; - ha = list_first_entry(&gdth_instances, gdth_ha_str, list); + ha = HADATA(gdth_ctr_tab[hanum]); spin_lock_irqsave(&ha->smp_lock, flags); for (act_stats=0,i=0; i= 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; icmd_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; icmd_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; icmd_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) { + 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: @@ -3932,23 +4820,29 @@ static const char *gdth_ctr_name(gdth_ha_str *ha) static const char *gdth_info(struct Scsi_Host *shp) { - gdth_ha_str *ha = shost_priv(shp); + int hanum; + gdth_ha_str *ha; 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) { - gdth_ha_str *ha = shost_priv(scp->device->host); - int i; + int i, hanum; + gdth_ha_str *ha; ulong flags; Scsi_Cmnd *cmnd; unchar b; TRACE2(("gdth_eh_bus_reset()\n")); - b = scp->device->channel; + hanum = NUMDATA(scp->device->host)->hanum; + b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; + ha = HADATA(gdth_ctr_tab[hanum]); /* clear command tab */ spin_lock_irqsave(&ha->smp_lock, flags); @@ -3965,9 +4859,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(ha)) + while (gdth_test_busy(hanum)) gdth_delay(0); - if (gdth_internal_cmd(ha, CACHESERVICE, + if (gdth_internal_cmd(hanum, CACHESERVICE, GDT_CLUST_RESET, i, 0, 0)) ha->hdr[i].cluster_type &= ~CLUSTER_RESERVED; gdth_polling = FALSE; @@ -3980,9 +4874,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(ha)) + while (gdth_test_busy(hanum)) gdth_delay(0); - gdth_internal_cmd(ha, SCSIRAWSERVICE, GDT_RESET_BUS, + gdth_internal_cmd(hanum, SCSIRAWSERVICE, GDT_RESET_BUS, BUS_L2P(ha,b), 0, 0); gdth_polling = FALSE; spin_unlock_irqrestore(&ha->smp_lock, flags); @@ -3990,18 +4884,30 @@ 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; - gdth_ha_str *ha = shost_priv(sdev->host); + int hanum; + gdth_ha_str *ha; struct scsi_device *sd; unsigned capacity; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) sd = sdev; capacity = cap; - b = sd->channel; +#else + sd = disk->device; + capacity = disk->capacity; +#endif + hanum = NUMDATA(sd->host)->hanum; + b = virt_ctr ? NUMDATA(sd->host)->busnum : sd->channel; t = sd->id; - TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", ha->hanum, b, t)); + TRACE2(("gdth_bios_param() ha %d bus %d target %d\n", hanum, b, t)); + ha = HADATA(gdth_ctr_tab[hanum]); if (b != ha->virt_bus || ha->hdr[t].heads == 0) { /* raw device or host drive without mapping information */ @@ -4019,42 +4925,33 @@ static int gdth_bios_param(struct scsi_device *sdev,struct block_device *bdev,se } -static int gdth_queuecommand(struct scsi_cmnd *scp, - void (*done)(struct scsi_cmnd *)) +static int gdth_queuecommand(Scsi_Cmnd *scp,void (*done)(Scsi_Cmnd *)) { - gdth_ha_str *ha = shost_priv(scp->device->host); - struct gdth_cmndinfo *cmndinfo; + int hanum; + int priority; TRACE(("gdth_queuecommand() cmd 0x%x\n", scp->cmnd[0])); - - 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; - + + 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; #ifdef GDTH_STATISTICS ++act_ios; #endif - gdth_putq(ha, scp, cmndinfo->priority); - gdth_next(ha); + 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 ); return 0; } @@ -4062,10 +4959,12 @@ static int __gdth_queuecommand(gdth_ha_str *ha, struct scsi_cmnd *scp, static int gdth_open(struct inode *inode, struct file *filep) { gdth_ha_str *ha; + int i; - list_for_each_entry(ha, &gdth_instances, list) { + for (i = 0; i < gdth_ctr_count; i++) { + ha = HADATA(gdth_ctr_tab[i]); if (!ha->sdev) - ha->sdev = scsi_get_host_dev(ha->shost); + ha->sdev = scsi_get_host_dev(gdth_ctr_tab[i]); } TRACE(("gdth_open()\n")); @@ -4084,11 +4983,10 @@ static int ioc_event(void __user *arg) gdth_ha_str *ha; ulong flags; - if (copy_from_user(&evt, arg, sizeof(gdth_ioctl_event))) - return -EFAULT; - ha = gdth_find_ha(evt.ionode); - if (!ha) + if (copy_from_user(&evt, arg, sizeof(gdth_ioctl_event)) || + evt.ionode >= gdth_ctr_count) return -EFAULT; + ha = HADATA(gdth_ctr_tab[evt.ionode]); if (evt.erase == 0xff) { if (evt.event.event_source == ES_TEST) @@ -4122,12 +5020,11 @@ static int ioc_lockdrv(void __user *arg) ulong flags; gdth_ha_str *ha; - if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv))) - return -EFAULT; - ha = gdth_find_ha(ldrv.ionode); - if (!ha) + if (copy_from_user(&ldrv, arg, sizeof(gdth_ioctl_lockdrv)) || + ldrv.ionode >= gdth_ctr_count) return -EFAULT; - + ha = HADATA(gdth_ctr_tab[ldrv.ionode]); + for (i = 0; i < ldrv.drive_cnt && i < MAX_HDRIVES; ++i) { j = ldrv.drives[i]; if (j >= MAX_HDRIVES || !ha->hdr[j].present) @@ -4136,14 +5033,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(ha, ha->bus_cnt, j); - gdth_stop_timeout(ha, ha->bus_cnt, j); + gdth_wait_completion(ldrv.ionode, ha->bus_cnt, j); + gdth_stop_timeout(ldrv.ionode, 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(ha, ha->bus_cnt, j); - gdth_next(ha); + gdth_start_timeout(ldrv.ionode, ha->bus_cnt, j); + gdth_next(ldrv.ionode); } } return 0; @@ -4153,16 +5050,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.number >= MAX_HDRIVES) + res.ionode >= gdth_ctr_count || res.number >= MAX_HDRIVES) return -EFAULT; - ha = gdth_find_ha(res.ionode); - if (!ha) - return -EFAULT; - + hanum = res.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); + if (!ha->hdr[res.number].present) return 0; memset(&cmd, 0, sizeof(gdth_cmd_str)); @@ -4188,21 +5085,22 @@ 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))) - return -EFAULT; - ha = gdth_find_ha(gen.ionode); - if (!ha) + + if (copy_from_user(&gen, arg, sizeof(gdth_ioctl_general)) || + gen.ionode >= gdth_ctr_count) return -EFAULT; + hanum = gen.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); if (gen.data_len + gen.sense_len != 0) { - if (!(buf = gdth_ioctl_alloc(ha, gen.data_len + gen.sense_len, + if (!(buf = gdth_ioctl_alloc(hanum, 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(ha, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); return -EFAULT; } @@ -4276,7 +5174,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(ha, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); return -EFAULT; } } @@ -4288,15 +5186,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(ha, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(hanum, 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(ha, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); return -EFAULT; } - gdth_ioctl_free(ha, gen.data_len+gen.sense_len, buf, paddr); + gdth_ioctl_free(hanum, gen.data_len+gen.sense_len, buf, paddr); return 0; } @@ -4306,7 +5204,7 @@ static int ioc_hdrlist(void __user *arg, char *cmnd) gdth_cmd_str *cmd; gdth_ha_str *ha; unchar i; - int rc = -ENOMEM; + int hanum, rc = -ENOMEM; u32 cluster_type = 0; rsc = kmalloc(sizeof(*rsc), GFP_KERNEL); @@ -4315,10 +5213,12 @@ static int ioc_hdrlist(void __user *arg, char *cmnd) goto free_fail; if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || - (NULL == (ha = gdth_find_ha(rsc->ionode)))) { + rsc->ionode >= gdth_ctr_count) { 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) { @@ -4359,7 +5259,7 @@ static int ioc_rescan(void __user *arg, char *cmnd) gdth_cmd_str *cmd; ushort i, status, hdr_cnt; ulong32 info; - int cyls, hds, secs; + int hanum, cyls, hds, secs; int rc = -ENOMEM; ulong flags; gdth_ha_str *ha; @@ -4370,10 +5270,12 @@ static int ioc_rescan(void __user *arg, char *cmnd) goto free_fail; if (copy_from_user(rsc, arg, sizeof(gdth_ioctl_rescan)) || - (NULL == (ha = gdth_find_ha(rsc->ionode)))) { + rsc->ionode >= gdth_ctr_count) { 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) { @@ -4530,9 +5432,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)) || - (NULL == (ha = gdth_find_ha(ctrt.ionode)))) + ctrt.ionode >= gdth_ctr_count) 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 { @@ -4571,9 +5473,10 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, unchar i, j; if (copy_from_user(&lchn, argp, sizeof(gdth_ioctl_lockchn)) || - (NULL == (ha = gdth_find_ha(lchn.ionode)))) + lchn.ionode >= gdth_ctr_count) return -EFAULT; - + ha = HADATA(gdth_ctr_tab[lchn.ionode]); + i = lchn.channel; if (i < ha->bus_cnt) { if (lchn.lock) { @@ -4581,16 +5484,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(ha, i, j); - gdth_stop_timeout(ha, i, j); + gdth_wait_completion(lchn.ionode, i, j); + gdth_stop_timeout(lchn.ionode, 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(ha, i, j); - gdth_next(ha); + gdth_start_timeout(lchn.ionode, i, j); + gdth_next(lchn.ionode); } } } @@ -4606,22 +5509,37 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, case GDTIOCTL_RESET_BUS: { gdth_ioctl_reset res; - int rval; + int hanum, rval; if (copy_from_user(&res, argp, sizeof(gdth_ioctl_reset)) || - (NULL == (ha = gdth_find_ha(res.ionode)))) + res.ionode >= gdth_ctr_count) return -EFAULT; + hanum = res.ionode; + ha = HADATA(gdth_ctr_tab[hanum]); - scp = kzalloc(sizeof(*scp), GFP_KERNEL); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) + scp = kmalloc(sizeof(*scp), GFP_KERNEL); if (!scp) return -ENOMEM; + memset(scp, 0, sizeof(*scp)); scp->device = ha->sdev; scp->cmd_len = 12; - scp->device->channel = res.number; + scp->use_sg = 0; + scp->device->channel = virt_ctr ? 0 : 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; @@ -4638,14 +5556,16 @@ static int gdth_ioctl(struct inode *inode, struct file *filep, /* flush routine */ -static void gdth_flush(gdth_ha_str *ha) +static void gdth_flush(int hanum) { 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", ha->hanum)); + TRACE2(("gdth_flush() hanum %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); for (i = 0; i < MAX_HDRIVES; ++i) { if (ha->hdr[i].present) { @@ -4661,9 +5581,9 @@ static void gdth_flush(gdth_ha_str *ha) gdtcmd.u.cache.BlockNo = 1; gdtcmd.u.cache.sg_canz = 0; } - TRACE2(("gdth_flush(): flush ha %d drive %d\n", ha->hanum, i)); + TRACE2(("gdth_flush(): flush ha %d drive %d\n", hanum, i)); - gdth_execute(ha->shost, &gdtcmd, cmnd, 30, NULL); + gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 30, NULL); } } } @@ -4671,7 +5591,7 @@ static void gdth_flush(gdth_ha_str *ha) /* shutdown routine */ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) { - gdth_ha_str *ha; + int hanum; #ifndef __alpha__ gdth_cmd_str gdtcmd; char cmnd[MAX_COMMAND_SIZE]; @@ -4686,8 +5606,8 @@ static int gdth_halt(struct notifier_block *nb, ulong event, void *buf) notifier_disabled = 1; printk("GDT-HA: Flushing all host drives .. "); - list_for_each_entry(ha, &gdth_instances, list) { - gdth_flush(ha); + for (hanum = 0; hanum < gdth_ctr_count; ++hanum) { + gdth_flush(hanum); #ifndef __alpha__ /* controller reset */ @@ -4695,8 +5615,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", ha->hanum)); - gdth_execute(ha->shost, &gdtcmd, cmnd, 10, NULL); + TRACE2(("gdth_halt(): reset controller %d\n", hanum)); + gdth_execute(gdth_ctr_tab[hanum], &gdtcmd, cmnd, 10, NULL); #endif } printk("Done.\n"); @@ -4707,6 +5627,7 @@ 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) { @@ -4715,536 +5636,40 @@ static int gdth_slave_configure(struct scsi_device *sdev) sdev->skip_ms_page_8 = 1; return 0; } +#endif -static struct scsi_host_template gdth_template = { +#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, .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, -}; - -#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; +#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, #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/trunk/drivers/scsi/gdth.h b/trunk/drivers/scsi/gdth.h index 1434c6b0297c..37423300592e 100644 --- a/trunk/drivers/scsi/gdth.h +++ b/trunk/drivers/scsi/gdth.h @@ -13,6 +13,7 @@ * $Id: gdth.h,v 1.58 2006/01/11 16:14:09 achim Exp $ */ +#include #include #ifndef TRUE @@ -303,8 +304,15 @@ #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 */ @@ -846,9 +854,6 @@ 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) */ @@ -860,7 +865,6 @@ 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 @@ -912,19 +916,6 @@ 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 */ @@ -947,10 +938,19 @@ typedef struct { struct scsi_device *sdev; } gdth_ha_str; -static inline struct gdth_cmndinfo *gdth_cmnd_priv(struct scsi_cmnd* cmd) -{ - return (struct gdth_cmndinfo *)cmd->host_scribble; -} +/* 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; + /* INQUIRY data format */ typedef struct { diff --git a/trunk/drivers/scsi/gdth_kcompat.h b/trunk/drivers/scsi/gdth_kcompat.h new file mode 100644 index 000000000000..2a302eee669a --- /dev/null +++ b/trunk/drivers/scsi/gdth_kcompat.h @@ -0,0 +1,31 @@ +#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/trunk/drivers/scsi/gdth_proc.c b/trunk/drivers/scsi/gdth_proc.c index de5773443c62..32982eb75c84 100644 --- a/trunk/drivers/scsi/gdth_proc.c +++ b/trunk/drivers/scsi/gdth_proc.c @@ -4,32 +4,62 @@ #include +#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) { - gdth_ha_str *ha = shost_priv(host); + int hanum,busnum; 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,host,ha)); + return(gdth_set_info(buffer,length,gdth_ctr_vtab[i],hanum,busnum)); else - return(gdth_get_info(buffer,start,offset,length,host,ha)); + return(gdth_get_info(buffer,start,offset,length, + gdth_ctr_vtab[i],hanum,busnum)); } +#endif static int gdth_set_info(char *buffer,int length,struct Scsi_Host *host, - gdth_ha_str *ha) + int hanum,int busnum) { int ret_val = -EINVAL; - TRACE2(("gdth_set_info() ha %d\n",ha->hanum,)); + TRACE2(("gdth_set_info() ha %d bus %d\n",hanum,busnum)); if (length >= 4) { if (strncmp(buffer,"gdth",4) == 0) { buffer += 5; length -= 5; - ret_val = gdth_set_asc_info(host, buffer, length, ha); + ret_val = gdth_set_asc_info(host, buffer, length, hanum); } } @@ -37,10 +67,11 @@ 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, gdth_ha_str *ha) + int length,int hanum) { int orig_length, drive, wb_mode; int i, found; + gdth_ha_str *ha; gdth_cmd_str gdtcmd; gdth_cpar_str *pcpar; ulong64 paddr; @@ -49,7 +80,8 @@ 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",ha->hanum)); + TRACE2(("gdth_set_asc_info() ha %d\n",hanum)); + ha = HADATA(gdth_ctr_tab[hanum]); orig_length = length + 5; drive = -1; wb_mode = 0; @@ -125,7 +157,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, } if (wb_mode) { - if (!gdth_ioctl_alloc(ha, sizeof(gdth_cpar_str), TRUE, &paddr)) + if (!gdth_ioctl_alloc(hanum, sizeof(gdth_cpar_str), TRUE, &paddr)) return(-EBUSY); pcpar = (gdth_cpar_str *)ha->pscratch; memcpy( pcpar, &ha->cpar, sizeof(gdth_cpar_str) ); @@ -139,7 +171,7 @@ static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, gdth_execute(host, &gdtcmd, cmnd, 30, NULL); - gdth_ioctl_free(ha, GDTH_SCRATCH, ha->pscratch, paddr); + gdth_ioctl_free(hanum, GDTH_SCRATCH, ha->pscratch, paddr); printk("Done.\n"); return(orig_length); } @@ -149,10 +181,11 @@ 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, gdth_ha_str *ha) + struct Scsi_Host *host,int hanum,int busnum) { 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; @@ -181,7 +214,8 @@ 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\n",ha->hanum)); + TRACE2(("gdth_get_info() ha %d bus %d\n",hanum,busnum)); + ha = HADATA(gdth_ctr_tab[hanum]); /* request is i.e. "cat /proc/scsi/gdth/0" */ @@ -211,10 +245,13 @@ 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; - strcpy(hrec, ha->binfo.type_string); + if (virt_ctr) + sprintf(hrec, "%s (Bus %d)", ha->binfo.type_string, busnum); + else + strcpy(hrec, ha->binfo.type_string); size = sprintf(buffer+len, " Number: \t%d \tName: \t%s\n", - ha->hanum, hrec); + hanum, hrec); len += size; pos = begin + len; if (ha->more_proc) @@ -264,7 +301,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(ha, GDTH_SCRATCH, FALSE, &paddr); + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < ha->bus_cnt; ++i) { @@ -367,7 +404,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, goto stop_output; } } - gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -379,7 +416,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(ha, GDTH_SCRATCH, FALSE, &paddr); + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -473,7 +510,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(ha, GDTH_SCRATCH, buf, paddr); + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -485,7 +522,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(ha, GDTH_SCRATCH, FALSE, &paddr); + buf = gdth_ioctl_alloc(hanum, GDTH_SCRATCH, FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -544,7 +581,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, goto stop_output; } } - gdth_ioctl_free(ha, GDTH_SCRATCH, buf, paddr); + gdth_ioctl_free(hanum, GDTH_SCRATCH, buf, paddr); if (!flag) { size = sprintf(buffer+len, "\n --\n"); @@ -556,7 +593,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(ha, sizeof(gdth_hget_str), FALSE, &paddr); + buf = gdth_ioctl_alloc(hanum, sizeof(gdth_hget_str), FALSE, &paddr); if (!buf) goto stop_output; for (i = 0; i < MAX_LDRIVES; ++i) { @@ -589,7 +626,7 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, } } } - gdth_ioctl_free(ha, sizeof(gdth_hget_str), buf, paddr); + gdth_ioctl_free(hanum, sizeof(gdth_hget_str), buf, paddr); for (i = 0; i < MAX_HDRIVES; ++i) { if (!(ha->hdr[i].present)) @@ -627,7 +664,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 == ha->hanum && + if (estr->event_data.eu.driver.ionode == hanum && estr->event_source == ES_ASYNC) { gdth_log_event(&estr->event_data, hrec); do_gettimeofday(&tv); @@ -662,15 +699,17 @@ static int gdth_get_info(char *buffer,char **start,off_t offset,int length, return rc; } -static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, +static char *gdth_ioctl_alloc(int hanum, 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) { @@ -690,10 +729,12 @@ static char *gdth_ioctl_alloc(gdth_ha_str *ha, int size, int scratch, return ret_val; } -static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr) +static void gdth_ioctl_free(int hanum, 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) { @@ -706,11 +747,13 @@ static void gdth_ioctl_free(gdth_ha_str *ha, int size, char *buf, ulong64 paddr) } #ifdef GDTH_IOCTL_PROC -static int gdth_ioctl_check_bin(gdth_ha_str *ha, ushort size) +static int gdth_ioctl_check_bin(int hanum, 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; @@ -723,27 +766,27 @@ static int gdth_ioctl_check_bin(gdth_ha_str *ha, ushort size) } #endif -static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id) +static void gdth_wait_completion(int hanum, 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 = scp->device->channel; + b = virt_ctr ? NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; if (!SPECIAL_SCP(scp) && t == (unchar)id && b == (unchar)busnum) { - cmndinfo->wait_for_completion = 0; + scp->SCp.have_data_in = 0; spin_unlock_irqrestore(&ha->smp_lock, flags); - while (!cmndinfo->wait_for_completion) + while (!scp->SCp.have_data_in) barrier(); spin_lock_irqsave(&ha->smp_lock, flags); } @@ -751,51 +794,55 @@ static void gdth_wait_completion(gdth_ha_str *ha, int busnum, int id) spin_unlock_irqrestore(&ha->smp_lock, flags); } -static void gdth_stop_timeout(gdth_ha_str *ha, int busnum, int id) +static void gdth_stop_timeout(int hanum, 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) { - struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); - if (!cmndinfo->internal_command) { - b = scp->device->channel; + if (scp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; if (t == (unchar)id && b == (unchar)busnum) { TRACE2(("gdth_stop_timeout(): update_timeout()\n")); - cmndinfo->timeout = gdth_update_timeout(scp, 0); + scp->SCp.buffers_residual = gdth_update_timeout(hanum, scp, 0); } } } spin_unlock_irqrestore(&ha->smp_lock, flags); } -static void gdth_start_timeout(gdth_ha_str *ha, int busnum, int id) +static void gdth_start_timeout(int hanum, 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) { - struct gdth_cmndinfo *cmndinfo = gdth_cmnd_priv(scp); - if (!cmndinfo->internal_command) { - b = scp->device->channel; + if (scp->done != gdth_scsi_done) { + b = virt_ctr ? + NUMDATA(scp->device->host)->busnum : scp->device->channel; t = scp->device->id; if (t == (unchar)id && b == (unchar)busnum) { TRACE2(("gdth_start_timeout(): update_timeout()\n")); - gdth_update_timeout(scp, cmndinfo->timeout); + gdth_update_timeout(hanum, scp, scp->SCp.buffers_residual); } } } spin_unlock_irqrestore(&ha->smp_lock, flags); } -static int gdth_update_timeout(Scsi_Cmnd *scp, int timeout) +static int gdth_update_timeout(int hanum, Scsi_Cmnd *scp, int timeout) { int oldto; diff --git a/trunk/drivers/scsi/gdth_proc.h b/trunk/drivers/scsi/gdth_proc.h index 45e6fdacf36e..a679eeb6820b 100644 --- a/trunk/drivers/scsi/gdth_proc.h +++ b/trunk/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, - gdth_ha_str *ha); + int hanum,int busnum); static int gdth_get_info(char *buffer,char **start,off_t offset,int length, - struct Scsi_Host *host, gdth_ha_str *ha); + struct Scsi_Host *host,int hanum,int busnum); static int gdth_set_asc_info(struct Scsi_Host *host, char *buffer, - int length, gdth_ha_str *ha); + int length, int hanum); -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); +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); #endif diff --git a/trunk/drivers/scsi/hosts.c b/trunk/drivers/scsi/hosts.c index adc9559cb6f4..96bc31266c98 100644 --- a/trunk/drivers/scsi/hosts.c +++ b/trunk/drivers/scsi/hosts.c @@ -342,7 +342,6 @@ 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/trunk/drivers/scsi/hptiop.c b/trunk/drivers/scsi/hptiop.c index 8b384fa7f048..0e579ca45814 100644 --- a/trunk/drivers/scsi/hptiop.c +++ b/trunk/drivers/scsi/hptiop.c @@ -1,6 +1,6 @@ /* * HighPoint RR3xxx controller driver for Linux - * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. + * Copyright (C) 2006 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.2 (070830)"; +static const char driver_ver[] = "v1.0 (060426)"; 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_ADDR_HOST_BIT) + if ((tag & IOPMU_QUEUE_MASK_HOST_BITS) == IOPMU_QUEUE_ADDR_HOST_BIT) return hptiop_host_request_callback(hba, tag & ~IOPMU_QUEUE_ADDR_HOST_BIT); else @@ -323,22 +323,12 @@ 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, @@ -507,7 +497,7 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, goto cmd_done; } - req = _req->req_virt; + req = (struct hpt_iop_request_scsi_command *)_req->req_virt; /* build S/G table */ sg_count = hptiop_buildsgl(scp, req->sg_list); @@ -531,19 +521,8 @@ static int hptiop_queuecommand(struct scsi_cmnd *scp, memcpy(req->cdb, scp->cmnd, sizeof(req->cdb)); - 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); + writel(IOPMU_QUEUE_ADDR_HOST_BIT | _req->req_shifted_phy, + &hba->iop->inbound_queue); return 0; @@ -709,7 +688,6 @@ 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); @@ -744,13 +722,8 @@ 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); @@ -758,15 +731,8 @@ 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; - 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.vbus_id = cpu_to_le32(host->host_no); 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", @@ -784,6 +750,10 @@ 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); @@ -909,10 +879,8 @@ static void hptiop_remove(struct pci_dev *pcidev) } static struct pci_device_id hptiop_id_table[] = { - { PCI_VDEVICE(TTI, 0x3220) }, - { PCI_VDEVICE(TTI, 0x3320) }, - { PCI_VDEVICE(TTI, 0x3520) }, - { PCI_VDEVICE(TTI, 0x4320) }, + { PCI_DEVICE(0x1103, 0x3220) }, + { PCI_DEVICE(0x1103, 0x3320) }, {}, }; @@ -942,4 +910,3 @@ module_init(hptiop_module_init); module_exit(hptiop_module_exit); MODULE_LICENSE("GPL"); - diff --git a/trunk/drivers/scsi/hptiop.h b/trunk/drivers/scsi/hptiop.h index 2a5e46e001cb..f04f7e81d1ae 100644 --- a/trunk/drivers/scsi/hptiop.h +++ b/trunk/drivers/scsi/hptiop.h @@ -1,6 +1,6 @@ /* * HighPoint RR3xxx controller driver for Linux - * Copyright (C) 2006-2007 HighPoint Technologies, Inc. All Rights Reserved. + * Copyright (C) 2006 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,6 +18,219 @@ #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]; @@ -39,8 +252,6 @@ 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 @@ -125,8 +336,7 @@ struct hpt_iop_request_set_config { struct hpt_iop_request_header header; __le32 iop_id; - __le16 vbus_id; - __le16 max_host_request_size; + __le32 vbus_id; __le32 reserve[6]; }; @@ -202,8 +412,9 @@ 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; @@ -212,10 +423,8 @@ struct hptiop_hba { u32 max_sg_descriptors; u32 req_size; /* host-allocated request buffer size */ - - int iopintf_v2: 1; - int initialized: 1; - int msg_done: 1; + int initialized; + int msg_done; struct hptiop_request * req_list; struct hptiop_request reqs[HPTIOP_MAX_REQUESTS]; diff --git a/trunk/drivers/scsi/ibmmca.c b/trunk/drivers/scsi/ibmmca.c index 1a924e9b0271..4275d1b04ced 100644 --- a/trunk/drivers/scsi/ibmmca.c +++ b/trunk/drivers/scsi/ibmmca.c @@ -460,6 +460,13 @@ 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 */ @@ -1686,7 +1693,6 @@ 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/trunk/drivers/scsi/ibmvscsi/Makefile b/trunk/drivers/scsi/ibmvscsi/Makefile index 6ac0633d5452..f67d9efc7a99 100644 --- a/trunk/drivers/scsi/ibmvscsi/Makefile +++ b/trunk/drivers/scsi/ibmvscsi/Makefile @@ -1,7 +1,9 @@ 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/trunk/drivers/scsi/ibmvscsi/ibmvscsi.c b/trunk/drivers/scsi/ibmvscsi/ibmvscsi.c index cda0cc3d182f..5ecc63d1b436 100644 --- a/trunk/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/trunk/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -70,13 +70,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include "ibmvscsi.h" /* The values below are somewhat arbitrary default values, but @@ -89,12 +87,8 @@ 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"); @@ -512,8 +506,8 @@ static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata) atomic_set(&hostdata->request_limit, 0); purge_requests(hostdata, DID_ERROR); - if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, hostdata)) || - (ibmvscsi_ops->send_crq(hostdata, 0xC001000000000000LL, 0)) || + if ((ibmvscsi_reset_crq_queue(&hostdata->queue, hostdata)) || + (ibmvscsi_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"); @@ -618,7 +612,7 @@ static int ibmvscsi_send_srp_event(struct srp_event_struct *evt_struct, } if ((rc = - ibmvscsi_ops->send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { + ibmvscsi_send_crq(hostdata, crq_as_u64[0], crq_as_u64[1])) != 0) { list_del(&evt_struct->list); del_timer(&evt_struct->timer); @@ -1217,8 +1211,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_ops->send_crq(hostdata, - 0xC002000000000000LL, 0)) == 0) { + if ((rc = ibmvscsi_send_crq(hostdata, + 0xC002000000000000LL, 0)) == 0) { /* Now login */ send_srp_login(hostdata); } else { @@ -1243,10 +1237,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_ops->reenable_crq_queue(&hostdata->queue, - hostdata)) || - (ibmvscsi_ops->send_crq(hostdata, - 0xC001000000000000LL, 0))) { + if ((ibmvscsi_reenable_crq_queue(&hostdata->queue, + hostdata)) || + (ibmvscsi_send_crq(hostdata, + 0xC001000000000000LL, 0))) { atomic_set(&hostdata->request_limit, -1); dev_err(hostdata->dev, "error after enable\n"); @@ -1256,10 +1250,10 @@ void ibmvscsi_handle_crq(struct viosrp_crq *crq, crq->format); purge_requests(hostdata, DID_ERROR); - if ((ibmvscsi_ops->reset_crq_queue(&hostdata->queue, - hostdata)) || - (ibmvscsi_ops->send_crq(hostdata, - 0xC001000000000000LL, 0))) { + if ((ibmvscsi_reset_crq_queue(&hostdata->queue, + hostdata)) || + (ibmvscsi_send_crq(hostdata, + 0xC001000000000000LL, 0))) { atomic_set(&hostdata->request_limit, -1); dev_err(hostdata->dev, "error after reset\n"); @@ -1559,8 +1553,6 @@ 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; @@ -1573,7 +1565,6 @@ 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); @@ -1582,7 +1573,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_ops->init_crq_queue(&hostdata->queue, hostdata, max_requests); + rc = ibmvscsi_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; @@ -1599,19 +1590,11 @@ 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_ops->send_crq(hostdata, 0xC001000000000000LL, 0) == 0 + if (ibmvscsi_send_crq(hostdata, 0xC001000000000000LL, 0) == 0 || rc == H_RESOURCE) { /* * Wait around max init_timeout secs for the adapter to finish @@ -1634,12 +1617,10 @@ 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_ops->release_crq_queue(&hostdata->queue, hostdata, max_requests); + ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, max_requests); init_crq_failed: scsi_host_put(host); scsi_host_alloc_failed: @@ -1650,10 +1631,9 @@ static int ibmvscsi_remove(struct vio_dev *vdev) { struct ibmvscsi_host_data *hostdata = vdev->dev.driver_data; release_event_pool(&hostdata->pool, hostdata); - ibmvscsi_ops->release_crq_queue(&hostdata->queue, hostdata, - max_requests); - - srp_remove_host(hostdata->host); + ibmvscsi_release_crq_queue(&hostdata->queue, hostdata, + max_requests); + scsi_remove_host(hostdata->host); scsi_host_put(hostdata->host); @@ -1680,35 +1660,14 @@ static struct vio_driver ibmvscsi_driver = { } }; -static struct srp_function_template ibmvscsi_transport_functions = { -}; - int __init ibmvscsi_module_init(void) { - 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; + return vio_register_driver(&ibmvscsi_driver); } 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/trunk/drivers/scsi/ibmvscsi/ibmvscsi.h b/trunk/drivers/scsi/ibmvscsi/ibmvscsi.h index 46e850e302c7..b19c2e26c2a5 100644 --- a/trunk/drivers/scsi/ibmvscsi/ibmvscsi.h +++ b/trunk/drivers/scsi/ibmvscsi/ibmvscsi.h @@ -98,25 +98,21 @@ struct ibmvscsi_host_data { }; /* routines for managing a command/response queue */ -void ibmvscsi_handle_crq(struct viosrp_crq *crq, - struct ibmvscsi_host_data *hostdata); +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); -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); -}; +int ibmvscsi_reenable_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata); -extern struct ibmvscsi_ops iseriesvscsi_ops; -extern struct ibmvscsi_ops rpavscsi_ops; +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); #endif /* IBMVSCSI_H */ diff --git a/trunk/drivers/scsi/ibmvscsi/ibmvstgt.c b/trunk/drivers/scsi/ibmvscsi/ibmvstgt.c index 82bcab688b44..8ba7dd09d01d 100644 --- a/trunk/drivers/scsi/ibmvscsi/ibmvstgt.c +++ b/trunk/drivers/scsi/ibmvscsi/ibmvstgt.c @@ -25,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -69,12 +68,9 @@ 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. @@ -192,7 +188,6 @@ 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; @@ -205,8 +200,7 @@ static void handle_cmd_queue(struct srp_target *target) 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, - (unsigned long)rport, 0); + err = srp_cmd_queue(shost, cmd, iue, 0); if (err) { eprintk("cannot queue cmd %p %d\n", cmd, err); srp_iu_put(iue); @@ -365,16 +359,6 @@ 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 @@ -428,9 +412,7 @@ static int process_tsk_mgmt(struct iu_entry *iue) fn = 0; } if (fn) - scsi_tgt_tsk_mgmt_request(iue->target->shost, - (unsigned long)iue->target->shost, - fn, + scsi_tgt_tsk_mgmt_request(iue->target->shost, fn, iu->srp.tsk_mgmt.task_tag, (struct scsi_lun *) &iu->srp.tsk_mgmt.lun, iue); @@ -739,8 +721,7 @@ static int ibmvstgt_eh_abort_handler(struct scsi_cmnd *sc) return 0; } -static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost, - u64 itn_id, u64 mid, int result) +static int ibmvstgt_tsk_mgmt_response(u64 mid, int result) { struct iu_entry *iue = (struct iu_entry *) ((void *) mid); union viosrp_iu *iu = vio_iu(iue); @@ -766,20 +747,6 @@ static int ibmvstgt_tsk_mgmt_response(struct Scsi_Host *shost, 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); @@ -818,9 +785,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) @@ -837,7 +804,6 @@ 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; @@ -871,8 +837,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; + destroy_queue: crq_queue_destroy(target); free_srp_target: @@ -891,7 +857,6 @@ 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); @@ -944,25 +909,15 @@ 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) - goto release_transport; + return err; err = get_system_info(); if (err) @@ -973,10 +928,9 @@ 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; } @@ -986,7 +940,6 @@ 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/trunk/drivers/scsi/ibmvscsi/iseries_vscsi.c b/trunk/drivers/scsi/ibmvscsi/iseries_vscsi.c index 0775fdee5fa8..6aeb5f003c3c 100644 --- a/trunk/drivers/scsi/ibmvscsi/iseries_vscsi.c +++ b/trunk/drivers/scsi/ibmvscsi/iseries_vscsi.c @@ -53,7 +53,7 @@ struct srp_lp_event { /** * standard interface for handling logical partition events. */ -static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt) +static void ibmvscsi_handle_event(struct HvLpEvent *lpevt) { struct srp_lp_event *evt = (struct srp_lp_event *)lpevt; @@ -74,9 +74,9 @@ static void iseriesvscsi_handle_event(struct HvLpEvent *lpevt) /* ------------------------------------------------------------ * Routines for driver initialization */ -static int iseriesvscsi_init_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata, - int max_requests) +int ibmvscsi_init_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata, + int max_requests) { int rc; @@ -88,7 +88,7 @@ static int iseriesvscsi_init_crq_queue(struct crq_queue *queue, goto viopath_open_failed; } - rc = vio_setHandler(viomajorsubtype_scsi, iseriesvscsi_handle_event); + rc = vio_setHandler(viomajorsubtype_scsi, ibmvscsi_handle_event); if (rc < 0) { printk("vio_setHandler failed with rc %d in open_event_path\n", rc); @@ -102,9 +102,9 @@ static int iseriesvscsi_init_crq_queue(struct crq_queue *queue, return -1; } -static void iseriesvscsi_release_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) { vio_clearHandler(viomajorsubtype_scsi); viopath_close(viopath_hostLp, viomajorsubtype_scsi, max_requests); @@ -117,8 +117,8 @@ static void iseriesvscsi_release_crq_queue(struct crq_queue *queue, * * no-op for iSeries */ -static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata) +int ibmvscsi_reset_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata) { return 0; } @@ -130,20 +130,19 @@ static int iseriesvscsi_reset_crq_queue(struct crq_queue *queue, * * no-op for iSeries */ -static int iseriesvscsi_reenable_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) { return 0; } /** - * iseriesvscsi_send_crq: - Send a CRQ + * ibmvscsi_send_crq: - Send a CRQ * @hostdata: the adapter * @word1: the first 64 bits of the data * @word2: the second 64 bits of the data */ -static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata, - u64 word1, u64 word2) +int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2) { single_host_data = hostdata; return HvCallEvent_signalLpEventFast(viopath_hostLp, @@ -157,11 +156,3 @@ static int iseriesvscsi_send_crq(struct ibmvscsi_host_data *hostdata, 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/trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c b/trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c index 182146100dc1..9c14e789df5f 100644 --- a/trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c +++ b/trunk/drivers/scsi/ibmvscsi/rpa_vscsi.c @@ -42,14 +42,14 @@ static unsigned int partition_number = -1; * Routines for managing the command/response queue */ /** - * rpavscsi_handle_event: - Interrupt handler for crq events + * ibmvscsi_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 rpavscsi_handle_event(int irq, void *dev_instance) +static irqreturn_t ibmvscsi_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 rpavscsi_handle_event(int irq, void *dev_instance) * Frees irq, deallocates a page for messages, unmaps dma, and unregisters * the crq with the hypervisor. */ -static void rpavscsi_release_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) { long rc; struct vio_dev *vdev = to_vio_dev(hostdata->dev); @@ -108,13 +108,12 @@ static struct viosrp_crq *crq_queue_next_crq(struct crq_queue *queue) } /** - * rpavscsi_send_crq: - Send a CRQ + * ibmvscsi_send_crq: - Send a CRQ * @hostdata: the adapter * @word1: the first 64 bits of the data * @word2: the second 64 bits of the data */ -static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata, - u64 word1, u64 word2) +int ibmvscsi_send_crq(struct ibmvscsi_host_data *hostdata, u64 word1, u64 word2) { struct vio_dev *vdev = to_vio_dev(hostdata->dev); @@ -122,10 +121,10 @@ static int rpavscsi_send_crq(struct ibmvscsi_host_data *hostdata, } /** - * rpavscsi_task: - Process srps asynchronously + * ibmvscsi_task: - Process srps asynchronously * @data: ibmvscsi_host_data of host */ -static void rpavscsi_task(void *data) +static void ibmvscsi_task(void *data) { struct ibmvscsi_host_data *hostdata = (struct ibmvscsi_host_data *)data; struct vio_dev *vdev = to_vio_dev(hostdata->dev); @@ -190,42 +189,6 @@ static void set_adapter_info(struct ibmvscsi_host_data *hostdata) hostdata->madapter_info.os_type = 2; } -/** - * 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 @@ -235,9 +198,9 @@ static int rpavscsi_reset_crq_queue(struct crq_queue *queue, * the crq with the hypervisor. * Returns zero on success. */ -static int rpavscsi_init_crq_queue(struct crq_queue *queue, - struct ibmvscsi_host_data *hostdata, - int max_requests) +int ibmvscsi_init_crq_queue(struct crq_queue *queue, + struct ibmvscsi_host_data *hostdata, + int max_requests) { int rc; int retrc; @@ -264,7 +227,7 @@ static int rpavscsi_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 = rpavscsi_reset_crq_queue(queue, + rc = ibmvscsi_reset_crq_queue(queue, hostdata); if (rc == 2) { @@ -277,7 +240,7 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue, } if (request_irq(vdev->irq, - rpavscsi_handle_event, + ibmvscsi_handle_event, 0, "ibmvscsi", (void *)hostdata) != 0) { dev_err(hostdata->dev, "couldn't register irq 0x%x\n", vdev->irq); @@ -293,7 +256,7 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue, queue->cur = 0; spin_lock_init(&queue->lock); - tasklet_init(&hostdata->srp_task, (void *)rpavscsi_task, + tasklet_init(&hostdata->srp_task, (void *)ibmvscsi_task, (unsigned long)hostdata); return retrc; @@ -318,8 +281,8 @@ static int rpavscsi_init_crq_queue(struct crq_queue *queue, * @hostdata: ibmvscsi_host_data of host * */ -static int rpavscsi_reenable_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) { int rc; struct vio_dev *vdev = to_vio_dev(hostdata->dev); @@ -334,10 +297,38 @@ static int rpavscsi_reenable_crq_queue(struct crq_queue *queue, 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, -}; +/** + * 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; +} diff --git a/trunk/drivers/scsi/ide-scsi.c b/trunk/drivers/scsi/ide-scsi.c index d81bb076a15a..1cc01acc2808 100644 --- a/trunk/drivers/scsi/ide-scsi.c +++ b/trunk/drivers/scsi/ide-scsi.c @@ -82,12 +82,14 @@ 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 */ /* @@ -173,8 +175,7 @@ static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigne char *buf; while (bcount) { - if (pc->sg - scsi_sglist(pc->scsi_cmd) > - scsi_sg_count(pc->scsi_cmd)) { + if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) { printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n"); idescsi_discard_data (drive, bcount); return; @@ -209,8 +210,7 @@ static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsign char *buf; while (bcount) { - if (pc->sg - scsi_sglist(pc->scsi_cmd) > - scsi_sg_count(pc->scsi_cmd)) { + if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) { printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n"); idescsi_output_zeros (drive, bcount); return; @@ -239,6 +239,77 @@ 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; @@ -322,6 +393,7 @@ 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; @@ -362,6 +434,15 @@ 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); @@ -556,14 +637,19 @@ static int idescsi_map_sg(ide_drive_t *drive, idescsi_pc_t *pc) return 1; sg = hwif->sg_table; - scsi_sg = scsi_sglist(pc->scsi_cmd); - segments = scsi_sg_count(pc->scsi_cmd); + scsi_sg = pc->scsi_cmd->request_buffer; + segments = pc->scsi_cmd->use_sg; if (segments > hwif->sg_max_nents) return 1; - hwif->sg_nents = segments; - memcpy(sg, scsi_sg, sizeof(*sg) * segments); + 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); + } return 0; } @@ -658,6 +744,7 @@ 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); @@ -671,7 +758,6 @@ 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); @@ -680,6 +766,7 @@ static void ide_scsi_remove(ide_drive_t *drive) g->private_data = NULL; put_disk(g); + scsi_remove_host(scsihost); ide_scsi_put(scsi); } @@ -751,8 +838,6 @@ 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; } @@ -777,6 +862,24 @@ 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 *)) { @@ -802,14 +905,23 @@ static int idescsi_queue (struct scsi_cmnd *cmd, pc->flags = 0; pc->rq = rq; memcpy (pc->c, cmd->cmnd, cmd->cmd_len); - pc->buffer = NULL; - pc->sg = scsi_sglist(cmd); + if (cmd->use_sg) { + pc->buffer = NULL; + pc->sg = cmd->request_buffer; + } else { + pc->buffer = cmd->request_buffer; + pc->sg = NULL; + } pc->b_count = 0; - pc->request_transfer = pc->buffer_size = scsi_bufflen(cmd); + pc->request_transfer = pc->buffer_size = cmd->request_bufflen; 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/trunk/drivers/scsi/imm.c b/trunk/drivers/scsi/imm.c index 74cdc1f0a78f..005d2b05f32d 100644 --- a/trunk/drivers/scsi/imm.c +++ b/trunk/drivers/scsi/imm.c @@ -740,6 +740,10 @@ 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/trunk/drivers/scsi/in2000.c b/trunk/drivers/scsi/in2000.c index ab7cbf3449ce..312190a69389 100644 --- a/trunk/drivers/scsi/in2000.c +++ b/trunk/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->serial_number)) + DB(DB_QUEUE_COMMAND, scmd_printk(KERN_DEBUG, cmd, "Q-%02x-%ld(", cmd->cmnd[0], cmd->pid)) /* 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->serial_number)) + DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid)) 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->serial_number)) + DB(DB_EXECUTE, printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid)) } @@ -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->serial_number)) + DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid)) 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->serial_number)) + DB(DB_INTR, printk("CCMP-%ld", cmd->pid)) 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->serial_number)) + DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid)) 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->serial_number); + printk("%02x:%02x:%02x-%ld: Unknown SEL_XFER_DONE phase!!---", asr, sr, phs, cmd->pid); } 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->serial_number)) + DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid)) 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->serial_number)) + DB(DB_INTR, printk("DISC-%ld", cmd->pid)) 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->serial_number)) + DB(DB_INTR, printk("-%ld", cmd->pid)) 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->serial_number); + printk(KERN_WARNING "scsi%d: Abort - removing command %ld from input_Q. ", instance->host_no, cmd->pid); 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->serial_number); + printk(KERN_WARNING "scsi%d: Aborting connected command %ld - ", instance->host_no, cmd->pid); 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->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, 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->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, 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->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + sprintf(tbuf, " %ld-%d:%d(%02x)", cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (Scsi_Cmnd *) cmd->host_scribble; } diff --git a/trunk/drivers/scsi/ips.c b/trunk/drivers/scsi/ips.c index 2ed099e2c20d..492a51bd6aa8 100644 --- a/trunk/drivers/scsi/ips.c +++ b/trunk/drivers/scsi/ips.c @@ -204,8 +204,8 @@ module_param(ips, charp, 0); /* * DRIVER_VER */ -#define IPS_VERSION_HIGH IPS_VER_MAJOR_STRING "." IPS_VER_MINOR_STRING -#define IPS_VERSION_LOW "." IPS_VER_BUILD_STRING " " +#define IPS_VERSION_HIGH "7.12" +#define IPS_VERSION_LOW ".05 " #if !defined(__i386__) && !defined(__ia64__) && !defined(__x86_64__) #warning "This driver has only been tested on the x86/ia64/x86_64 platforms" @@ -656,8 +656,6 @@ 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) { @@ -709,6 +707,7 @@ ips_release(struct Scsi_Host *sh) /* free IRQ */ free_irq(ha->irq, ha); + scsi_remove_host(sh); scsi_host_put(sh); ips_released_controllers++; @@ -6947,7 +6946,7 @@ module_exit(ips_module_exit); static int __devinit ips_insert_device(struct pci_dev *pci_dev, const struct pci_device_id *ent) { - int uninitialized_var(index); + int index; int rc; METHOD_TRACE("ips_insert_device", 1); diff --git a/trunk/drivers/scsi/ips.h b/trunk/drivers/scsi/ips.h index 3bcbd9ff056b..24123d537c58 100644 --- a/trunk/drivers/scsi/ips.h +++ b/trunk/drivers/scsi/ips.h @@ -1172,13 +1172,12 @@ typedef struct { *************************************************************************/ #define IPS_VER_MAJOR 7 -#define IPS_VER_MAJOR_STRING __stringify(IPS_VER_MAJOR) +#define IPS_VER_MAJOR_STRING "7" #define IPS_VER_MINOR 12 -#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_VER_MINOR_STRING "12" +#define IPS_VER_BUILD 02 +#define IPS_VER_BUILD_STRING "02" +#define IPS_VER_STRING "7.12.02" #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/trunk/drivers/scsi/libsrp.c b/trunk/drivers/scsi/libsrp.c index 2ad0a27dbaab..732446e63963 100644 --- a/trunk/drivers/scsi/libsrp.c +++ b/trunk/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 itn_id, u64 addr) + u64 addr) { enum dma_data_direction dir; struct scsi_cmnd *sc; @@ -428,8 +428,7 @@ 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, itn_id, (struct scsi_lun *)&cmd->lun, - cmd->tag); + err = scsi_tgt_queue_command(sc, (struct scsi_lun *) &cmd->lun, cmd->tag); if (err) scsi_host_put_command(shost, sc); diff --git a/trunk/drivers/scsi/lpfc/lpfc_debugfs.c b/trunk/drivers/scsi/lpfc/lpfc_debugfs.c index 149fdd25f8e8..2e3c01bebed6 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/trunk/drivers/scsi/lpfc/lpfc_debugfs.c @@ -43,6 +43,7 @@ #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 @@ -901,7 +902,7 @@ lpfc_debugfs_initialize(struct lpfc_vport *vport) } } - vport->disc_trc = kmzlloc( + vport->disc_trc = kmalloc( (sizeof(struct lpfc_debugfs_trc) * lpfc_debugfs_max_disc_trc), GFP_KERNEL); @@ -912,6 +913,8 @@ 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/trunk/drivers/scsi/lpfc/lpfc_init.c b/trunk/drivers/scsi/lpfc/lpfc_init.c index ecebdfa00470..414350ab584e 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_init.c +++ b/trunk/drivers/scsi/lpfc/lpfc_init.c @@ -43,6 +43,7 @@ #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 *); @@ -1265,10 +1266,11 @@ lpfc_hba_init(struct lpfc_hba *phba, uint32_t *hbainit) uint32_t *HashWorking; uint32_t *pwwnn = (uint32_t *) phba->wwnn; - HashWorking = kcalloc(80, sizeof(uint32_t), GFP_KERNEL); + HashWorking = kmalloc(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/trunk/drivers/scsi/lpfc/lpfc_scsi.c b/trunk/drivers/scsi/lpfc/lpfc_scsi.c index cd674938ccd5..17d7dc05149b 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_scsi.c +++ b/trunk/drivers/scsi/lpfc/lpfc_scsi.c @@ -202,9 +202,10 @@ lpfc_new_scsi_buf(struct lpfc_vport *vport) dma_addr_t pdma_phys; uint16_t iotag; - psb = kzalloc(sizeof(struct lpfc_scsi_buf), GFP_KERNEL); + psb = kmalloc(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/trunk/drivers/scsi/lpfc/lpfc_sli.c b/trunk/drivers/scsi/lpfc/lpfc_sli.c index e5337ad4121e..ce5ff2bccba6 100644 --- a/trunk/drivers/scsi/lpfc/lpfc_sli.c +++ b/trunk/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/trunk/drivers/scsi/megaraid.c b/trunk/drivers/scsi/megaraid.c index e7e11f282c8f..da56163c30a8 100644 --- a/trunk/drivers/scsi/megaraid.c +++ b/trunk/drivers/scsi/megaraid.c @@ -4416,7 +4416,8 @@ mega_internal_command(adapter_t *adapter, megacmd_t *mc, mega_passthru *pthru) scmd = &adapter->int_scmd; memset(scmd, 0, sizeof(Scsi_Cmnd)); - sdev = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); + sdev = kmalloc(sizeof(struct scsi_device), GFP_KERNEL); + memset(sdev, 0, sizeof(struct scsi_device)); scmd->device = sdev; scmd->device->host = adapter->host; diff --git a/trunk/drivers/scsi/mvme16x_scsi.c b/trunk/drivers/scsi/mvme16x_scsi.c index b264b499d982..1bdddad48571 100644 --- a/trunk/drivers/scsi/mvme16x_scsi.c +++ b/trunk/drivers/scsi/mvme16x_scsi.c @@ -48,12 +48,13 @@ mvme16x_probe(struct device *dev) goto out; } - hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + hostdata = kmalloc(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/trunk/drivers/scsi/ncr53c8xx.c b/trunk/drivers/scsi/ncr53c8xx.c index 016c462bc771..030ba49f33ff 100644 --- a/trunk/drivers/scsi/ncr53c8xx.c +++ b/trunk/drivers/scsi/ncr53c8xx.c @@ -8143,7 +8143,12 @@ static int ncr53c8xx_abort(struct scsi_cmnd *cmd) unsigned long flags; struct scsi_cmnd *done_list; - printk("ncr53c8xx_abort: command pid %lu\n", cmd->serial_number); +#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 NCR_LOCK_NCB(np, flags); @@ -8523,15 +8528,18 @@ struct Scsi_Host * __init ncr_attach(struct scsi_host_template *tpnt, } -void ncr53c8xx_release(struct Scsi_Host *host) +int ncr53c8xx_release(struct Scsi_Host *host) { - struct host_data *host_data = shost_priv(host); + struct host_data *host_data; #ifdef DEBUG_NCR53C8XX printk("ncr53c8xx: release\n"); #endif - if (host_data->ncb) + if (!host) + return 1; + host_data = (struct host_data *)host->hostdata; + if (host_data && host_data->ncb) ncr_detach(host_data->ncb); - scsi_host_put(host); + return 1; } static void ncr53c8xx_set_period(struct scsi_target *starget, int period) diff --git a/trunk/drivers/scsi/ncr53c8xx.h b/trunk/drivers/scsi/ncr53c8xx.h index 0e008dacf679..b39357d9af8d 100644 --- a/trunk/drivers/scsi/ncr53c8xx.h +++ b/trunk/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 void ncr53c8xx_release(struct Scsi_Host *host); +extern int 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/trunk/drivers/scsi/osst.c b/trunk/drivers/scsi/osst.c index 331b789937c4..08060fb478b6 100644 --- a/trunk/drivers/scsi/osst.c +++ b/trunk/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 (mutex_lock_interruptible(&STp->lock)) + if (down_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); - mutex_unlock(&STp->lock); + up(&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 (mutex_lock_interruptible(&STp->lock)) + if (down_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); - mutex_unlock(&STp->lock); + up(&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 (mutex_lock_interruptible(&STp->lock)) + if (down_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); - mutex_unlock(&STp->lock); + up(&STp->lock); return scsi_ioctl(STp->device, cmd_in, p); out: if (SRpnt) osst_release_request(SRpnt); - mutex_unlock(&STp->lock); + up(&STp->lock); return retval; } @@ -5778,12 +5778,13 @@ static int osst_probe(struct device *dev) dev_num = i; /* allocate a struct osst_tape for this device */ - tpnt = kzalloc(sizeof(struct osst_tape), GFP_ATOMIC); - if (!tpnt) { + tpnt = kmalloc(sizeof(struct osst_tape), GFP_ATOMIC); + if (tpnt == NULL) { 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; @@ -5865,7 +5866,7 @@ static int osst_probe(struct device *dev) tpnt->modes[2].defined = 1; tpnt->density_changed = tpnt->compression_changed = tpnt->blksize_changed = 0; - mutex_init(&tpnt->lock); + init_MUTEX(&tpnt->lock); osst_nr_dev++; write_unlock(&os_scsi_tapes_lock); diff --git a/trunk/drivers/scsi/osst.h b/trunk/drivers/scsi/osst.h index 5aa22740b5df..2cc7b5a1606a 100644 --- a/trunk/drivers/scsi/osst.h +++ b/trunk/drivers/scsi/osst.h @@ -4,7 +4,6 @@ #include #include -#include /* FIXME - rename and use the following two types or delete them! * and the types really should go to st.h anyway... @@ -533,7 +532,7 @@ struct osst_tape { struct scsi_driver *driver; unsigned capacity; struct scsi_device *device; - struct mutex lock; /* for serialization */ + struct semaphore lock; /* for serialization */ struct completion wait; /* for SCSI commands */ struct osst_buffer * buffer; diff --git a/trunk/drivers/scsi/pcmcia/nsp_cs.c b/trunk/drivers/scsi/pcmcia/nsp_cs.c index a45d89b14147..445cfbbca9b3 100644 --- a/trunk/drivers/scsi/pcmcia/nsp_cs.c +++ b/trunk/drivers/scsi/pcmcia/nsp_cs.c @@ -25,6 +25,8 @@ ***********************************************************************/ +/* $Id: nsp_cs.c,v 1.23 2003/08/18 11:09:19 elca Exp $ */ + #include #include #include @@ -57,7 +59,7 @@ #include "nsp_cs.h" MODULE_AUTHOR("YOKOTA Hiroshi "); -MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module"); +MODULE_DESCRIPTION("WorkBit NinjaSCSI-3 / NinjaSCSI-32Bi(16bit) PCMCIA SCSI host adapter module $Revision: 1.23 $"); MODULE_SUPPORTED_DEVICE("sd,sr,sg,st"); #ifdef MODULE_LICENSE MODULE_LICENSE("GPL"); @@ -81,6 +83,10 @@ 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,*/ @@ -91,6 +97,9 @@ 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 */ @@ -1304,7 +1313,11 @@ 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; @@ -1341,6 +1354,37 @@ 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 */ /*----------------------------------------------------------------*/ @@ -1359,9 +1403,19 @@ 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(struct Scsi_Host *host, char *buffer, char **start, - off_t offset, int length, int inout) +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) { int id; char *pos = buffer; @@ -1369,13 +1423,24 @@ static int nsp_proc_info(struct Scsi_Host *host, char *buffer, char **start, 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; @@ -1610,6 +1675,10 @@ 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"); @@ -1742,7 +1811,17 @@ 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"); @@ -1750,6 +1829,7 @@ 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; @@ -1760,6 +1840,52 @@ 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); @@ -1812,9 +1938,13 @@ 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) { @@ -1824,9 +1954,11 @@ 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) @@ -1873,6 +2005,7 @@ 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), @@ -1896,12 +2029,28 @@ 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/trunk/drivers/scsi/pcmcia/nsp_cs.h b/trunk/drivers/scsi/pcmcia/nsp_cs.h index b7f0fa246413..9102cbdf1359 100644 --- a/trunk/drivers/scsi/pcmcia/nsp_cs.h +++ b/trunk/drivers/scsi/pcmcia/nsp_cs.h @@ -10,6 +10,8 @@ =========================================================*/ +/* $Id: nsp_cs.h,v 1.19 2003/08/18 11:09:19 elca Exp $ */ + #ifndef __nsp_cs__ #define __nsp_cs__ @@ -225,7 +227,13 @@ 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/trunk/drivers/scsi/pluto.c b/trunk/drivers/scsi/pluto.c index 0363c1cd68c1..d953d43fe2e6 100644 --- a/trunk/drivers/scsi/pluto.c +++ b/trunk/drivers/scsi/pluto.c @@ -111,12 +111,13 @@ int __init pluto_detect(struct scsi_host_template *tpnt) #endif return 0; } - fcs = kcalloc(fcscount, sizeof (struct ctrl_inquiry), GFP_DMA); + fcs = kmalloc(sizeof (struct ctrl_inquiry) * fcscount, 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); @@ -160,6 +161,7 @@ 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)) @@ -194,7 +196,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt) SCpnt = &(fcs[i].cmd); /* Let FC mid-level free allocated resources */ - pluto_detect_scsi_done(SCpnt); + SCpnt->done (SCpnt); if (!SCpnt->result) { struct pluto_inquiry *inq; @@ -209,7 +211,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt) char *p; long *ages; - ages = kcalloc((inq->channels + 1) * inq->targets, sizeof(long), GFP_KERNEL); + ages = kmalloc (((inq->channels + 1) * inq->targets) * sizeof(long), GFP_KERNEL); if (!ages) continue; host = scsi_register (tpnt, sizeof (struct pluto)); @@ -236,6 +238,7 @@ 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); @@ -257,7 +260,7 @@ int __init pluto_detect(struct scsi_host_template *tpnt) } else fc->fcp_register(fc, TYPE_SCSI_FCP, 1); } - kfree(fcs); + kfree((char *)fcs); if (nplutos) printk ("PLUTO: Total of %d SparcSTORAGE Arrays found\n", nplutos); return nplutos; diff --git a/trunk/drivers/scsi/ps3rom.c b/trunk/drivers/scsi/ps3rom.c index 0f43d1d046d9..b50f1e14f2a5 100644 --- a/trunk/drivers/scsi/ps3rom.c +++ b/trunk/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 = scsi_bufflen(cmd); + buflen = cmd->request_bufflen; if (!buflen) return 0; - if (!scsi_sglist(cmd)) + if (!cmd->request_buffer) return -1; + sgpnt = cmd->request_buffer; active = 1; - req_len = act_len = 0; - scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { + for (k = 0, req_len = 0, act_len = 0; k < cmd->use_sg; ++k, ++sgpnt) { 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; } - scsi_set_resid(cmd, req_len - act_len); + cmd->resid = 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 = scsi_bufflen(cmd); + buflen = cmd->request_bufflen; if (!buflen) return 0; - if (!scsi_sglist(cmd)) + if (!cmd->request_buffer) return -1; - req_len = fin = 0; - scsi_for_each_sg(cmd, sgpnt, scsi_sg_count(cmd), k) { + sgpnt = cmd->request_buffer; + for (k = 0, req_len = 0, fin = 0; k < cmd->use_sg; ++k, ++sgpnt) { 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 = scsi_bufflen(cmd); + atapi_cmnd.blocks = atapi_cmnd.arglen = cmd->request_bufflen; atapi_cmnd.buffer = dev->bounce_lpar; switch (cmd->sc_data_direction) { case DMA_FROM_DEVICE: - if (scsi_bufflen(cmd) >= CD_FRAMESIZE) + if (cmd->request_bufflen >= 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 (scsi_bufflen(cmd) >= CD_FRAMESIZE) + if (cmd->request_bufflen >= CD_FRAMESIZE) atapi_cmnd.proto = DMA_PROTO; else atapi_cmnd.proto = PIO_DATA_OUT_PROTO; diff --git a/trunk/drivers/scsi/qla1280.c b/trunk/drivers/scsi/qla1280.c index fba8aa8a81b5..54d8bdf86852 100644 --- a/trunk/drivers/scsi/qla1280.c +++ b/trunk/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->serial_number, CMD_SP(cmd)); + printk(" Pid=%li, SP=0x%p\n", cmd->pid, CMD_SP(cmd)); printk(" underflow size = 0x%x, direction=0x%x\n", cmd->underflow, cmd->sc_data_direction); } diff --git a/trunk/drivers/scsi/qla2xxx/qla_attr.c b/trunk/drivers/scsi/qla2xxx/qla_attr.c index 05fa7796a559..0f2a9f5d801c 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_attr.c +++ b/trunk/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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); if (ha->optrom_state != QLA_SREADING) return 0; - if (off > ha->optrom_region_size) + if (off > ha->optrom_size) return 0; - if (off + count > ha->optrom_region_size) - count = ha->optrom_region_size - off; + if (off + count > ha->optrom_size) + count = ha->optrom_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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); if (ha->optrom_state != QLA_SWRITING) return -EINVAL; - if (off > ha->optrom_region_size) + if (off > ha->optrom_size) return -ERANGE; - if (off + count > ha->optrom_region_size) - count = ha->optrom_region_size - off; + if (off + count > ha->optrom_size) + count = ha->optrom_size - off; memcpy(&ha->optrom_buffer[off], buf, count); @@ -220,18 +220,14 @@ 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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); - uint32_t start = 0; - uint32_t size = ha->optrom_size; - int val, valid; + int val; if (off) return 0; - if (sscanf(buf, "%d:%x:%x", &val, &start, &size) < 1) - return -EINVAL; - if (start > ha->optrom_size) + if (sscanf(buf, "%d", &val) != 1) return -EINVAL; switch (val) { @@ -241,11 +237,6 @@ 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; @@ -253,107 +244,44 @@ 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 = vmalloc(ha->optrom_region_size); + ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); if (ha->optrom_buffer == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocate memory for optrom retrieval " - "(%x).\n", ha->optrom_region_size); + "(%x).\n", ha->optrom_size); ha->optrom_state = QLA_SWAITING; return count; } - 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); + memset(ha->optrom_buffer, 0, ha->optrom_size); + ha->isp_ops->read_optrom(ha, ha->optrom_buffer, 0, + ha->optrom_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 = vmalloc(ha->optrom_region_size); + ha->optrom_buffer = (uint8_t *)vmalloc(ha->optrom_size); if (ha->optrom_buffer == NULL) { qla_printk(KERN_WARNING, ha, "Unable to allocate memory for optrom update " - "(%x).\n", ha->optrom_region_size); + "(%x).\n", ha->optrom_size); ha->optrom_state = QLA_SWAITING; return count; } - - 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); + memset(ha->optrom_buffer, 0, ha->optrom_size); break; case 3: if (ha->optrom_state != QLA_SWRITING) break; - 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); + ha->isp_ops->write_optrom(ha, ha->optrom_buffer, 0, + ha->optrom_size); break; - default: - count = -EINVAL; } return count; } @@ -372,7 +300,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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); int size = ha->vpd_size; char *vpd_cache = ha->vpd; @@ -395,7 +323,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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); unsigned long flags; @@ -426,7 +354,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 = shost_priv(dev_to_shost(container_of(kobj, + struct scsi_qla_host *ha = to_qla_host(dev_to_shost(container_of(kobj, struct device, kobj))); uint16_t iter, addr, offset; int rval; @@ -531,7 +459,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); char fw_str[30]; return snprintf(buf, PAGE_SIZE, "%s\n", @@ -541,7 +469,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); uint32_t sn; sn = ((ha->serial0 & 0x1f) << 16) | (ha->serial2 << 8) | ha->serial1; @@ -552,14 +480,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(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]); @@ -568,14 +496,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%s\n", ha->model_desc ? ha->model_desc: ""); } @@ -583,7 +511,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); char pci_info[30]; return snprintf(buf, PAGE_SIZE, "%s\n", @@ -593,7 +521,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); int len = 0; if (atomic_read(&ha->loop_state) == LOOP_DOWN || @@ -631,7 +559,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); int len = 0; switch (ha->zio_mode) { @@ -648,7 +576,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); int val = 0; uint16_t zio_mode; @@ -674,7 +602,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d us\n", ha->zio_timer * 100); } @@ -683,7 +611,7 @@ static ssize_t qla2x00_zio_timer_store(struct class_device *cdev, const char *buf, size_t count) { - scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); int val = 0; uint16_t zio_timer; @@ -701,7 +629,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); int len = 0; if (ha->beacon_blink_led) @@ -715,7 +643,7 @@ static ssize_t qla2x00_beacon_store(struct class_device *cdev, const char *buf, size_t count) { - scsi_qla_host_t *ha = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); int val = 0; int rval; @@ -745,7 +673,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->bios_revision[1], ha->bios_revision[0]); @@ -754,7 +682,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->efi_revision[1], ha->efi_revision[0]); @@ -763,7 +691,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(class_to_shost(cdev)); return snprintf(buf, PAGE_SIZE, "%d.%02d\n", ha->fcode_revision[1], ha->fcode_revision[0]); @@ -772,7 +700,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 = shost_priv(class_to_shost(cdev)); + scsi_qla_host_t *ha = to_qla_host(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], @@ -829,7 +757,7 @@ struct class_device_attribute *qla2x00_host_attrs[] = { static void qla2x00_get_host_port_id(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); fc_host_port_id(shost) = ha->d_id.b.domain << 16 | ha->d_id.b.area << 8 | ha->d_id.b.al_pa; @@ -838,7 +766,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 = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); uint32_t speed = 0; switch (ha->link_data_rate) { @@ -858,7 +786,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 = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); uint32_t port_type = FC_PORTTYPE_UNKNOWN; switch (ha->current_topology) { @@ -882,7 +810,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 = shost_priv(host); + scsi_qla_host_t *ha = to_qla_host(host); fc_port_t *fcport; u64 node_name = 0; @@ -900,7 +828,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 = shost_priv(host); + scsi_qla_host_t *ha = to_qla_host(host); fc_port_t *fcport; u64 port_name = 0; @@ -918,7 +846,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 = shost_priv(host); + scsi_qla_host_t *ha = to_qla_host(host); fc_port_t *fcport; uint32_t port_id = ~0U; @@ -937,7 +865,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 = shost_priv(host); + scsi_qla_host_t *ha = to_qla_host(host); rport->dev_loss_tmo = ha->port_down_retry_count + 5; } @@ -946,7 +874,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 = shost_priv(host); + scsi_qla_host_t *ha = to_qla_host(host); if (timeout) ha->port_down_retry_count = timeout; @@ -959,7 +887,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 = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); set_bit(LOOP_RESET_NEEDED, &ha->dpc_flags); return 0; @@ -968,7 +896,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 = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); int rval; uint16_t mb_stat[1]; link_stat_t stat_buf; @@ -1006,7 +934,7 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost) static void qla2x00_get_host_symbolic_name(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); qla2x00_get_sym_node_name(ha, fc_host_symbolic_name(shost)); } @@ -1014,7 +942,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 = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); set_bit(REGISTER_FDMI_NEEDED, &ha->dpc_flags); } @@ -1022,7 +950,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 = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); u64 node_name; if (ha->device_flags & SWITCH_FOUND) @@ -1036,7 +964,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 = shost_priv(shost); + scsi_qla_host_t *ha = to_qla_host(shost); if (!ha->flags.online) fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; @@ -1050,7 +978,7 @@ static int qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) { int ret = 0; - scsi_qla_host_t *ha = shost_priv(fc_vport->shost); + scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; scsi_qla_host_t *vha; ret = qla24xx_vport_create_req_sanity_check(fc_vport); @@ -1119,7 +1047,7 @@ qla24xx_vport_create(struct fc_vport *fc_vport, bool disable) int qla24xx_vport_delete(struct fc_vport *fc_vport) { - scsi_qla_host_t *ha = shost_priv(fc_vport->shost); + scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; scsi_qla_host_t *vha = fc_vport->dd_data; qla24xx_disable_vp(vha); @@ -1250,6 +1178,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) = ha->max_npiv_vports;; + fc_host_max_npiv_vports(ha->host) = MAX_NUM_VPORT_FABRIC; fc_host_npiv_vports_inuse(ha->host) = ha->cur_vport_count; } diff --git a/trunk/drivers/scsi/qla2xxx/qla_dbg.c b/trunk/drivers/scsi/qla2xxx/qla_dbg.c index eaa04dabcdf6..c6680348b648 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_dbg.c +++ b/trunk/drivers/scsi/qla2xxx/qla_dbg.c @@ -38,7 +38,7 @@ qla2xxx_copy_queues(scsi_qla_host_t *ha, void *ptr) } static int -qla24xx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, +qla2xxx_dump_memory(scsi_qla_host_t *ha, uint32_t *code_ram, uint32_t cram_size, uint32_t *ext_mem, void **nxt) { int rval; @@ -152,103 +152,6 @@ qla24xx_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 @@ -311,61 +214,88 @@ qla2300_fw_dump(scsi_qla_host_t *ha, int hardware_locked) } if (rval == QLA_SUCCESS) { - dmp_reg = ®->flash_address; + dmp_reg = (uint16_t __iomem *)(reg + 0); for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = ®->u.isp2300.req_q_in; + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); for (cnt = 0; cnt < sizeof(fw->risc_host_reg) / 2; cnt++) fw->risc_host_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = ®->u.isp2300.mailbox0; + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x40); 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); - qla2xxx_read_window(reg, 32, fw->resp_dma_reg); + 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++)); WRT_REG_WORD(®->ctrl_status, 0x50); - qla2xxx_read_window(reg, 48, fw->dma_reg); + 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++)); WRT_REG_WORD(®->ctrl_status, 0x00); - dmp_reg = ®->risc_hw; + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); 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); - qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2200); - qla2xxx_read_window(reg, 16, fw->risc_gp1_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2400); - qla2xxx_read_window(reg, 16, fw->risc_gp2_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2600); - qla2xxx_read_window(reg, 16, fw->risc_gp3_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2800); - qla2xxx_read_window(reg, 16, fw->risc_gp4_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2A00); - qla2xxx_read_window(reg, 16, fw->risc_gp5_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2C00); - qla2xxx_read_window(reg, 16, fw->risc_gp6_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2E00); - qla2xxx_read_window(reg, 16, fw->risc_gp7_reg); + 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++)); WRT_REG_WORD(®->ctrl_status, 0x10); - qla2xxx_read_window(reg, 64, fw->frame_buf_hdw_reg); + 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++)); WRT_REG_WORD(®->ctrl_status, 0x20); - qla2xxx_read_window(reg, 64, fw->fpm_b0_reg); + 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++)); WRT_REG_WORD(®->ctrl_status, 0x30); - qla2xxx_read_window(reg, 64, fw->fpm_b1_reg); + 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++)); /* Reset RISC. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); @@ -637,59 +567,83 @@ qla2100_fw_dump(scsi_qla_host_t *ha, int hardware_locked) rval = QLA_FUNCTION_TIMEOUT; } if (rval == QLA_SUCCESS) { - dmp_reg = ®->flash_address; + dmp_reg = (uint16_t __iomem *)(reg + 0); for (cnt = 0; cnt < sizeof(fw->pbiu_reg) / 2; cnt++) fw->pbiu_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); - dmp_reg = ®->u.isp2100.mailbox0; + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x10); for (cnt = 0; cnt < ha->mbx_count; cnt++) { - if (cnt == 8) - dmp_reg = ®->u_end.isp2200.mailbox8; - + if (cnt == 8) { + dmp_reg = (uint16_t __iomem *) + ((uint8_t __iomem *)reg + 0xe0); + } fw->mailbox_reg[cnt] = htons(RD_REG_WORD(dmp_reg++)); } - dmp_reg = ®->u.isp2100.unused_2[0]; + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0x20); 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 = ®->risc_hw; + dmp_reg = (uint16_t __iomem *)((uint8_t __iomem *)reg + 0xA0); 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); - qla2xxx_read_window(reg, 16, fw->risc_gp0_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2100); - qla2xxx_read_window(reg, 16, fw->risc_gp1_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2200); - qla2xxx_read_window(reg, 16, fw->risc_gp2_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2300); - qla2xxx_read_window(reg, 16, fw->risc_gp3_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2400); - qla2xxx_read_window(reg, 16, fw->risc_gp4_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2500); - qla2xxx_read_window(reg, 16, fw->risc_gp5_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2600); - qla2xxx_read_window(reg, 16, fw->risc_gp6_reg); + 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++)); WRT_REG_WORD(®->pcr, 0x2700); - qla2xxx_read_window(reg, 16, fw->risc_gp7_reg); + 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++)); WRT_REG_WORD(®->ctrl_status, 0x10); - qla2xxx_read_window(reg, 16, fw->frame_buf_hdw_reg); + 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++)); WRT_REG_WORD(®->ctrl_status, 0x20); - qla2xxx_read_window(reg, 64, fw->fpm_b0_reg); + 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++)); WRT_REG_WORD(®->ctrl_status, 0x30); - qla2xxx_read_window(reg, 64, fw->fpm_b1_reg); + 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++)); /* Reset the ISP. */ WRT_REG_WORD(®->ctrl_status, CSR_ISP_SOFT_RESET); @@ -796,6 +750,7 @@ 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; @@ -827,198 +782,547 @@ 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. */ - 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 ((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)); + } + if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); @@ -1042,6 +1346,7 @@ 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; @@ -1072,260 +1377,655 @@ 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. */ - 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 ((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)); + } + if (rval != QLA_SUCCESS) { qla_printk(KERN_WARNING, ha, "Failed to dump firmware (%x)!!!\n", rval); @@ -1402,7 +2102,7 @@ qla2x00_print_scsi_cmd(struct scsi_cmnd * cmd) struct scsi_qla_host *ha; srb_t *sp; - ha = shost_priv(cmd->device->host); + ha = (struct scsi_qla_host *)cmd->device->host->hostdata; sp = (srb_t *) cmd->SCp.ptr; printk("SCSI Command @=0x%p, Handle=0x%p\n", cmd, cmd->host_scribble); diff --git a/trunk/drivers/scsi/qla2xxx/qla_dbg.h b/trunk/drivers/scsi/qla2xxx/qla_dbg.h index a50ecf0b7c84..cca4b0d8253e 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_dbg.h +++ b/trunk/drivers/scsi/qla2xxx/qla_dbg.h @@ -215,8 +215,6 @@ 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/trunk/drivers/scsi/qla2xxx/qla_def.h b/trunk/drivers/scsi/qla2xxx/qla_def.h index 1900fbf6cd74..c1964866a423 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_def.h +++ b/trunk/drivers/scsi/qla2xxx/qla_def.h @@ -23,7 +23,6 @@ #include #include #include -#include #include #include @@ -185,6 +184,8 @@ * 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; @@ -315,9 +316,7 @@ struct device_reg_2xxx { } u; uint16_t fpm_diag_config; - uint16_t unused_5[0x4]; /* Gap */ - uint16_t risc_hw; - uint16_t unused_5_1; /* Gap */ + uint16_t unused_5[0x6]; /* Gap */ uint16_t pcr; /* Processor Control Register. */ uint16_t unused_6[0x5]; /* Gap */ uint16_t mctr; /* Memory Configuration and Timing. */ @@ -1703,7 +1702,7 @@ struct ct_fdmi_hba_attributes { /* * Port attribute types. */ -#define FDMI_PORT_ATTR_COUNT 6 +#define FDMI_PORT_ATTR_COUNT 5 #define FDMI_PORT_FC4_TYPES 1 #define FDMI_PORT_SUPPORT_SPEED 2 #define FDMI_PORT_CURRENT_SPEED 3 @@ -2477,8 +2476,6 @@ 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 @@ -2532,7 +2529,7 @@ typedef struct scsi_qla_host { #define VP_ERR_FAB_NORESOURCES 3 #define VP_ERR_FAB_LOGOUT 4 #define VP_ERR_ADAP_NORESOURCES 5 - uint16_t max_npiv_vports; /* 63 or 125 per topoloty */ + int max_npiv_vports; /* 63 or 125 per topoloty */ int cur_vport_count; } scsi_qla_host_t; @@ -2545,6 +2542,8 @@ 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/trunk/drivers/scsi/qla2xxx/qla_fw.h b/trunk/drivers/scsi/qla2xxx/qla_fw.h index 25364b1aaf12..99fe49618d61 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_fw.h +++ b/trunk/drivers/scsi/qla2xxx/qla_fw.h @@ -779,8 +779,6 @@ 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 @@ -942,9 +940,7 @@ struct device_reg_24xx { uint16_t mailbox31; uint32_t iobase_window; - uint32_t iobase_c4; - uint32_t iobase_c8; - uint32_t unused_4_1[6]; /* Gap. */ + uint32_t unused_4[8]; /* Gap. */ uint32_t iobase_q; uint32_t unused_5[2]; /* Gap. */ uint32_t iobase_select; diff --git a/trunk/drivers/scsi/qla2xxx/qla_gbl.h b/trunk/drivers/scsi/qla2xxx/qla_gbl.h index 09cb2a908059..aa1e41152283 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_gbl.h +++ b/trunk/drivers/scsi/qla2xxx/qla_gbl.h @@ -133,9 +133,6 @@ int __qla2x00_marker(scsi_qla_host_t *, uint16_t, uint16_t, uint8_t); 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); @@ -215,8 +212,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 *, uint16_t *); +qla2x00_get_resource_cnts(scsi_qla_host_t *, uint16_t *, uint16_t *, uint16_t *, + uint16_t *); extern int qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map); @@ -305,8 +302,6 @@ 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/trunk/drivers/scsi/qla2xxx/qla_gs.c b/trunk/drivers/scsi/qla2xxx/qla_gs.c index eb0784c9ff83..a7e23583f899 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_gs.c +++ b/trunk/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 - 1); + __constant_cpu_to_be32(FDMI_PORT_ATTR_COUNT); 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); - strcpy(eiter->a.os_dev_name, QLA2XXX_DRIVER_NAME); + sprintf(eiter->a.os_dev_name, "/proc/scsi/qla2xxx/%ld", ha->host_no); alen = strlen(eiter->a.os_dev_name); alen += (alen & 3) ? (4 - (alen & 3)) : 4; eiter->len = cpu_to_be16(4 + alen); @@ -1611,8 +1611,6 @@ 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/trunk/drivers/scsi/qla2xxx/qla_init.c b/trunk/drivers/scsi/qla2xxx/qla_init.c index 191dafd89be0..1a058ec9bd0c 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_init.c +++ b/trunk/drivers/scsi/qla2xxx/qla_init.c @@ -849,8 +849,7 @@ 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, - &ha->max_npiv_vports); + rval = qla2x00_get_resource_cnts(ha, NULL, NULL, NULL, &fw_iocb_cnt); if (rval) return; /* No point in continuing if current settings are sufficient. */ @@ -917,15 +916,9 @@ 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) || IS_QLA25XX(ha)) && - (ha->fw_attributes & BIT_2)) { + if (IS_QLA24XX(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); @@ -1162,7 +1155,8 @@ qla2x00_init_rings(scsi_qla_host_t *ha) DEBUG(printk("scsi(%ld): Issue init firmware.\n", ha->host_no)); - mid_init_cb->count = ha->max_npiv_vports; + mid_init_cb->count = MAX_NUM_VPORT_FABRIC; + ha->max_npiv_vports = MAX_NUM_VPORT_FABRIC; rval = qla2x00_init_firmware(ha, ha->init_cb_size); if (rval) { @@ -1792,11 +1786,12 @@ qla2x00_alloc_fcport(scsi_qla_host_t *ha, gfp_t flags) { fc_port_t *fcport; - fcport = kzalloc(sizeof(fc_port_t), flags); - if (!fcport) - return NULL; + fcport = kmalloc(sizeof(fc_port_t), flags); + if (fcport == NULL) + return (fcport); /* 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; @@ -1806,7 +1801,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); } /* @@ -2132,9 +2127,15 @@ 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 || - fcport->fp_speed > ha->link_data_rate) + 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])); return; + } rval = qla2x00_set_idma_speed(ha, fcport->loop_id, fcport->fp_speed, mb); @@ -2472,12 +2473,13 @@ 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 = kcalloc(MAX_FIBRE_DEVICES, sizeof(sw_info_t), GFP_ATOMIC); - if (!swl) { + swl = kmalloc(sizeof(sw_info_t) * MAX_FIBRE_DEVICES, GFP_ATOMIC); + if (swl == NULL) { /*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/trunk/drivers/scsi/qla2xxx/qla_iocb.c b/trunk/drivers/scsi/qla2xxx/qla_iocb.c index 7f6a89bd94f3..3a5e78cb6b3f 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_iocb.c +++ b/trunk/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]) + if (ha->outstanding_cmds[handle] == 0) 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]) + if (ha->outstanding_cmds[handle] == 0) break; } if (index == MAX_OUTSTANDING_COMMANDS) diff --git a/trunk/drivers/scsi/qla2xxx/qla_isr.c b/trunk/drivers/scsi/qla2xxx/qla_isr.c index c4768c4f3990..eecae9905ece 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_isr.c +++ b/trunk/drivers/scsi/qla2xxx/qla_isr.c @@ -6,7 +6,6 @@ */ #include "qla_def.h" -#include #include static void qla2x00_mbx_completion(scsi_qla_host_t *, uint16_t); @@ -35,7 +34,6 @@ 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; @@ -50,23 +48,7 @@ qla2100_intr_handler(int irq, void *dev_id) spin_lock_irqsave(&ha->hardware_lock, flags); for (iter = 50; iter--; ) { - 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) + if ((RD_REG_WORD(®->istatus) & ISR_RISC_INT) == 0) break; if (RD_REG_WORD(®->semaphore) & BIT_0) { @@ -145,9 +127,6 @@ 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 -- " @@ -1485,52 +1464,6 @@ 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: @@ -1566,16 +1499,10 @@ 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; @@ -1679,6 +1606,7 @@ 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); @@ -1692,6 +1620,7 @@ 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]; @@ -1701,19 +1630,13 @@ qla24xx_msix_default(int irq, void *dev_id) status = 0; spin_lock_irqsave(&ha->hardware_lock, flags); - do { + 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; @@ -1746,7 +1669,8 @@ qla24xx_msix_default(int irq, void *dev_id) break; } WRT_REG_DWORD(®->hccr, HCCRX_CLR_RISC_INT); - } while (0); + RD_REG_DWORD_RELAXED(®->hccr); + } spin_unlock_irqrestore(&ha->hardware_lock, flags); if (test_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags) && diff --git a/trunk/drivers/scsi/qla2xxx/qla_mbx.c b/trunk/drivers/scsi/qla2xxx/qla_mbx.c index c53ec67c47f4..d3746ec80a85 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_mbx.c +++ b/trunk/drivers/scsi/qla2xxx/qla_mbx.c @@ -391,8 +391,7 @@ 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->mb[4] = 0; - mcp->out_mb |= MBX_4|MBX_3|MBX_2|MBX_1; + mcp->out_mb |= MBX_3|MBX_2|MBX_1; mcp->in_mb |= MBX_1; } else { mcp->mb[1] = LSW(risc_addr); @@ -1920,8 +1919,7 @@ 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 *max_npiv_vports) + uint16_t *orig_xchg_cnt, uint16_t *cur_iocb_cnt, uint16_t *orig_iocb_cnt) { int rval; mbx_cmd_t mc; @@ -1931,7 +1929,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_11|MBX_10|MBX_7|MBX_6|MBX_3|MBX_2|MBX_1|MBX_0; + mcp->in_mb = 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); @@ -1942,9 +1940,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 mb11=%x.\n", __func__, ha->host_no, + "mb7=%x mb10=%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[11])); + mcp->mb[10])); if (cur_xchg_cnt) *cur_xchg_cnt = mcp->mb[3]; @@ -1954,8 +1952,6 @@ 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); @@ -2984,51 +2980,3 @@ 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/trunk/drivers/scsi/qla2xxx/qla_mid.c b/trunk/drivers/scsi/qla2xxx/qla_mid.c index 821ee74aadc6..54dc415d8b53 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_mid.c +++ b/trunk/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: */ -static void +void qla2x00_mark_vp_devices_dead(scsi_qla_host_t *vha) { fc_port_t *fcport; @@ -179,7 +179,37 @@ qla24xx_enable_vp(scsi_qla_host_t *vha) return 1; } -static void +/** + * 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 qla24xx_configure_vp(scsi_qla_host_t *vha) { struct fc_vport *fc_vport; @@ -333,7 +363,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 = shost_priv(fc_vport->shost); + scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; scsi_qla_host_t *vha; uint8_t port_name[WWN_SIZE]; @@ -367,7 +397,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 = shost_priv(fc_vport->shost); + scsi_qla_host_t *ha = (scsi_qla_host_t *) fc_vport->shost->hostdata; scsi_qla_host_t *vha; struct Scsi_Host *host; @@ -379,7 +409,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport) return(NULL); } - vha = shost_priv(host); + vha = (scsi_qla_host_t *)host->hostdata; /* clone the parent hba */ memcpy(vha, ha, sizeof (scsi_qla_host_t)); diff --git a/trunk/drivers/scsi/qla2xxx/qla_os.c b/trunk/drivers/scsi/qla2xxx/qla_os.c index a6bb8d0ecf13..acca898ce0a2 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_os.c +++ b/trunk/drivers/scsi/qla2xxx/qla_os.c @@ -379,17 +379,12 @@ 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 = shost_priv(cmd->device->host); + scsi_qla_host_t *ha = to_qla_host(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; @@ -445,18 +440,13 @@ qla2x00_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) static int qla24xx_queuecommand(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *)) { - scsi_qla_host_t *ha = shost_priv(cmd->device->host); + scsi_qla_host_t *ha = to_qla_host(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; @@ -663,7 +653,7 @@ qla2x00_block_error_handler(struct scsi_cmnd *cmnd) static int qla2xxx_eh_abort(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = shost_priv(cmd->device->host); + scsi_qla_host_t *ha = to_qla_host(cmd->device->host); srb_t *sp; int ret, i; unsigned int id, lun; @@ -803,7 +793,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 = shost_priv(cmd->device->host); + scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; unsigned int id, lun; @@ -932,7 +922,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 = shost_priv(cmd->device->host); + scsi_qla_host_t *ha = to_qla_host(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; @@ -992,7 +982,7 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd) static int qla2xxx_eh_host_reset(struct scsi_cmnd *cmd) { - scsi_qla_host_t *ha = shost_priv(cmd->device->host); + scsi_qla_host_t *ha = to_qla_host(cmd->device->host); fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata; int ret = FAILED; unsigned int id, lun; @@ -1142,7 +1132,7 @@ qla2xxx_slave_alloc(struct scsi_device *sdev) static int qla2xxx_slave_configure(struct scsi_device *sdev) { - scsi_qla_host_t *ha = shost_priv(sdev->host); + scsi_qla_host_t *ha = to_qla_host(sdev->host); struct fc_rport *rport = starget_to_rport(sdev->sdev_target); if (sdev->tagged_supported) @@ -1394,7 +1384,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 = qla25xx_read_optrom_data, + .read_optrom = qla24xx_read_optrom_data, .write_optrom = qla24xx_write_optrom_data, .get_flash_version = qla24xx_get_flash_version, }; @@ -1543,7 +1533,7 @@ qla2x00_iospace_config(scsi_qla_host_t *ha) static void qla2xxx_scan_start(struct Scsi_Host *shost) { - scsi_qla_host_t *ha = shost_priv(shost); + scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; set_bit(LOOP_RESYNC_NEEDED, &ha->dpc_flags); set_bit(LOCAL_LOOP_UPDATE, &ha->dpc_flags); @@ -1553,7 +1543,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 = shost_priv(shost); + scsi_qla_host_t *ha = (scsi_qla_host_t *)shost->hostdata; if (!ha->host) return 1; @@ -1581,10 +1571,6 @@ 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 || @@ -1600,7 +1586,7 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) } /* Clear our data area */ - ha = shost_priv(host); + ha = (scsi_qla_host_t *)host->hostdata; memset(ha, 0, sizeof(scsi_qla_host_t)); ha->pdev = pdev; @@ -2437,6 +2423,7 @@ 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) @@ -2452,7 +2439,6 @@ 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; @@ -2470,8 +2456,6 @@ 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; @@ -2830,105 +2814,6 @@ 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) }, @@ -2954,7 +2839,6 @@ 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/trunk/drivers/scsi/qla2xxx/qla_sup.c b/trunk/drivers/scsi/qla2xxx/qla_sup.c index 40b059fc1981..a925a3f179f9 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_sup.c +++ b/trunk/drivers/scsi/qla2xxx/qla_sup.c @@ -425,9 +425,6 @@ 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) { @@ -547,59 +544,41 @@ qla24xx_write_flash_data(scsi_qla_host_t *ha, uint32_t *dwptr, uint32_t faddr, uint32_t dwords) { int ret; - uint32_t liter, miter; - uint32_t sec_mask, rest_addr, conf_addr; + uint32_t liter; + uint32_t sec_mask, rest_addr, conf_addr, sec_end_mask; 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. */ - if (flash_id == 0x8e) { - rest_addr = 0x3fff; - sec_mask = 0x7c000; - } else { - rest_addr = 0x1fff; - sec_mask = 0x7e000; - } + rest_addr = 0x1fff; + sec_mask = 0x3e000; if (flash_id == 0x80) conf_addr = flash_conf_to_access_addr(0x0352); break; case 0x13: /* ST M25P80. */ rest_addr = 0x3fff; - sec_mask = 0x7c000; + sec_mask = 0x3c000; break; case 0x1f: // Atmel 26DF081A - rest_addr = 0x3fff; - sec_mask = 0x7c000; + rest_addr = 0x0fff; + sec_mask = 0xff000; + sec_end_mask = 0x003ff; conf_addr = flash_conf_to_access_addr(0x0320); break; default: /* Default to 64 kb sector size. */ rest_addr = 0x3fff; - sec_mask = 0x7c000; + sec_mask = 0x3c000; break; } @@ -613,81 +592,56 @@ 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); - 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; - } + 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; + } - /* 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) & + /* 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) & 0xff0000) | ((fdata >> 16) & 0xff)); - 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; + if (ret != QLA_SUCCESS) { + DEBUG9(printk("%s(%ld) Unable to flash " + "sector: address=%x.\n", __func__, + ha->host_no, faddr)); + break; + } } - } - - /* 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, + ret = qla24xx_write_flash_dword(ha, flash_data_to_access_addr(faddr), - OPTROM_BURST_DWORDS); + cpu_to_le32(*dwptr)); if (ret != QLA_SUCCESS) { - 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; + DEBUG9(printk("%s(%ld) Unable to program flash " + "address=%x data=%x.\n", __func__, + ha->host_no, faddr, *dwptr)); + break; } - } - 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; + /* 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)); } - - /* 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)); - } + } while (0); /* Enable flash write-protection. */ qla24xx_write_flash_dword(ha, flash_conf_to_access_addr(0x101), 0x9c); @@ -697,10 +651,6 @@ 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; } @@ -1778,6 +1728,7 @@ 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. */ @@ -1785,6 +1736,7 @@ 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; @@ -1798,6 +1750,7 @@ 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. */ @@ -1814,70 +1767,6 @@ 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/trunk/drivers/scsi/qla2xxx/qla_version.h b/trunk/drivers/scsi/qla2xxx/qla_version.h index 2d551a3006f6..18095b9b76f4 100644 --- a/trunk/drivers/scsi/qla2xxx/qla_version.h +++ b/trunk/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.02.00-k4" +#define QLA2XXX_VERSION "8.02.00-k3" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 diff --git a/trunk/drivers/scsi/qlogicfas.c b/trunk/drivers/scsi/qlogicfas.c index 1e874f1fb5c6..94baca840efe 100644 --- a/trunk/drivers/scsi/qlogicfas.c +++ b/trunk/drivers/scsi/qlogicfas.c @@ -166,7 +166,6 @@ 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); @@ -175,6 +174,7 @@ 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/trunk/drivers/scsi/qlogicpti.c b/trunk/drivers/scsi/qlogicpti.c index e93f80316a19..594887205b0f 100644 --- a/trunk/drivers/scsi/qlogicpti.c +++ b/trunk/drivers/scsi/qlogicpti.c @@ -310,6 +310,8 @@ 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) @@ -949,35 +951,153 @@ 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 int qlogicpti_slave_configure(struct scsi_device *sdev) +static unsigned int scsi_rbuf_get(struct scsi_cmnd *cmd, unsigned char **buf_out) { - struct qlogicpti *qpti = shost_priv(sdev->host); - int tgt = sdev->id; - u_short param[6]; + unsigned char *buf; + unsigned int buflen; + + if (cmd->use_sg) { + struct scatterlist *sg; - /* tags handled in midlayer */ - /* enable sync mode? */ - if (sdev->sdtr) { - qpti->dev_param[tgt].device_flags |= 0x10; + sg = (struct scatterlist *) cmd->request_buffer; + buf = kmap_atomic(sg->page, KM_IRQ0) + sg->offset; + buflen = sg->length; } else { - qpti->dev_param[tgt].synchronous_offset = 0; - qpti->dev_param[tgt].synchronous_period = 0; + buf = cmd->request_buffer; + buflen = cmd->request_bufflen; } - /* 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; + + *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); } - qlogicpti_mbox_command(qpti, param, 0); - return 0; +} + +/* + * 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; + } + } + + /* + * 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); } /* @@ -1270,8 +1390,7 @@ static struct scsi_host_template qpti_template = { .module = THIS_MODULE, .name = "qlogicpti", .info = qlogicpti_info, - .queuecommand = qlogicpti_queuecommand, - .slave_configure = qlogicpti_slave_configure, + .queuecommand = qlogicpti_queuecommand_slow, .eh_abort_handler = qlogicpti_abort, .eh_bus_reset_handler = qlogicpti_reset, .can_queue = QLOGICPTI_REQ_QUEUE_LEN, diff --git a/trunk/drivers/scsi/qlogicpti.h b/trunk/drivers/scsi/qlogicpti.h index ef6da2df584b..6cd1c0771d29 100644 --- a/trunk/drivers/scsi/qlogicpti.h +++ b/trunk/drivers/scsi/qlogicpti.h @@ -380,7 +380,8 @@ 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. */ + is_pti : 1, /* Non-zero if this is a PTI board. */ + sbits : 16; /* syncmode known bits */ }; /* How to twiddle them bits... */ diff --git a/trunk/drivers/scsi/scsi.c b/trunk/drivers/scsi/scsi.c index 192948822455..a5de1a829a76 100644 --- a/trunk/drivers/scsi/scsi.c +++ b/trunk/drivers/scsi/scsi.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -368,8 +367,9 @@ void scsi_log_send(struct scsi_cmnd *cmd) scsi_print_command(cmd); if (level > 3) { printk(KERN_INFO "buffer = 0x%p, bufflen = %d," - " queuecommand 0x%p\n", + " done = 0x%p, 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 to the request for error recovery + * Assign a serial number and pid 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,6 +450,10 @@ 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++; } /* @@ -654,12 +658,6 @@ 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 * @@ -671,8 +669,6 @@ 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); @@ -698,13 +694,7 @@ void scsi_finish_command(struct scsi_cmnd *cmd) "Notifying upper driver of completion " "(result %x)\n", cmd->result)); - 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); + cmd->done(cmd); } EXPORT_SYMBOL(scsi_finish_command); diff --git a/trunk/drivers/scsi/scsi_devinfo.c b/trunk/drivers/scsi/scsi_devinfo.c index 348cc5a6e3cd..e2ea739e33df 100644 --- a/trunk/drivers/scsi/scsi_devinfo.c +++ b/trunk/drivers/scsi/scsi_devinfo.c @@ -214,7 +214,6 @@ 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/trunk/drivers/scsi/scsi_error.c b/trunk/drivers/scsi/scsi_error.c index d29f8464b74f..8a525abda30f 100644 --- a/trunk/drivers/scsi/scsi_error.c +++ b/trunk/drivers/scsi/scsi_error.c @@ -37,7 +37,6 @@ #include "scsi_priv.h" #include "scsi_logging.h" -#include "scsi_transport_api.h" #define SENSE_TIMEOUT (10*HZ) @@ -590,23 +589,39 @@ static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd) } /** - * scsi_eh_prep_cmnd - Save a scsi command info as part of error recory + * scsi_send_eh_cmnd - submit a scsi command as part of error recory * @scmd: SCSI command structure to hijack - * @ses: structure to save restore information - * @cmnd: CDB to send. Can be NULL if no new cmnd is needed + * @cmnd: CDB to send * @cmnd_size: size in bytes of @cmnd - * @sense_bytes: size of sense data to copy. or 0 (if != 0 @cmnd is ignored) + * @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. * - * 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. + * Return value: + * SUCCESS or FAILED or NEEDS_RETRY **/ -void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, - unsigned char *cmnd, int cmnd_size, unsigned sense_bytes) +static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, + int cmnd_size, int timeout, int copy_sense) { 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 @@ -615,42 +630,35 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, * we will need to restore these values prior to running the actual * command. */ - 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; + 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)); + 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 && sdev->scsi_level != SCSI_UNKNOWN) + if (sdev->scsi_level <= SCSI_2) scmd->cmnd[1] = (scmd->cmnd[1] & 0x1f) | (sdev->lun << 5 & 0xe0); @@ -659,58 +667,7 @@ void scsi_eh_prep_cmnd(struct scsi_cmnd *scmd, struct scsi_eh_save *ses, * 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); @@ -754,7 +711,17 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, rtn = FAILED; } - scsi_eh_restore_cmnd(scmd, &ses); + + /* + * 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; return rtn; } @@ -769,7 +736,10 @@ static int scsi_send_eh_cmnd(struct scsi_cmnd *scmd, unsigned char *cmnd, **/ static int scsi_request_sense(struct scsi_cmnd *scmd) { - return scsi_send_eh_cmnd(scmd, NULL, 0, SENSE_TIMEOUT, ~0); + 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); } /** @@ -1166,8 +1136,9 @@ 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, "Device offlined - " - "not ready after error recovery\n"); + sdev_printk(KERN_INFO, scmd->device, + "scsi: Device offlined - not" + " ready after error recovery\n"); scsi_device_set_state(scmd->device, SDEV_OFFLINE); if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD) { /* @@ -1700,6 +1671,7 @@ 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; @@ -1709,6 +1681,12 @@ 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/trunk/drivers/scsi/scsi_lib.c b/trunk/drivers/scsi/scsi_lib.c index 207f1aa08869..604f4d717933 100644 --- a/trunk/drivers/scsi/scsi_lib.c +++ b/trunk/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 = bufflen, len, bytes, off; + unsigned int data_len = 0, len, bytes, off; struct page *page; struct bio *bio = NULL; int i, err, nr_vecs = 0; @@ -297,15 +297,10 @@ 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 && data_len > 0) { - /* - * sg sends a scatterlist that is larger than - * the data_len it wants transferred for certain - * IO sizes - */ + while (len > 0) { 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); @@ -337,13 +332,12 @@ 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 = bufflen; + rq->data_len = data_len; return 0; free_bios: @@ -436,7 +430,6 @@ 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]); @@ -931,11 +924,11 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) break; } } - if (!(req->cmd_flags & REQ_QUIET)) - scsi_cmd_print_sense_hdr(cmd, - "Device not ready", - &sshdr); - + if (!(req->cmd_flags & REQ_QUIET)) { + scmd_printk(KERN_INFO, cmd, + "Device not ready: "); + scsi_print_sense_hdr("", &sshdr); + } scsi_end_request(cmd, 0, this_count, 1); return; case VOLUME_OVERFLOW: @@ -969,6 +962,7 @@ 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() @@ -1025,6 +1019,9 @@ 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; } @@ -1049,13 +1046,21 @@ static struct scsi_cmnd *scsi_get_cmd_from_req(struct scsi_device *sdev, return cmd; } -int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) +static void scsi_blk_pc_done(struct scsi_cmnd *cmd) { - struct scsi_cmnd *cmd; - int ret = scsi_prep_state_check(sdev, req); + 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); +} - if (ret != BLKPREP_OK) - return ret; +static int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) +{ + struct scsi_cmnd *cmd; cmd = scsi_get_cmd_from_req(sdev, req); if (unlikely(!cmd)) @@ -1098,22 +1103,21 @@ 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. */ -int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) +static int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) { struct scsi_cmnd *cmd; - int ret = scsi_prep_state_check(sdev, req); + struct scsi_driver *drv; + int ret; - if (ret != BLKPREP_OK) - return ret; /* * Filesystem requests must transfer data. */ @@ -1123,12 +1127,26 @@ int scsi_setup_fs_cmnd(struct scsi_device *sdev, struct request *req) if (unlikely(!cmd)) return BLKPREP_DEFER; - return scsi_init_io(cmd); + 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; } -EXPORT_SYMBOL(scsi_setup_fs_cmnd); -int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) +static int scsi_prep_fn(struct request_queue *q, struct request *req) { + struct scsi_device *sdev = q->queuedata; int ret = BLKPREP_OK; /* @@ -1174,25 +1192,35 @@ int scsi_prep_state_check(struct scsi_device *sdev, struct request *req) ret = BLKPREP_KILL; break; } + + if (ret != BLKPREP_OK) + goto out; } - return ret; -} -EXPORT_SYMBOL(scsi_prep_state_check); -int scsi_prep_return(struct request_queue *q, struct request *req, int ret) -{ - struct scsi_device *sdev = q->queuedata; + 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; + } + 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: /* @@ -1209,17 +1237,6 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret) 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/trunk/drivers/scsi/scsi_priv.h b/trunk/drivers/scsi/scsi_priv.h index eff005951895..ee8efe849bf4 100644 --- a/trunk/drivers/scsi/scsi_priv.h +++ b/trunk/drivers/scsi/scsi_priv.h @@ -68,7 +68,6 @@ 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/trunk/drivers/scsi/scsi_scan.c b/trunk/drivers/scsi/scsi_scan.c index b53c5f67e372..a86e62f4b3ba 100644 --- a/trunk/drivers/scsi/scsi_scan.c +++ b/trunk/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, uint, S_IRUGO|S_IWUSR); +module_param_named(max_luns, max_scsi_luns, int, S_IRUGO|S_IWUSR); MODULE_PARM_DESC(max_luns, "last scsi LUN (should be between 1 and 2^32-1)"); @@ -109,19 +109,18 @@ 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, uint, S_IRUGO|S_IWUSR); +module_param_named(max_report_luns, max_scsi_report_luns, int, 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, uint, S_IRUGO|S_IWUSR); +module_param_named(inq_timeout, scsi_inq_timeout, int, 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); @@ -1467,14 +1466,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); @@ -1587,10 +1586,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); @@ -1635,15 +1634,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; @@ -1662,8 +1661,7 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost) { struct scsi_device *sdev; shost_for_each_device(sdev, shost) { - if (!scsi_host_scan_allowed(shost) || - scsi_sysfs_add_sdev(sdev) != 0) + if (scsi_sysfs_add_sdev(sdev) != 0) scsi_destroy_sdev(sdev); } } @@ -1681,7 +1679,6 @@ 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; @@ -1701,13 +1698,8 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost) goto err; init_completion(&data->prev_finished); - 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); + shost->async_scan = 1; if (list_empty(&scanning_hosts)) complete(&data->prev_finished); list_add_tail(&data->list, &scanning_hosts); @@ -1731,15 +1723,11 @@ 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); @@ -1751,13 +1739,8 @@ static void scsi_finish_async_scan(struct async_scan_data *data) scsi_sysfs_add_devices(shost); - 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); + shost->async_scan = 0; list_del(&data->list); if (!list_empty(&scanning_hosts)) { struct async_scan_data *next = list_entry(scanning_hosts.next, @@ -1799,7 +1782,6 @@ 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) @@ -1811,9 +1793,7 @@ void scsi_scan_host(struct Scsi_Host *shost) return; } - p = kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); - if (unlikely(IS_ERR(p))) - do_scan_async(data); + kthread_run(do_scan_async, data, "scsi_scan_%d", shost->host_no); } EXPORT_SYMBOL(scsi_scan_host); diff --git a/trunk/drivers/scsi/scsi_sysfs.c b/trunk/drivers/scsi/scsi_sysfs.c index daed37df00b1..ede9986d349a 100644 --- a/trunk/drivers/scsi/scsi_sysfs.c +++ b/trunk/drivers/scsi/scsi_sysfs.c @@ -190,46 +190,6 @@ 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"); @@ -248,8 +208,6 @@ 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 }; @@ -613,31 +571,24 @@ 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 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, +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, NULL }; @@ -699,6 +650,56 @@ 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 @@ -730,24 +731,6 @@ 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) @@ -758,10 +741,9 @@ 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 = device_create_file(&sdev->sdev_gendev, + error = attr_add(&sdev->sdev_gendev, sdev->host->hostt->sdev_attrs[i]); if (error) { __scsi_remove_device(sdev); @@ -769,6 +751,20 @@ 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: @@ -955,12 +951,6 @@ 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; @@ -969,7 +959,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.type = &scsi_dev_type; + sdev->sdev_gendev.release = scsi_device_dev_release; sprintf(sdev->sdev_gendev.bus_id,"%d:%d:%d:%d", sdev->host->host_no, sdev->channel, sdev->id, sdev->lun); @@ -990,7 +980,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev) int scsi_is_sdev_device(const struct device *dev) { - return dev->type == &scsi_dev_type; + return dev->release == scsi_device_dev_release; } EXPORT_SYMBOL(scsi_is_sdev_device); diff --git a/trunk/drivers/scsi/scsi_tgt_if.c b/trunk/drivers/scsi/scsi_tgt_if.c index 9815a1a2db24..ca22ddf81746 100644 --- a/trunk/drivers/scsi/scsi_tgt_if.c +++ b/trunk/drivers/scsi/scsi_tgt_if.c @@ -102,8 +102,7 @@ static int tgt_uspace_send_event(u32 type, struct tgt_event *p) return 0; } -int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id, - struct scsi_lun *lun, u64 tag) +int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, struct scsi_lun *lun, u64 tag) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); struct tgt_event ev; @@ -111,7 +110,6 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id, 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)); @@ -129,7 +127,7 @@ int scsi_tgt_uspace_send_cmd(struct scsi_cmnd *cmd, u64 itn_id, return err; } -int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag) +int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 tag) { struct Scsi_Host *shost = scsi_tgt_cmd_to_host(cmd); struct tgt_event ev; @@ -137,7 +135,6 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, 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; @@ -152,15 +149,14 @@ int scsi_tgt_uspace_send_status(struct scsi_cmnd *cmd, u64 itn_id, u64 tag) return err; } -int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function, - u64 tag, struct scsi_lun *scsilun, void *data) +int scsi_tgt_uspace_send_tsk_mgmt(int host_no, 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)); @@ -176,29 +172,6 @@ int scsi_tgt_uspace_send_tsk_mgmt(int host_no, u64 itn_id, int function, 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; @@ -206,7 +179,6 @@ 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, @@ -217,15 +189,9 @@ 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/trunk/drivers/scsi/scsi_tgt_lib.c b/trunk/drivers/scsi/scsi_tgt_lib.c index 66c692ffa305..371b69c110bc 100644 --- a/trunk/drivers/scsi/scsi_tgt_lib.c +++ b/trunk/drivers/scsi/scsi_tgt_lib.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include "scsi_tgt_priv.h" @@ -47,7 +46,6 @@ struct scsi_tgt_cmd { struct list_head hash_list; struct request *rq; - u64 itn_id; u64 tag; }; @@ -187,13 +185,12 @@ 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 itn_id, u64 tag) + 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); @@ -237,7 +234,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->can_queue; + q->nr_requests = shost->hostt->can_queue; /* * We currently only support software LLDs so this does * not matter for now. Do we need this for the cards we support? @@ -304,14 +301,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, u64 itn_id, - struct scsi_lun *scsilun, u64 tag) +int scsi_tgt_queue_command(struct scsi_cmnd *cmd, 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, itn_id, tag); - err = scsi_tgt_uspace_send_cmd(cmd, itn_id, scsilun, tag); + init_scsi_tgt_cmd(cmd->request, tcmd, tag); + err = scsi_tgt_uspace_send_cmd(cmd, scsilun, tag); if (err) cmd_hashlist_del(cmd); @@ -329,7 +326,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->itn_id, tcmd->tag); + scsi_tgt_uspace_send_status(cmd, tcmd->tag); if (cmd->request_buffer) scsi_free_sgtable(cmd->request_buffer, cmd->sglist_len); @@ -462,7 +459,7 @@ static struct request *tgt_cmd_hash_lookup(struct request_queue *q, u64 tag) return rq; } -int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, +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) { @@ -544,22 +541,21 @@ int scsi_tgt_kspace_exec(int host_no, u64 itn_id, int result, u64 tag, return err; } -int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, u64 itn_id, - int function, u64 tag, struct scsi_lun *scsilun, - void *data) +int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *shost, 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, itn_id, - function, tag, scsilun, data); + err = scsi_tgt_uspace_send_tsk_mgmt(shost->host_no, 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 itn_id, u64 mid, int result) +int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result) { struct Scsi_Host *shost; int err = -EINVAL; @@ -577,60 +573,7 @@ int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 itn_id, u64 mid, int result) goto done; } - 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); + err = shost->hostt->tsk_mgmt_response(mid, result); done: scsi_host_put(shost); return err; diff --git a/trunk/drivers/scsi/scsi_tgt_priv.h b/trunk/drivers/scsi/scsi_tgt_priv.h index cb92888948f9..e9e6db1c417f 100644 --- a/trunk/drivers/scsi/scsi_tgt_priv.h +++ b/trunk/drivers/scsi/scsi_tgt_priv.h @@ -15,18 +15,12 @@ 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, 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, +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, struct scsi_lun *scsilun, void *data); -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); +extern int scsi_tgt_kspace_tsk_mgmt(int host_no, u64 mid, int result); diff --git a/trunk/drivers/scsi/scsi_transport_fc.c b/trunk/drivers/scsi/scsi_transport_fc.c index 7a7cfe583b2a..47057254850d 100644 --- a/trunk/drivers/scsi/scsi_transport_fc.c +++ b/trunk/drivers/scsi/scsi_transport_fc.c @@ -36,7 +36,6 @@ #include #include #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); @@ -474,7 +473,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, uint, S_IRUGO|S_IWUSR); +module_param_named(dev_loss_tmo, fc_dev_loss_tmo, int, 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" @@ -1957,19 +1956,6 @@ 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) { @@ -2013,10 +1999,6 @@ 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. */ @@ -2774,10 +2756,6 @@ 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 */ @@ -2818,7 +2796,6 @@ 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) { @@ -2827,12 +2804,6 @@ 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; @@ -3017,12 +2988,10 @@ 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) && - !(i->f->disable_target_scan)) { + (rport->roles & FC_PORT_ROLE_FCP_TARGET)) { scsi_scan_target(&rport->dev, rport->channel, rport->scsi_target_id, SCAN_WILD_CARD, 1); } diff --git a/trunk/drivers/scsi/scsi_transport_fc_internal.h b/trunk/drivers/scsi/scsi_transport_fc_internal.h deleted file mode 100644 index e7bfbe751c1f..000000000000 --- a/trunk/drivers/scsi/scsi_transport_fc_internal.h +++ /dev/null @@ -1,26 +0,0 @@ -#include - -#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/trunk/drivers/scsi/scsi_transport_srp.c b/trunk/drivers/scsi/scsi_transport_srp.c deleted file mode 100644 index 44a340bd937b..000000000000 --- a/trunk/drivers/scsi/scsi_transport_srp.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * SCSI RDMA (SRP) transport class - * - * Copyright (C) 2007 FUJITA Tomonori - * - * 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 -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#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/trunk/drivers/scsi/scsi_transport_srp_internal.h b/trunk/drivers/scsi/scsi_transport_srp_internal.h deleted file mode 100644 index 8a79747f9f3d..000000000000 --- a/trunk/drivers/scsi/scsi_transport_srp_internal.h +++ /dev/null @@ -1,25 +0,0 @@ -#include - -#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/trunk/drivers/scsi/sd.c b/trunk/drivers/scsi/sd.c index 0a3a528212c2..2c6116fd4578 100644 --- a/trunk/drivers/scsi/sd.c +++ b/trunk/drivers/scsi/sd.c @@ -86,19 +86,6 @@ 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); @@ -253,7 +240,7 @@ static struct scsi_driver sd_template = { .shutdown = sd_shutdown, }, .rescan = sd_rescan, - .done = sd_done, + .init_command = sd_init_command, }; /* @@ -344,31 +331,14 @@ 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_prep_fn(struct request_queue *q, struct request *rq) +static int sd_init_command(struct scsi_cmnd * SCpnt) { - struct scsi_cmnd *SCpnt; - struct scsi_device *sdp = q->queuedata; + struct scsi_device *sdp = SCpnt->device; + struct request *rq = SCpnt->request; struct gendisk *disk = rq->rq_disk; sector_t block = rq->sector; - unsigned int this_count = rq->nr_sectors; + unsigned int this_count = SCpnt->request_bufflen >> 9; 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, " @@ -383,7 +353,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) rq->nr_sectors)); SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "Retry with 0x%p\n", SCpnt)); - goto out; + return 0; } if (sdp->changed) { @@ -392,9 +362,8 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) * the changed bit has been reset */ /* printk("SCSI disk has been changed. Prohibiting further I/O.\n"); */ - goto out; + return 0; } - SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, "block=%llu\n", (unsigned long long)block)); @@ -413,7 +382,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) if ((block & 1) || (rq->nr_sectors & 1)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - goto out; + return 0; } else { block = block >> 1; this_count = this_count >> 1; @@ -423,7 +392,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) if ((block & 3) || (rq->nr_sectors & 3)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - goto out; + return 0; } else { block = block >> 2; this_count = this_count >> 2; @@ -433,7 +402,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) if ((block & 7) || (rq->nr_sectors & 7)) { scmd_printk(KERN_ERR, SCpnt, "Bad block number requested\n"); - goto out; + return 0; } else { block = block >> 3; this_count = this_count >> 3; @@ -441,7 +410,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) } if (rq_data_dir(rq) == WRITE) { if (!sdp->writeable) { - goto out; + return 0; } SCpnt->cmnd[0] = WRITE_6; SCpnt->sc_data_direction = DMA_TO_DEVICE; @@ -450,7 +419,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { scmd_printk(KERN_ERR, SCpnt, "Unknown command %x\n", rq->cmd_flags); - goto out; + return 0; } SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, @@ -501,7 +470,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) */ scmd_printk(KERN_ERR, SCpnt, "FUA write on READ/WRITE(6) drive\n"); - goto out; + return 0; } SCpnt->cmnd[1] |= (unsigned char) ((block >> 16) & 0x1f); @@ -522,13 +491,17 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) SCpnt->allowed = SD_MAX_RETRIES; 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. */ - ret = BLKPREP_OK; - out: - return scsi_prep_return(q, rq, ret); + return 1; } /** @@ -916,13 +889,13 @@ static struct block_device_operations sd_fops = { }; /** - * sd_done - bottom half handler: called when the lower level + * sd_rw_intr - 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 int sd_done(struct scsi_cmnd *SCpnt) +static void sd_rw_intr(struct scsi_cmnd * SCpnt) { int result = SCpnt->result; unsigned int xfer_size = SCpnt->request_bufflen; @@ -943,7 +916,7 @@ static int sd_done(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_done: sb[respc,sk,asc," + "sd_rw_intr: sb[respc,sk,asc," "ascq]=%x,%x,%x,%x\n", sshdr.response_code, sshdr.sense_key, sshdr.asc, @@ -1015,7 +988,7 @@ static int sd_done(struct scsi_cmnd *SCpnt) break; } out: - return good_bytes; + scsi_io_completion(SCpnt, good_bytes); } static int media_not_present(struct scsi_disk *sdkp, @@ -1696,7 +1669,6 @@ 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/trunk/drivers/scsi/sg.c b/trunk/drivers/scsi/sg.c index f6f5fc7d0cee..85d38940a6c9 100644 --- a/trunk/drivers/scsi/sg.c +++ b/trunk/drivers/scsi/sg.c @@ -43,7 +43,6 @@ static int sg_version_num = 30534; /* 2 digits for each component */ #include #include #include -#include #include #include #include @@ -100,11 +99,12 @@ 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_IDR(sg_index_idr); -static DEFINE_RWLOCK(sg_index_lock); /* Also used to lock +static DEFINE_RWLOCK(sg_dev_arr_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 sglist_len; /* size of malloc'd scatter-gather list ++ */ + unsigned short 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,7 +162,6 @@ 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 */ @@ -210,6 +209,10 @@ 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) @@ -1328,35 +1331,40 @@ static struct class *sg_sysfs_class; static int sg_sysfs_valid = 0; -static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) +static int sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) { struct request_queue *q = scsidp->request_queue; Sg_device *sdp; unsigned long iflags; - int error; - u32 k; + void *old_sg_dev_arr = NULL; + int k, error; sdp = kzalloc(sizeof(Sg_device), GFP_KERNEL); if (!sdp) { printk(KERN_WARNING "kmalloc Sg_device failure\n"); - return ERR_PTR(-ENOMEM); - } - error = -ENOMEM; - if (!idr_pre_get(&sg_index_idr, GFP_KERNEL)) { - printk(KERN_WARNING "idr expansion Sg_device failure\n"); - goto out; + return -ENOMEM; } - 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); + 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); - if (error) { - printk(KERN_WARNING "idr allocation Sg_device failure: %d\n", - error); - goto out; + tmp_da = kzalloc(tmp_dev_max * sizeof(Sg_device *), GFP_KERNEL); + if (unlikely(!tmp_da)) + goto expand_failed; + + 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; } + for (k = 0; k < sg_dev_max; k++) + if (!sg_dev_arr[k]) + break; if (unlikely(k >= SG_MAX_DEVS)) goto overflow; @@ -1367,17 +1375,25 @@ static Sg_device *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; - error = 0; + sg_nr_dev++; + sg_dev_arr[k] = sdp; + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); + error = k; + out: - if (error) { + if (error < 0) kfree(sdp); - return ERR_PTR(error); - } - return 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; 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); @@ -1392,7 +1408,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; + int error, k; unsigned long iflags; disk = alloc_disk(1); @@ -1411,15 +1427,15 @@ sg_add(struct class_device *cl_dev, struct class_interface *cl_intf) cdev->owner = THIS_MODULE; cdev->ops = &sg_fops; - sdp = sg_alloc(disk, scsidp); - if (IS_ERR(sdp)) { + error = sg_alloc(disk, scsidp); + if (error < 0) { printk(KERN_WARNING "sg_alloc failed\n"); - error = PTR_ERR(sdp); goto out; } + k = error; + sdp = sg_dev_arr[k]; - class_set_devdata(cl_dev, sdp); - error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, sdp->index), 1); + error = cdev_add(cdev, MKDEV(SCSI_GENERIC_MAJOR, k), 1); if (error) goto cdev_add_err; @@ -1428,8 +1444,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, sdp->index), - cl_dev->dev, "%s", + MKDEV(SCSI_GENERIC_MAJOR, k), + cl_dev->dev, "%s", disk->disk_name); if (IS_ERR(sg_class_member)) printk(KERN_WARNING "sg_add: " @@ -1439,21 +1455,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", sdp->index); + "'generic' back to sg%d\n", k); } 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", sdp->index, - scsidp->type); + "Attached scsi generic sg%d type %d\n", k,scsidp->type); return 0; cdev_add_err: - write_lock_irqsave(&sg_index_lock, iflags); - idr_remove(&sg_index_idr, sdp->index); - write_unlock_irqrestore(&sg_index_lock, iflags); - kfree(sdp); + 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); out: put_disk(disk); @@ -1466,56 +1482,64 @@ 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 = class_get_devdata(cl_dev); + Sg_device *sdp = NULL; unsigned long iflags; Sg_fd *sfp; Sg_fd *tsfp; Sg_request *srp; Sg_request *tsrp; - int delay; + int k, delay; - if (!sdp) + if (NULL == sg_dev_arr) return; - delay = 0; - 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); + 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); + } } - if (sfp->closed) { - scsi_device_put(sdp->device); - __sg_remove_sfp(sdp, sfp); - } else { - delay = 1; - wake_up_interruptible(&sfp->read_wait); - kill_fasync(&sfp->async_qp, SIGPOLL, - POLL_HUP); + SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d, dirty\n", k)); + if (NULL == sdp->headfp) { + sg_dev_arr[k] = NULL; } + } else { /* nothing active, simple case */ + SCSI_LOG_TIMEOUT(3, printk("sg_remove: dev=%d\n", k)); + sg_dev_arr[k] = NULL; } - 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); + 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); + } if (delay) msleep(10); /* dirty detach so delay device destruction */ @@ -1585,7 +1609,9 @@ exit_sg(void) sg_sysfs_valid = 0; unregister_chrdev_region(MKDEV(SCSI_GENERIC_MAJOR, 0), SG_MAX_DEVS); - idr_destroy(&sg_index_idr); + kfree((char *)sg_dev_arr); + sg_dev_arr = NULL; + sg_dev_max = 0; } static int @@ -2305,10 +2331,10 @@ sg_get_nth_sfp(Sg_device * sdp, int nth) unsigned long iflags; int k; - read_lock_irqsave(&sg_index_lock, iflags); + read_lock_irqsave(&sg_dev_arr_lock, iflags); for (k = 0, resp = sdp->headfp; resp && (k < nth); ++k, resp = resp->nextfp) ; - read_unlock_irqrestore(&sg_index_lock, iflags); + read_unlock_irqrestore(&sg_dev_arr_lock, iflags); return resp; } #endif @@ -2335,7 +2361,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_index_lock, iflags); + write_lock_irqsave(&sg_dev_arr_lock, iflags); if (!sdp->headfp) sdp->headfp = sfp; else { /* add to tail of existing list */ @@ -2344,7 +2370,7 @@ sg_add_sfp(Sg_device * sdp, int dev) pfp = pfp->nextfp; pfp->nextfp = sfp; } - write_unlock_irqrestore(&sg_index_lock, iflags); + write_unlock_irqrestore(&sg_dev_arr_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; @@ -2405,14 +2431,22 @@ sg_remove_sfp(Sg_device * sdp, Sg_fd * sfp) if (0 == dirty) { unsigned long iflags; - write_lock_irqsave(&sg_index_lock, iflags); + write_lock_irqsave(&sg_dev_arr_lock, iflags); __sg_remove_sfp(sdp, sfp); if (sdp->detached && (NULL == sdp->headfp)) { - idr_remove(&sg_index_idr, sdp->index); - kfree(sdp); + 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); res = 1; } - write_unlock_irqrestore(&sg_index_lock, iflags); + write_unlock_irqrestore(&sg_dev_arr_lock, iflags); } else { /* MOD_INC's to inhibit unloading sg and associated adapter driver */ /* only bump the access_count if we actually succeeded in @@ -2511,26 +2545,17 @@ 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 = 0; + int k; unsigned long 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); + 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); return k + 1; /* origin 1 */ } #endif @@ -2538,13 +2563,15 @@ sg_last_dev(void) static Sg_device * sg_get_dev(int dev) { - Sg_device *sdp; + Sg_device *sdp = NULL; unsigned long iflags; - read_lock_irqsave(&sg_index_lock, iflags); - sdp = idr_find(&sg_index_idr, dev); - read_unlock_irqrestore(&sg_index_lock, 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); + } return sdp; } @@ -2778,6 +2805,8 @@ 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) @@ -2913,8 +2942,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, "max_active_device=%d(origin 1)\n", - (int)it->max); + seq_printf(s, "dev_max(currently)=%d max_active_device=%d " + "(origin 1)\n", sg_dev_max, (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/trunk/drivers/scsi/sr.c b/trunk/drivers/scsi/sr.c index c61999031141..902eb11ffe8a 100644 --- a/trunk/drivers/scsi/sr.c +++ b/trunk/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_done(struct scsi_cmnd *); +static int sr_init_command(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, }, - .done = sr_done, + .init_command = sr_init_command, }; 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) } /* - * sr_done is the interrupt routine for the device driver. + * rw_intr is the interrupt routine for the device driver. * - * It will be notified on the end of a SCSI read / write, and will take one + * It will be notified on the end of a SCSI read / write, and will take on * of several actions based on success or failure. */ -static int sr_done(struct scsi_cmnd *SCpnt) +static void rw_intr(struct scsi_cmnd * SCpnt) { int result = SCpnt->result; int this_count = SCpnt->request_bufflen; @@ -288,42 +288,27 @@ static int sr_done(struct scsi_cmnd *SCpnt) } } - return good_bytes; + /* + * 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); } -static int sr_prep_fn(struct request_queue *q, struct request *rq) +static int sr_init_command(struct scsi_cmnd * SCpnt) { int block=0, this_count, s_size, timeout = SR_TIMEOUT; - 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; + struct scsi_cd *cd = scsi_cd(SCpnt->request->rq_disk); 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", - rq->nr_sectors)); + SCpnt->request->nr_sectors)); SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); - goto out; + return 0; } if (cd->device->changed) { @@ -331,7 +316,7 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) * quietly refuse to do anything to a changed disc until the * changed bit has been reset */ - goto out; + return 0; } /* @@ -348,21 +333,21 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) if (s_size != 512 && s_size != 1024 && s_size != 2048) { scmd_printk(KERN_ERR, SCpnt, "bad sector size %d\n", s_size); - goto out; + return 0; } - if (rq_data_dir(rq) == WRITE) { + if (rq_data_dir(SCpnt->request) == WRITE) { if (!cd->device->writeable) - goto out; + return 0; SCpnt->cmnd[0] = WRITE_10; SCpnt->sc_data_direction = DMA_TO_DEVICE; cd->cdi.media_written = 1; - } else if (rq_data_dir(rq) == READ) { + } else if (rq_data_dir(SCpnt->request) == READ) { SCpnt->cmnd[0] = READ_10; SCpnt->sc_data_direction = DMA_FROM_DEVICE; } else { - blk_dump_rq_flags(rq, "Unknown sr command"); - goto out; + blk_dump_rq_flags(SCpnt->request, "Unknown sr command"); + return 0; } { @@ -383,10 +368,10 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) /* * request doesn't start on hw block boundary, add scatter pads */ - if (((unsigned int)rq->sector % (s_size >> 9)) || + if (((unsigned int)SCpnt->request->sector % (s_size >> 9)) || (SCpnt->request_bufflen % s_size)) { scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n"); - goto out; + return 0; } this_count = (SCpnt->request_bufflen >> 9) / (s_size >> 9); @@ -394,12 +379,12 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", cd->cdi.name, - (rq_data_dir(rq) == WRITE) ? + (rq_data_dir(SCpnt->request) == WRITE) ? "writing" : "reading", - this_count, rq->nr_sectors)); + this_count, SCpnt->request->nr_sectors)); SCpnt->cmnd[1] = 0; - block = (unsigned int)rq->sector / (s_size >> 9); + block = (unsigned int)SCpnt->request->sector / (s_size >> 9); if (this_count > 0xffff) { this_count = 0xffff; @@ -424,13 +409,17 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) SCpnt->allowed = MAX_RETRIES; 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. */ - ret = BLKPREP_OK; - out: - return scsi_prep_return(q, rq, ret); + return 1; } static int sr_block_open(struct inode *inode, struct file *file) @@ -601,7 +590,6 @@ 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/trunk/drivers/scsi/sun3_NCR5380.c b/trunk/drivers/scsi/sun3_NCR5380.c index dc15a22105f7..98e3fe10c1dc 100644 --- a/trunk/drivers/scsi/sun3_NCR5380.c +++ b/trunk/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->scsi_done(cmd); + cmd->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->scsi_done(cmd); + cmd->done(cmd); /* XXX - need to source or sink data here, as appropriate */ } else { #ifdef REAL_DMA @@ -2254,21 +2254,25 @@ 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/trunk/drivers/scsi/tmscsim.c b/trunk/drivers/scsi/tmscsim.c index 5c72ca31a47a..5db1520f8ba9 100644 --- a/trunk/drivers/scsi/tmscsim.c +++ b/trunk/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->serial_number, pSRB, tag[1])); + DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for Cmd %li (SRB %p), block tag %02x\n", scmd->pid, 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->serial_number, pSRB)); + DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", disc_allowed ? "" : "o", scmd->pid, 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->serial_number, scmd->device->id, scmd->device->lun)); + scmd->pid, 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->serial_number)); + pSRB, pcmd->pid)); 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->serial_number, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, 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->serial_number, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->device->id, pcmd->device->lun)); pSRB->TotalXferredLen = 0; SET_RES_DID(pcmd->result, DID_SOFT_ERROR); } @@ -1803,7 +1803,7 @@ dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* /* Add to free list */ dc390_Free_insert (pACB, pSRB); - DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->serial_number)); + DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid)); 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->serial_number); + "DC390: Abort command (pid %li)\n", cmd->pid); /* 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->serial_number); + printk(KERN_INFO "DC390: Aborted pid %li\n", cmd->pid); return FAILED; } diff --git a/trunk/drivers/scsi/u14-34f.c b/trunk/drivers/scsi/u14-34f.c index fc9f51818e8f..9e8232a1f169 100644 --- a/trunk/drivers/scsi/u14-34f.c +++ b/trunk/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->serial_number, SCpnt); + BN(j), SCpnt->pid, 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->serial_number); + SCpnt->device->lun, SCpnt->pid); 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->serial_number); + "qcomm, pid %ld, adapter busy.\n", SCpnt->pid); 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->serial_number); + SCarg->pid); return SUCCESS; } i = *(unsigned int *)SCarg->host_scribble; scmd_printk(KERN_INFO, SCarg, "abort, mbox %d, pid %ld.\n", - i, SCarg->serial_number); + i, SCarg->pid); 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->serial_number); + BN(j), i, SCarg->pid); 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->serial_number); + scmd_printk(KERN_INFO, SCarg, "reset, enter, pid %ld.\n", SCarg->pid); spin_lock_irq(sh[j]->host_lock); if (SCarg->host_scribble == NULL) - printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->serial_number); + printk("%s: reset, pid %ld inactive.\n", BN(j), SCarg->pid); 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->serial_number); + BN(j), i, SCpnt->pid); } else { HD(j)->cp_stat[i] = IN_RESET; printk("%s: reset, mbox %d in reset, pid %ld.\n", - BN(j), i, SCpnt->serial_number); + BN(j), i, SCpnt->pid); } 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->serial_number); + BN(j), i, SCpnt->pid); } 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->serial_number); + BN(j), i, SCpnt->pid); } 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->serial_number); + if (arg_done) printk("%s: reset, exit, pid %ld done.\n", BN(j), SCarg->pid); 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->serial_number; + ll[n] = SCpnt->request->nr_sectors; pl[n] = SCpnt->pid; 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->serial_number, k, flushcount, n_ready, + SCpnt->lun, SCpnt->pid, 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->serial_number, k); + SCpnt->pid, 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->serial_number, SCpnt); + SCpnt->pid, SCpnt); if (*(unsigned int *)SCpnt->host_scribble != i) panic("%s: ihdlr, mbox %d, pid %ld, index mismatch %d.\n", - BN(j), i, SCpnt->serial_number, *(unsigned int *)SCpnt->host_scribble); + BN(j), i, SCpnt->pid, *(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->serial_number, spp->target_status, + SCpnt->pid, 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->serial_number) HD(j)->retries = 0; + if (HD(j)->last_retried_pid == SCpnt->pid) 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->serial_number; + HD(j)->last_retried_pid = SCpnt->pid; } 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->serial_number, + i, spp->adapter_status, spp->target_status, SCpnt->pid, reg, HD(j)->iocount); unmap_dma(i, j); diff --git a/trunk/drivers/scsi/wd33c93.c b/trunk/drivers/scsi/wd33c93.c index 0e8e642fd3b0..b92ff047af38 100644 --- a/trunk/drivers/scsi/wd33c93.c +++ b/trunk/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->serial_number)) + printk("Q-%d-%02x-%ld( ", cmd->device->id, cmd->cmnd[0], cmd->pid)) /* 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->serial_number)) + DB(DB_QUEUE_COMMAND, printk(")Q-%ld ", cmd->pid)) 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->serial_number)) + printk("%s%ld)EX-2 ", (cmd->SCp.phase) ? "d:" : "", cmd->pid)) } 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->serial_number)) + DB(DB_INTR, printk("CMND-%02x,%ld", cmd->cmnd[0], cmd->pid)) 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->serial_number)) + DB(DB_INTR, printk("CCMP-%ld", cmd->pid)) 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->serial_number)) + DB(DB_INTR, printk("SX-DONE-%ld", cmd->pid)) 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->serial_number); + asr, sr, phs, cmd->pid); 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->serial_number)) + DB(DB_INTR, printk("UNEXP_DISC-%ld", cmd->pid)) 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->serial_number)) + DB(DB_INTR, printk("DISC-%ld", cmd->pid)) 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->serial_number)) + DB(DB_INTR, printk("-%ld", cmd->pid)) 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->serial_number); + instance->host_no, cmd->pid); 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->serial_number); + instance->host_no, cmd->pid); 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->serial_number); + instance->host_no, cmd->pid); 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->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->pid, 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->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->pid, 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->serial_number, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); + cmd->pid, cmd->device->id, cmd->device->lun, cmd->cmnd[0]); strcat(bp, tbuf); cmd = (struct scsi_cmnd *) cmd->host_scribble; } diff --git a/trunk/drivers/scsi/zorro7xx.c b/trunk/drivers/scsi/zorro7xx.c index ac67394c7373..c822debc2668 100644 --- a/trunk/drivers/scsi/zorro7xx.c +++ b/trunk/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; + struct Scsi_Host * host = NULL; struct NCR_700_Host_Parameters *hostdata; struct zorro_driver_data *zdd; unsigned long board, ioaddr; @@ -89,12 +89,14 @@ static int __devinit zorro7xx_init_one(struct zorro_dev *z, return -EBUSY; } - hostdata = kzalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); - if (!hostdata) { + hostdata = kmalloc(sizeof(struct NCR_700_Host_Parameters), GFP_KERNEL); + if (hostdata == NULL) { 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/trunk/drivers/usb/image/microtek.c b/trunk/drivers/usb/image/microtek.c index e7d982a71548..768b2c11a231 100644 --- a/trunk/drivers/usb/image/microtek.c +++ b/trunk/drivers/usb/image/microtek.c @@ -446,8 +446,7 @@ static void mts_data_done( struct urb* transfer ) MTS_INT_INIT(); if ( context->data_length != transfer->actual_length ) { - scsi_set_resid(context->srb, context->data_length - - transfer->actual_length); + context->srb->resid = context->data_length - transfer->actual_length; } else if ( unlikely(status) ) { context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; } @@ -491,8 +490,7 @@ static void mts_command_done( struct urb *transfer ) context->data_pipe, context->data, context->data_length, - scsi_sg_count(context->srb) > 1 ? - mts_do_sg : mts_data_done); + context->srb->use_sg > 1 ? mts_do_sg : mts_data_done); } else { mts_get_status(transfer); } @@ -507,23 +505,21 @@ 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, - scsi_sg_count(context->srb)); + MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg); if (unlikely(status)) { context->srb->result = (status == -ENOENT ? DID_ABORT : DID_ERROR)<<16; mts_transfer_cleanup(transfer); } - sg = scsi_sglist(context->srb); + sg = context->srb->request_buffer; 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 == scsi_sg_count(context->srb) ? - mts_data_done : mts_do_sg); + context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg); return; } @@ -551,12 +547,20 @@ mts_build_transfer_context(struct scsi_cmnd *srb, struct mts_desc* desc) desc->context.srb = srb; desc->context.fragment = 0; - if (!scsi_bufflen(srb)) { - desc->context.data = NULL; - desc->context.data_length = 0; - return; + 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); + } } else { - sg = scsi_sglist(srb); + MTS_DEBUG("Using scatter/gather\n"); + sg = srb->request_buffer; desc->context.data = page_address(sg[0].page) + sg[0].offset; desc->context.data_length = sg[0].length; } diff --git a/trunk/drivers/usb/storage/transport.c b/trunk/drivers/usb/storage/transport.c index c646750ccc30..323293a3e61f 100644 --- a/trunk/drivers/usb/storage/transport.c +++ b/trunk/drivers/usb/storage/transport.c @@ -50,7 +50,7 @@ #include #include -#include +#include #include #include "usb.h" @@ -580,11 +580,25 @@ 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; - struct scsi_eh_save ses; + 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; US_DEBUGP("Issuing auto-REQUEST_SENSE\n"); - scsi_eh_prep_cmnd(srb, &ses, NULL, 0, US_SENSE_SIZE); + /* 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; /* FIXME: we must do the protocol translation here */ if (us->subclass == US_SC_RBC || us->subclass == US_SC_SCSI) @@ -592,12 +606,36 @@ 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 */ - scsi_eh_restore_cmnd(srb, &ses); + 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); if (test_bit(US_FLIDX_TIMED_OUT, &us->flags)) { US_DEBUGP("-- auto-sense aborted\n"); diff --git a/trunk/fs/nfsd/nfs3xdr.c b/trunk/fs/nfsd/nfs3xdr.c index 2d116d2298f8..10f6e7dcf633 100644 --- a/trunk/fs/nfsd/nfs3xdr.c +++ b/trunk/fs/nfsd/nfs3xdr.c @@ -174,6 +174,9 @@ 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); @@ -188,9 +191,10 @@ 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, stat->ino); + p = xdr_encode_hyper(p, (u64) stat->ino); p = encode_time3(p, &stat->atime); - p = encode_time3(p, &stat->mtime); + lease_get_mtime(dentry->d_inode, &time); + p = encode_time3(p, &time); p = encode_time3(p, &stat->ctime); return p; @@ -199,9 +203,31 @@ 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; - return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr); + + *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; } /* @@ -220,7 +246,6 @@ 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); } } @@ -259,23 +284,6 @@ 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 @@ -635,11 +643,8 @@ int nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p, struct nfsd3_attrstat *resp) { - if (resp->status == 0) { - lease_get_mtime(resp->fh.fh_dentry->d_inode, - &resp->stat.mtime); + if (resp->status == 0) p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat); - } return xdr_ressize_check(rqstp, p); } @@ -797,7 +802,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, u64 ino) + int namlen, ino_t ino) { *p++ = xdr_one; /* mark entry present */ p = xdr_encode_hyper(p, ino); /* file id */ @@ -868,7 +873,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, u64 ino, unsigned int d_type, int plus) + loff_t offset, ino_t ino, unsigned int d_type, int plus) { struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres, common); diff --git a/trunk/fs/nfsd/nfs4callback.c b/trunk/fs/nfsd/nfs4callback.c index 9d536a8cb379..31d6633c7fe4 100644 --- a/trunk/fs/nfsd/nfs4callback.c +++ b/trunk/fs/nfsd/nfs4callback.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include #include @@ -344,28 +343,26 @@ static struct rpc_version * nfs_cb_version[] = { &nfs_cb_version4, }; -/* Reference counting, callback cleanup, etc., all look racy as heck. - * And why is cb_set an atomic? */ - -static int do_probe_callback(void *data) +/* + * Use the SETCLIENTID credential + */ +static struct rpc_cred * +nfsd4_lookupcred(struct nfs4_client *clp, int taskflags) { - 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; + 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; } /* @@ -393,7 +390,11 @@ nfsd4_probe_callback(struct nfs4_client *clp) .authflavor = RPC_AUTH_UNIX, /* XXX: need AUTH_GSS... */ .flags = (RPC_CLNT_CREATE_NOPING), }; - struct task_struct *t; + struct rpc_message msg = { + .rpc_proc = &nfs4_cb_procedures[NFSPROC4_CLNT_CB_NULL], + .rpc_argp = clp, + }; + int status; if (atomic_read(&cb->cb_set)) return; @@ -425,11 +426,16 @@ nfsd4_probe_callback(struct nfs4_client *clp) /* the task holds a reference to the nfs4_client struct */ atomic_inc(&clp->cl_count); - t = kthread_run(do_probe_callback, clp, "nfs4_cb_probe"); - - if (IS_ERR(t)) + 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); + if (status != 0) { + dprintk("NFSD: asynchronous NFSPROC4_CB_NULL failed!\n"); + goto out_release_clp; + } return; out_release_clp: @@ -441,6 +447,30 @@ nfsd4_probe_callback(struct nfs4_client *clp) (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. @@ -461,6 +491,10 @@ 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; @@ -481,12 +515,13 @@ 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/trunk/fs/nfsd/nfs4idmap.c b/trunk/fs/nfsd/nfs4idmap.c index 4c0c683ce07a..2ccffde81b84 100644 --- a/trunk/fs/nfsd/nfs4idmap.c +++ b/trunk/fs/nfsd/nfs4idmap.c @@ -207,7 +207,6 @@ 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') @@ -249,11 +248,10 @@ idtoname_parse(struct cache_detail *cd, char *buf, int buflen) goto out; /* Name */ - error = -EINVAL; - len = qword_get(&buf, buf1, PAGE_SIZE); - if (len < 0) + error = qword_get(&buf, buf1, PAGE_SIZE); + if (error == -EINVAL) goto out; - if (len == 0) + if (error == -ENOENT) set_bit(CACHE_NEGATIVE, &ent.h.flags); else { if (error >= IDMAP_NAMESZ) { diff --git a/trunk/fs/nfsd/nfs4proc.c b/trunk/fs/nfsd/nfs4proc.c index 18ead1790bb3..29b7e63cb32c 100644 --- a/trunk/fs/nfsd/nfs4proc.c +++ b/trunk/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; - dprintk("NFSD: unsupported OPEN claim type %d\n", + printk("NFSD: unsupported OPEN claim type %d\n", open->op_claim_type); status = nfserr_notsupp; goto out; default: - dprintk("NFSD: Invalid OPEN claim type %d\n", + printk("NFSD: Invalid OPEN claim type %d\n", open->op_claim_type); status = nfserr_inval; goto out; diff --git a/trunk/fs/nfsd/nfs4state.c b/trunk/fs/nfsd/nfs4state.c index 6f182d25793d..3f559700788f 100644 --- a/trunk/fs/nfsd/nfs4state.c +++ b/trunk/fs/nfsd/nfs4state.c @@ -358,22 +358,9 @@ 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); @@ -387,6 +374,18 @@ put_nfs4_client(struct nfs4_client *clp) free_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) { @@ -397,6 +396,8 @@ 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)) { @@ -461,28 +462,26 @@ 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 -same_verf(nfs4_verifier *v1, nfs4_verifier *v2) -{ - return 0 == memcmp(v1->data, v2->data, sizeof(v1->data)); +cmp_verf(nfs4_verifier *v1, nfs4_verifier *v2) { + return(!memcmp(v1->data,v2->data,sizeof(v1->data))); } static int -same_clid(clientid_t *cl1, clientid_t *cl2) -{ - return (cl1->cl_boot == cl2->cl_boot) && (cl1->cl_id == cl2->cl_id); +cmp_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 -same_creds(struct svc_cred *cr1, struct svc_cred *cr2) -{ - return cr1->cr_uid == cr2->cr_uid; +cmp_creds(struct svc_cred *cr1, struct svc_cred *cr2){ + return(cr1->cr_uid == cr2->cr_uid); + } static void @@ -508,7 +507,7 @@ check_name(struct xdr_netobj name) { if (name.len == 0) return 0; if (name.len > NFS4_OPAQUE_LIMIT) { - dprintk("NFSD: check_name: name too long(%d)!\n", name.len); + printk("NFSD: check_name: name too long(%d)!\n", name.len); return 0; } return 1; @@ -547,7 +546,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 (same_clid(&clp->cl_clientid, clid)) + if (cmp_clid(&clp->cl_clientid, clid)) return clp; } return NULL; @@ -560,7 +559,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 (same_clid(&clp->cl_clientid, clid)) + if (cmp_clid(&clp->cl_clientid, clid)) return clp; } return NULL; @@ -754,7 +753,7 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, * or different ip_address */ status = nfserr_clid_inuse; - if (!same_creds(&conf->cl_cred, &rqstp->rq_cred) + if (!cmp_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)); @@ -773,8 +772,14 @@ 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); - } else if (same_verf(&conf->cl_verifier, &clverifier)) { + gen_confirm(new); + gen_callback(new, setclid); + add_to_unconfirmed(new, strhashval); + } else if (cmp_verf(&conf->cl_verifier, &clverifier)) { /* * CASE 1: * cl_name match, confirmed, principal match @@ -799,7 +804,13 @@ 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: @@ -812,8 +823,14 @@ 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); - } else if (!same_verf(&conf->cl_confirm, &unconf->cl_confirm)) { + gen_confirm(new); + gen_callback(new, setclid); + add_to_unconfirmed(new, strhashval); + } else if (!cmp_verf(&conf->cl_confirm, &unconf->cl_confirm)) { /* * CASE3: * confirmed found (name, principal match) @@ -833,19 +850,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)); @@ -893,16 +910,16 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, goto out; if ((conf && unconf) && - (same_verf(&unconf->cl_confirm, &confirm)) && - (same_verf(&conf->cl_verifier, &unconf->cl_verifier)) && + (cmp_verf(&unconf->cl_confirm, &confirm)) && + (cmp_verf(&conf->cl_verifier, &unconf->cl_verifier)) && (same_name(conf->cl_recdir,unconf->cl_recdir)) && - (!same_verf(&conf->cl_confirm, &unconf->cl_confirm))) { + (!cmp_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 (!same_creds(&conf->cl_cred, &unconf->cl_cred)) + if (!cmp_creds(&conf->cl_cred, &unconf->cl_cred)) status = nfserr_clid_inuse; else { /* XXX: We just turn off callbacks until we can handle @@ -916,7 +933,7 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, } } else if ((conf && !unconf) || ((conf && unconf) && - (!same_verf(&conf->cl_verifier, &unconf->cl_verifier) || + (!cmp_verf(&conf->cl_verifier, &unconf->cl_verifier) || !same_name(conf->cl_recdir, unconf->cl_recdir)))) { /* CASE 2: * conf record that matches input clientid. @@ -924,18 +941,18 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, * unconf->cl_name or unconf->cl_verifier don't match the * conf record. */ - if (!same_creds(&conf->cl_cred, &rqstp->rq_cred)) + if (!cmp_creds(&conf->cl_cred,&rqstp->rq_cred)) status = nfserr_clid_inuse; else status = nfs_ok; } else if (!conf && unconf - && same_verf(&unconf->cl_confirm, &confirm)) { + && cmp_verf(&unconf->cl_confirm, &confirm)) { /* CASE 3: * conf record not found. * unconf record found. * unconf->cl_confirm matches input confirm */ - if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred)) { + if (!cmp_creds(&unconf->cl_cred, &rqstp->rq_cred)) { status = nfserr_clid_inuse; } else { unsigned int hash = @@ -950,8 +967,8 @@ nfsd4_setclientid_confirm(struct svc_rqst *rqstp, conf = unconf; status = nfs_ok; } - } else if ((!conf || (conf && !same_verf(&conf->cl_confirm, &confirm))) - && (!unconf || (unconf && !same_verf(&unconf->cl_confirm, + } else if ((!conf || (conf && !cmp_verf(&conf->cl_confirm, &confirm))) + && (!unconf || (unconf && !cmp_verf(&unconf->cl_confirm, &confirm)))) { /* CASE 4: * conf record not found, or if conf, conf->cl_confirm does not @@ -1002,7 +1019,7 @@ nfsd4_free_slab(struct kmem_cache **slab) *slab = NULL; } -void +static void nfsd4_free_slabs(void) { nfsd4_free_slab(&stateowner_slab); @@ -1190,12 +1207,10 @@ move_to_close_lru(struct nfs4_stateowner *sop) } static int -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); +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)); } static struct nfs4_stateowner * @@ -1204,7 +1219,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 (same_owner_str(so, &open->op_owner, &open->op_clientid)) + if (cmp_owner_str(so, &open->op_owner, &open->op_clientid)) return so; } return NULL; @@ -1345,7 +1360,6 @@ 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); @@ -1354,12 +1368,8 @@ void nfsd_break_deleg_cb(struct file_lock *fl) /* only place dl_time is set. protected by lock_kernel*/ dp->dl_time = get_seconds(); - /* - * 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; + /* XXX need to merge NFSD_LEASE_TIME with fs/locks.c:lease_break_time */ + fl->fl_break_time = jiffies + NFSD_LEASE_TIME * HZ; t = kthread_run(do_recall, dp, "%s", "nfs4_cb_recall"); if (IS_ERR(t)) { @@ -1368,7 +1378,6 @@ 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); } } @@ -1729,7 +1738,7 @@ nfs4_open_delegation(struct svc_fh *fh, struct nfsd4_open *open, struct nfs4_sta if (open->op_claim_type == NFS4_OPEN_CLAIM_PREVIOUS && flag == NFS4_OPEN_DELEGATE_NONE && open->op_delegate_type != NFS4_OPEN_DELEGATE_NONE) - dprintk("NFSD: WARNING: refusing delegation reclaim\n"); + printk("NFSD: WARNING: refusing delegation reclaim\n"); open->op_delegate_type = flag; } @@ -2138,7 +2147,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei *sopp = NULL; if (ZERO_STATEID(stateid) || ONE_STATEID(stateid)) { - dprintk("NFSD: preprocess_seqid_op: magic stateid!\n"); + printk("NFSD: preprocess_seqid_op: magic stateid!\n"); return nfserr_bad_stateid; } @@ -2172,24 +2181,25 @@ 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 (!same_clid(&clp->cl_clientid, lockclid)) + if (!sop->so_is_open_owner) 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; + if (!cmp_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; } + } if ((flags & CHECK_FH) && nfs4_check_fh(current_fh, stp)) { - dprintk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); + printk("NFSD: preprocess_seqid_op: fh-stateid mismatch!\n"); return nfserr_bad_stateid; } @@ -2205,22 +2215,22 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei goto check_replay; if (sop->so_confirmed && flags & CONFIRM) { - dprintk("NFSD: preprocess_seqid_op: expected" + printk("NFSD: preprocess_seqid_op: expected" " unconfirmed stateowner!\n"); return nfserr_bad_stateid; } if (!sop->so_confirmed && !(flags & CONFIRM)) { - dprintk("NFSD: preprocess_seqid_op: stateowner not" + printk("NFSD: preprocess_seqid_op: stateowner not" " confirmed yet!\n"); return nfserr_bad_stateid; } if (stateid->si_generation > stp->st_stateid.si_generation) { - dprintk("NFSD: preprocess_seqid_op: future stateid?!\n"); + printk("NFSD: preprocess_seqid_op: future stateid?!\n"); return nfserr_bad_stateid; } if (stateid->si_generation < stp->st_stateid.si_generation) { - dprintk("NFSD: preprocess_seqid_op: old stateid!\n"); + printk("NFSD: preprocess_seqid_op: old stateid!\n"); return nfserr_old_stateid; } renew_client(sop->so_client); @@ -2232,7 +2242,7 @@ nfs4_preprocess_seqid_op(struct svc_fh *current_fh, u32 seqid, stateid_t *statei /* indicate replay to calling function */ return nfserr_replay_me; } - dprintk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", + printk("NFSD: preprocess_seqid_op: bad seqid (expected %d, got %d)\n", sop->so_seqid, seqid); *sopp = NULL; return nfserr_bad_seqid; @@ -2551,7 +2561,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 (same_owner_str(op, owner, clid)) + if (cmp_owner_str(op, owner, clid)) return op; } return NULL; @@ -2845,7 +2855,7 @@ nfsd4_lockt(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, file_lock.fl_type = F_WRLCK; break; default: - dprintk("NFSD: nfs4_lockt: bad lock type!\n"); + printk("NFSD: nfs4_lockt: bad lock type!\n"); status = nfserr_inval; goto out; } @@ -3015,7 +3025,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 (!same_owner_str(sop, owner, clid)) + if (!cmp_owner_str(sop, owner, clid)) continue; list_for_each_entry(stp, &sop->so_stateids, st_perstateowner) { @@ -3139,14 +3149,11 @@ nfs4_check_open_reclaim(clientid_t *clid) /* initialization to perform at module load time: */ -int +void nfs4_state_init(void) { - int i, status; + int i; - 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]); @@ -3175,7 +3182,6 @@ 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 @@ -3236,15 +3242,20 @@ __nfs4_state_start(void) set_max_delegations(); } -void +int nfs4_state_start(void) { + int status; + if (nfs4_init) - return; + return 0; + status = nfsd4_init_slabs(); + if (status) + return status; nfsd4_load_reboot_recovery_data(); __nfs4_state_start(); nfs4_init = 1; - return; + return 0; } int @@ -3302,6 +3313,7 @@ nfs4_state_shutdown(void) nfs4_lock_state(); nfs4_release_reclaim(); __nfs4_state_shutdown(); + nfsd4_free_slabs(); nfs4_unlock_state(); } diff --git a/trunk/fs/nfsd/nfs4xdr.c b/trunk/fs/nfsd/nfs4xdr.c index e15f2cf8ac15..8ef0964179bc 100644 --- a/trunk/fs/nfsd/nfs4xdr.c +++ b/trunk/fs/nfsd/nfs4xdr.c @@ -1475,8 +1475,7 @@ 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 | - FATTR4_WORD0_MAXNAME)) || + if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | FATTR4_WORD1_SPACE_TOTAL))) { err = vfs_statfs(dentry, &statfs); @@ -1680,7 +1679,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, if (bmval0 & FATTR4_WORD0_FILEID) { if ((buflen -= 8) < 0) goto out_resource; - WRITE64(stat.ino); + WRITE64((u64) stat.ino); } if (bmval0 & FATTR4_WORD0_FILES_AVAIL) { if ((buflen -= 8) < 0) @@ -1722,7 +1721,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, if (bmval0 & FATTR4_WORD0_MAXNAME) { if ((buflen -= 4) < 0) goto out_resource; - WRITE32(statfs.f_namelen); + WRITE32(~(u32) 0); } if (bmval0 & FATTR4_WORD0_MAXREAD) { if ((buflen -= 8) < 0) @@ -1822,15 +1821,16 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, 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; - 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); + 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); } *attrlenp = htonl((char *)p - (char *)attrlenp - 4); *countp = p - buffer; diff --git a/trunk/fs/nfsd/nfsctl.c b/trunk/fs/nfsd/nfsctl.c index 77dc9893b7ba..baac89d917ca 100644 --- a/trunk/fs/nfsd/nfsctl.c +++ b/trunk/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 uninitialized_var(maxsize); + int maxsize; char *mesg = buf; int len; struct auth_domain *dom; @@ -679,13 +679,11 @@ 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; @@ -714,7 +712,6 @@ 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/trunk/fs/nfsd/nfssvc.c b/trunk/fs/nfsd/nfssvc.c index 1190aeaa92be..a8c89ae4c743 100644 --- a/trunk/fs/nfsd/nfssvc.c +++ b/trunk/fs/nfsd/nfssvc.c @@ -349,7 +349,9 @@ nfsd_svc(unsigned short port, int nrservs) error = nfsd_racache_init(2*nrservs); if (error<0) goto out; - nfs4_state_start(); + error = nfs4_state_start(); + if (error<0) + goto out; nfsd_reset_versions(); @@ -544,8 +546,10 @@ 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; may be revisited later\n"); + dprintk("nfsd: Dropping request due to malloc failure!\n"); nfsd_cache_update(rqstp, RC_NOCACHE, NULL); return 0; } diff --git a/trunk/fs/nfsd/nfsxdr.c b/trunk/fs/nfsd/nfsxdr.c index 986f9b32083c..cb3e7fadb772 100644 --- a/trunk/fs/nfsd/nfsxdr.c +++ b/trunk/fs/nfsd/nfsxdr.c @@ -523,10 +523,6 @@ 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/trunk/fs/nfsd/vfs.c b/trunk/fs/nfsd/vfs.c index cec78c82b1f9..7867151ebb83 100644 --- a/trunk/fs/nfsd/vfs.c +++ b/trunk/fs/nfsd/vfs.c @@ -295,8 +295,7 @@ 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 @@ -309,33 +308,25 @@ 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. + 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" */ - 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; - } + 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/trunk/include/linux/hid.h b/trunk/include/linux/hid.h index edb8024d744b..55e51f9f76cb 100644 --- a/trunk/include/linux/hid.h +++ b/trunk/include/linux/hid.h @@ -29,6 +29,13 @@ * Vojtech Pavlik, Simunkova 1594, Prague 8, 182 00 Czech Republic */ +#include +#include +#include +#include +#include +#include + /* * USB HID (Human Interface Device) interface class code */ @@ -62,17 +69,6 @@ #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 -#include -#include -#include -#include -#include - /* * We parse each description item into this structure. Short items data * values are expanded to 32-bit signed int, long items contain a pointer @@ -315,6 +311,7 @@ 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 @@ -563,5 +560,4 @@ 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/trunk/include/linux/hidraw.h b/trunk/include/linux/hidraw.h index 0536f299f7ff..6676cd5e9954 100644 --- a/trunk/include/linux/hidraw.h +++ b/trunk/include/linux/hidraw.h @@ -15,11 +15,9 @@ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. */ -#include - struct hidraw_report_descriptor { __u32 size; - __u8 value[HID_MAX_DESCRIPTOR_SIZE]; + __u8 *value; }; struct hidraw_devinfo { @@ -42,6 +40,8 @@ struct hidraw_devinfo { /* kernel-only API declarations */ #ifdef __KERNEL__ +#include + struct hidraw { unsigned int minor; int exist; diff --git a/trunk/include/linux/nfsd/nfsd.h b/trunk/include/linux/nfsd/nfsd.h index 604a0d786bc6..e452256d3f72 100644 --- a/trunk/include/linux/nfsd/nfsd.h +++ b/trunk/include/linux/nfsd/nfsd.h @@ -153,21 +153,19 @@ extern int nfsd_max_blksize; */ #ifdef CONFIG_NFSD_V4 extern unsigned int max_delegations; -int nfs4_state_init(void); -void nfsd4_free_slabs(void); -void nfs4_state_start(void); +void nfs4_state_init(void); +int 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 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; } +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;} #endif /* diff --git a/trunk/include/linux/nfsd/nfsfh.h b/trunk/include/linux/nfsd/nfsfh.h index d1941cb965e9..11e568ee0eeb 100644 --- a/trunk/include/linux/nfsd/nfsfh.h +++ b/trunk/include/linux/nfsd/nfsfh.h @@ -150,7 +150,17 @@ typedef struct svc_fh { struct timespec fh_pre_ctime; /* ctime before oper */ /* Post-op attributes saved in fh_unlock */ - struct kstat fh_post_attr; /* full attrs after operation */ + 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 */ #endif /* CONFIG_NFSD_V3 */ } svc_fh; @@ -287,12 +297,36 @@ 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; } } -extern void fill_post_wcc(struct svc_fh *); +/* + * 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; +} #else #define fill_pre_wcc(ignored) #define fill_post_wcc(notused) diff --git a/trunk/include/linux/nfsd/xdr4.h b/trunk/include/linux/nfsd/xdr4.h index b0ddfb41c790..1b653267133a 100644 --- a/trunk/include/linux/nfsd/xdr4.h +++ b/trunk/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_attr.ctime.tv_sec; - cinfo->after_ctime_nsec = fhp->fh_post_attr.ctime.tv_nsec; + cinfo->after_ctime_sec = fhp->fh_post_ctime.tv_sec; + cinfo->after_ctime_nsec = fhp->fh_post_ctime.tv_nsec; } int nfs4svc_encode_voidres(struct svc_rqst *, __be32 *, void *); diff --git a/trunk/include/linux/pci_ids.h b/trunk/include/linux/pci_ids.h index 2aaf1c16ce98..87439ad94685 100644 --- a/trunk/include/linux/pci_ids.h +++ b/trunk/include/linux/pci_ids.h @@ -1467,8 +1467,6 @@ #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 @@ -2077,9 +2075,6 @@ #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/trunk/include/linux/sunrpc/cache.h b/trunk/include/linux/sunrpc/cache.h index bd7a6b0a87af..3699dff7db8f 100644 --- a/trunk/include/linux/sunrpc/cache.h +++ b/trunk/include/linux/sunrpc/cache.h @@ -136,6 +136,16 @@ 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/trunk/include/scsi/libsrp.h b/trunk/include/scsi/libsrp.h index ba615e4c1d7c..d143171896ae 100644 --- a/trunk/include/scsi/libsrp.h +++ b/trunk/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, u64); +extern int srp_cmd_queue(struct Scsi_Host *, struct srp_cmd *, void *, u64); extern int srp_transfer_data(struct scsi_cmnd *, struct srp_cmd *, srp_rdma_t, int, int); diff --git a/trunk/include/scsi/scsi_cmnd.h b/trunk/include/scsi/scsi_cmnd.h index 65ab5145a09b..53e170586c26 100644 --- a/trunk/include/scsi/scsi_cmnd.h +++ b/trunk/include/scsi/scsi_cmnd.h @@ -33,17 +33,20 @@ 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 is a bug for LLDDs to use this number - * for purposes other than printk (and even that is only useful - * for debugging). + * 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. */ 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 @@ -113,6 +116,7 @@ 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); @@ -120,6 +124,7 @@ 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/trunk/include/scsi/scsi_dbg.h b/trunk/include/scsi/scsi_dbg.h index e89844cc2cd3..5a43a4cd96c6 100644 --- a/trunk/include/scsi/scsi_dbg.h +++ b/trunk/include/scsi/scsi_dbg.h @@ -9,8 +9,6 @@ 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/trunk/include/scsi/scsi_driver.h b/trunk/include/scsi/scsi_driver.h index 1f5ca7f62116..3465f31a21c4 100644 --- a/trunk/include/scsi/scsi_driver.h +++ b/trunk/include/scsi/scsi_driver.h @@ -5,17 +5,14 @@ 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) @@ -28,9 +25,4 @@ 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/trunk/include/scsi/scsi_eh.h b/trunk/include/scsi/scsi_eh.h index 44224ba4dd90..c5c0f6762a01 100644 --- a/trunk/include/scsi/scsi_eh.h +++ b/trunk/include/scsi/scsi_eh.h @@ -1,7 +1,7 @@ #ifndef _SCSI_SCSI_EH_H #define _SCSI_SCSI_EH_H -#include +struct scsi_cmnd; struct scsi_device; struct Scsi_Host; @@ -65,25 +65,4 @@ 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/trunk/include/scsi/scsi_host.h b/trunk/include/scsi/scsi_host.h index 7d210cd6c38d..3b8a6a85c2f8 100644 --- a/trunk/include/scsi/scsi_host.h +++ b/trunk/include/scsi/scsi_host.h @@ -32,9 +32,6 @@ 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 @@ -148,6 +145,9 @@ 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 @@ -407,11 +407,6 @@ 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. */ @@ -580,9 +575,8 @@ struct Scsi_Host { * Used to assign serial numbers to the cmds. * Protected by the host lock. */ - unsigned long cmd_serial_number; + unsigned long cmd_serial_number, cmd_pid; - unsigned active_mode:2; unsigned unchecked_isa_dma:1; unsigned use_clustering:1; unsigned use_blk_tcq:1; diff --git a/trunk/include/scsi/scsi_tgt.h b/trunk/include/scsi/scsi_tgt.h index d0fefb96158f..4f4427937af2 100644 --- a/trunk/include/scsi/scsi_tgt.h +++ b/trunk/include/scsi/scsi_tgt.h @@ -11,11 +11,9 @@ 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 *, u64, struct scsi_lun *, u64); -extern int scsi_tgt_tsk_mgmt_request(struct Scsi_Host *, u64, int, u64, - struct scsi_lun *, void *); +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 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/trunk/include/scsi/scsi_tgt_if.h b/trunk/include/scsi/scsi_tgt_if.h index f2ee7c238a45..4cf9dff29a2f 100644 --- a/trunk/include/scsi/scsi_tgt_if.h +++ b/trunk/include/scsi/scsi_tgt_if.h @@ -23,15 +23,13 @@ #define __SCSI_TARGET_IF_H /* user -> kernel */ -#define TGT_UEVENT_CMD_RSP 0x0001 -#define TGT_UEVENT_IT_NEXUS_RSP 0x0002 -#define TGT_UEVENT_TSK_MGMT_RSP 0x0003 +#define TGT_UEVENT_CMD_RSP 0x0001 +#define TGT_UEVENT_TSK_MGMT_RSP 0x0002 /* kernel -> user */ -#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 +#define TGT_KEVENT_CMD_REQ 0x1001 +#define TGT_KEVENT_CMD_DONE 0x1002 +#define TGT_KEVENT_TSK_MGMT_REQ 0x1003 struct tgt_event_hdr { uint16_t version; @@ -48,7 +46,6 @@ struct tgt_event { struct { int host_no; int result; - aligned_u64 itn_id; aligned_u64 tag; aligned_u64 uaddr; aligned_u64 sense_uaddr; @@ -58,22 +55,15 @@ struct tgt_event { } cmd_rsp; struct { int host_no; - int result; - aligned_u64 itn_id; aligned_u64 mid; + int result; } 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; @@ -81,25 +71,16 @@ struct tgt_event { } cmd_req; struct { int host_no; - int result; - aligned_u64 itn_id; aligned_u64 tag; + int result; } 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/trunk/include/scsi/scsi_transport.h b/trunk/include/scsi/scsi_transport.h index 0dfef752f0e2..3c18baa65a72 100644 --- a/trunk/include/scsi/scsi_transport.h +++ b/trunk/include/scsi/scsi_transport.h @@ -65,18 +65,6 @@ 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/trunk/include/scsi/scsi_transport_fc.h b/trunk/include/scsi/scsi_transport_fc.h index e466d886e192..a0d80bcaa93d 100644 --- a/trunk/include/scsi/scsi_transport_fc.h +++ b/trunk/include/scsi/scsi_transport_fc.h @@ -589,10 +589,6 @@ 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; @@ -636,8 +632,6 @@ 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/trunk/include/scsi/scsi_transport_iscsi.h b/trunk/include/scsi/scsi_transport_iscsi.h index 7ff6199cbd55..706c0cd36c14 100644 --- a/trunk/include/scsi/scsi_transport_iscsi.h +++ b/trunk/include/scsi/scsi_transport_iscsi.h @@ -24,8 +24,6 @@ #define SCSI_TRANSPORT_ISCSI_H #include -#include -#include #include struct scsi_transport_template; diff --git a/trunk/include/scsi/scsi_transport_srp.h b/trunk/include/scsi/scsi_transport_srp.h deleted file mode 100644 index 9c60ca1c08c5..000000000000 --- a/trunk/include/scsi/scsi_transport_srp.h +++ /dev/null @@ -1,39 +0,0 @@ -#ifndef SCSI_TRANSPORT_SRP_H -#define SCSI_TRANSPORT_SRP_H - -#include -#include -#include - -#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/trunk/include/scsi/sd.h b/trunk/include/scsi/sd.h index f7513313ef0d..ce02ad1f5185 100644 --- a/trunk/include/scsi/sd.h +++ b/trunk/include/scsi/sd.h @@ -47,6 +47,20 @@ 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/trunk/kernel/sched.c b/trunk/kernel/sched.c index 6c10fa796ca0..2054e557d0d2 100644 --- a/trunk/kernel/sched.c +++ b/trunk/kernel/sched.c @@ -1688,10 +1688,8 @@ void fastcall wake_up_new_task(struct task_struct *p, unsigned long clone_flags) 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 (task_cpu(p) != this_cpu || !p->sched_class->task_new || + !current->se.on_rq) { activate_task(rq, p, 0); } else { /* diff --git a/trunk/net/sunrpc/auth_gss/svcauth_gss.c b/trunk/net/sunrpc/auth_gss/svcauth_gss.c index 73940df6c460..7da7050f06c3 100644 --- a/trunk/net/sunrpc/auth_gss/svcauth_gss.c +++ b/trunk/net/sunrpc/auth_gss/svcauth_gss.c @@ -631,8 +631,7 @@ 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,78 +960,6 @@ gss_write_init_verf(struct svc_rqst *rqstp, struct rsi *rsip) return rc; } -/* - * 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 @@ -1047,9 +974,11 @@ 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; @@ -1094,14 +1023,30 @@ 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: - return svcauth_gss_handle_init(rqstp, gc, authp); + 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; 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) @@ -1122,6 +1067,51 @@ 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; @@ -1168,7 +1158,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) goto out; } auth_err: - /* Restore write pointer to its original value: */ + /* Restore write pointer to original value: */ xdr_ressize_check(rqstp, reject_stat); ret = SVC_DENIED; goto out; diff --git a/trunk/net/sunrpc/svc.c b/trunk/net/sunrpc/svc.c index a4a6bf7deaa4..55ea6df069de 100644 --- a/trunk/net/sunrpc/svc.c +++ b/trunk/net/sunrpc/svc.c @@ -776,30 +776,6 @@ svc_register(struct svc_serv *serv, int proto, unsigned short port) return error; } -/* - * 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. */ @@ -987,13 +963,14 @@ svc_process(struct svc_rqst *rqstp) return 0; err_short_len: - svc_printk(rqstp, "short len %Zd, dropping request\n", - argv->iov_len); + if (net_ratelimit()) + printk("svc: short len %Zd, dropping request\n", argv->iov_len); goto dropit; /* drop request */ err_bad_dir: - svc_printk(rqstp, "bad direction %d, dropping request\n", dir); + if (net_ratelimit()) + printk("svc: bad direction %d, dropping request\n", dir); serv->sv_stats->rpcbadfmt++; goto dropit; /* drop request */ @@ -1023,7 +1000,8 @@ svc_process(struct svc_rqst *rqstp) goto sendit; err_bad_vers: - svc_printk(rqstp, "unknown version (%d for prog %d, %s)\n", + if (net_ratelimit()) + printk("svc: unknown version (%d for prog %d, %s)\n", vers, prog, progp->pg_name); serv->sv_stats->rpcbadfmt++; @@ -1033,14 +1011,16 @@ svc_process(struct svc_rqst *rqstp) goto sendit; err_bad_proc: - svc_printk(rqstp, "unknown procedure (%d)\n", proc); + if (net_ratelimit()) + printk("svc: unknown procedure (%d)\n", proc); serv->sv_stats->rpcbadfmt++; svc_putnl(resv, RPC_PROC_UNAVAIL); goto sendit; err_garbage: - svc_printk(rqstp, "failed to decode args\n"); + if (net_ratelimit()) + printk("svc: failed to decode args\n"); rpc_stat = rpc_garbage_args; err_bad: