ia64/xen-unstable

changeset 227:ef5e27f96b09

bitkeeper revision 1.85 (3e56416dqUx5ejRHgvOG3eSEByO2Fg)

Many files:
new file
Sync of SMH's new SCSI world with latest repository.
author kaf24@labyrinth.cl.cam.ac.uk
date Fri Feb 21 15:10:37 2003 +0000 (2003-02-21)
parents 8554489b6ce4
children 5636f106ea84
files .rootkeys xen-2.4.16/Rules.mk xen-2.4.16/drivers/Makefile xen-2.4.16/drivers/scsi/Makefile xen-2.4.16/drivers/scsi/aacraid/Makefile xen-2.4.16/drivers/scsi/aacraid/README xen-2.4.16/drivers/scsi/aacraid/TODO xen-2.4.16/drivers/scsi/aacraid/aachba.c xen-2.4.16/drivers/scsi/aacraid/aacraid.h xen-2.4.16/drivers/scsi/aacraid/commctrl.c xen-2.4.16/drivers/scsi/aacraid/comminit.c xen-2.4.16/drivers/scsi/aacraid/commsup.c xen-2.4.16/drivers/scsi/aacraid/dpcsup.c xen-2.4.16/drivers/scsi/aacraid/linit.c xen-2.4.16/drivers/scsi/aacraid/rx.c xen-2.4.16/drivers/scsi/aacraid/sa.c xen-2.4.16/drivers/scsi/constants.c xen-2.4.16/drivers/scsi/hosts.c xen-2.4.16/drivers/scsi/hosts.h xen-2.4.16/drivers/scsi/scsi.c xen-2.4.16/drivers/scsi/scsi.h xen-2.4.16/drivers/scsi/scsi_dma.c xen-2.4.16/drivers/scsi/scsi_error.c xen-2.4.16/drivers/scsi/scsi_ioctl.c xen-2.4.16/drivers/scsi/scsi_lib.c xen-2.4.16/drivers/scsi/scsi_merge.c xen-2.4.16/drivers/scsi/scsi_module.c.inc xen-2.4.16/drivers/scsi/scsi_proc.c xen-2.4.16/drivers/scsi/scsi_queue.c xen-2.4.16/drivers/scsi/scsi_scan.c xen-2.4.16/drivers/scsi/scsi_syms.c xen-2.4.16/drivers/scsi/scsicam.c xen-2.4.16/drivers/scsi/sd.c xen-2.4.16/include/asm-i386/dma.h xen-2.4.16/include/xeno/interrupt.h
line diff
     1.1 --- a/.rootkeys	Fri Feb 21 14:25:47 2003 +0000
     1.2 +++ b/.rootkeys	Fri Feb 21 15:10:37 2003 +0000
     1.3 @@ -122,7 +122,21 @@ 3ddb79bfl1H1arbB0pzAEC2uPmY_3g xen-2.4.1
     1.4  3ddb79bfJaf0bkE1Y67bnll8-kjEPg xen-2.4.16/drivers/pci/setup-res.c
     1.5  3ddb79bfIcCWJsBDNcQQE3ok2Azn-Q xen-2.4.16/drivers/pci/syscall.c
     1.6  3ddb79be3kwzyKagpMHGoXZFdan7dg xen-2.4.16/drivers/scsi/Makefile
     1.7 +3e564137sVLmo7rTnKLNzLSCvuUz8g xen-2.4.16/drivers/scsi/aacraid/Makefile
     1.8 +3e5641379FXvLDjV-0OrRNOBTwL_Lw xen-2.4.16/drivers/scsi/aacraid/README
     1.9 +3e564137MAHzHSRYoWGNmIferNjFVA xen-2.4.16/drivers/scsi/aacraid/TODO
    1.10 +3e564137QLUGVlcwTpnMYATKahDmCg xen-2.4.16/drivers/scsi/aacraid/aachba.c
    1.11 +3e564137Tm_t6rMYyxFtnY9yo_abMg xen-2.4.16/drivers/scsi/aacraid/aacraid.h
    1.12 +3e564137AtfQtRJZiS9B00To0AmKSg xen-2.4.16/drivers/scsi/aacraid/commctrl.c
    1.13 +3e564137a9aOGMOFgQ5CYQJBOD3DvQ xen-2.4.16/drivers/scsi/aacraid/comminit.c
    1.14 +3e564137fw_bPuKcvVi0qwntc_RB-Q xen-2.4.16/drivers/scsi/aacraid/commsup.c
    1.15 +3e564137iEHmY_e6xGZ7TLsjy5yS-g xen-2.4.16/drivers/scsi/aacraid/dpcsup.c
    1.16 +3e564137taxQbEVa39h3mEVLFxRydQ xen-2.4.16/drivers/scsi/aacraid/linit.c
    1.17 +3e564137vmALxpfK7vNINqEklSmQ1A xen-2.4.16/drivers/scsi/aacraid/rx.c
    1.18 +3e564137EuYUJgvqnOunPERWxnp_mw xen-2.4.16/drivers/scsi/aacraid/sa.c
    1.19 +3e56411aOLzeD5CRbuXquOrX0lRijw xen-2.4.16/drivers/scsi/constants.c
    1.20  3ddb79beXZxwKh7cGyPfr40bhDyRrA xen-2.4.16/drivers/scsi/constants.h
    1.21 +3e564120ZeinH9nf3IVSerB80T7dHg xen-2.4.16/drivers/scsi/hosts.c
    1.22  3ddb79beGiGljlTNq_kRnCBZECgC9Q xen-2.4.16/drivers/scsi/hosts.h
    1.23  3ddb79bexarQo1tQ541PPUyK9HXNDA xen-2.4.16/drivers/scsi/scsi.c
    1.24  3ddb79beBOiYxQUiWTHosepRlJyuGA xen-2.4.16/drivers/scsi/scsi.h
    1.25 @@ -132,6 +146,7 @@ 3ddb79bepDvUltYDsInaUsH9lII9Sw xen-2.4.1
    1.26  3ddb79berPStE_-ILQHgcl1BLDLywA xen-2.4.16/drivers/scsi/scsi_lib.c
    1.27  3ddb79beRXjB7_nNUbJMIRyjDmeByQ xen-2.4.16/drivers/scsi/scsi_merge.c
    1.28  3ddb79beGNb7Es1bATZAGsPZEu5F2Q xen-2.4.16/drivers/scsi/scsi_module.c
    1.29 +3e56412a_O2cnz-e36volrKvofGe-Q xen-2.4.16/drivers/scsi/scsi_module.c.inc
    1.30  3ddb79beZ--AZB0twliIm3qmQJO8Zg xen-2.4.16/drivers/scsi/scsi_obsolete.c
    1.31  3ddb79beQgG_st0eBZUX8AQI7kBkHA xen-2.4.16/drivers/scsi/scsi_obsolete.h
    1.32  3ddb79beK65cNRldY0CFGXjZ3-A74Q xen-2.4.16/drivers/scsi/scsi_proc.c
    1.33 @@ -152,6 +167,7 @@ 3ddb79c2ADvRmdexd9y3AYK9_NTx-Q xen-2.4.1
    1.34  3ddb79c2jFkPAZTDmU35L6IUssYMgQ xen-2.4.16/include/asm-i386/debugreg.h
    1.35  3ddb79c3r9-31dIsewPV3P3i8HALsQ xen-2.4.16/include/asm-i386/delay.h
    1.36  3ddb79c34BFiXjBJ_cCKB0aCsV1IDw xen-2.4.16/include/asm-i386/desc.h
    1.37 +3e564149UkU91RX7onzpCAmbj_IFjw xen-2.4.16/include/asm-i386/dma.h
    1.38  3e20b82fl1jmQiKdLy7fxMcutfpjWA xen-2.4.16/include/asm-i386/domain_page.h
    1.39  3ddb79c2O729EttZTYu1c8LcsUO_GQ xen-2.4.16/include/asm-i386/elf.h
    1.40  3ddb79c3NU8Zy40OTrq3D-i30Y3t4A xen-2.4.16/include/asm-i386/fixmap.h
     2.1 --- a/xen-2.4.16/Rules.mk	Fri Feb 21 14:25:47 2003 +0000
     2.2 +++ b/xen-2.4.16/Rules.mk	Fri Feb 21 15:10:37 2003 +0000
     2.3 @@ -20,6 +20,7 @@ ALL_OBJS += $(BASEDIR)/drivers/pci/drive
     2.4  ALL_OBJS += $(BASEDIR)/drivers/net/driver.o
     2.5  ALL_OBJS += $(BASEDIR)/drivers/block/driver.o
     2.6  ALL_OBJS += $(BASEDIR)/drivers/ide/driver.o
     2.7 +#ALL_OBJS += $(BASEDIR)/drivers/scsi/driver.o
     2.8  ALL_OBJS += $(BASEDIR)/arch/$(ARCH)/arch.o
     2.9  
    2.10  HOSTCC     = gcc
     3.1 --- a/xen-2.4.16/drivers/Makefile	Fri Feb 21 14:25:47 2003 +0000
     3.2 +++ b/xen-2.4.16/drivers/Makefile	Fri Feb 21 15:10:37 2003 +0000
     3.3 @@ -5,7 +5,7 @@ default:
     3.4  	$(MAKE) -C net
     3.5  	$(MAKE) -C block
     3.6  	$(MAKE) -C ide
     3.7 -#	$(MAKE) -C scsi
     3.8 +	$(MAKE) -C scsi
     3.9  
    3.10  clean:
    3.11  	$(MAKE) -C char clean
    3.12 @@ -13,4 +13,4 @@ clean:
    3.13  	$(MAKE) -C net clean
    3.14  	$(MAKE) -C block clean
    3.15  	$(MAKE) -C ide clean
    3.16 -#	$(MAKE) -C scsi clean
    3.17 +	$(MAKE) -C scsi clean
     4.1 --- a/xen-2.4.16/drivers/scsi/Makefile	Fri Feb 21 14:25:47 2003 +0000
     4.2 +++ b/xen-2.4.16/drivers/scsi/Makefile	Fri Feb 21 15:10:37 2003 +0000
     4.3 @@ -2,7 +2,10 @@
     4.4  include $(BASEDIR)/Rules.mk
     4.5  
     4.6  default: $(OBJS)
     4.7 -	$(LD) -r -o driver.o $(OBJS)
     4.8 +	$(MAKE) -C aacraid
     4.9 +	$(LD) -r -o driver.o $(OBJS) aacraid/aacraid.o
    4.10 +#	$(LD) -r -o driver.o $(OBJS) 
    4.11  
    4.12  clean:
    4.13 +	$(MAKE) -C aacraid clean
    4.14  	rm -f *.o *~ core
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/Makefile	Fri Feb 21 15:10:37 2003 +0000
     5.3 @@ -0,0 +1,17 @@
     5.4 +
     5.5 +include $(BASEDIR)/Rules.mk
     5.6 +
     5.7 +CFLAGS	+= -I$(BASEDIR)/drivers/scsi
     5.8 +
     5.9 +
    5.10 +# -y		:= linit.o aachba.o commctrl.o comminit.o commsup.o \
    5.11 +# 		   dpcsup.o rx.o sa.o
    5.12 +
    5.13 +default: $(OBJS)
    5.14 +	$(LD) -r -o aacraid.o $(OBJS)
    5.15 +
    5.16 +clean:
    5.17 +	rm -f *.o *~ core
    5.18 +
    5.19 +
    5.20 +
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/README	Fri Feb 21 15:10:37 2003 +0000
     6.3 @@ -0,0 +1,42 @@
     6.4 +AACRAID Driver for Linux (take two)
     6.5 +
     6.6 +Introduction
     6.7 +-------------------------
     6.8 +The aacraid driver adds support for Adaptec (http://www.adaptec.com)
     6.9 +RAID controllers. This is a major rewrite from the original 
    6.10 +Adaptec supplied driver. It has signficantly cleaned up both the code
    6.11 +and the running binary size (the module is less than half the size of
    6.12 +the original).
    6.13 +
    6.14 +Supported Cards/Chipsets
    6.15 +-------------------------
    6.16 +	Dell Computer Corporation PERC 2 Quad Channel
    6.17 +	Dell Computer Corporation PERC 2/Si
    6.18 +	Dell Computer Corporation PERC 3/Si
    6.19 +	Dell Computer Corporation PERC 3/Di
    6.20 +	HP NetRAID-4M
    6.21 +	ADAPTEC 2120S
    6.22 +	ADAPTEC 2200S
    6.23 +	ADAPTEC 5400S
    6.24 +
    6.25 +People
    6.26 +-------------------------
    6.27 +Alan Cox <alan@redhat.com>
    6.28 +Christoph Hellwig <hch@infradead.org>	(small cleanups/fixes)
    6.29 +Matt Domsch <matt_domsch@dell.com>	(revision ioctl, adapter messages)
    6.30 +Deanna Bonds <deanna_bonds@adaptec.com> (non-DASD support, PAE fibs and 64 bit, added new adaptec controllers
    6.31 +					 added new ioctls, changed scsi interface to use new error handler,
    6.32 +					 increased the number of fibs and outstanding commands to a container)
    6.33 +
    6.34 +Original Driver
    6.35 +-------------------------
    6.36 +Adaptec Unix OEM Product Group
    6.37 +
    6.38 +Mailing List
    6.39 +-------------------------
    6.40 +None currently. Also note this is very different to Brian's original driver
    6.41 +so don't expect him to support it.
    6.42 +Adaptec does support this driver.  Contact either tech support or deanna bonds.
    6.43 +
    6.44 +Original by Brian Boerner February 2001
    6.45 +Rewritten by Alan Cox, November 2001
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/TODO	Fri Feb 21 15:10:37 2003 +0000
     7.3 @@ -0,0 +1,4 @@
     7.4 +o	Testing
     7.5 +o	More testing
     7.6 +o	Feature request: display the firmware/bios/etc revisions in the
     7.7 +	/proc info
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/aachba.c	Fri Feb 21 15:10:37 2003 +0000
     8.3 @@ -0,0 +1,1685 @@
     8.4 +/*
     8.5 + *	Adaptec AAC series RAID controller driver
     8.6 + *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
     8.7 + *
     8.8 + * based on the old aacraid driver that is..
     8.9 + * Adaptec aacraid device driver for Linux.
    8.10 + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
    8.11 + *
    8.12 + * This program is free software; you can redistribute it and/or modify
    8.13 + * it under the terms of the GNU General Public License as published by
    8.14 + * the Free Software Foundation; either version 2, or (at your option)
    8.15 + * any later version.
    8.16 + *
    8.17 + * This program is distributed in the hope that it will be useful,
    8.18 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    8.19 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    8.20 + * GNU General Public License for more details.
    8.21 + *
    8.22 + * You should have received a copy of the GNU General Public License
    8.23 + * along with this program; see the file COPYING.  If not, write to
    8.24 + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
    8.25 + *
    8.26 + */
    8.27 +
    8.28 +#include <xeno/config.h>
    8.29 +/*  #include <xeno/kernel.h> */
    8.30 +#include <xeno/init.h>
    8.31 +#include <xeno/sched.h>
    8.32 +#include <xeno/pci.h>
    8.33 +/*  #include <xeno/spinlock.h> */
    8.34 +/*  #include <xeno/slab.h> */
    8.35 +/*  #include <xeno/completion.h> */
    8.36 +/*  #include <asm/semaphore.h> */
    8.37 +#include <asm/uaccess.h>
    8.38 +#define MAJOR_NR SCSI_DISK0_MAJOR	/* For DEVICE_NR() */
    8.39 +#include <linux/blk.h>
    8.40 +#include "scsi.h"
    8.41 +#include "hosts.h"
    8.42 +#include "sd.h"
    8.43 +
    8.44 +#include "aacraid.h"
    8.45 +
    8.46 +/*	SCSI Commands */
    8.47 +/*	TODO:  dmb - use the ones defined in include/scsi/scsi.h */
    8.48 +
    8.49 +#define	SS_TEST			0x00	/* Test unit ready */
    8.50 +#define SS_REZERO		0x01	/* Rezero unit */
    8.51 +#define	SS_REQSEN		0x03	/* Request Sense */
    8.52 +#define SS_REASGN		0x07	/* Reassign blocks */
    8.53 +#define	SS_READ			0x08	/* Read 6   */
    8.54 +#define	SS_WRITE		0x0A	/* Write 6  */
    8.55 +#define	SS_INQUIR		0x12	/* inquiry */
    8.56 +#define	SS_ST_SP		0x1B	/* Start/Stop unit */
    8.57 +#define	SS_LOCK			0x1E	/* prevent/allow medium removal */
    8.58 +#define SS_RESERV		0x16	/* Reserve */
    8.59 +#define SS_RELES		0x17	/* Release */
    8.60 +#define SS_MODESEN		0x1A	/* Mode Sense 6 */
    8.61 +#define	SS_RDCAP		0x25	/* Read Capacity */
    8.62 +#define	SM_READ			0x28	/* Read 10  */
    8.63 +#define	SM_WRITE		0x2A	/* Write 10 */
    8.64 +#define SS_SEEK			0x2B	/* Seek */
    8.65 +
    8.66 +/* values for inqd_pdt: Peripheral device type in plain English */
    8.67 +#define	INQD_PDT_DA	0x00		/* Direct-access (DISK) device */
    8.68 +#define	INQD_PDT_PROC	0x03		/* Processor device */
    8.69 +#define	INQD_PDT_CHNGR	0x08		/* Changer (jukebox, scsi2) */
    8.70 +#define	INQD_PDT_COMM	0x09		/* Communication device (scsi2) */
    8.71 +#define	INQD_PDT_NOLUN2 0x1f		/* Unknown Device (scsi2) */
    8.72 +#define	INQD_PDT_NOLUN	0x7f		/* Logical Unit Not Present */
    8.73 +
    8.74 +#define	INQD_PDT_DMASK	0x1F		/* Peripheral Device Type Mask */
    8.75 +#define	INQD_PDT_QMASK	0xE0		/* Peripheral Device Qualifer Mask */
    8.76 +
    8.77 +#define	TARGET_LUN_TO_CONTAINER(target, lun)	(target)
    8.78 +#define CONTAINER_TO_TARGET(cont)		((cont))
    8.79 +#define CONTAINER_TO_LUN(cont)			(0)
    8.80 +
    8.81 +#define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER))
    8.82 +
    8.83 +#define MAX_DRIVER_SG_SEGMENT_COUNT 17
    8.84 +
    8.85 +/*
    8.86 + *	Sense keys
    8.87 + */
    8.88 +#define SENKEY_NO_SENSE      			0x00	
    8.89 +#define SENKEY_UNDEFINED     			0x01	
    8.90 +#define SENKEY_NOT_READY     			0x02	
    8.91 +#define SENKEY_MEDIUM_ERR    			0x03	
    8.92 +#define SENKEY_HW_ERR        			0x04	
    8.93 +#define SENKEY_ILLEGAL       			0x05	
    8.94 +#define SENKEY_ATTENTION     			0x06	
    8.95 +#define SENKEY_PROTECTED     			0x07	
    8.96 +#define SENKEY_BLANK         			0x08	
    8.97 +#define SENKEY_V_UNIQUE      			0x09	
    8.98 +#define SENKEY_CPY_ABORT     			0x0A	
    8.99 +#define SENKEY_ABORT         			0x0B	
   8.100 +#define SENKEY_EQUAL         			0x0C	
   8.101 +#define SENKEY_VOL_OVERFLOW  			0x0D	
   8.102 +#define SENKEY_MISCOMP       			0x0E	
   8.103 +#define SENKEY_RESERVED      			0x0F	
   8.104 +
   8.105 +/*
   8.106 + *	Sense codes
   8.107 + */
   8.108 + 
   8.109 +#define SENCODE_NO_SENSE                        0x00
   8.110 +#define SENCODE_END_OF_DATA                     0x00
   8.111 +#define SENCODE_BECOMING_READY                  0x04
   8.112 +#define SENCODE_INIT_CMD_REQUIRED               0x04
   8.113 +#define SENCODE_PARAM_LIST_LENGTH_ERROR         0x1A
   8.114 +#define SENCODE_INVALID_COMMAND                 0x20
   8.115 +#define SENCODE_LBA_OUT_OF_RANGE                0x21
   8.116 +#define SENCODE_INVALID_CDB_FIELD               0x24
   8.117 +#define SENCODE_LUN_NOT_SUPPORTED               0x25
   8.118 +#define SENCODE_INVALID_PARAM_FIELD             0x26
   8.119 +#define SENCODE_PARAM_NOT_SUPPORTED             0x26
   8.120 +#define SENCODE_PARAM_VALUE_INVALID             0x26
   8.121 +#define SENCODE_RESET_OCCURRED                  0x29
   8.122 +#define SENCODE_LUN_NOT_SELF_CONFIGURED_YET     0x3E
   8.123 +#define SENCODE_INQUIRY_DATA_CHANGED            0x3F
   8.124 +#define SENCODE_SAVING_PARAMS_NOT_SUPPORTED     0x39
   8.125 +#define SENCODE_DIAGNOSTIC_FAILURE              0x40
   8.126 +#define SENCODE_INTERNAL_TARGET_FAILURE         0x44
   8.127 +#define SENCODE_INVALID_MESSAGE_ERROR           0x49
   8.128 +#define SENCODE_LUN_FAILED_SELF_CONFIG          0x4c
   8.129 +#define SENCODE_OVERLAPPED_COMMAND              0x4E
   8.130 +
   8.131 +/*
   8.132 + *	Additional sense codes
   8.133 + */
   8.134 + 
   8.135 +#define ASENCODE_NO_SENSE                       0x00
   8.136 +#define ASENCODE_END_OF_DATA                    0x05
   8.137 +#define ASENCODE_BECOMING_READY                 0x01
   8.138 +#define ASENCODE_INIT_CMD_REQUIRED              0x02
   8.139 +#define ASENCODE_PARAM_LIST_LENGTH_ERROR        0x00
   8.140 +#define ASENCODE_INVALID_COMMAND                0x00
   8.141 +#define ASENCODE_LBA_OUT_OF_RANGE               0x00
   8.142 +#define ASENCODE_INVALID_CDB_FIELD              0x00
   8.143 +#define ASENCODE_LUN_NOT_SUPPORTED              0x00
   8.144 +#define ASENCODE_INVALID_PARAM_FIELD            0x00
   8.145 +#define ASENCODE_PARAM_NOT_SUPPORTED            0x01
   8.146 +#define ASENCODE_PARAM_VALUE_INVALID            0x02
   8.147 +#define ASENCODE_RESET_OCCURRED                 0x00
   8.148 +#define ASENCODE_LUN_NOT_SELF_CONFIGURED_YET    0x00
   8.149 +#define ASENCODE_INQUIRY_DATA_CHANGED           0x03
   8.150 +#define ASENCODE_SAVING_PARAMS_NOT_SUPPORTED    0x00
   8.151 +#define ASENCODE_DIAGNOSTIC_FAILURE             0x80
   8.152 +#define ASENCODE_INTERNAL_TARGET_FAILURE        0x00
   8.153 +#define ASENCODE_INVALID_MESSAGE_ERROR          0x00
   8.154 +#define ASENCODE_LUN_FAILED_SELF_CONFIG         0x00
   8.155 +#define ASENCODE_OVERLAPPED_COMMAND             0x00
   8.156 +
   8.157 +#define BYTE0(x) (unsigned char)(x)
   8.158 +#define BYTE1(x) (unsigned char)((x) >> 8)
   8.159 +#define BYTE2(x) (unsigned char)((x) >> 16)
   8.160 +#define BYTE3(x) (unsigned char)((x) >> 24)
   8.161 +
   8.162 +/*------------------------------------------------------------------------------
   8.163 + *              S T R U C T S / T Y P E D E F S
   8.164 + *----------------------------------------------------------------------------*/
   8.165 +/* SCSI inquiry data */
   8.166 +struct inquiry_data {
   8.167 +	u8 inqd_pdt;		/* Peripheral qualifier | Peripheral Device Type  */
   8.168 +	u8 inqd_dtq;		/* RMB | Device Type Qualifier  */
   8.169 +	u8 inqd_ver;		/* ISO version | ECMA version | ANSI-approved version */
   8.170 +	u8 inqd_rdf;		/* AENC | TrmIOP | Response data format */
   8.171 +	u8 inqd_len;		/* Additional length (n-4) */
   8.172 +	u8 inqd_pad1[2];	/* Reserved - must be zero */
   8.173 +	u8 inqd_pad2;		/* RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
   8.174 +	u8 inqd_vid[8];		/* Vendor ID */
   8.175 +	u8 inqd_pid[16];	/* Product ID */
   8.176 +	u8 inqd_prl[4];		/* Product Revision Level */
   8.177 +};
   8.178 +
   8.179 +struct sense_data {
   8.180 +	u8 error_code;		/* 70h (current errors), 71h(deferred errors) */
   8.181 +	u8 valid:1;		/* A valid bit of one indicates that the information  */
   8.182 +	/* field contains valid information as defined in the
   8.183 +	 * SCSI-2 Standard.
   8.184 +	 */
   8.185 +	u8 segment_number;	/* Only used for COPY, COMPARE, or COPY AND VERIFY Commands */
   8.186 +	u8 sense_key:4;		/* Sense Key */
   8.187 +	u8 reserved:1;
   8.188 +	u8 ILI:1;		/* Incorrect Length Indicator */
   8.189 +	u8 EOM:1;		/* End Of Medium - reserved for random access devices */
   8.190 +	u8 filemark:1;		/* Filemark - reserved for random access devices */
   8.191 +
   8.192 +	u8 information[4];	/* for direct-access devices, contains the unsigned 
   8.193 +				 * logical block address or residue associated with 
   8.194 +				 * the sense key 
   8.195 +				 */
   8.196 +	u8 add_sense_len;	/* number of additional sense bytes to follow this field */
   8.197 +	u8 cmnd_info[4];	/* not used */
   8.198 +	u8 ASC;			/* Additional Sense Code */
   8.199 +	u8 ASCQ;		/* Additional Sense Code Qualifier */
   8.200 +	u8 FRUC;		/* Field Replaceable Unit Code - not used */
   8.201 +	u8 bit_ptr:3;		/* indicates which byte of the CDB or parameter data
   8.202 +				 * was in error
   8.203 +				 */
   8.204 +	u8 BPV:1;		/* bit pointer valid (BPV): 1- indicates that 
   8.205 +				 * the bit_ptr field has valid value
   8.206 +				 */
   8.207 +	u8 reserved2:2;
   8.208 +	u8 CD:1;		/* command data bit: 1- illegal parameter in CDB.
   8.209 +				 * 0- illegal parameter in data.
   8.210 +				 */
   8.211 +	u8 SKSV:1;
   8.212 +	u8 field_ptr[2];	/* byte of the CDB or parameter data in error */
   8.213 +};
   8.214 +
   8.215 +/*
   8.216 + *              M O D U L E   G L O B A L S
   8.217 + */
   8.218 + 
   8.219 +static struct fsa_scsi_hba *fsa_dev[MAXIMUM_NUM_ADAPTERS]; /*  SCSI Device 
   8.220 +							       Instance Ptrs */
   8.221 +static struct sense_data sense_data[MAXIMUM_NUM_CONTAINERS];
   8.222 +static void get_sd_devname(int disknum, char *buffer);
   8.223 +static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* sgmap);
   8.224 +static unsigned long aac_build_sg64(Scsi_Cmnd* scsicmd, struct sgmap64* psg);
   8.225 +static int aac_send_srb_fib(Scsi_Cmnd* scsicmd);
   8.226 +#ifdef AAC_DETAILED_STATUS_INFO
   8.227 +static char *aac_get_status_string(u32 status);
   8.228 +#endif
   8.229 +
   8.230 +/**
   8.231 + *	aac_get_containers	-	list containers
   8.232 + *	@common: adapter to probe
   8.233 + *
   8.234 + *	Make a list of all containers on this controller
   8.235 + */
   8.236 +int aac_get_containers(struct aac_dev *dev)
   8.237 +{
   8.238 +    struct fsa_scsi_hba *fsa_dev_ptr;
   8.239 +    u32 index, status = 0;
   8.240 +    struct aac_query_mount *dinfo;
   8.241 +    struct aac_mount *dresp;
   8.242 +    struct fib * fibptr;
   8.243 +    unsigned instance;
   8.244 +    
   8.245 +    fsa_dev_ptr = &(dev->fsa_dev);
   8.246 +    instance = dev->scsi_host_ptr->unique_id;
   8.247 +    
   8.248 +    if (!(fibptr = fib_alloc(dev)))
   8.249 +	return -ENOMEM;
   8.250 +    
   8.251 +    for (index = 0; index < MAXIMUM_NUM_CONTAINERS; index++) {
   8.252 +	fib_init(fibptr);
   8.253 +	dinfo = (struct aac_query_mount *) fib_data(fibptr);
   8.254 +	
   8.255 +	dinfo->command = cpu_to_le32(VM_NameServe);
   8.256 +	dinfo->count = cpu_to_le32(index);
   8.257 +	dinfo->type = cpu_to_le32(FT_FILESYS);
   8.258 +
   8.259 +	printk("aac_get_container: getting info for container %d\n", index); 
   8.260 +	status = fib_send(ContainerCommand,
   8.261 +			  fibptr,
   8.262 +			  sizeof (struct aac_query_mount),
   8.263 +			  FsaNormal,
   8.264 +			  1, 1,
   8.265 +			  NULL, NULL);
   8.266 +	if (status < 0 ) {
   8.267 +	    printk(KERN_WARNING "ProbeContainers: SendFIB failed.\n");
   8.268 +	    break;
   8.269 +	}
   8.270 +	dresp = (struct aac_mount *)fib_data(fibptr);
   8.271 +	
   8.272 +	if ((le32_to_cpu(dresp->status) == ST_OK) &&
   8.273 +	    (le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
   8.274 +	    fsa_dev_ptr->valid[index] = 1;
   8.275 +	    fsa_dev_ptr->type[index] = le32_to_cpu(dresp->mnt[0].vol);
   8.276 +	    fsa_dev_ptr->size[index] = le32_to_cpu(dresp->mnt[0].capacity);
   8.277 +	    if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
   8.278 +		fsa_dev_ptr->ro[index] = 1;
   8.279 +	}
   8.280 +	fib_complete(fibptr);
   8.281 +	/*
   8.282 +	 *	If there are no more containers, then stop asking.
   8.283 +	 */
   8.284 +	if ((index + 1) >= le32_to_cpu(dresp->count))
   8.285 +	    break;
   8.286 +    }
   8.287 +    fib_free(fibptr);
   8.288 +    fsa_dev[instance] = fsa_dev_ptr;
   8.289 +    return status;
   8.290 +}
   8.291 +
   8.292 +/**
   8.293 + *	probe_container		-	query a logical volume
   8.294 + *	@dev: device to query
   8.295 + *	@cid: container identifier
   8.296 + *
   8.297 + *	Queries the controller about the given volume. The volume information
   8.298 + *	is updated in the struct fsa_scsi_hba structure rather than returned.
   8.299 + */
   8.300 + 
   8.301 +static int probe_container(struct aac_dev *dev, int cid)
   8.302 +{
   8.303 +    struct fsa_scsi_hba *fsa_dev_ptr;
   8.304 +    int status;
   8.305 +    struct aac_query_mount *dinfo;
   8.306 +    struct aac_mount *dresp;
   8.307 +    struct fib * fibptr;
   8.308 +    unsigned instance;
   8.309 +    
   8.310 +    fsa_dev_ptr = &(dev->fsa_dev);
   8.311 +    instance = dev->scsi_host_ptr->unique_id;
   8.312 +    
   8.313 +    if (!(fibptr = fib_alloc(dev)))
   8.314 +	return -ENOMEM;
   8.315 +    
   8.316 +    fib_init(fibptr);
   8.317 +    
   8.318 +    dinfo = (struct aac_query_mount *)fib_data(fibptr);
   8.319 +    
   8.320 +    dinfo->command = cpu_to_le32(VM_NameServe);
   8.321 +    dinfo->count = cpu_to_le32(cid);
   8.322 +    dinfo->type = cpu_to_le32(FT_FILESYS);
   8.323 +    
   8.324 +    status = fib_send(ContainerCommand,
   8.325 +		      fibptr,
   8.326 +		      sizeof(struct aac_query_mount),
   8.327 +		      FsaNormal,
   8.328 +		      1, 1,
   8.329 +		      NULL, NULL);
   8.330 +    if (status < 0) {
   8.331 +	printk(KERN_WARNING "aacraid: probe_containers query failed.\n");
   8.332 +	goto error;
   8.333 +    }
   8.334 +    
   8.335 +    dresp = (struct aac_mount *) fib_data(fibptr);
   8.336 +    
   8.337 +    if ((le32_to_cpu(dresp->status) == ST_OK) &&
   8.338 +	(le32_to_cpu(dresp->mnt[0].vol) != CT_NONE)) {
   8.339 +	fsa_dev_ptr->valid[cid] = 1;
   8.340 +	fsa_dev_ptr->type[cid] = le32_to_cpu(dresp->mnt[0].vol);
   8.341 +	fsa_dev_ptr->size[cid] = le32_to_cpu(dresp->mnt[0].capacity);
   8.342 +	if (le32_to_cpu(dresp->mnt[0].state) & FSCS_READONLY)
   8.343 +	    fsa_dev_ptr->ro[cid] = 1;
   8.344 +    }
   8.345 +    
   8.346 + error:
   8.347 +    fib_complete(fibptr);
   8.348 +    fib_free(fibptr);
   8.349 +    
   8.350 +    return status;
   8.351 +}
   8.352 +
   8.353 +/* Local Structure to set SCSI inquiry data strings */
   8.354 +struct scsi_inq {
   8.355 +	char vid[8];         /* Vendor ID */
   8.356 +	char pid[16];        /* Product ID */
   8.357 +	char prl[4];         /* Product Revision Level */
   8.358 +};
   8.359 +
   8.360 +/**
   8.361 + *	InqStrCopy	-	string merge
   8.362 + *	@a:	string to copy from
   8.363 + *	@b:	string to copy to
   8.364 + *
   8.365 + * 	Copy a String from one location to another
   8.366 + *	without copying \0
   8.367 + */
   8.368 +
   8.369 +static void inqstrcpy(char *a, char *b)
   8.370 +{
   8.371 +
   8.372 +	while(*a != (char)0) 
   8.373 +		*b++ = *a++;
   8.374 +}
   8.375 +
   8.376 +static char *container_types[] = {
   8.377 +        "None",
   8.378 +        "Volume",
   8.379 +        "Mirror",
   8.380 +        "Stripe",
   8.381 +        "RAID5",
   8.382 +        "SSRW",
   8.383 +        "SSRO",
   8.384 +        "Morph",
   8.385 +        "Legacy",
   8.386 +        "RAID4",
   8.387 +        "RAID10",             
   8.388 +        "RAID00",             
   8.389 +        "V-MIRRORS",          
   8.390 +        "PSEUDO R4",          
   8.391 +	"RAID50",
   8.392 +        "Unknown"
   8.393 +};
   8.394 +
   8.395 +
   8.396 +
   8.397 +/* Function: setinqstr
   8.398 + *
   8.399 + * Arguments: [1] pointer to void [1] int
   8.400 + *
   8.401 + * Purpose: Sets SCSI inquiry data strings for vendor, product
   8.402 + * and revision level. Allows strings to be set in platform dependant
   8.403 + * files instead of in OS dependant driver source.
   8.404 + */
   8.405 +
   8.406 +static void setinqstr(int devtype, void *data, int tindex)
   8.407 +{
   8.408 +	struct scsi_inq *str;
   8.409 +	char *findit;
   8.410 +	struct aac_driver_ident *mp;
   8.411 +
   8.412 +	mp = aac_get_driver_ident(devtype);
   8.413 +   
   8.414 +	str = (struct scsi_inq *)(data); /* cast data to scsi inq block */
   8.415 +
   8.416 +	inqstrcpy (mp->vname, str->vid); 
   8.417 +	inqstrcpy (mp->model, str->pid); /* last six chars reserved for vol type */
   8.418 +
   8.419 +	findit = str->pid;
   8.420 +
   8.421 +	for ( ; *findit != ' '; findit++); /* walk till we find a space then incr by 1 */
   8.422 +		findit++;
   8.423 +	
   8.424 +	if (tindex < (sizeof(container_types)/sizeof(char *))){
   8.425 +		inqstrcpy (container_types[tindex], findit);
   8.426 +	}
   8.427 +	inqstrcpy ("V1.0", str->prl);
   8.428 +}
   8.429 +
   8.430 +void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
   8.431 +		    u8 a_sense_code, u8 incorrect_length,
   8.432 +		    u8 bit_pointer, u16 field_pointer,
   8.433 +		    u32 residue)
   8.434 +{
   8.435 +	sense_buf[0] = 0xF0;	/* Sense data valid, err code 70h (current error) */
   8.436 +	sense_buf[1] = 0;	/* Segment number, always zero */
   8.437 +
   8.438 +	if (incorrect_length) {
   8.439 +		sense_buf[2] = sense_key | 0x20;	/* Set ILI bit | sense key */
   8.440 +		sense_buf[3] = BYTE3(residue);
   8.441 +		sense_buf[4] = BYTE2(residue);
   8.442 +		sense_buf[5] = BYTE1(residue);
   8.443 +		sense_buf[6] = BYTE0(residue);
   8.444 +	} else
   8.445 +		sense_buf[2] = sense_key;	/* Sense key */
   8.446 +
   8.447 +	if (sense_key == SENKEY_ILLEGAL)
   8.448 +		sense_buf[7] = 10;	/* Additional sense length */
   8.449 +	else
   8.450 +		sense_buf[7] = 6;	/* Additional sense length */
   8.451 +
   8.452 +	sense_buf[12] = sense_code;	/* Additional sense code */
   8.453 +	sense_buf[13] = a_sense_code;	/* Additional sense code qualifier */
   8.454 +	if (sense_key == SENKEY_ILLEGAL) {
   8.455 +		sense_buf[15] = 0;
   8.456 +
   8.457 +		if (sense_code == SENCODE_INVALID_PARAM_FIELD)
   8.458 +			sense_buf[15] = 0x80;	/* Std sense key specific field */
   8.459 +		/* Illegal parameter is in the parameter block */
   8.460 +
   8.461 +		if (sense_code == SENCODE_INVALID_CDB_FIELD)
   8.462 +			sense_buf[15] = 0xc0;	/* Std sense key specific field */
   8.463 +		/* Illegal parameter is in the CDB block */
   8.464 +		sense_buf[15] |= bit_pointer;
   8.465 +		sense_buf[16] = field_pointer >> 8;	/* MSB */
   8.466 +		sense_buf[17] = field_pointer;		/* LSB */
   8.467 +	}
   8.468 +}
   8.469 +
   8.470 +static void aac_io_done(Scsi_Cmnd * scsicmd)
   8.471 +{
   8.472 +	unsigned long cpu_flags;
   8.473 +	spin_lock_irqsave(&io_request_lock, cpu_flags);
   8.474 +	scsicmd->scsi_done(scsicmd);
   8.475 +	spin_unlock_irqrestore(&io_request_lock, cpu_flags);
   8.476 +}
   8.477 +
   8.478 +static void __aac_io_done(Scsi_Cmnd * scsicmd)
   8.479 +{
   8.480 +	scsicmd->scsi_done(scsicmd);
   8.481 +}
   8.482 +
   8.483 +int aac_get_adapter_info(struct aac_dev* dev)
   8.484 +{
   8.485 +	struct fib* fibptr;
   8.486 +	struct aac_adapter_info* info;
   8.487 +	int rcode;
   8.488 +	u32 tmp;
   8.489 +
   8.490 +	if (!(fibptr = fib_alloc(dev)))
   8.491 +		return -ENOMEM;
   8.492 +
   8.493 +	fib_init(fibptr);
   8.494 +	info = (struct aac_adapter_info*) fib_data(fibptr);
   8.495 +
   8.496 +	memset(info,0,sizeof(struct aac_adapter_info));
   8.497 +
   8.498 +	rcode = fib_send(RequestAdapterInfo,
   8.499 +			fibptr, 
   8.500 +			sizeof(struct aac_adapter_info),
   8.501 +			FsaNormal, 
   8.502 +			1, 1, 
   8.503 +			NULL, 
   8.504 +			NULL);
   8.505 +
   8.506 +	memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
   8.507 +
   8.508 +	tmp = dev->adapter_info.kernelrev;
   8.509 +	printk(KERN_INFO "%s%d: kernel %d.%d.%d build %d\n", 
   8.510 +			dev->name, dev->id,
   8.511 +			tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
   8.512 +			dev->adapter_info.kernelbuild);
   8.513 +	tmp = dev->adapter_info.monitorrev;
   8.514 +	printk(KERN_INFO "%s%d: monitor %d.%d.%d build %d\n", 
   8.515 +			dev->name, dev->id,
   8.516 +			tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
   8.517 +			dev->adapter_info.monitorbuild);
   8.518 +	tmp = dev->adapter_info.biosrev;
   8.519 +	printk(KERN_INFO "%s%d: bios %d.%d.%d build %d\n", 
   8.520 +			dev->name, dev->id,
   8.521 +			tmp>>24,(tmp>>16)&0xff,(tmp>>8)&0xff,
   8.522 +			dev->adapter_info.biosbuild);
   8.523 +	printk(KERN_INFO "%s%d: serial %x%x\n",
   8.524 +			dev->name, dev->id,
   8.525 +			dev->adapter_info.serial[0],
   8.526 +			dev->adapter_info.serial[1]);
   8.527 +	dev->pae_support = 0;
   8.528 +	dev->nondasd_support = 0;
   8.529 +	if( BITS_PER_LONG >= 64 && 
   8.530 +	  (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)){
   8.531 +		printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", 
   8.532 +		       dev->name, dev->id);
   8.533 +		dev->pae_support = 1;
   8.534 +	}
   8.535 +	/* TODO - dmb temporary until fw can set this bit  */
   8.536 +	dev->pae_support = (BITS_PER_LONG >= 64);
   8.537 +	if(dev->pae_support != 0) {
   8.538 +		printk(KERN_INFO "%s%d: 64 Bit PAE enabled\n", 
   8.539 +		       dev->name, dev->id);
   8.540 +	}
   8.541 +
   8.542 +	if(dev->adapter_info.options & AAC_OPT_NONDASD){
   8.543 +		dev->nondasd_support = 1;
   8.544 +	}
   8.545 +	return rcode;
   8.546 +}
   8.547 +
   8.548 +
   8.549 +static void read_callback(void *context, struct fib * fibptr)
   8.550 +{
   8.551 +	struct aac_dev *dev;
   8.552 +	struct aac_read_reply *readreply;
   8.553 +	Scsi_Cmnd *scsicmd;
   8.554 +	u32 lba;
   8.555 +	u32 cid;
   8.556 +
   8.557 +	scsicmd = (Scsi_Cmnd *) context;
   8.558 +
   8.559 +	dev = (struct aac_dev *)scsicmd->host->hostdata;
   8.560 +	cid =TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun);
   8.561 +
   8.562 +	lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
   8.563 +	dprintk((KERN_DEBUG "read_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies));
   8.564 +
   8.565 +	if (fibptr == NULL)
   8.566 +		BUG();
   8.567 +		
   8.568 +	if(scsicmd->use_sg)
   8.569 +		pci_unmap_sg(dev->pdev, 
   8.570 +			(struct scatterlist *)scsicmd->buffer,
   8.571 +			scsicmd->use_sg,
   8.572 +			scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
   8.573 +	else if(scsicmd->request_bufflen)
   8.574 +		pci_unmap_single(dev->pdev, (dma_addr_t)(unsigned long)scsicmd->SCp.ptr,
   8.575 +				 scsicmd->request_bufflen,
   8.576 +				 scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
   8.577 +	readreply = (struct aac_read_reply *)fib_data(fibptr);
   8.578 +	if (le32_to_cpu(readreply->status) == ST_OK)
   8.579 +		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
   8.580 +	else {
   8.581 +		printk(KERN_WARNING "read_callback: read failed, status = %d\n", readreply->status);
   8.582 +		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
   8.583 +		set_sense((u8 *) &sense_data[cid],
   8.584 +				    SENKEY_HW_ERR,
   8.585 +				    SENCODE_INTERNAL_TARGET_FAILURE,
   8.586 +				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
   8.587 +				    0, 0);
   8.588 +	}
   8.589 +	fib_complete(fibptr);
   8.590 +	fib_free(fibptr);
   8.591 +
   8.592 +	aac_io_done(scsicmd);
   8.593 +}
   8.594 +
   8.595 +static void write_callback(void *context, struct fib * fibptr)
   8.596 +{
   8.597 +	struct aac_dev *dev;
   8.598 +	struct aac_write_reply *writereply;
   8.599 +	Scsi_Cmnd *scsicmd;
   8.600 +	u32 lba;
   8.601 +	u32 cid;
   8.602 +
   8.603 +	scsicmd = (Scsi_Cmnd *) context;
   8.604 +	dev = (struct aac_dev *)scsicmd->host->hostdata;
   8.605 +	cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun);
   8.606 +
   8.607 +	lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
   8.608 +	dprintk((KERN_DEBUG "write_callback[cpu %d]: lba = %d, t = %ld.\n", smp_processor_id(), lba, jiffies));
   8.609 +	if (fibptr == NULL)
   8.610 +		BUG();
   8.611 +
   8.612 +	if(scsicmd->use_sg)
   8.613 +		pci_unmap_sg(dev->pdev, 
   8.614 +			(struct scatterlist *)scsicmd->buffer,
   8.615 +			scsicmd->use_sg,
   8.616 +			scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
   8.617 +	else if(scsicmd->request_bufflen)
   8.618 +		pci_unmap_single(dev->pdev, (dma_addr_t)(unsigned long)scsicmd->SCp.ptr,
   8.619 +				 scsicmd->request_bufflen,
   8.620 +				 scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
   8.621 +
   8.622 +	writereply = (struct aac_write_reply *) fib_data(fibptr);
   8.623 +	if (le32_to_cpu(writereply->status) == ST_OK)
   8.624 +		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
   8.625 +	else {
   8.626 +		printk(KERN_WARNING "write_callback: write failed, status = %d\n", writereply->status);
   8.627 +		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | CHECK_CONDITION;
   8.628 +		set_sense((u8 *) &sense_data[cid],
   8.629 +				    SENKEY_HW_ERR,
   8.630 +				    SENCODE_INTERNAL_TARGET_FAILURE,
   8.631 +				    ASENCODE_INTERNAL_TARGET_FAILURE, 0, 0,
   8.632 +				    0, 0);
   8.633 +	}
   8.634 +
   8.635 +	fib_complete(fibptr);
   8.636 +	fib_free(fibptr);
   8.637 +	aac_io_done(scsicmd);
   8.638 +}
   8.639 +
   8.640 +int aac_read(Scsi_Cmnd * scsicmd, int cid)
   8.641 +{
   8.642 +	u32 lba;
   8.643 +	u32 count;
   8.644 +	int status;
   8.645 +
   8.646 +	u16 fibsize;
   8.647 +	struct aac_dev *dev;
   8.648 +	struct fib * cmd_fibcontext;
   8.649 +
   8.650 +	dev = (struct aac_dev *)scsicmd->host->hostdata;
   8.651 +	/*
   8.652 +	 *	Get block address and transfer length
   8.653 +	 */
   8.654 +	if (scsicmd->cmnd[0] == SS_READ)	/* 6 byte command */
   8.655 +	{
   8.656 +		dprintk((KERN_DEBUG "aachba: received a read(6) command on target %d.\n", cid));
   8.657 +
   8.658 +		lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
   8.659 +		count = scsicmd->cmnd[4];
   8.660 +
   8.661 +		if (count == 0)
   8.662 +			count = 256;
   8.663 +	} else {
   8.664 +		dprintk((KERN_DEBUG "aachba: received a read(10) command on target %d.\n", cid));
   8.665 +
   8.666 +		lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
   8.667 +		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
   8.668 +	}
   8.669 +	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
   8.670 +	/*
   8.671 +	 *	Alocate and initialize a Fib
   8.672 +	 */
   8.673 +	if (!(cmd_fibcontext = fib_alloc(dev))) {
   8.674 +		scsicmd->result = DID_ERROR << 16;
   8.675 +		aac_io_done(scsicmd);
   8.676 +		return (-1);
   8.677 +	}
   8.678 +
   8.679 +	fib_init(cmd_fibcontext);
   8.680 +
   8.681 +	if(dev->pae_support == 1){
   8.682 +		struct aac_read64 *readcmd;
   8.683 +		readcmd = (struct aac_read64 *) fib_data(cmd_fibcontext);
   8.684 +		readcmd->command = cpu_to_le32(VM_CtHostRead64);
   8.685 +		readcmd->cid = cpu_to_le16(cid);
   8.686 +		readcmd->sector_count = cpu_to_le16(count);
   8.687 +		readcmd->block = cpu_to_le32(lba);
   8.688 +		readcmd->pad   = cpu_to_le16(0);
   8.689 +		readcmd->flags = cpu_to_le16(0); 
   8.690 +		
   8.691 +		aac_build_sg64(scsicmd, &readcmd->sg);
   8.692 +		if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
   8.693 +			BUG();
   8.694 +		fibsize = sizeof(struct aac_read64) + 
   8.695 +		    ((readcmd->sg.count - 1) * sizeof (struct sgentry64));
   8.696 +		/*
   8.697 +		 *	Now send the Fib to the adapter
   8.698 +		 */
   8.699 +		status = fib_send(ContainerCommand64, 
   8.700 +			  cmd_fibcontext, 
   8.701 +			  fibsize, 
   8.702 +			  FsaNormal, 
   8.703 +			  0, 1, 
   8.704 +			  (fib_callback) read_callback, 
   8.705 +			  (void *) scsicmd);
   8.706 +	} else {
   8.707 +		struct aac_read *readcmd;
   8.708 +		readcmd = (struct aac_read *) fib_data(cmd_fibcontext);
   8.709 +		readcmd->command = cpu_to_le32(VM_CtBlockRead);
   8.710 +		readcmd->cid = cpu_to_le32(cid);
   8.711 +		readcmd->block = cpu_to_le32(lba);
   8.712 +		readcmd->count = cpu_to_le32(count * 512);
   8.713 +
   8.714 +		if (count * 512 > (64 * 1024))
   8.715 +			BUG();
   8.716 +
   8.717 +		aac_build_sg(scsicmd, &readcmd->sg);
   8.718 +		if(readcmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
   8.719 +			BUG();
   8.720 +		fibsize = sizeof(struct aac_read) + 
   8.721 +		    ((readcmd->sg.count - 1) * sizeof (struct sgentry));
   8.722 +		/*
   8.723 +		 *	Now send the Fib to the adapter
   8.724 +		 */
   8.725 +		status = fib_send(ContainerCommand, 
   8.726 +			  cmd_fibcontext, 
   8.727 +			  fibsize, 
   8.728 +			  FsaNormal, 
   8.729 +			  0, 1, 
   8.730 +			  (fib_callback) read_callback, 
   8.731 +			  (void *) scsicmd);
   8.732 +	}
   8.733 +	
   8.734 +	
   8.735 +	/*
   8.736 +	 *	Check that the command queued to the controller
   8.737 +	 */
   8.738 +	if (status == -EINPROGRESS) 
   8.739 +		return 0;
   8.740 +		
   8.741 +	printk(KERN_WARNING "aac_read: fib_send failed with status: %d.\n", 
   8.742 +	       status);
   8.743 +	/*
   8.744 +	 *	For some reason, the Fib didn't queue, return QUEUE_FULL
   8.745 +	 */
   8.746 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL;
   8.747 +	aac_io_done(scsicmd);
   8.748 +	fib_complete(cmd_fibcontext);
   8.749 +	fib_free(cmd_fibcontext);
   8.750 +	return -1;
   8.751 +}
   8.752 +
   8.753 +static int aac_write(Scsi_Cmnd * scsicmd, int cid)
   8.754 +{
   8.755 +	u32 lba;
   8.756 +	u32 count;
   8.757 +	int status;
   8.758 +	u16 fibsize;
   8.759 +	struct aac_dev *dev;
   8.760 +	struct fib * cmd_fibcontext;
   8.761 +
   8.762 +	dev = (struct aac_dev *)scsicmd->host->hostdata;
   8.763 +	/*
   8.764 +	 *	Get block address and transfer length
   8.765 +	 */
   8.766 +	if (scsicmd->cmnd[0] == SS_WRITE)	/* 6 byte command */
   8.767 +	{
   8.768 +		lba = ((scsicmd->cmnd[1] & 0x1F) << 16) | (scsicmd->cmnd[2] << 8) | scsicmd->cmnd[3];
   8.769 +		count = scsicmd->cmnd[4];
   8.770 +		if (count == 0)
   8.771 +			count = 256;
   8.772 +	} else {
   8.773 +		dprintk((KERN_DEBUG "aachba: received a write(10) command on target %d.\n", cid));
   8.774 +		lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
   8.775 +		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
   8.776 +	}
   8.777 +	dprintk((KERN_DEBUG "aac_write[cpu %d]: lba = %u, t = %ld.\n", 
   8.778 +		 smp_processor_id(), lba, jiffies));
   8.779 +	/*
   8.780 +	 *	Allocate and initialize a Fib then setup a BlockWrite command
   8.781 +	 */
   8.782 +	if (!(cmd_fibcontext = fib_alloc(dev))) {
   8.783 +		scsicmd->result = DID_ERROR << 16;
   8.784 +		aac_io_done(scsicmd);
   8.785 +		return -1;
   8.786 +	}
   8.787 +	fib_init(cmd_fibcontext);
   8.788 +
   8.789 +	if(dev->pae_support == 1)
   8.790 +	{
   8.791 +		struct aac_write64 *writecmd;
   8.792 +		writecmd = (struct aac_write64 *) fib_data(cmd_fibcontext);
   8.793 +		writecmd->command = cpu_to_le32(VM_CtHostWrite64);
   8.794 +		writecmd->cid = cpu_to_le16(cid);
   8.795 +		writecmd->sector_count = cpu_to_le16(count); 
   8.796 +		writecmd->block = cpu_to_le32(lba);
   8.797 +		writecmd->pad	= cpu_to_le16(0);
   8.798 +		writecmd->flags	= cpu_to_le16(0);
   8.799 +
   8.800 +		aac_build_sg64(scsicmd, &writecmd->sg);
   8.801 +		if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
   8.802 +			BUG();
   8.803 +		fibsize = sizeof(struct aac_write64) + 
   8.804 +		    ((writecmd->sg.count - 1) * sizeof (struct sgentry64));
   8.805 +		/*
   8.806 +		 *	Now send the Fib to the adapter
   8.807 +		 */
   8.808 +		status = fib_send(ContainerCommand64, 
   8.809 +			  cmd_fibcontext, 
   8.810 +			  fibsize, 
   8.811 +			  FsaNormal, 
   8.812 +			  0, 1, 
   8.813 +			  (fib_callback) write_callback, 
   8.814 +			  (void *) scsicmd);
   8.815 +	}
   8.816 +	else 
   8.817 +	{
   8.818 +		struct aac_write *writecmd;
   8.819 +		writecmd = (struct aac_write *) fib_data(cmd_fibcontext);
   8.820 +		writecmd->command = cpu_to_le32(VM_CtBlockWrite);
   8.821 +		writecmd->cid = cpu_to_le32(cid);
   8.822 +		writecmd->block = cpu_to_le32(lba);
   8.823 +		writecmd->count = cpu_to_le32(count * 512);
   8.824 +		writecmd->sg.count = cpu_to_le32(1);
   8.825 +		/* ->stable is not used - it did mean which type of write */
   8.826 +
   8.827 +		if (count * 512 > (64 * 1024))
   8.828 +			BUG();
   8.829 +		aac_build_sg(scsicmd, &writecmd->sg);
   8.830 +		if(writecmd->sg.count > MAX_DRIVER_SG_SEGMENT_COUNT)
   8.831 +			BUG();
   8.832 +		fibsize = sizeof(struct aac_write) + 
   8.833 +		    ((writecmd->sg.count - 1) * sizeof (struct sgentry));
   8.834 +		/*
   8.835 +		 *	Now send the Fib to the adapter
   8.836 +		 */
   8.837 +		status = fib_send(ContainerCommand, 
   8.838 +			  cmd_fibcontext, 
   8.839 +			  fibsize, 
   8.840 +			  FsaNormal, 
   8.841 +			  0, 1, 
   8.842 +			  (fib_callback) write_callback, 
   8.843 +			  (void *) scsicmd);
   8.844 +	}
   8.845 +
   8.846 +	/*
   8.847 +	 *	Check that the command queued to the controller
   8.848 +	 */
   8.849 +	if (status == -EINPROGRESS)
   8.850 +		return 0;
   8.851 +
   8.852 +	printk(KERN_WARNING "aac_write: fib_send failed with status: %d\n", status);
   8.853 +	/*
   8.854 +	 *	For some reason, the Fib didn't queue, return QUEUE_FULL
   8.855 +	 */
   8.856 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL;
   8.857 +	aac_io_done(scsicmd);
   8.858 +
   8.859 +	fib_complete(cmd_fibcontext);
   8.860 +	fib_free(cmd_fibcontext);
   8.861 +	return -1;
   8.862 +}
   8.863 +
   8.864 +
   8.865 +/**
   8.866 + *	aac_scsi_cmd()		-	Process SCSI command
   8.867 + *	@scsicmd:		SCSI command block
   8.868 + *	@wait:			1 if the user wants to await completion
   8.869 + *
   8.870 + *	Emulate a SCSI command and queue the required request for the
   8.871 + *	aacraid firmware.
   8.872 + */
   8.873 + 
   8.874 +int aac_scsi_cmd(Scsi_Cmnd * scsicmd)
   8.875 +{
   8.876 +    u32 cid = 0;
   8.877 +    struct fsa_scsi_hba *fsa_dev_ptr;
   8.878 +    int cardtype;
   8.879 +    int ret;
   8.880 +    struct aac_dev *dev = (struct aac_dev *)scsicmd->host->hostdata;
   8.881 +    
   8.882 +    cardtype = dev->cardtype;
   8.883 +
   8.884 +    fsa_dev_ptr = fsa_dev[scsicmd->host->unique_id];
   8.885 +    
   8.886 +    /*
   8.887 +     *	If the bus, target or lun is out of range, return fail
   8.888 +     *	Test does not apply to ID 16, the pseudo id for the controller
   8.889 +     *	itself.
   8.890 +     */
   8.891 +    if (scsicmd->target != scsicmd->host->this_id) {
   8.892 +	if ((scsicmd->channel == 0) ){
   8.893 +	    if( (scsicmd->target >= AAC_MAX_TARGET) || (scsicmd->lun != 0)){ 
   8.894 +		scsicmd->result = DID_NO_CONNECT << 16;
   8.895 +		__aac_io_done(scsicmd);
   8.896 +		return 0;
   8.897 +	    }
   8.898 +	    cid = TARGET_LUN_TO_CONTAINER(scsicmd->target, scsicmd->lun);
   8.899 +	    
   8.900 +	    /*
   8.901 +	     *	If the target container doesn't exist, it may have
   8.902 +	     *	been newly created
   8.903 +	     */
   8.904 +	    if (fsa_dev_ptr->valid[cid] == 0) {
   8.905 +		switch (scsicmd->cmnd[0]) {
   8.906 +		case SS_INQUIR:
   8.907 +		case SS_RDCAP:
   8.908 +		case SS_TEST:
   8.909 +		    spin_unlock_irq(&io_request_lock);
   8.910 +		    probe_container(dev, cid);
   8.911 +		    spin_lock_irq(&io_request_lock);
   8.912 +		    if (fsa_dev_ptr->valid[cid] == 0) {
   8.913 +			scsicmd->result = DID_NO_CONNECT << 16;
   8.914 +			__aac_io_done(scsicmd);
   8.915 +			return 0;
   8.916 +		    }
   8.917 +		default:
   8.918 +		    break;
   8.919 +		}
   8.920 +	    }
   8.921 +	    /*
   8.922 +	     *	If the target container still doesn't exist, 
   8.923 +	     *	return failure
   8.924 +	     */
   8.925 +	    if (fsa_dev_ptr->valid[cid] == 0) {
   8.926 +		scsicmd->result = DID_BAD_TARGET << 16;
   8.927 +		__aac_io_done(scsicmd);
   8.928 +		return -1;
   8.929 +			}
   8.930 +	} else {  /* check for physical non-dasd devices */
   8.931 +	    if(dev->nondasd_support == 1){
   8.932 +		return aac_send_srb_fib(scsicmd);
   8.933 +	    } else {
   8.934 +		scsicmd->result = DID_NO_CONNECT << 16;
   8.935 +		__aac_io_done(scsicmd);
   8.936 +		return 0;
   8.937 +	    }
   8.938 +	}
   8.939 +    }
   8.940 +    /*
   8.941 +     * else Command for the controller itself
   8.942 +     */
   8.943 +    else if ((scsicmd->cmnd[0] != SS_INQUIR) &&	
   8.944 +	     (scsicmd->cmnd[0] != SS_TEST)) 
   8.945 +    {
   8.946 +	/* only INQUIRY & TUR cmnd supported for controller */
   8.947 +	dprintk((KERN_WARNING "Only INQUIRY & TUR command supported for "
   8.948 +		 "controller, rcvd = 0x%x.\n", scsicmd->cmnd[0]));
   8.949 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | 
   8.950 +	    CHECK_CONDITION;
   8.951 +	set_sense((u8 *) &sense_data[cid],
   8.952 +		  SENKEY_ILLEGAL,
   8.953 +		  SENCODE_INVALID_COMMAND,
   8.954 +		  ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
   8.955 +	__aac_io_done(scsicmd);
   8.956 +	return -1;
   8.957 +    }
   8.958 +    
   8.959 +    
   8.960 +    /* Handle commands here that don't require going out to the adapter */
   8.961 +    switch (scsicmd->cmnd[0]) {
   8.962 +    case SS_INQUIR:
   8.963 +    {
   8.964 +	struct inquiry_data *inq_data_ptr;
   8.965 +	
   8.966 +	dprintk((KERN_DEBUG "INQUIRY command, ID: %d.\n", scsicmd->target));
   8.967 +	inq_data_ptr = (struct inquiry_data *)scsicmd->request_buffer;
   8.968 +	memset(inq_data_ptr, 0, sizeof (struct inquiry_data));
   8.969 +	
   8.970 +	inq_data_ptr->inqd_ver = 2;	/* claim compliance to SCSI-2 */
   8.971 +	inq_data_ptr->inqd_dtq = 0x80;	/* set RMB bit to one indicating that the medium is removable */
   8.972 +	inq_data_ptr->inqd_rdf = 2;	/* A response data format value of two indicates that the data shall be in the format specified in SCSI-2 */
   8.973 +	inq_data_ptr->inqd_len = 31;
   8.974 +	/*Format for "pad2" is  RelAdr | WBus32 | WBus16 |  Sync  | Linked |Reserved| CmdQue | SftRe */
   8.975 +	inq_data_ptr->inqd_pad2= 0x32 ;	 /*WBus16|Sync|CmdQue */
   8.976 +	/*
   8.977 +	 *	Set the Vendor, Product, and Revision Level
   8.978 +	 *	see: <vendor>.c i.e. aac.c
   8.979 +	 */
   8.980 +	setinqstr(cardtype, (void *) (inq_data_ptr->inqd_vid), fsa_dev_ptr->type[cid]);
   8.981 +	if (scsicmd->target == scsicmd->host->this_id)
   8.982 +	    inq_data_ptr->inqd_pdt = INQD_PDT_PROC;	/* Processor device */
   8.983 +	else
   8.984 +	    inq_data_ptr->inqd_pdt = INQD_PDT_DA;	/* Direct/random access device */
   8.985 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
   8.986 +	__aac_io_done(scsicmd);
   8.987 +	return 0;
   8.988 +    }
   8.989 +    case SS_RDCAP:
   8.990 +    {
   8.991 +	int capacity;
   8.992 +	char *cp;
   8.993 +	
   8.994 +	dprintk((KERN_DEBUG "READ CAPACITY command.\n"));
   8.995 +	capacity = fsa_dev_ptr->size[cid] - 1;
   8.996 +	cp = scsicmd->request_buffer;
   8.997 +	cp[0] = (capacity >> 24) & 0xff;
   8.998 +	cp[1] = (capacity >> 16) & 0xff;
   8.999 +	cp[2] = (capacity >> 8) & 0xff;
  8.1000 +	cp[3] = (capacity >> 0) & 0xff;
  8.1001 +	cp[4] = 0;
  8.1002 +	cp[5] = 0;
  8.1003 +	cp[6] = 2;
  8.1004 +	cp[7] = 0;
  8.1005 +	
  8.1006 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
  8.1007 +	__aac_io_done(scsicmd);
  8.1008 +	
  8.1009 +	return 0;
  8.1010 +    }
  8.1011 +    
  8.1012 +    case SS_MODESEN:
  8.1013 +    {
  8.1014 +	char *mode_buf;
  8.1015 +	
  8.1016 +	dprintk((KERN_DEBUG "MODE SENSE command.\n"));
  8.1017 +	mode_buf = scsicmd->request_buffer;
  8.1018 +	mode_buf[0] = 0;  /* Mode data length (MSB) */
  8.1019 +	mode_buf[1] = 6;  /* Mode data length (LSB) */
  8.1020 +	mode_buf[2] = 0;  /* Medium type - default */
  8.1021 +	mode_buf[3] = 0;  /* Device-specific param, 
  8.1022 +			     bit 8: 0/1 = write enabled/protected */
  8.1023 +	mode_buf[4] = 0;  /* reserved */
  8.1024 +	mode_buf[5] = 0;  /* reserved */
  8.1025 +	mode_buf[6] = 0;  /* Block descriptor length (MSB) */
  8.1026 +	mode_buf[7] = 0;  /* Block descriptor length (LSB) */
  8.1027 +	
  8.1028 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
  8.1029 +	__aac_io_done(scsicmd);
  8.1030 +	
  8.1031 +	return 0;
  8.1032 +    }
  8.1033 +    case SS_REQSEN:
  8.1034 +	dprintk((KERN_DEBUG "REQUEST SENSE command.\n"));
  8.1035 +	memcpy(scsicmd->sense_buffer, &sense_data[cid], 
  8.1036 +	       sizeof (struct sense_data));
  8.1037 +	memset(&sense_data[cid], 0, sizeof (struct sense_data));
  8.1038 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
  8.1039 +	__aac_io_done(scsicmd);
  8.1040 +	return (0);
  8.1041 +	
  8.1042 +    case SS_LOCK:
  8.1043 +	dprintk((KERN_DEBUG "LOCK command.\n"));
  8.1044 +	if (scsicmd->cmnd[4])
  8.1045 +	    fsa_dev_ptr->locked[cid] = 1;
  8.1046 +	else
  8.1047 +	    fsa_dev_ptr->locked[cid] = 0;
  8.1048 +	
  8.1049 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
  8.1050 +	__aac_io_done(scsicmd);
  8.1051 +	return 0;
  8.1052 +	/*
  8.1053 +	 *	These commands are all No-Ops
  8.1054 +	 */
  8.1055 +    case SS_TEST:
  8.1056 +    case SS_RESERV:
  8.1057 +    case SS_RELES:
  8.1058 +    case SS_REZERO:
  8.1059 +    case SS_REASGN:
  8.1060 +    case SS_SEEK:
  8.1061 +    case SS_ST_SP:
  8.1062 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | GOOD;
  8.1063 +	__aac_io_done(scsicmd);
  8.1064 +	return (0);
  8.1065 +    }
  8.1066 +    
  8.1067 +    switch (scsicmd->cmnd[0]) 
  8.1068 +    {
  8.1069 +    case SS_READ:
  8.1070 +    case SM_READ:
  8.1071 +	/*
  8.1072 +	 *	Hack to keep track of ordinal number of the device that
  8.1073 +	 *	corresponds to a container. Needed to convert
  8.1074 +	 *	containers to /dev/sd device names
  8.1075 +	 */
  8.1076 +	
  8.1077 +	spin_unlock_irq(&io_request_lock);
  8.1078 +	fsa_dev_ptr->devno[cid] = DEVICE_NR(scsicmd->request.rq_dev);
  8.1079 +	ret = aac_read(scsicmd, cid);
  8.1080 +	spin_lock_irq(&io_request_lock);
  8.1081 +	return ret;
  8.1082 +	
  8.1083 +    case SS_WRITE:
  8.1084 +    case SM_WRITE:
  8.1085 +	spin_unlock_irq(&io_request_lock);
  8.1086 +	ret = aac_write(scsicmd, cid);
  8.1087 +	spin_lock_irq(&io_request_lock);
  8.1088 +	return ret;
  8.1089 +    default:
  8.1090 +	/*
  8.1091 +	 *	Unhandled commands
  8.1092 +	 */
  8.1093 +	printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", 
  8.1094 +	       scsicmd->cmnd[0]);
  8.1095 +	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | 
  8.1096 +	    CHECK_CONDITION;
  8.1097 +	set_sense((u8 *) &sense_data[cid],
  8.1098 +		  SENKEY_ILLEGAL, SENCODE_INVALID_COMMAND,
  8.1099 +		  ASENCODE_INVALID_COMMAND, 0, 0, 0, 0);
  8.1100 +	__aac_io_done(scsicmd);
  8.1101 +	return -1;
  8.1102 +    }
  8.1103 +}
  8.1104 +
  8.1105 +static int query_disk(struct aac_dev *dev, void *arg)
  8.1106 +{
  8.1107 +    struct aac_query_disk qd;
  8.1108 +    struct fsa_scsi_hba *fsa_dev_ptr;
  8.1109 +    
  8.1110 +    fsa_dev_ptr = &(dev->fsa_dev);
  8.1111 +    if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
  8.1112 +	return -EFAULT;
  8.1113 +    if (qd.cnum == -1)
  8.1114 +	qd.cnum = TARGET_LUN_TO_CONTAINER(qd.target, qd.lun);
  8.1115 +    else if ((qd.bus == -1) && (qd.target == -1) && (qd.lun == -1)) 
  8.1116 +    {
  8.1117 +	if (qd.cnum < 0 || qd.cnum > MAXIMUM_NUM_CONTAINERS)
  8.1118 +	    return -EINVAL;
  8.1119 +	qd.instance = dev->scsi_host_ptr->host_no;
  8.1120 +	qd.bus = 0;
  8.1121 +	qd.target = CONTAINER_TO_TARGET(qd.cnum);
  8.1122 +	qd.lun = CONTAINER_TO_LUN(qd.cnum);
  8.1123 +    }
  8.1124 +    else return -EINVAL;
  8.1125 +    
  8.1126 +    qd.valid = fsa_dev_ptr->valid[qd.cnum];
  8.1127 +    qd.locked = fsa_dev_ptr->locked[qd.cnum];
  8.1128 +    qd.deleted = fsa_dev_ptr->deleted[qd.cnum];
  8.1129 +    
  8.1130 +    if (fsa_dev_ptr->devno[qd.cnum] == -1)
  8.1131 +	qd.unmapped = 1;
  8.1132 +    else
  8.1133 +	qd.unmapped = 0;
  8.1134 +    
  8.1135 +    get_sd_devname(fsa_dev_ptr->devno[qd.cnum], qd.name);
  8.1136 +    
  8.1137 +    if (copy_to_user(arg, &qd, sizeof (struct aac_query_disk)))
  8.1138 +	return -EFAULT;
  8.1139 +    return 0;
  8.1140 +}
  8.1141 +
  8.1142 +static void get_sd_devname(int disknum, char *buffer)
  8.1143 +{
  8.1144 +    if (disknum < 0) {
  8.1145 +	sprintf(buffer, "%s", "");
  8.1146 +	return;
  8.1147 +    }
  8.1148 +    
  8.1149 +    if (disknum < 26)
  8.1150 +	sprintf(buffer, "sd%c", 'a' + disknum);
  8.1151 +    else {
  8.1152 +	unsigned int min1;
  8.1153 +	unsigned int min2;
  8.1154 +	/*
  8.1155 +	 * For larger numbers of disks, we need to go to a new
  8.1156 +	 * naming scheme.
  8.1157 +	 */
  8.1158 +	min1 = disknum / 26;
  8.1159 +	min2 = disknum % 26;
  8.1160 +	sprintf(buffer, "sd%c%c", 'a' + min1 - 1, 'a' + min2);
  8.1161 +    }
  8.1162 +}
  8.1163 +
  8.1164 +static int force_delete_disk(struct aac_dev *dev, void *arg)
  8.1165 +{
  8.1166 +    struct aac_delete_disk dd;
  8.1167 +    struct fsa_scsi_hba *fsa_dev_ptr;
  8.1168 +    
  8.1169 +    fsa_dev_ptr = &(dev->fsa_dev);
  8.1170 +    
  8.1171 +    if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
  8.1172 +	return -EFAULT;
  8.1173 +    
  8.1174 +    if (dd.cnum > MAXIMUM_NUM_CONTAINERS)
  8.1175 +	return -EINVAL;
  8.1176 +    /*
  8.1177 +     *	Mark this container as being deleted.
  8.1178 +     */
  8.1179 +    fsa_dev_ptr->deleted[dd.cnum] = 1;
  8.1180 +    /*
  8.1181 +     *	Mark the container as no longer valid
  8.1182 +     */
  8.1183 +    fsa_dev_ptr->valid[dd.cnum] = 0;
  8.1184 +    return 0;
  8.1185 +}
  8.1186 +
  8.1187 +static int delete_disk(struct aac_dev *dev, void *arg)
  8.1188 +{
  8.1189 +    struct aac_delete_disk dd;
  8.1190 +    struct fsa_scsi_hba *fsa_dev_ptr;
  8.1191 +
  8.1192 +    fsa_dev_ptr = &(dev->fsa_dev);
  8.1193 +
  8.1194 +    if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
  8.1195 +	return -EFAULT;
  8.1196 +
  8.1197 +    if (dd.cnum > MAXIMUM_NUM_CONTAINERS)
  8.1198 +	return -EINVAL;
  8.1199 +    /*
  8.1200 +     *	If the container is locked, it can not be deleted by the API.
  8.1201 +     */
  8.1202 +    if (fsa_dev_ptr->locked[dd.cnum])
  8.1203 +	return -EBUSY;
  8.1204 +    else {
  8.1205 +	/*
  8.1206 +	 *	Mark the container as no longer being valid.
  8.1207 +	 */
  8.1208 +	fsa_dev_ptr->valid[dd.cnum] = 0;
  8.1209 +	fsa_dev_ptr->devno[dd.cnum] = -1;
  8.1210 +	return 0;
  8.1211 +    }
  8.1212 +}
  8.1213 +
  8.1214 +int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg)
  8.1215 +{
  8.1216 +    switch (cmd) {
  8.1217 +    case FSACTL_QUERY_DISK:
  8.1218 +	return query_disk(dev, arg);
  8.1219 +    case FSACTL_DELETE_DISK:
  8.1220 +	return delete_disk(dev, arg);
  8.1221 +    case FSACTL_FORCE_DELETE_DISK:
  8.1222 +	return force_delete_disk(dev, arg);
  8.1223 +    case 2131:
  8.1224 +	return aac_get_containers(dev);
  8.1225 +    default:
  8.1226 +	return -ENOTTY;
  8.1227 +    }
  8.1228 +}
  8.1229 +
  8.1230 +/**
  8.1231 + *
  8.1232 + * aac_srb_callback
  8.1233 + * @context: the context set in the fib - here it is scsi cmd
  8.1234 + * @fibptr: pointer to the fib
  8.1235 + *
  8.1236 + * Handles the completion of a scsi command to a non dasd device
  8.1237 + *
  8.1238 + */
  8.1239 +
  8.1240 +static void aac_srb_callback(void *context, struct fib * fibptr)
  8.1241 +{
  8.1242 +    struct aac_dev *dev;
  8.1243 +    struct aac_srb_reply *srbreply;
  8.1244 +    Scsi_Cmnd *scsicmd;
  8.1245 +
  8.1246 +    scsicmd = (Scsi_Cmnd *) context;
  8.1247 +    dev = (struct aac_dev *)scsicmd->host->hostdata;
  8.1248 +
  8.1249 +    if (fibptr == NULL)
  8.1250 +	BUG();
  8.1251 +
  8.1252 +    srbreply = (struct aac_srb_reply *) fib_data(fibptr);
  8.1253 +
  8.1254 +    scsicmd->sense_buffer[0] = '\0';  // initialize sense valid flag to false
  8.1255 +    // calculate resid for sg 
  8.1256 +    scsicmd->resid = scsicmd->request_bufflen - srbreply->data_xfer_length;
  8.1257 +
  8.1258 +    if(scsicmd->use_sg)
  8.1259 +	pci_unmap_sg(dev->pdev, 
  8.1260 +		     (struct scatterlist *)scsicmd->buffer,
  8.1261 +		     scsicmd->use_sg,
  8.1262 +		     scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
  8.1263 +    else if(scsicmd->request_bufflen)
  8.1264 +	pci_unmap_single(dev->pdev, (ulong)scsicmd->SCp.ptr, 
  8.1265 +			 scsicmd->request_bufflen,
  8.1266 +			 scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
  8.1267 +
  8.1268 +    /*
  8.1269 +     * First check the fib status
  8.1270 +     */
  8.1271 +
  8.1272 +    if (le32_to_cpu(srbreply->status) != ST_OK){
  8.1273 +	int len;
  8.1274 +	printk(KERN_WARNING "aac_srb_callback: srb failed, status = %d\n", 
  8.1275 +	       le32_to_cpu(srbreply->status));
  8.1276 +	len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
  8.1277 +	    sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
  8.1278 +	scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8 | 
  8.1279 +	    CHECK_CONDITION;
  8.1280 +	memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
  8.1281 +    }
  8.1282 +
  8.1283 +    /*
  8.1284 +     * Next check the srb status
  8.1285 +     */
  8.1286 +    switch(le32_to_cpu(srbreply->srb_status)){
  8.1287 +    case SRB_STATUS_ERROR_RECOVERY:
  8.1288 +    case SRB_STATUS_PENDING:
  8.1289 +    case SRB_STATUS_SUCCESS:
  8.1290 +	if(scsicmd->cmnd[0] == INQUIRY ){
  8.1291 +	    u8 b;
  8.1292 +	    /* We can't expose disk devices because we can't tell whether they
  8.1293 +	     * are the raw container drives or stand alone drives
  8.1294 +	     */
  8.1295 +	    b = *(u8*)scsicmd->buffer;
  8.1296 +	    if( (b & 0x0f) == TYPE_DISK ){
  8.1297 +		scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
  8.1298 +	    }
  8.1299 +	} else {
  8.1300 +	    scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
  8.1301 +	}
  8.1302 +	break;
  8.1303 +    case SRB_STATUS_DATA_OVERRUN:
  8.1304 +	switch(scsicmd->cmnd[0]){
  8.1305 +	case  READ_6:
  8.1306 +	case  WRITE_6:
  8.1307 +	case  READ_10:
  8.1308 +	case  WRITE_10:
  8.1309 +	case  READ_12:
  8.1310 +	case  WRITE_12:
  8.1311 +	    if(le32_to_cpu(srbreply->data_xfer_length) < scsicmd->underflow ) {
  8.1312 +		printk(KERN_WARNING"aacraid: SCSI CMD underflow\n");
  8.1313 +	    } else {
  8.1314 +		printk(KERN_WARNING"aacraid: SCSI CMD Data Overrun\n");
  8.1315 +	    }
  8.1316 +	    scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
  8.1317 +	    break;
  8.1318 +	default:
  8.1319 +	    scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8;
  8.1320 +	    break;
  8.1321 +	}
  8.1322 +	break;
  8.1323 +    case SRB_STATUS_ABORTED:
  8.1324 +	scsicmd->result = DID_ABORT << 16 | ABORT << 8;
  8.1325 +	break;
  8.1326 +    case SRB_STATUS_ABORT_FAILED:
  8.1327 +	// Not sure about this one - but assuming the hba was trying 
  8.1328 +	// to abort for some reason
  8.1329 +	scsicmd->result = DID_ERROR << 16 | ABORT << 8;
  8.1330 +	break;
  8.1331 +    case SRB_STATUS_PARITY_ERROR:
  8.1332 +	scsicmd->result = DID_PARITY << 16 | MSG_PARITY_ERROR << 8;
  8.1333 +	break;
  8.1334 +    case SRB_STATUS_NO_DEVICE:
  8.1335 +    case SRB_STATUS_INVALID_PATH_ID:
  8.1336 +    case SRB_STATUS_INVALID_TARGET_ID:
  8.1337 +    case SRB_STATUS_INVALID_LUN:
  8.1338 +    case SRB_STATUS_SELECTION_TIMEOUT:
  8.1339 +	scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
  8.1340 +	break;
  8.1341 +
  8.1342 +    case SRB_STATUS_COMMAND_TIMEOUT:
  8.1343 +    case SRB_STATUS_TIMEOUT:
  8.1344 +	scsicmd->result = DID_TIME_OUT << 16 | COMMAND_COMPLETE << 8;
  8.1345 +	break;
  8.1346 +
  8.1347 +    case SRB_STATUS_BUSY:
  8.1348 +	scsicmd->result = DID_NO_CONNECT << 16 | COMMAND_COMPLETE << 8;
  8.1349 +	break;
  8.1350 +
  8.1351 +    case SRB_STATUS_BUS_RESET:
  8.1352 +	scsicmd->result = DID_RESET << 16 | COMMAND_COMPLETE << 8;
  8.1353 +	break;
  8.1354 +
  8.1355 +    case SRB_STATUS_MESSAGE_REJECTED:
  8.1356 +	scsicmd->result = DID_ERROR << 16 | MESSAGE_REJECT << 8;
  8.1357 +	break;
  8.1358 +    case SRB_STATUS_REQUEST_FLUSHED:
  8.1359 +    case SRB_STATUS_ERROR:
  8.1360 +    case SRB_STATUS_INVALID_REQUEST:
  8.1361 +    case SRB_STATUS_REQUEST_SENSE_FAILED:
  8.1362 +    case SRB_STATUS_NO_HBA:
  8.1363 +    case SRB_STATUS_UNEXPECTED_BUS_FREE:
  8.1364 +    case SRB_STATUS_PHASE_SEQUENCE_FAILURE:
  8.1365 +    case SRB_STATUS_BAD_SRB_BLOCK_LENGTH:
  8.1366 +    case SRB_STATUS_DELAYED_RETRY:
  8.1367 +    case SRB_STATUS_BAD_FUNCTION:
  8.1368 +    case SRB_STATUS_NOT_STARTED:
  8.1369 +    case SRB_STATUS_NOT_IN_USE:
  8.1370 +    case SRB_STATUS_FORCE_ABORT:
  8.1371 +    case SRB_STATUS_DOMAIN_VALIDATION_FAIL:
  8.1372 +    default:
  8.1373 +#ifdef AAC_DETAILED_STATUS_INFO
  8.1374 +	printk("aacraid: SRB ERROR (%s)\n", 
  8.1375 +	       aac_get_status_string(le32_to_cpu(srbreply->srb_status)));
  8.1376 +#endif
  8.1377 +	scsicmd->result = DID_ERROR << 16 | COMMAND_COMPLETE << 8;
  8.1378 +	break;
  8.1379 +    }
  8.1380 +    if (le32_to_cpu(srbreply->scsi_status) == 0x02 ){  // Check Condition
  8.1381 +	int len;
  8.1382 +	len = (srbreply->sense_data_size > sizeof(scsicmd->sense_buffer))?
  8.1383 +	    sizeof(scsicmd->sense_buffer):srbreply->sense_data_size;
  8.1384 +	printk(KERN_WARNING "aac_srb_callback: check condition, "
  8.1385 +	       "status = %d len=%d\n", le32_to_cpu(srbreply->status), len);
  8.1386 +	memcpy(scsicmd->sense_buffer, srbreply->sense_data, len);
  8.1387 +    }
  8.1388 +    /*
  8.1389 +     * OR in the scsi status (already shifted up a bit)
  8.1390 +     */
  8.1391 +    scsicmd->result |= le32_to_cpu(srbreply->scsi_status);
  8.1392 +
  8.1393 +    fib_complete(fibptr);
  8.1394 +    fib_free(fibptr);
  8.1395 +    aac_io_done(scsicmd);
  8.1396 +}
  8.1397 +
  8.1398 +/**
  8.1399 + *
  8.1400 + * aac_send_scb_fib
  8.1401 + * @scsicmd: the scsi command block
  8.1402 + *
  8.1403 + * This routine will form a FIB and fill in the aac_srb from the 
  8.1404 + * scsicmd passed in.
  8.1405 + */
  8.1406 +
  8.1407 +static int aac_send_srb_fib(Scsi_Cmnd* scsicmd)
  8.1408 +{
  8.1409 +    struct fib* cmd_fibcontext;
  8.1410 +    struct aac_dev* dev;
  8.1411 +    int status;
  8.1412 +    struct aac_srb *srbcmd;
  8.1413 +    u16 fibsize;
  8.1414 +    u32 flag;
  8.1415 +
  8.1416 +    if( scsicmd->target > 15 || scsicmd->lun > 7) {
  8.1417 +	scsicmd->result = DID_NO_CONNECT << 16;
  8.1418 +	__aac_io_done(scsicmd);
  8.1419 +	return 0;
  8.1420 +    }
  8.1421 +
  8.1422 +    dev = (struct aac_dev *)scsicmd->host->hostdata;
  8.1423 +    switch(scsicmd->sc_data_direction){
  8.1424 +    case SCSI_DATA_WRITE:
  8.1425 +	flag = SRB_DataOut;
  8.1426 +	break;
  8.1427 +    case SCSI_DATA_UNKNOWN:  
  8.1428 +	flag = SRB_DataIn | SRB_DataOut;
  8.1429 +	break;
  8.1430 +    case SCSI_DATA_READ:
  8.1431 +	flag = SRB_DataIn;
  8.1432 +	break;
  8.1433 +    case SCSI_DATA_NONE: 
  8.1434 +    default:
  8.1435 +	flag = SRB_NoDataXfer;
  8.1436 +	break;
  8.1437 +    }
  8.1438 +
  8.1439 +
  8.1440 +    /*
  8.1441 +     *	Allocate and initialize a Fib then setup a BlockWrite command
  8.1442 +     */
  8.1443 +    if (!(cmd_fibcontext = fib_alloc(dev))) {
  8.1444 +	scsicmd->result = DID_ERROR << 16;
  8.1445 +	__aac_io_done(scsicmd);
  8.1446 +	return -1;
  8.1447 +    }
  8.1448 +    fib_init(cmd_fibcontext);
  8.1449 +
  8.1450 +    srbcmd = (struct aac_srb*) fib_data(cmd_fibcontext);
  8.1451 +    srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);
  8.1452 +    srbcmd->channel  = cpu_to_le32(aac_logical_to_phys(scsicmd->channel));
  8.1453 +    srbcmd->target   = cpu_to_le32(scsicmd->target);
  8.1454 +    srbcmd->lun      = cpu_to_le32(scsicmd->lun);
  8.1455 +    srbcmd->flags    = cpu_to_le32(flag);
  8.1456 +    srbcmd->timeout  = cpu_to_le32(0);  // timeout not used
  8.1457 +    srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
  8.1458 +    srbcmd->cdb_size = cpu_to_le32(scsicmd->cmd_len);
  8.1459 +	
  8.1460 +    if( dev->pae_support ==1 ) {
  8.1461 +	aac_build_sg64(scsicmd, (struct sgmap64*) &srbcmd->sg);
  8.1462 +	srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
  8.1463 +
  8.1464 +	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
  8.1465 +	memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);
  8.1466 +	/*
  8.1467 +	 *	Build Scatter/Gather list
  8.1468 +	 */
  8.1469 +	fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) 
  8.1470 +					     * sizeof (struct sgentry64));
  8.1471 +
  8.1472 +	/*
  8.1473 +	 *	Now send the Fib to the adapter
  8.1474 +	 */
  8.1475 +	status = fib_send(ScsiPortCommand64, cmd_fibcontext, fibsize, 
  8.1476 +			  FsaNormal, 0, 1, (fib_callback) aac_srb_callback, 
  8.1477 +			  (void *) scsicmd);
  8.1478 +    } else {
  8.1479 +	aac_build_sg(scsicmd, (struct sgmap*)&srbcmd->sg);
  8.1480 +	srbcmd->count = cpu_to_le32(scsicmd->request_bufflen);
  8.1481 +
  8.1482 +	memset(srbcmd->cdb, 0, sizeof(srbcmd->cdb));
  8.1483 +	memcpy(srbcmd->cdb, scsicmd->cmnd, scsicmd->cmd_len);
  8.1484 +	/*
  8.1485 +	 *	Build Scatter/Gather list
  8.1486 +	 */
  8.1487 +	fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) 
  8.1488 +					     * sizeof (struct sgentry));
  8.1489 +
  8.1490 +	/*
  8.1491 +	 *	Now send the Fib to the adapter
  8.1492 +	 */
  8.1493 +	status = fib_send(ScsiPortCommand, cmd_fibcontext, fibsize, 
  8.1494 +			  FsaNormal, 0, 1, (fib_callback) aac_srb_callback, 
  8.1495 +			  (void *) scsicmd);
  8.1496 +    }
  8.1497 +    /*
  8.1498 +     *	Check that the command queued to the controller
  8.1499 +     */
  8.1500 +    if (status == -EINPROGRESS){
  8.1501 +	return 0;
  8.1502 +    }
  8.1503 +
  8.1504 +    printk(KERN_WARNING "aac_srb: fib_send failed with status: %d\n", status);
  8.1505 +    /*
  8.1506 +     *	For some reason, the Fib didn't queue, return QUEUE_FULL
  8.1507 +     */
  8.1508 +    scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | QUEUE_FULL;
  8.1509 +    __aac_io_done(scsicmd);
  8.1510 +
  8.1511 +    fib_complete(cmd_fibcontext);
  8.1512 +    fib_free(cmd_fibcontext);
  8.1513 +
  8.1514 +    return -1;
  8.1515 +}
  8.1516 +
  8.1517 +static unsigned long aac_build_sg(Scsi_Cmnd* scsicmd, struct sgmap* psg)
  8.1518 +{
  8.1519 +    struct aac_dev *dev;
  8.1520 +    unsigned long byte_count = 0;
  8.1521 +
  8.1522 +    dev = (struct aac_dev *)scsicmd->host->hostdata;
  8.1523 +    // Get rid of old data
  8.1524 +    psg->count = cpu_to_le32(0);
  8.1525 +    psg->sg[0].addr = cpu_to_le32(NULL);
  8.1526 +    psg->sg[0].count = cpu_to_le32(0);  
  8.1527 +    if (scsicmd->use_sg) {
  8.1528 +	struct scatterlist *sg;
  8.1529 +	int i;
  8.1530 +	int sg_count;
  8.1531 +	sg = (struct scatterlist *) scsicmd->request_buffer;
  8.1532 +
  8.1533 +	sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
  8.1534 +			      scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
  8.1535 +	psg->count = cpu_to_le32(sg_count);
  8.1536 +
  8.1537 +	byte_count = 0;
  8.1538 +
  8.1539 +	for (i = 0; i < sg_count; i++) {
  8.1540 +	    psg->sg[i].addr = cpu_to_le32(sg_dma_address(sg));
  8.1541 +	    psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
  8.1542 +	    byte_count += sg_dma_len(sg);
  8.1543 +	    sg++;
  8.1544 +	}
  8.1545 +	/* hba wants the size to be exact */
  8.1546 +	if(byte_count > scsicmd->request_bufflen){
  8.1547 +	    psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
  8.1548 +	    byte_count = scsicmd->request_bufflen;
  8.1549 +	}
  8.1550 +	/* Check for command underflow */
  8.1551 +	if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
  8.1552 +	    printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
  8.1553 +		   byte_count, scsicmd->underflow);
  8.1554 +	}
  8.1555 +    }
  8.1556 +    else if(scsicmd->request_bufflen) {
  8.1557 +	dma_addr_t addr; 
  8.1558 +	addr = pci_map_single(dev->pdev,
  8.1559 +			      scsicmd->request_buffer,
  8.1560 +			      scsicmd->request_bufflen,
  8.1561 +			      scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
  8.1562 +	psg->count = cpu_to_le32(1);
  8.1563 +	psg->sg[0].addr = cpu_to_le32(addr);
  8.1564 +	psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
  8.1565 +	scsicmd->SCp.ptr = (void *)addr;
  8.1566 +	byte_count = scsicmd->request_bufflen;
  8.1567 +    }
  8.1568 +    return byte_count;
  8.1569 +}
  8.1570 +
  8.1571 +
  8.1572 +static unsigned long aac_build_sg64(Scsi_Cmnd* scsicmd, struct sgmap64* psg)
  8.1573 +{
  8.1574 +    struct aac_dev *dev;
  8.1575 +    unsigned long byte_count = 0;
  8.1576 +    u64 le_addr;
  8.1577 +
  8.1578 +    dev = (struct aac_dev *)scsicmd->host->hostdata;
  8.1579 +    // Get rid of old data
  8.1580 +    psg->count = cpu_to_le32(0);
  8.1581 +    psg->sg[0].addr[0] = cpu_to_le32(NULL);
  8.1582 +    psg->sg[0].addr[1] = cpu_to_le32(NULL);
  8.1583 +    psg->sg[0].count = cpu_to_le32(0);  
  8.1584 +    if (scsicmd->use_sg) {
  8.1585 +	struct scatterlist *sg;
  8.1586 +	int i;
  8.1587 +	int sg_count;
  8.1588 +	sg = (struct scatterlist *) scsicmd->request_buffer;
  8.1589 +
  8.1590 +	sg_count = pci_map_sg(dev->pdev, sg, scsicmd->use_sg,
  8.1591 +			      scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
  8.1592 +	psg->count = cpu_to_le32(sg_count);
  8.1593 +
  8.1594 +	byte_count = 0;
  8.1595 +
  8.1596 +	for (i = 0; i < sg_count; i++) {
  8.1597 +	    le_addr = cpu_to_le64(sg_dma_address(sg));
  8.1598 +	    psg->sg[i].addr[1] = (u32)(le_addr>>32);
  8.1599 +	    psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
  8.1600 +	    psg->sg[i].count = cpu_to_le32(sg_dma_len(sg));
  8.1601 +	    byte_count += sg_dma_len(sg);
  8.1602 +	    sg++;
  8.1603 +	}
  8.1604 +	/* hba wants the size to be exact */
  8.1605 +	if(byte_count > scsicmd->request_bufflen){
  8.1606 +	    psg->sg[i-1].count -= (byte_count - scsicmd->request_bufflen);
  8.1607 +	    byte_count = scsicmd->request_bufflen;
  8.1608 +	}
  8.1609 +	/* Check for command underflow */
  8.1610 +	if(scsicmd->underflow && (byte_count < scsicmd->underflow)){
  8.1611 +	    printk(KERN_WARNING"aacraid: cmd len %08lX cmd underflow %08X\n",
  8.1612 +		   byte_count, scsicmd->underflow);
  8.1613 +	}
  8.1614 +    }
  8.1615 +    else if(scsicmd->request_bufflen) {
  8.1616 +	dma_addr_t addr; 
  8.1617 +	addr = pci_map_single(dev->pdev,
  8.1618 +			      scsicmd->request_buffer,
  8.1619 +			      scsicmd->request_bufflen,
  8.1620 +			      scsi_to_pci_dma_dir(scsicmd->sc_data_direction));
  8.1621 +	psg->count = cpu_to_le32(1);
  8.1622 +	le_addr = cpu_to_le64(addr);
  8.1623 +	psg->sg[0].addr[1] = (u32)(le_addr>>32);
  8.1624 +	psg->sg[0].addr[0] = (u32)(le_addr & 0xffffffff);
  8.1625 +	psg->sg[0].count = cpu_to_le32(scsicmd->request_bufflen);  
  8.1626 +	scsicmd->SCp.ptr = (void *)addr;
  8.1627 +	byte_count = scsicmd->request_bufflen;
  8.1628 +    }
  8.1629 +    return byte_count;
  8.1630 +}
  8.1631 +
  8.1632 +#ifdef AAC_DETAILED_STATUS_INFO
  8.1633 +
  8.1634 +struct aac_srb_status_info {
  8.1635 +	u32	status;
  8.1636 +	char	*str;
  8.1637 +};
  8.1638 +
  8.1639 +
  8.1640 +static struct aac_srb_status_info srb_status_info[] = {
  8.1641 +	{ SRB_STATUS_PENDING,		"Pending Status"},
  8.1642 +	{ SRB_STATUS_SUCCESS,		"Success"},
  8.1643 +	{ SRB_STATUS_ABORTED,		"Aborted Command"},
  8.1644 +	{ SRB_STATUS_ABORT_FAILED,	"Abort Failed"},
  8.1645 +	{ SRB_STATUS_ERROR,		"Error Event"}, 
  8.1646 +	{ SRB_STATUS_BUSY,		"Device Busy"},
  8.1647 +	{ SRB_STATUS_INVALID_REQUEST,	"Invalid Request"},
  8.1648 +	{ SRB_STATUS_INVALID_PATH_ID,	"Invalid Path ID"},
  8.1649 +	{ SRB_STATUS_NO_DEVICE,		"No Device"},
  8.1650 +	{ SRB_STATUS_TIMEOUT,		"Timeout"},
  8.1651 +	{ SRB_STATUS_SELECTION_TIMEOUT,	"Selection Timeout"},
  8.1652 +	{ SRB_STATUS_COMMAND_TIMEOUT,	"Command Timeout"},
  8.1653 +	{ SRB_STATUS_MESSAGE_REJECTED,	"Message Rejected"},
  8.1654 +	{ SRB_STATUS_BUS_RESET,		"Bus Reset"},
  8.1655 +	{ SRB_STATUS_PARITY_ERROR,	"Parity Error"},
  8.1656 +	{ SRB_STATUS_REQUEST_SENSE_FAILED,"Request Sense Failed"},
  8.1657 +	{ SRB_STATUS_NO_HBA,		"No HBA"},
  8.1658 +	{ SRB_STATUS_DATA_OVERRUN,	"Data Overrun/Data Underrun"},
  8.1659 +	{ SRB_STATUS_UNEXPECTED_BUS_FREE,"Unexpected Bus Free"},
  8.1660 +	{ SRB_STATUS_PHASE_SEQUENCE_FAILURE,"Phase Error"},
  8.1661 +	{ SRB_STATUS_BAD_SRB_BLOCK_LENGTH,"Bad Srb Block Length"},
  8.1662 +	{ SRB_STATUS_REQUEST_FLUSHED,	"Request Flushed"},
  8.1663 +	{ SRB_STATUS_DELAYED_RETRY,	"Delayed Retry"},
  8.1664 +	{ SRB_STATUS_INVALID_LUN,	"Invalid LUN"}, 
  8.1665 +	{ SRB_STATUS_INVALID_TARGET_ID,	"Invalid TARGET ID"},
  8.1666 +	{ SRB_STATUS_BAD_FUNCTION,	"Bad Function"},
  8.1667 +	{ SRB_STATUS_ERROR_RECOVERY,	"Error Recovery"},
  8.1668 +	{ SRB_STATUS_NOT_STARTED,	"Not Started"},
  8.1669 +	{ SRB_STATUS_NOT_IN_USE,	"Not In Use"},
  8.1670 +    	{ SRB_STATUS_FORCE_ABORT,	"Force Abort"},
  8.1671 +	{ SRB_STATUS_DOMAIN_VALIDATION_FAIL,"Domain Validation Failure"},
  8.1672 +	{ 0xff,				"Unknown Error"}
  8.1673 +};
  8.1674 +
  8.1675 +char *aac_get_status_string(u32 status)
  8.1676 +{
  8.1677 +	int i;
  8.1678 +
  8.1679 +	for(i=0; i < (sizeof(srb_status_info)/sizeof(struct aac_srb_status_info)); i++ ){
  8.1680 +		if(srb_status_info[i].status == status){
  8.1681 +			return srb_status_info[i].str;
  8.1682 +		}
  8.1683 +	}
  8.1684 +
  8.1685 +	return "Bad Status Code";
  8.1686 +}
  8.1687 +
  8.1688 +#endif
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/aacraid.h	Fri Feb 21 15:10:37 2003 +0000
     9.3 @@ -0,0 +1,1419 @@
     9.4 +
     9.5 +/* #define dprintk(x) */
     9.6 +// #define dprintk(x) printk x
     9.7 +#define dprintk(x)
     9.8 +
     9.9 +
    9.10 +#include <asm/byteorder.h>
    9.11 +
    9.12 +#define TRY_SOFTIRQ
    9.13 +#ifdef TRY_SOFTIRQ
    9.14 +/* XXX SMH: trying to use softirqs to trigger stuff done prev by threads */
    9.15 +#include <xeno/interrupt.h>  /* for softirq stuff */
    9.16 +#endif
    9.17 +
    9.18 +/*------------------------------------------------------------------------------
    9.19 + *              D E F I N E S
    9.20 + *----------------------------------------------------------------------------*/
    9.21 +
    9.22 +#define MAXIMUM_NUM_CONTAINERS	31
    9.23 +#define MAXIMUM_NUM_ADAPTERS	8
    9.24 +
    9.25 +#define AAC_NUM_FIB	578
    9.26 +#define AAC_NUM_IO_FIB	512
    9.27 +
    9.28 +#define AAC_MAX_TARGET (MAXIMUM_NUM_CONTAINERS+1)
    9.29 +//#define AAC_MAX_TARGET 	(16)
    9.30 +#define AAC_MAX_LUN	(8)
    9.31 +
    9.32 +/*
    9.33 + * These macros convert from physical channels to virtual channels
    9.34 + */
    9.35 +#define CONTAINER_CHANNEL	(0)
    9.36 +#define aac_phys_to_logical(x)  (x+1)
    9.37 +#define aac_logical_to_phys(x)  (x?x-1:0)
    9.38 +
    9.39 +#define AAC_DETAILED_STATUS_INFO
    9.40 +
    9.41 +struct diskparm
    9.42 +{
    9.43 +	int heads;
    9.44 +	int sectors;
    9.45 +	int cylinders;
    9.46 +};
    9.47 +
    9.48 +
    9.49 +/*
    9.50 + *	DON'T CHANGE THE ORDER, this is set by the firmware
    9.51 + */
    9.52 + 
    9.53 +#define		CT_NONE			0
    9.54 +#define		CT_VOLUME		1
    9.55 +#define		CT_MIRROR		2
    9.56 +#define		CT_STRIPE		3
    9.57 +#define		CT_RAID5		4
    9.58 +#define		CT_SSRW			5
    9.59 +#define		CT_SSRO			6
    9.60 +#define		CT_MORPH		7
    9.61 +#define		CT_PASSTHRU		8
    9.62 +#define		CT_RAID4		9
    9.63 +#define		CT_RAID10		10	/* stripe of mirror */
    9.64 +#define		CT_RAID00		11	/* stripe of stripe */
    9.65 +#define		CT_VOLUME_OF_MIRRORS	12	/* volume of mirror */
    9.66 +#define		CT_PSEUDO_RAID		13	/* really raid4 */
    9.67 +#define		CT_LAST_VOLUME_TYPE	14
    9.68 +
    9.69 +/*
    9.70 + *	Types of objects addressable in some fashion by the client.
    9.71 + *	This is a superset of those objects handled just by the filesystem
    9.72 + *	and includes "raw" objects that an administrator would use to
    9.73 + *	configure containers and filesystems.
    9.74 + */
    9.75 +
    9.76 +#define		FT_REG		1	/* regular file */
    9.77 +#define		FT_DIR		2	/* directory */
    9.78 +#define		FT_BLK		3	/* "block" device - reserved */
    9.79 +#define		FT_CHR		4	/* "character special" device - reserved */
    9.80 +#define		FT_LNK		5	/* symbolic link */
    9.81 +#define		FT_SOCK		6	/* socket */
    9.82 +#define		FT_FIFO		7	/* fifo */
    9.83 +#define		FT_FILESYS	8	/* ADAPTEC's "FSA"(tm) filesystem */
    9.84 +#define		FT_DRIVE	9	/* physical disk - addressable in scsi by bus/target/lun */
    9.85 +#define		FT_SLICE	10	/* virtual disk - raw volume - slice */
    9.86 +#define		FT_PARTITION	11	/* FSA partition - carved out of a slice - building block for containers */
    9.87 +#define		FT_VOLUME	12	/* Container - Volume Set */
    9.88 +#define		FT_STRIPE	13	/* Container - Stripe Set */
    9.89 +#define		FT_MIRROR	14	/* Container - Mirror Set */
    9.90 +#define		FT_RAID5	15	/* Container - Raid 5 Set */
    9.91 +#define		FT_DATABASE	16	/* Storage object with "foreign" content manager */
    9.92 +
    9.93 +/*
    9.94 + *	Host side memory scatter gather list
    9.95 + *	Used by the adapter for read, write, and readdirplus operations
    9.96 + *	We have seperate 32 and 64 bit version because even
    9.97 + *	on 64 bit systems not all cards support the 64 bit version
    9.98 + */
    9.99 +struct sgentry {
   9.100 +	u32	addr;	/* 32-bit address. */
   9.101 +	u32	count;	/* Length. */
   9.102 +};
   9.103 +
   9.104 +struct sgentry64 {
   9.105 +	u32	addr[2];	/* 64-bit addr. 2 pieces for data alignment */
   9.106 +	u32	count;	/* Length. */
   9.107 +};
   9.108 +
   9.109 +/*
   9.110 + *	SGMAP
   9.111 + *
   9.112 + *	This is the SGMAP structure for all commands that use
   9.113 + *	32-bit addressing.
   9.114 + */
   9.115 +
   9.116 +struct sgmap {
   9.117 +	u32		count;
   9.118 +	struct sgentry	sg[1]; 
   9.119 +};
   9.120 +
   9.121 +struct sgmap64 {
   9.122 +	u32		count;
   9.123 +	struct sgentry64 sg[1];
   9.124 +};
   9.125 +
   9.126 +struct creation_info
   9.127 +{
   9.128 +	u8 		buildnum;		/* e.g., 588 */
   9.129 +	u8 		usec;			/* e.g., 588 */
   9.130 +	u8	 	via;			/* e.g., 1 = FSU,
   9.131 +						 * 	 2 = API
   9.132 +						 */
   9.133 +	u8	 	year;		 	/* e.g., 1997 = 97 */
   9.134 +	u32		date;			/*
   9.135 +						 * unsigned 	Month		:4;	// 1 - 12
   9.136 +						 * unsigned 	Day		:6;	// 1 - 32
   9.137 +						 * unsigned 	Hour		:6;	// 0 - 23
   9.138 +						 * unsigned 	Minute		:6;	// 0 - 60
   9.139 +						 * unsigned 	Second		:6;	// 0 - 60
   9.140 +						 */
   9.141 +	u32		serial[2];			/* e.g., 0x1DEADB0BFAFAF001 */
   9.142 +};
   9.143 +
   9.144 +
   9.145 +/*
   9.146 + *	Define all the constants needed for the communication interface
   9.147 + */
   9.148 +
   9.149 +/*
   9.150 + *	Define how many queue entries each queue will have and the total
   9.151 + *	number of entries for the entire communication interface. Also define
   9.152 + *	how many queues we support.
   9.153 + *
   9.154 + *	This has to match the controller
   9.155 + */
   9.156 +
   9.157 +#define NUMBER_OF_COMM_QUEUES  8   // 4 command; 4 response
   9.158 +#define HOST_HIGH_CMD_ENTRIES  4
   9.159 +#define HOST_NORM_CMD_ENTRIES  8
   9.160 +#define ADAP_HIGH_CMD_ENTRIES  4
   9.161 +#define ADAP_NORM_CMD_ENTRIES  512
   9.162 +#define HOST_HIGH_RESP_ENTRIES 4
   9.163 +#define HOST_NORM_RESP_ENTRIES 512
   9.164 +#define ADAP_HIGH_RESP_ENTRIES 4
   9.165 +#define ADAP_NORM_RESP_ENTRIES 8
   9.166 +
   9.167 +#define TOTAL_QUEUE_ENTRIES  \
   9.168 +    (HOST_NORM_CMD_ENTRIES + HOST_HIGH_CMD_ENTRIES + ADAP_NORM_CMD_ENTRIES + ADAP_HIGH_CMD_ENTRIES + \
   9.169 +	    HOST_NORM_RESP_ENTRIES + HOST_HIGH_RESP_ENTRIES + ADAP_NORM_RESP_ENTRIES + ADAP_HIGH_RESP_ENTRIES)
   9.170 +
   9.171 +
   9.172 +/*
   9.173 + *	Set the queues on a 16 byte alignment
   9.174 + */
   9.175 + 
   9.176 +#define QUEUE_ALIGNMENT		16
   9.177 +
   9.178 +/*
   9.179 + *	The queue headers define the Communication Region queues. These
   9.180 + *	are physically contiguous and accessible by both the adapter and the
   9.181 + *	host. Even though all queue headers are in the same contiguous block
   9.182 + *	they will be represented as individual units in the data structures.
   9.183 + */
   9.184 +
   9.185 +struct aac_entry {
   9.186 +	u32 size;          /* Size in bytes of Fib which this QE points to */
   9.187 +	u32 addr; /* Receiver address of the FIB */
   9.188 +};
   9.189 +
   9.190 +/*
   9.191 + *	The adapter assumes the ProducerIndex and ConsumerIndex are grouped
   9.192 + *	adjacently and in that order.
   9.193 + */
   9.194 + 
   9.195 +struct aac_qhdr {
   9.196 +	u64 header_addr;		/* Address to hand the adapter to access to this queue head */
   9.197 +	u32 *producer;			/* The producer index for this queue (host address) */
   9.198 +	u32 *consumer;			/* The consumer index for this queue (host address) */
   9.199 +};
   9.200 +
   9.201 +/*
   9.202 + *	Define all the events which the adapter would like to notify
   9.203 + *	the host of.
   9.204 + */
   9.205 + 
   9.206 +#define		HostNormCmdQue		1	/* Change in host normal priority command queue */
   9.207 +#define		HostHighCmdQue		2	/* Change in host high priority command queue */
   9.208 +#define		HostNormRespQue		3	/* Change in host normal priority response queue */
   9.209 +#define		HostHighRespQue		4	/* Change in host high priority response queue */
   9.210 +#define		AdapNormRespNotFull	5
   9.211 +#define		AdapHighRespNotFull	6
   9.212 +#define		AdapNormCmdNotFull	7
   9.213 +#define		AdapHighCmdNotFull	8
   9.214 +#define		SynchCommandComplete	9
   9.215 +#define		AdapInternalError	0xfe    /* The adapter detected an internal error shutting down */
   9.216 +
   9.217 +/*
   9.218 + *	Define all the events the host wishes to notify the
   9.219 + *	adapter of. The first four values much match the Qid the
   9.220 + *	corresponding queue.
   9.221 + */
   9.222 +
   9.223 +#define		AdapNormCmdQue		2
   9.224 +#define		AdapHighCmdQue		3
   9.225 +#define		AdapNormRespQue		6
   9.226 +#define		AdapHighRespQue		7
   9.227 +#define		HostShutdown		8
   9.228 +#define		HostPowerFail		9
   9.229 +#define		FatalCommError		10
   9.230 +#define		HostNormRespNotFull	11
   9.231 +#define		HostHighRespNotFull	12
   9.232 +#define		HostNormCmdNotFull	13
   9.233 +#define		HostHighCmdNotFull	14
   9.234 +#define		FastIo			15
   9.235 +#define		AdapPrintfDone		16
   9.236 +
   9.237 +/*
   9.238 + *	Define all the queues that the adapter and host use to communicate
   9.239 + *	Number them to match the physical queue layout.
   9.240 + */
   9.241 +
   9.242 +enum aac_queue_types {
   9.243 +        HostNormCmdQueue = 0,	/* Adapter to host normal priority command traffic */
   9.244 +        HostHighCmdQueue,	/* Adapter to host high priority command traffic */
   9.245 +        AdapNormCmdQueue,	/* Host to adapter normal priority command traffic */
   9.246 +        AdapHighCmdQueue,	/* Host to adapter high priority command traffic */
   9.247 +        HostNormRespQueue,	/* Adapter to host normal priority response traffic */
   9.248 +        HostHighRespQueue,	/* Adapter to host high priority response traffic */
   9.249 +        AdapNormRespQueue,	/* Host to adapter normal priority response traffic */
   9.250 +        AdapHighRespQueue	/* Host to adapter high priority response traffic */
   9.251 +};
   9.252 +
   9.253 +/*
   9.254 + *	Assign type values to the FSA communication data structures
   9.255 + */
   9.256 +
   9.257 +#define		FIB_MAGIC	0x0001
   9.258 +
   9.259 +/*
   9.260 + *	Define the priority levels the FSA communication routines support.
   9.261 + */
   9.262 +
   9.263 +#define		FsaNormal	1
   9.264 +#define		FsaHigh		2
   9.265 +
   9.266 +/*
   9.267 + * Define the FIB. The FIB is the where all the requested data and
   9.268 + * command information are put to the application on the FSA adapter.
   9.269 + */
   9.270 +
   9.271 +struct aac_fibhdr {
   9.272 +    u32 XferState;		// Current transfer state for this CCB
   9.273 +    u16 Command;		// Routing information for the destination
   9.274 +    u8 StructType;		// Type FIB
   9.275 +    u8 Flags;			// Flags for FIB
   9.276 +    u16 Size;			// Size of this FIB in bytes
   9.277 +    u16 SenderSize;		// Size of the FIB in the sender (for 
   9.278 +                                // response sizing)
   9.279 +    u32 SenderFibAddress;	// Host defined data in the FIB
   9.280 +    u32 ReceiverFibAddress;	// Logical address of this FIB for the adapter
   9.281 +    u32 SenderData;		// Place holder for the sender to store data
   9.282 +    union {
   9.283 +	struct {
   9.284 +	    u32 _ReceiverTimeStart;  // Timestamp for receipt of fib
   9.285 +	    u32 _ReceiverTimeDone;   // Timestamp for completion of fib
   9.286 +	} _s;
   9.287 +	struct list_head _FibLinks;  // Used to link Adapter Initiated 
   9.288 +	                             // Fibs on the host
   9.289 +    } _u;
   9.290 +};
   9.291 +
   9.292 +#define FibLinks			_u._FibLinks
   9.293 +
   9.294 +#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr))
   9.295 +
   9.296 +
   9.297 +struct hw_fib {
   9.298 +	struct aac_fibhdr header;
   9.299 +	u8 data[FIB_DATA_SIZE_IN_BYTES];		// Command specific data
   9.300 +};
   9.301 +
   9.302 +/*
   9.303 + *	FIB commands
   9.304 + */
   9.305 +
   9.306 +#define 	TestCommandResponse		1
   9.307 +#define		TestAdapterCommand		2
   9.308 +/*
   9.309 + *	Lowlevel and comm commands
   9.310 + */
   9.311 +#define		LastTestCommand			100
   9.312 +#define		ReinitHostNormCommandQueue	101
   9.313 +#define		ReinitHostHighCommandQueue	102
   9.314 +#define		ReinitHostHighRespQueue		103
   9.315 +#define		ReinitHostNormRespQueue		104
   9.316 +#define		ReinitAdapNormCommandQueue	105
   9.317 +#define		ReinitAdapHighCommandQueue	107
   9.318 +#define		ReinitAdapHighRespQueue		108
   9.319 +#define		ReinitAdapNormRespQueue		109
   9.320 +#define		InterfaceShutdown		110
   9.321 +#define		DmaCommandFib			120
   9.322 +#define		StartProfile			121
   9.323 +#define		TermProfile			122
   9.324 +#define		SpeedTest			123
   9.325 +#define		TakeABreakPt			124
   9.326 +#define		RequestPerfData			125
   9.327 +#define		SetInterruptDefTimer		126
   9.328 +#define		SetInterruptDefCount		127
   9.329 +#define		GetInterruptDefStatus		128
   9.330 +#define		LastCommCommand			129
   9.331 +/*
   9.332 + *	Filesystem commands
   9.333 + */
   9.334 +#define		NuFileSystem			300
   9.335 +#define		UFS				301
   9.336 +#define		HostFileSystem			302
   9.337 +#define		LastFileSystemCommand		303
   9.338 +/*
   9.339 + *	Container Commands
   9.340 + */
   9.341 +#define		ContainerCommand		500
   9.342 +#define		ContainerCommand64		501
   9.343 +/*
   9.344 + *	Cluster Commands
   9.345 + */
   9.346 +#define		ClusterCommand	 		550
   9.347 +/*
   9.348 + *	Scsi Port commands (scsi passthrough)
   9.349 + */
   9.350 +#define		ScsiPortCommand			600
   9.351 +#define		ScsiPortCommand64		601
   9.352 +/*
   9.353 + *	Misc house keeping and generic adapter initiated commands
   9.354 + */
   9.355 +#define		AifRequest			700
   9.356 +#define		CheckRevision			701
   9.357 +#define		FsaHostShutdown			702
   9.358 +#define		RequestAdapterInfo		703
   9.359 +#define		IsAdapterPaused			704
   9.360 +#define		SendHostTime			705
   9.361 +#define		LastMiscCommand			706
   9.362 +
   9.363 +//
   9.364 +// Commands that will target the failover level on the FSA adapter
   9.365 +//
   9.366 +
   9.367 +enum fib_xfer_state {
   9.368 +	HostOwned 			= (1<<0),
   9.369 +	AdapterOwned 			= (1<<1),
   9.370 +	FibInitialized 			= (1<<2),
   9.371 +	FibEmpty 			= (1<<3),
   9.372 +	AllocatedFromPool 		= (1<<4),
   9.373 +	SentFromHost 			= (1<<5),
   9.374 +	SentFromAdapter 		= (1<<6),
   9.375 +	ResponseExpected 		= (1<<7),
   9.376 +	NoResponseExpected 		= (1<<8),
   9.377 +	AdapterProcessed 		= (1<<9),
   9.378 +	HostProcessed 			= (1<<10),
   9.379 +	HighPriority 			= (1<<11),
   9.380 +	NormalPriority 			= (1<<12),
   9.381 +	Async				= (1<<13),
   9.382 +	AsyncIo				= (1<<13),	// rpbfix: remove with new regime
   9.383 +	PageFileIo			= (1<<14),	// rpbfix: remove with new regime
   9.384 +	ShutdownRequest			= (1<<15),
   9.385 +	LazyWrite			= (1<<16),	// rpbfix: remove with new regime
   9.386 +	AdapterMicroFib			= (1<<17),
   9.387 +	BIOSFibPath			= (1<<18),
   9.388 +	FastResponseCapable		= (1<<19),
   9.389 +	ApiFib				= (1<<20)	// Its an API Fib.
   9.390 +};
   9.391 +
   9.392 +/*
   9.393 + *	The following defines needs to be updated any time there is an
   9.394 + *	incompatible change made to the aac_init structure.
   9.395 + */
   9.396 +
   9.397 +#define ADAPTER_INIT_STRUCT_REVISION		3
   9.398 +
   9.399 +struct aac_init
   9.400 +{
   9.401 +	u32	InitStructRevision;
   9.402 +	u32	MiniPortRevision;
   9.403 +	u32	fsrev;
   9.404 +	u32	CommHeaderAddress;
   9.405 +	u32	FastIoCommAreaAddress;
   9.406 +	u32	AdapterFibsPhysicalAddress;
   9.407 +	u32	AdapterFibsVirtualAddress;
   9.408 +	u32	AdapterFibsSize;
   9.409 +	u32	AdapterFibAlign;
   9.410 +	u32	printfbuf;
   9.411 +	u32	printfbufsiz;
   9.412 +	u32	HostPhysMemPages;		// number of 4k pages of host physical memory
   9.413 +	u32	HostElapsedSeconds;		// number of seconds since 1970.
   9.414 +};
   9.415 +
   9.416 +enum aac_log_level {
   9.417 +	LOG_INIT			= 10,
   9.418 +	LOG_INFORMATIONAL		= 20,
   9.419 +	LOG_WARNING			= 30,
   9.420 +	LOG_LOW_ERROR			= 40,
   9.421 +	LOG_MEDIUM_ERROR		= 50,
   9.422 +	LOG_HIGH_ERROR			= 60,
   9.423 +	LOG_PANIC			= 70,
   9.424 +	LOG_DEBUG			= 80,
   9.425 +	LOG_WINDBG_PRINT		= 90
   9.426 +};
   9.427 +
   9.428 +#define FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT	0x030b
   9.429 +#define FSAFS_NTC_FIB_CONTEXT			0x030c
   9.430 +
   9.431 +struct aac_dev;
   9.432 +
   9.433 +struct adapter_ops
   9.434 +{
   9.435 +	void (*adapter_interrupt)(struct aac_dev *dev);
   9.436 +	void (*adapter_notify)(struct aac_dev *dev, u32 event);
   9.437 +	void (*adapter_enable_int)(struct aac_dev *dev, u32 event);
   9.438 +	void (*adapter_disable_int)(struct aac_dev *dev, u32 event);
   9.439 +	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status);
   9.440 +};
   9.441 +
   9.442 +/*
   9.443 + *	Define which interrupt handler needs to be installed
   9.444 + */
   9.445 +
   9.446 +struct aac_driver_ident
   9.447 +{
   9.448 +	u16	vendor;
   9.449 +	u16	device;
   9.450 +	u16	subsystem_vendor;
   9.451 +	u16	subsystem_device;
   9.452 +	int 	(*init)(struct aac_dev *dev, unsigned long num);
   9.453 +	char *	name;
   9.454 +	char *	vname;
   9.455 +	char *	model;
   9.456 +	u16	channels;
   9.457 +};
   9.458 +
   9.459 +/*
   9.460 + *	The adapter interface specs all queues to be located in the same
   9.461 + *	physically contigous block. The host structure that defines the
   9.462 + *	commuication queues will assume they are each a seperate physically
   9.463 + *	contigous memory region that will support them all being one big
   9.464 + *	contigous block. 
   9.465 + *	There is a command and response queue for each level and direction of
   9.466 + *	commuication. These regions are accessed by both the host and adapter.
   9.467 + */
   9.468 + 
   9.469 +struct aac_queue {
   9.470 +	u64		 	logical;		/* This is the address we give the adapter */
   9.471 +	struct aac_entry	*base;		   	/* This is the system virtual address */
   9.472 +	struct aac_qhdr 	headers;       		/* A pointer to the producer and consumer queue headers for this queue */
   9.473 +	u32	 		entries;	   	/* Number of queue entries on this queue */
   9.474 +#if 0
   9.475 +	wait_queue_head_t	qfull;		      	/* Event to wait on if the queue is full */
   9.476 +	wait_queue_head_t	cmdready;	  	/* Indicates there is a Command ready from the adapter on this queue. */
   9.477 +#endif
   9.478 +                                        		/* This is only valid for adapter to host command queues. */                      
   9.479 +	spinlock_t	 	*lock;		     	/* Spinlock for this queue must take this lock before accessing the lock */
   9.480 +	spinlock_t		lockdata;		/* Actual lock (used only on one side of the lock) */
   9.481 +	unsigned long		SavedIrql;      	/* Previous IRQL when the spin lock is taken */
   9.482 +	u32			padding;		/* Padding - FIXME - can remove I believe */
   9.483 +	struct list_head 	cmdq;		   	/* A queue of FIBs which need to be prcessed by the FS thread. This is */
   9.484 +                                		        /* only valid for command queues which receive entries from the adapter. */
   9.485 +	struct list_head	pendingq;		/* A queue of outstanding fib's to the adapter. */
   9.486 +	unsigned long		numpending;		/* Number of entries on outstanding queue. */
   9.487 +	struct aac_dev *	dev;			/* Back pointer to adapter structure */
   9.488 +};
   9.489 +
   9.490 +/*
   9.491 + *	Message queues. The order here is important, see also the 
   9.492 + *	queue type ordering
   9.493 + */
   9.494 +
   9.495 +struct aac_queue_block
   9.496 +{
   9.497 +	struct aac_queue queue[8];
   9.498 +};
   9.499 +
   9.500 +/*
   9.501 + *	SaP1 Message Unit Registers
   9.502 + */
   9.503 + 
   9.504 +struct sa_drawbridge_CSR {
   9.505 +						//	 Offset |	Name
   9.506 +	u32	reserved[10];			//	00h-27h |   Reserved
   9.507 +	u8	LUT_Offset;			//	28h	|	Looup Table Offset
   9.508 +	u8	reserved1[3];			// 	29h-2bh	|	Reserved
   9.509 +	u32	LUT_Data;			//	2ch	|	Looup Table Data	
   9.510 +	u32	reserved2[26];			//	30h-97h	|	Reserved
   9.511 +	u16	PRICLEARIRQ;			//	98h	|	Primary Clear Irq
   9.512 +	u16	SECCLEARIRQ;			//	9ah	|	Secondary Clear Irq
   9.513 +	u16	PRISETIRQ;			//	9ch	|	Primary Set Irq
   9.514 +	u16	SECSETIRQ;			//	9eh	|	Secondary Set Irq
   9.515 +	u16	PRICLEARIRQMASK;		//	a0h	|	Primary Clear Irq Mask
   9.516 +	u16	SECCLEARIRQMASK;		//	a2h	|	Secondary Clear Irq Mask
   9.517 +	u16	PRISETIRQMASK;			//	a4h	|	Primary Set Irq Mask
   9.518 +	u16	SECSETIRQMASK;			//	a6h	|	Secondary Set Irq Mask
   9.519 +	u32	MAILBOX0;			//	a8h	|	Scratchpad 0
   9.520 +	u32	MAILBOX1;			//	ach	|	Scratchpad 1
   9.521 +	u32	MAILBOX2;			//	b0h	|	Scratchpad 2
   9.522 +	u32	MAILBOX3;			//	b4h	|	Scratchpad 3
   9.523 +	u32	MAILBOX4;			//	b8h	|	Scratchpad 4
   9.524 +	u32	MAILBOX5;			//	bch	|	Scratchpad 5
   9.525 +	u32	MAILBOX6;			//	c0h	|	Scratchpad 6
   9.526 +	u32	MAILBOX7;			//	c4h	|	Scratchpad 7
   9.527 +
   9.528 +	u32	ROM_Setup_Data;			//	c8h | 	Rom Setup and Data
   9.529 +	u32	ROM_Control_Addr;		//	cch | 	Rom Control and Address
   9.530 +
   9.531 +	u32	reserved3[12];			//	d0h-ffh	| 	reserved
   9.532 +	u32	LUT[64];			// 100h-1ffh|	Lookup Table Entries
   9.533 +
   9.534 +	//
   9.535 +	//  TO DO
   9.536 +	//	need to add DMA, I2O, UART, etc registers form 80h to 364h
   9.537 +	//
   9.538 +
   9.539 +};
   9.540 +
   9.541 +#define Mailbox0	SaDbCSR.MAILBOX0
   9.542 +#define Mailbox1	SaDbCSR.MAILBOX1
   9.543 +#define Mailbox2	SaDbCSR.MAILBOX2
   9.544 +#define Mailbox3	SaDbCSR.MAILBOX3
   9.545 +#define Mailbox4	SaDbCSR.MAILBOX4
   9.546 +#define Mailbox5	SaDbCSR.MAILBOX5
   9.547 +#define Mailbox7	SaDbCSR.MAILBOX7
   9.548 +	
   9.549 +#define DoorbellReg_p SaDbCSR.PRISETIRQ
   9.550 +#define DoorbellReg_s SaDbCSR.SECSETIRQ
   9.551 +#define DoorbellClrReg_p SaDbCSR.PRICLEARIRQ
   9.552 +
   9.553 +
   9.554 +#define	DOORBELL_0	cpu_to_le16(0x0001)
   9.555 +#define DOORBELL_1	cpu_to_le16(0x0002)
   9.556 +#define DOORBELL_2	cpu_to_le16(0x0004)
   9.557 +#define DOORBELL_3	cpu_to_le16(0x0008)
   9.558 +#define DOORBELL_4	cpu_to_le16(0x0010)
   9.559 +#define DOORBELL_5	cpu_to_le16(0x0020)
   9.560 +#define DOORBELL_6	cpu_to_le16(0x0040)
   9.561 +
   9.562 +	
   9.563 +#define PrintfReady	DOORBELL_5
   9.564 +#define PrintfDone	DOORBELL_5
   9.565 +	
   9.566 +struct sa_registers {
   9.567 +	struct sa_drawbridge_CSR	SaDbCSR;			/* 98h - c4h */
   9.568 +};
   9.569 +	
   9.570 +
   9.571 +#define Sa_MINIPORT_REVISION			1
   9.572 +
   9.573 +#define sa_readw(AEP, CSR)		readl(&((AEP)->regs.sa->CSR))
   9.574 +#define sa_readl(AEP,  CSR)		readl(&((AEP)->regs.sa->CSR))
   9.575 +#define sa_writew(AEP, CSR, value)	writew(value, &((AEP)->regs.sa->CSR))
   9.576 +#define sa_writel(AEP, CSR, value)	writel(value, &((AEP)->regs.sa->CSR))
   9.577 +
   9.578 +/*
   9.579 + *	Rx Message Unit Registers
   9.580 + */
   9.581 +
   9.582 +struct rx_mu_registers {
   9.583 +						//	 Local	|   PCI*	|	Name
   9.584 +						//			|		|
   9.585 +	u32	ARSR;				//	1300h	|	00h	|	APIC Register Select Register
   9.586 +	u32	reserved0;			//	1304h	|	04h	|	Reserved
   9.587 +	u32	AWR;				//	1308h	|	08h	|	APIC Window Register
   9.588 +	u32	reserved1;			//	130Ch	|	0Ch	|	Reserved
   9.589 +	u32	IMRx[2];			//	1310h	|	10h	|	Inbound Message Registers
   9.590 +	u32	OMRx[2];			//	1318h	|	18h	|	Outbound Message Registers
   9.591 +	u32	IDR;				//	1320h	|	20h	|	Inbound Doorbell Register
   9.592 +	u32	IISR;				//	1324h	|	24h	|	Inbound Interrupt Status Register
   9.593 +	u32	IIMR;				//	1328h	|	28h	|	Inbound Interrupt Mask Register
   9.594 +	u32	ODR;				//	132Ch	|	2Ch	|	Outbound Doorbell Register
   9.595 +	u32	OISR;				//	1330h	|	30h	|	Outbound Interrupt Status Register
   9.596 +	u32	OIMR;				//	1334h	|	34h	|	Outbound Interrupt Mask Register
   9.597 +						// * Must access through ATU Inbound Translation Window
   9.598 +};
   9.599 +
   9.600 +struct rx_inbound {
   9.601 +	u32	Mailbox[8];
   9.602 +};
   9.603 +
   9.604 +#define	InboundMailbox0		IndexRegs.Mailbox[0]
   9.605 +#define	InboundMailbox1		IndexRegs.Mailbox[1]
   9.606 +#define	InboundMailbox2		IndexRegs.Mailbox[2]
   9.607 +#define	InboundMailbox3		IndexRegs.Mailbox[3]
   9.608 +#define	InboundMailbox4		IndexRegs.Mailbox[4]
   9.609 +
   9.610 +#define	INBOUNDDOORBELL_0	cpu_to_le32(0x00000001)
   9.611 +#define INBOUNDDOORBELL_1	cpu_to_le32(0x00000002)
   9.612 +#define INBOUNDDOORBELL_2	cpu_to_le32(0x00000004)
   9.613 +#define INBOUNDDOORBELL_3	cpu_to_le32(0x00000008)
   9.614 +#define INBOUNDDOORBELL_4	cpu_to_le32(0x00000010)
   9.615 +#define INBOUNDDOORBELL_5	cpu_to_le32(0x00000020)
   9.616 +#define INBOUNDDOORBELL_6	cpu_to_le32(0x00000040)
   9.617 +
   9.618 +#define	OUTBOUNDDOORBELL_0	cpu_to_le32(0x00000001)
   9.619 +#define OUTBOUNDDOORBELL_1	cpu_to_le32(0x00000002)
   9.620 +#define OUTBOUNDDOORBELL_2	cpu_to_le32(0x00000004)
   9.621 +#define OUTBOUNDDOORBELL_3	cpu_to_le32(0x00000008)
   9.622 +#define OUTBOUNDDOORBELL_4	cpu_to_le32(0x00000010)
   9.623 +
   9.624 +#define InboundDoorbellReg	MUnit.IDR
   9.625 +#define OutboundDoorbellReg	MUnit.ODR
   9.626 +
   9.627 +struct rx_registers {
   9.628 +	struct rx_mu_registers		MUnit;		// 1300h - 1334h
   9.629 +	u32				reserved1[6];	// 1338h - 134ch
   9.630 +	struct rx_inbound		IndexRegs;
   9.631 +};
   9.632 +
   9.633 +#define rx_readb(AEP, CSR)		readb(&((AEP)->regs.rx->CSR))
   9.634 +#define rx_readl(AEP, CSR)		readl(&((AEP)->regs.rx->CSR))
   9.635 +#define rx_writeb(AEP, CSR, value)	writeb(value, &((AEP)->regs.rx->CSR))
   9.636 +#define rx_writel(AEP, CSR, value)	writel(value, &((AEP)->regs.rx->CSR))
   9.637 +
   9.638 +struct fib;
   9.639 +
   9.640 +typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
   9.641 +
   9.642 +struct aac_fib_context {
   9.643 +	s16	 		type;		// used for verification of structure	
   9.644 +	s16	 		size;
   9.645 +	ulong			jiffies;	// used for cleanup - dmb changed to ulong
   9.646 +	struct list_head	next;		// used to link context's into a linked list
   9.647 +#if 0
   9.648 +	struct semaphore 	wait_sem;	// this is used to wait for the next fib to arrive.
   9.649 +#endif
   9.650 +	int			wait;		// Set to true when thread is in WaitForSingleObject
   9.651 +	unsigned long		count;		// total number of FIBs on FibList
   9.652 +	struct list_head	fibs;
   9.653 +};
   9.654 +
   9.655 +struct fsa_scsi_hba {
   9.656 +	u32		size[MAXIMUM_NUM_CONTAINERS];
   9.657 +	u32		type[MAXIMUM_NUM_CONTAINERS];
   9.658 +	u8		valid[MAXIMUM_NUM_CONTAINERS];
   9.659 +	u8		ro[MAXIMUM_NUM_CONTAINERS];
   9.660 +	u8		locked[MAXIMUM_NUM_CONTAINERS];
   9.661 +	u8		deleted[MAXIMUM_NUM_CONTAINERS];
   9.662 +	u32		devno[MAXIMUM_NUM_CONTAINERS];
   9.663 +};
   9.664 +
   9.665 +struct fib {
   9.666 +	void			*next;	/* this is used by the allocator */
   9.667 +	s16			type;
   9.668 +	s16			size;
   9.669 +	/*
   9.670 +	 *	The Adapter that this I/O is destined for.
   9.671 +	 */
   9.672 +	struct aac_dev 		*dev;
   9.673 +	u64			logicaladdr;	/* 64 bit */
   9.674 +#if 0
   9.675 +	/*
   9.676 +	 *	This is the event the sendfib routine will wait on if the
   9.677 +	 *	caller did not pass one and this is synch io.
   9.678 +	 */
   9.679 +	struct semaphore 	event_wait;
   9.680 +#endif
   9.681 +	spinlock_t		event_lock;
   9.682 +
   9.683 +	u32			done;	/* gets set to 1 when fib is complete */
   9.684 +	fib_callback 		callback;
   9.685 +	void 			*callback_data;
   9.686 +	u32			flags; // u32 dmb was ulong
   9.687 +	/*
   9.688 +	 *	The following is used to put this fib context onto the 
   9.689 +	 *	Outstanding I/O queue.
   9.690 +	 */
   9.691 +	struct list_head	queue;
   9.692 +
   9.693 +	void 			*data;
   9.694 +	struct hw_fib		*fib;		/* Actual shared object */
   9.695 +};
   9.696 +
   9.697 +/*
   9.698 + *	Adapter Information Block
   9.699 + *
   9.700 + *	This is returned by the RequestAdapterInfo block
   9.701 + */
   9.702 + 
   9.703 +struct aac_adapter_info
   9.704 +{
   9.705 +	u32	platform;
   9.706 +	u32	cpu;
   9.707 +	u32	subcpu;
   9.708 +	u32	clock;
   9.709 +	u32	execmem;
   9.710 +	u32	buffermem;
   9.711 +	u32	totalmem;
   9.712 +	u32	kernelrev;
   9.713 +	u32	kernelbuild;
   9.714 +	u32	monitorrev;
   9.715 +	u32	monitorbuild;
   9.716 +	u32	hwrev;
   9.717 +	u32	hwbuild;
   9.718 +	u32	biosrev;
   9.719 +	u32	biosbuild;
   9.720 +	u32	cluster;
   9.721 +	u32	serial[2];
   9.722 +	u32	battery;
   9.723 +	u32	options;
   9.724 +	u32	OEM;
   9.725 +};
   9.726 +
   9.727 +/*
   9.728 + * Battery platforms
   9.729 + */
   9.730 +#define AAC_BAT_REQ_PRESENT	(1)
   9.731 +#define AAC_BAT_REQ_NOTPRESENT	(2)
   9.732 +#define AAC_BAT_OPT_PRESENT	(3)
   9.733 +#define AAC_BAT_OPT_NOTPRESENT	(4)
   9.734 +#define AAC_BAT_NOT_SUPPORTED	(5)
   9.735 +/*
   9.736 + * cpu types
   9.737 + */
   9.738 +#define AAC_CPU_SIMULATOR	(1)
   9.739 +#define AAC_CPU_I960		(2)
   9.740 +#define AAC_CPU_STRONGARM	(3)
   9.741 +
   9.742 +/*
   9.743 + * Supported Options
   9.744 + */
   9.745 +#define AAC_OPT_SNAPSHOT	cpu_to_le32(1)
   9.746 +#define AAC_OPT_CLUSTERS	cpu_to_le32(1<<1)
   9.747 +#define AAC_OPT_WRITE_CACHE	cpu_to_le32(1<<2)
   9.748 +#define AAC_OPT_64BIT_DATA	cpu_to_le32(1<<3)
   9.749 +#define AAC_OPT_HOST_TIME_FIB	cpu_to_le32(1<<4)
   9.750 +#define AAC_OPT_RAID50		cpu_to_le32(1<<5)
   9.751 +#define AAC_OPT_4GB_WINDOW	cpu_to_le32(1<<6)
   9.752 +#define AAC_OPT_SCSI_UPGRADEABLE cpu_to_le32(1<<7)
   9.753 +#define AAC_OPT_SOFT_ERR_REPORT	cpu_to_le32(1<<8)
   9.754 +#define AAC_OPT_SUPPORTED_RECONDITION cpu_to_le32(1<<9)
   9.755 +#define AAC_OPT_SGMAP_HOST64	cpu_to_le32(1<<10)
   9.756 +#define AAC_OPT_ALARM		cpu_to_le32(1<<11)
   9.757 +#define AAC_OPT_NONDASD		cpu_to_le32(1<<12)
   9.758 +
   9.759 +struct aac_dev
   9.760 +{
   9.761 +	struct aac_dev		*next;
   9.762 +	const char		*name;
   9.763 +	int			id;
   9.764 +
   9.765 +	u16			irq_mask;
   9.766 +	/*
   9.767 +	 *	Map for 128 fib objects (64k)
   9.768 +	 */	
   9.769 +	dma_addr_t		hw_fib_pa;
   9.770 +	struct hw_fib		*hw_fib_va;
   9.771 +#if BITS_PER_LONG >= 64
   9.772 +	ulong			fib_base_va;
   9.773 +#endif
   9.774 +	/*
   9.775 +	 *	Fib Headers
   9.776 +	 */
   9.777 +	struct fib		fibs[AAC_NUM_FIB];
   9.778 +	struct fib		*free_fib;
   9.779 +	struct fib		*timeout_fib;
   9.780 +	spinlock_t		fib_lock;
   9.781 +	
   9.782 +	struct aac_queue_block *queues;
   9.783 +	/*
   9.784 +	 *	The user API will use an IOCTL to register itself to receive
   9.785 +	 *	FIBs from the adapter.  The following list is used to keep
   9.786 +	 *	track of all the threads that have requested these FIBs.  The
   9.787 +	 *	mutex is used to synchronize access to all data associated 
   9.788 +	 *	with the adapter fibs.
   9.789 +	 */
   9.790 +	struct list_head	fib_list;
   9.791 +
   9.792 +	struct adapter_ops	a_ops;
   9.793 +	unsigned long		fsrev;		/* Main driver's revision number */
   9.794 +	
   9.795 +	struct aac_init		*init;		/* Holds initialization info to communicate with adapter */
   9.796 +	dma_addr_t		init_pa; 	/* Holds physical address of the init struct */
   9.797 +	
   9.798 +	struct pci_dev		*pdev;		/* Our PCI interface */
   9.799 +	void *			printfbuf;	/* pointer to buffer used for printf's from the adapter */
   9.800 +	void *			comm_addr;	/* Base address of Comm area */
   9.801 +	dma_addr_t		comm_phys;	/* Physical Address of Comm area */
   9.802 +	size_t			comm_size;
   9.803 +
   9.804 +	struct Scsi_Host	*scsi_host_ptr;
   9.805 +	struct fsa_scsi_hba	fsa_dev;
   9.806 +	int			thread_pid;
   9.807 +	int			cardtype;
   9.808 +	
   9.809 +	/*
   9.810 +	 *	The following is the device specific extension.
   9.811 +	 */
   9.812 +	union
   9.813 +	{
   9.814 +		struct sa_registers *sa;
   9.815 +		struct rx_registers *rx;
   9.816 +	} regs;
   9.817 +	/*
   9.818 +	 *	The following is the number of the individual adapter
   9.819 +	 */
   9.820 +	u32			devnum;
   9.821 +	u32			aif_thread;
   9.822 +#if 0
   9.823 +	struct completion	aif_completion;
   9.824 +#endif
   9.825 +	struct aac_adapter_info adapter_info;
   9.826 +	/* These are in adapter info but they are in the io flow so
   9.827 +	 * lets break them out so we don't have to do an AND to check them
   9.828 +	 */
   9.829 +	u8			nondasd_support; 
   9.830 +	u8			pae_support;
   9.831 +};
   9.832 +
   9.833 +#define aac_adapter_interrupt(dev) \
   9.834 +	dev->a_ops.adapter_interrupt(dev)
   9.835 +
   9.836 +#define aac_adapter_notify(dev, event) \
   9.837 +	dev->a_ops.adapter_notify(dev, event)
   9.838 +
   9.839 +#define aac_adapter_enable_int(dev, event) \
   9.840 +	dev->a_ops.adapter_enable_int(dev, event)
   9.841 +
   9.842 +#define aac_adapter_disable_int(dev, event) \
   9.843 +	dev->a_ops.adapter_disable_int(dev, event)
   9.844 +
   9.845 +
   9.846 +
   9.847 +#define FIB_CONTEXT_FLAG_TIMED_OUT		(0x00000001)
   9.848 +
   9.849 +/*
   9.850 + *	Define the command values
   9.851 + */
   9.852 + 
   9.853 +#define		Null			0
   9.854 +#define 	GetAttributes		1
   9.855 +#define 	SetAttributes		2
   9.856 +#define 	Lookup			3
   9.857 +#define 	ReadLink		4
   9.858 +#define 	Read			5
   9.859 +#define 	Write			6
   9.860 +#define		Create			7
   9.861 +#define		MakeDirectory		8
   9.862 +#define		SymbolicLink		9
   9.863 +#define		MakeNode		10
   9.864 +#define		Removex			11
   9.865 +#define		RemoveDirectoryx	12
   9.866 +#define		Rename			13
   9.867 +#define		Link			14
   9.868 +#define		ReadDirectory		15
   9.869 +#define		ReadDirectoryPlus	16
   9.870 +#define		FileSystemStatus	17
   9.871 +#define		FileSystemInfo		18
   9.872 +#define		PathConfigure		19
   9.873 +#define		Commit			20
   9.874 +#define		Mount			21
   9.875 +#define		UnMount			22
   9.876 +#define		Newfs			23
   9.877 +#define		FsCheck			24
   9.878 +#define		FsSync			25
   9.879 +#define		SimReadWrite		26
   9.880 +#define		SetFileSystemStatus	27
   9.881 +#define		BlockRead		28
   9.882 +#define		BlockWrite		29
   9.883 +#define		NvramIoctl		30
   9.884 +#define		FsSyncWait		31
   9.885 +#define		ClearArchiveBit		32
   9.886 +#define		SetAcl			33
   9.887 +#define		GetAcl			34
   9.888 +#define		AssignAcl		35
   9.889 +#define		FaultInsertion		36	/* Fault Insertion Command */
   9.890 +#define		CrazyCache		37	/* Crazycache */
   9.891 +
   9.892 +#define		MAX_FSACOMMAND_NUM	38
   9.893 +
   9.894 +
   9.895 +/*
   9.896 + *	Define the status returns. These are very unixlike although
   9.897 + *	most are not in fact used
   9.898 + */
   9.899 +
   9.900 +#define		ST_OK		0
   9.901 +#define		ST_PERM		1
   9.902 +#define		ST_NOENT	2
   9.903 +#define		ST_IO		5
   9.904 +#define		ST_NXIO		6
   9.905 +#define		ST_E2BIG	7
   9.906 +#define		ST_ACCES	13
   9.907 +#define		ST_EXIST	17
   9.908 +#define		ST_XDEV		18
   9.909 +#define		ST_NODEV	19
   9.910 +#define		ST_NOTDIR	20
   9.911 +#define		ST_ISDIR	21
   9.912 +#define		ST_INVAL	22
   9.913 +#define		ST_FBIG		27
   9.914 +#define		ST_NOSPC	28
   9.915 +#define		ST_ROFS		30
   9.916 +#define		ST_MLINK	31
   9.917 +#define		ST_WOULDBLOCK	35
   9.918 +#define		ST_NAMETOOLONG	63
   9.919 +#define		ST_NOTEMPTY	66
   9.920 +#define		ST_DQUOT	69
   9.921 +#define		ST_STALE	70
   9.922 +#define		ST_REMOTE	71
   9.923 +#define		ST_BADHANDLE	10001
   9.924 +#define		ST_NOT_SYNC	10002
   9.925 +#define		ST_BAD_COOKIE	10003
   9.926 +#define		ST_NOTSUPP	10004
   9.927 +#define		ST_TOOSMALL	10005
   9.928 +#define		ST_SERVERFAULT	10006
   9.929 +#define		ST_BADTYPE	10007
   9.930 +#define		ST_JUKEBOX	10008
   9.931 +#define		ST_NOTMOUNTED	10009
   9.932 +#define		ST_MAINTMODE	10010
   9.933 +#define		ST_STALEACL	10011
   9.934 +
   9.935 +/*
   9.936 + *	On writes how does the client want the data written.
   9.937 + */
   9.938 +
   9.939 +#define	CACHE_CSTABLE		1
   9.940 +#define CACHE_UNSTABLE		2
   9.941 +
   9.942 +/*
   9.943 + *	Lets the client know at which level the data was commited on
   9.944 + *	a write request
   9.945 + */
   9.946 +
   9.947 +#define	CMFILE_SYNCH_NVRAM	1
   9.948 +#define	CMDATA_SYNCH_NVRAM	2
   9.949 +#define	CMFILE_SYNCH		3
   9.950 +#define CMDATA_SYNCH		4
   9.951 +#define CMUNSTABLE		5
   9.952 +
   9.953 +struct aac_read
   9.954 +{
   9.955 +	u32	 	command;
   9.956 +	u32 		cid;
   9.957 +	u32 		block;
   9.958 +	u32 		count;
   9.959 +	struct sgmap	sg;	// Must be last in struct because it is variable
   9.960 +};
   9.961 +
   9.962 +struct aac_read64
   9.963 +{
   9.964 +	u32	 	command;
   9.965 +	u16 		cid;
   9.966 +	u16 		sector_count;
   9.967 +	u32 		block;
   9.968 +	u16		pad;
   9.969 +	u16		flags;
   9.970 +	struct sgmap64	sg;	// Must be last in struct because it is variable
   9.971 +};
   9.972 +
   9.973 +struct aac_read_reply
   9.974 +{
   9.975 +	u32	 	status;
   9.976 +	u32 		count;
   9.977 +};
   9.978 +
   9.979 +struct aac_write
   9.980 +{
   9.981 +	u32		command;
   9.982 +	u32 		cid;
   9.983 +	u32 		block;
   9.984 +	u32 		count;
   9.985 +	u32	 	stable;	// Not used
   9.986 +	struct sgmap	sg;	// Must be last in struct because it is variable
   9.987 +};
   9.988 +
   9.989 +struct aac_write64
   9.990 +{
   9.991 +	u32	 	command;
   9.992 +	u16 		cid;
   9.993 +	u16 		sector_count;
   9.994 +	u32 		block;
   9.995 +	u16		pad;
   9.996 +	u16		flags;
   9.997 +	struct sgmap64	sg;	// Must be last in struct because it is variable
   9.998 +};
   9.999 +struct aac_write_reply
  9.1000 +{
  9.1001 +	u32		status;
  9.1002 +	u32 		count;
  9.1003 +	u32		committed;
  9.1004 +};
  9.1005 +
  9.1006 +struct aac_srb
  9.1007 +{
  9.1008 +	u32		function;
  9.1009 +	u32		channel;
  9.1010 +	u32		target;
  9.1011 +	u32		lun;
  9.1012 +	u32		timeout;
  9.1013 +	u32		flags;
  9.1014 +	u32		count;		// Data xfer size
  9.1015 +	u32		retry_limit;
  9.1016 +	u32		cdb_size;
  9.1017 +	u8		cdb[16];
  9.1018 +	struct	sgmap	sg;
  9.1019 +};
  9.1020 +
  9.1021 +
  9.1022 +
  9.1023 +#define		AAC_SENSE_BUFFERSIZE	 30
  9.1024 +
  9.1025 +struct aac_srb_reply
  9.1026 +{
  9.1027 +	u32		status;
  9.1028 +	u32		srb_status;
  9.1029 +	u32		scsi_status;
  9.1030 +	u32		data_xfer_length;
  9.1031 +	u32		sense_data_size;
  9.1032 +	u8		sense_data[AAC_SENSE_BUFFERSIZE]; // Can this be SCSI_SENSE_BUFFERSIZE
  9.1033 +};
  9.1034 +/*
  9.1035 + * SRB Flags
  9.1036 + */
  9.1037 +#define		SRB_NoDataXfer		 0x0000
  9.1038 +#define		SRB_DisableDisconnect	 0x0004
  9.1039 +#define		SRB_DisableSynchTransfer 0x0008
  9.1040 +#define 	SRB_BypassFrozenQueue	 0x0010
  9.1041 +#define		SRB_DisableAutosense	 0x0020
  9.1042 +#define		SRB_DataIn		 0x0040
  9.1043 +#define 	SRB_DataOut		 0x0080
  9.1044 +
  9.1045 +/*
  9.1046 + * SRB Functions - set in aac_srb->function
  9.1047 + */
  9.1048 +#define	SRBF_ExecuteScsi	0x0000
  9.1049 +#define	SRBF_ClaimDevice	0x0001
  9.1050 +#define	SRBF_IO_Control		0x0002
  9.1051 +#define	SRBF_ReceiveEvent	0x0003
  9.1052 +#define	SRBF_ReleaseQueue	0x0004
  9.1053 +#define	SRBF_AttachDevice	0x0005
  9.1054 +#define	SRBF_ReleaseDevice	0x0006
  9.1055 +#define	SRBF_Shutdown		0x0007
  9.1056 +#define	SRBF_Flush		0x0008
  9.1057 +#define	SRBF_AbortCommand	0x0010
  9.1058 +#define	SRBF_ReleaseRecovery	0x0011
  9.1059 +#define	SRBF_ResetBus		0x0012
  9.1060 +#define	SRBF_ResetDevice	0x0013
  9.1061 +#define	SRBF_TerminateIO	0x0014
  9.1062 +#define	SRBF_FlushQueue		0x0015
  9.1063 +#define	SRBF_RemoveDevice	0x0016
  9.1064 +#define	SRBF_DomainValidation	0x0017
  9.1065 +
  9.1066 +/* 
  9.1067 + * SRB SCSI Status - set in aac_srb->scsi_status
  9.1068 + */
  9.1069 +#define SRB_STATUS_PENDING                  0x00
  9.1070 +#define SRB_STATUS_SUCCESS                  0x01
  9.1071 +#define SRB_STATUS_ABORTED                  0x02
  9.1072 +#define SRB_STATUS_ABORT_FAILED             0x03
  9.1073 +#define SRB_STATUS_ERROR                    0x04
  9.1074 +#define SRB_STATUS_BUSY                     0x05
  9.1075 +#define SRB_STATUS_INVALID_REQUEST          0x06
  9.1076 +#define SRB_STATUS_INVALID_PATH_ID          0x07
  9.1077 +#define SRB_STATUS_NO_DEVICE                0x08
  9.1078 +#define SRB_STATUS_TIMEOUT                  0x09
  9.1079 +#define SRB_STATUS_SELECTION_TIMEOUT        0x0A
  9.1080 +#define SRB_STATUS_COMMAND_TIMEOUT          0x0B
  9.1081 +#define SRB_STATUS_MESSAGE_REJECTED         0x0D
  9.1082 +#define SRB_STATUS_BUS_RESET                0x0E
  9.1083 +#define SRB_STATUS_PARITY_ERROR             0x0F
  9.1084 +#define SRB_STATUS_REQUEST_SENSE_FAILED     0x10
  9.1085 +#define SRB_STATUS_NO_HBA                   0x11
  9.1086 +#define SRB_STATUS_DATA_OVERRUN             0x12
  9.1087 +#define SRB_STATUS_UNEXPECTED_BUS_FREE      0x13
  9.1088 +#define SRB_STATUS_PHASE_SEQUENCE_FAILURE   0x14
  9.1089 +#define SRB_STATUS_BAD_SRB_BLOCK_LENGTH     0x15
  9.1090 +#define SRB_STATUS_REQUEST_FLUSHED          0x16
  9.1091 +#define SRB_STATUS_DELAYED_RETRY	    0x17
  9.1092 +#define SRB_STATUS_INVALID_LUN              0x20
  9.1093 +#define SRB_STATUS_INVALID_TARGET_ID        0x21
  9.1094 +#define SRB_STATUS_BAD_FUNCTION             0x22
  9.1095 +#define SRB_STATUS_ERROR_RECOVERY           0x23
  9.1096 +#define SRB_STATUS_NOT_STARTED		    0x24
  9.1097 +#define SRB_STATUS_NOT_IN_USE		    0x30
  9.1098 +#define SRB_STATUS_FORCE_ABORT		    0x31
  9.1099 +#define SRB_STATUS_DOMAIN_VALIDATION_FAIL   0x32
  9.1100 +
  9.1101 +/*
  9.1102 + * Object-Server / Volume-Manager Dispatch Classes
  9.1103 + */
  9.1104 +
  9.1105 +#define		VM_Null			0
  9.1106 +#define		VM_NameServe		1
  9.1107 +#define		VM_ContainerConfig	2
  9.1108 +#define		VM_Ioctl		3
  9.1109 +#define		VM_FilesystemIoctl	4
  9.1110 +#define		VM_CloseAll		5
  9.1111 +#define		VM_CtBlockRead		6
  9.1112 +#define		VM_CtBlockWrite		7
  9.1113 +#define		VM_SliceBlockRead	8	/* raw access to configured "storage objects" */
  9.1114 +#define		VM_SliceBlockWrite	9
  9.1115 +#define		VM_DriveBlockRead	10	/* raw access to physical devices */
  9.1116 +#define		VM_DriveBlockWrite	11
  9.1117 +#define		VM_EnclosureMgt		12	/* enclosure management */
  9.1118 +#define		VM_Unused		13	/* used to be diskset management */
  9.1119 +#define		VM_CtBlockVerify	14
  9.1120 +#define		VM_CtPerf		15	/* performance test */
  9.1121 +#define		VM_CtBlockRead64	16
  9.1122 +#define		VM_CtBlockWrite64	17
  9.1123 +#define		VM_CtBlockVerify64	18
  9.1124 +#define		VM_CtHostRead64		19
  9.1125 +#define		VM_CtHostWrite64	20
  9.1126 +
  9.1127 +#define		MAX_VMCOMMAND_NUM	21	/* used for sizing stats array - leave last */
  9.1128 +
  9.1129 +/*
  9.1130 + *	Descriptive information (eg, vital stats)
  9.1131 + *	that a content manager might report.  The
  9.1132 + *	FileArray filesystem component is one example
  9.1133 + *	of a content manager.  Raw mode might be
  9.1134 + *	another.
  9.1135 + */
  9.1136 +
  9.1137 +struct aac_fsinfo {
  9.1138 +	u32  fsTotalSize;	/* Consumed by fs, incl. metadata */
  9.1139 +	u32  fsBlockSize;
  9.1140 +	u32  fsFragSize;
  9.1141 +	u32  fsMaxExtendSize;
  9.1142 +	u32  fsSpaceUnits;
  9.1143 +	u32  fsMaxNumFiles;
  9.1144 +	u32  fsNumFreeFiles;
  9.1145 +	u32  fsInodeDensity;
  9.1146 +};	/* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */
  9.1147 +
  9.1148 +union aac_contentinfo {
  9.1149 +	struct aac_fsinfo filesys;	/* valid iff ObjType == FT_FILESYS && !(ContentState & FSCS_NOTCLEAN) */
  9.1150 +};
  9.1151 +
  9.1152 +/*
  9.1153 + *	Query for "mountable" objects, ie, objects that are typically
  9.1154 + *	associated with a drive letter on the client (host) side.
  9.1155 + */
  9.1156 +
  9.1157 +struct aac_mntent {
  9.1158 +	u32    			oid;
  9.1159 +	u8			name[16];	// if applicable
  9.1160 +	struct creation_info	create_info;	// if applicable
  9.1161 +	u32			capacity;
  9.1162 +	u32			vol;    	// substrate structure
  9.1163 +	u32			obj;	        // FT_FILESYS, FT_DATABASE, etc.
  9.1164 +	u32			state;		// unready for mounting, readonly, etc.
  9.1165 +	union aac_contentinfo	fileinfo;	// Info specific to content manager (eg, filesystem)
  9.1166 +	u32			altoid;		// != oid <==> snapshot or broken mirror exists
  9.1167 +};
  9.1168 +
  9.1169 +#define FSCS_READONLY	0x0002	/*	possible result of broken mirror */
  9.1170 +
  9.1171 +struct aac_query_mount {
  9.1172 +	u32		command;
  9.1173 +	u32		type;
  9.1174 +	u32		count;
  9.1175 +};
  9.1176 +
  9.1177 +struct aac_mount {
  9.1178 +	u32		status;
  9.1179 +	u32	   	type;           /* should be same as that requested */
  9.1180 +	u32		count;
  9.1181 +	struct aac_mntent mnt[1];
  9.1182 +};
  9.1183 +
  9.1184 +/*
  9.1185 + * The following command is sent to shut down each container.
  9.1186 + */
  9.1187 +
  9.1188 +struct aac_close {
  9.1189 +	u32	command;
  9.1190 +	u32	cid;
  9.1191 +};
  9.1192 +
  9.1193 +struct aac_query_disk
  9.1194 +{
  9.1195 +	s32	cnum;
  9.1196 +	s32	bus;
  9.1197 +	s32	target;
  9.1198 +	s32	lun;
  9.1199 +	u32	valid;
  9.1200 +	u32	locked;
  9.1201 +	u32	deleted;
  9.1202 +	s32	instance;
  9.1203 +	s8	name[10];
  9.1204 +	u32	unmapped;
  9.1205 +};
  9.1206 +
  9.1207 +struct aac_delete_disk {
  9.1208 +	u32	disknum;
  9.1209 +	u32	cnum;
  9.1210 +};
  9.1211 +
  9.1212 +struct fib_ioctl
  9.1213 +{
  9.1214 +	char	*fibctx;
  9.1215 +	int	wait;
  9.1216 +	char	*fib;
  9.1217 +};
  9.1218 +
  9.1219 +struct revision
  9.1220 +{
  9.1221 +	u32 compat;
  9.1222 +	u32 version;
  9.1223 +	u32 build;
  9.1224 +};
  9.1225 +	
  9.1226 +/*
  9.1227 + * 	Ugly - non Linux like ioctl coding for back compat.
  9.1228 + */
  9.1229 +
  9.1230 +#define CTL_CODE(function, method) (                 \
  9.1231 +    (4<< 16) | ((function) << 2) | (method) \
  9.1232 +)
  9.1233 +
  9.1234 +/*
  9.1235 + *	Define the method codes for how buffers are passed for I/O and FS 
  9.1236 + *	controls
  9.1237 + */
  9.1238 +
  9.1239 +#define METHOD_BUFFERED                 0
  9.1240 +#define METHOD_NEITHER                  3
  9.1241 +
  9.1242 +/*
  9.1243 + *	Filesystem ioctls
  9.1244 + */
  9.1245 +
  9.1246 +#define FSACTL_SENDFIB                  	CTL_CODE(2050, METHOD_BUFFERED)
  9.1247 +#define FSACTL_SEND_RAW_SRB               	CTL_CODE(2067, METHOD_BUFFERED)
  9.1248 +#define FSACTL_DELETE_DISK			0x163
  9.1249 +#define FSACTL_QUERY_DISK			0x173
  9.1250 +#define FSACTL_OPEN_GET_ADAPTER_FIB		CTL_CODE(2100, METHOD_BUFFERED)
  9.1251 +#define FSACTL_GET_NEXT_ADAPTER_FIB		CTL_CODE(2101, METHOD_BUFFERED)
  9.1252 +#define FSACTL_CLOSE_GET_ADAPTER_FIB		CTL_CODE(2102, METHOD_BUFFERED)
  9.1253 +#define FSACTL_MINIPORT_REV_CHECK               CTL_CODE(2107, METHOD_BUFFERED)
  9.1254 +#define FSACTL_GET_PCI_INFO               	CTL_CODE(2119, METHOD_BUFFERED)
  9.1255 +#define FSACTL_FORCE_DELETE_DISK		CTL_CODE(2120, METHOD_NEITHER)
  9.1256 +
  9.1257 +
  9.1258 +struct aac_common
  9.1259 +{
  9.1260 +	/*
  9.1261 +	 *	If this value is set to 1 then interrupt moderation will occur 
  9.1262 +	 *	in the base commuication support.
  9.1263 +	 */
  9.1264 +	u32 irq_mod;
  9.1265 +	u32 peak_fibs;
  9.1266 +	u32 zero_fibs;
  9.1267 +	u32 fib_timeouts;
  9.1268 +	/*
  9.1269 +	 *	Statistical counters in debug mode
  9.1270 +	 */
  9.1271 +#ifdef DBG
  9.1272 +	u32 FibsSent;
  9.1273 +	u32 FibRecved;
  9.1274 +	u32 NoResponseSent;
  9.1275 +	u32 NoResponseRecved;
  9.1276 +	u32 AsyncSent;
  9.1277 +	u32 AsyncRecved;
  9.1278 +	u32 NormalSent;
  9.1279 +	u32 NormalRecved;
  9.1280 +#endif
  9.1281 +};
  9.1282 +
  9.1283 +extern struct aac_common aac_config;
  9.1284 +
  9.1285 +
  9.1286 +/*
  9.1287 + *	The following macro is used when sending and receiving FIBs. It is
  9.1288 + *	only used for debugging.
  9.1289 + */
  9.1290 + 
  9.1291 +#if DBG
  9.1292 +#define	FIB_COUNTER_INCREMENT(counter)		(counter)++
  9.1293 +#else
  9.1294 +#define	FIB_COUNTER_INCREMENT(counter)		
  9.1295 +#endif
  9.1296 +
  9.1297 +/*
  9.1298 + *	Adapter direct commands
  9.1299 + *	Monitor/Kernel API
  9.1300 + */
  9.1301 +
  9.1302 +#define	BREAKPOINT_REQUEST		cpu_to_le32(0x00000004)
  9.1303 +#define	INIT_STRUCT_BASE_ADDRESS	cpu_to_le32(0x00000005)
  9.1304 +#define READ_PERMANENT_PARAMETERS	cpu_to_le32(0x0000000a)
  9.1305 +#define WRITE_PERMANENT_PARAMETERS	cpu_to_le32(0x0000000b)
  9.1306 +#define HOST_CRASHING			cpu_to_le32(0x0000000d)
  9.1307 +#define	SEND_SYNCHRONOUS_FIB		cpu_to_le32(0x0000000c)
  9.1308 +#define GET_ADAPTER_PROPERTIES		cpu_to_le32(0x00000019)
  9.1309 +#define RE_INIT_ADAPTER			cpu_to_le32(0x000000ee)
  9.1310 +
  9.1311 +/*
  9.1312 + *	Adapter Status Register
  9.1313 + *
  9.1314 + *  Phase Staus mailbox is 32bits:
  9.1315 + *	<31:16> = Phase Status
  9.1316 + *	<15:0>  = Phase
  9.1317 + *
  9.1318 + *	The adapter reports is present state through the phase.  Only
  9.1319 + *	a single phase should be ever be set.  Each phase can have multiple
  9.1320 + *	phase status bits to provide more detailed information about the 
  9.1321 + *	state of the board.  Care should be taken to ensure that any phase 
  9.1322 + *	status bits that are set when changing the phase are also valid
  9.1323 + *	for the new phase or be cleared out.  Adapter software (monitor,
  9.1324 + *	iflash, kernel) is responsible for properly maintining the phase 
  9.1325 + *	status mailbox when it is running.
  9.1326 + *											
  9.1327 + *	MONKER_API Phases							
  9.1328 + *
  9.1329 + *	Phases are bit oriented.  It is NOT valid  to have multiple bits set						
  9.1330 + */					
  9.1331 +
  9.1332 +#define	SELF_TEST_FAILED		cpu_to_le32(0x00000004)
  9.1333 +#define	KERNEL_UP_AND_RUNNING		cpu_to_le32(0x00000080)
  9.1334 +#define	KERNEL_PANIC			cpu_to_le32(0x00000100)
  9.1335 +
  9.1336 +/*
  9.1337 + *	Doorbell bit defines
  9.1338 + */
  9.1339 +
  9.1340 +#define DoorBellPrintfDone		cpu_to_le32(1<<5)	// Host -> Adapter
  9.1341 +#define DoorBellAdapterNormCmdReady	cpu_to_le32(1<<1)	// Adapter -> Host
  9.1342 +#define DoorBellAdapterNormRespReady	cpu_to_le32(1<<2)	// Adapter -> Host
  9.1343 +#define DoorBellAdapterNormCmdNotFull	cpu_to_le32(1<<3)	// Adapter -> Host
  9.1344 +#define DoorBellAdapterNormRespNotFull	cpu_to_le32(1<<4)	// Adapter -> Host
  9.1345 +#define DoorBellPrintfReady		cpu_to_le32(1<<5)	// Adapter -> Host
  9.1346 +
  9.1347 +/*
  9.1348 + *	For FIB communication, we need all of the following things
  9.1349 + *	to send back to the user.
  9.1350 + */
  9.1351 + 
  9.1352 +#define 	AifCmdEventNotify	1	/* Notify of event */
  9.1353 +#define		AifCmdJobProgress	2	/* Progress report */
  9.1354 +#define		AifCmdAPIReport		3	/* Report from other user of API */
  9.1355 +#define		AifCmdDriverNotify	4	/* Notify host driver of event */
  9.1356 +#define		AifReqJobList		100	/* Gets back complete job list */
  9.1357 +#define		AifReqJobsForCtr	101	/* Gets back jobs for specific container */
  9.1358 +#define		AifReqJobsForScsi	102	/* Gets back jobs for specific SCSI device */ 
  9.1359 +#define		AifReqJobReport		103	/* Gets back a specific job report or list of them */ 
  9.1360 +#define		AifReqTerminateJob	104	/* Terminates job */
  9.1361 +#define		AifReqSuspendJob	105	/* Suspends a job */
  9.1362 +#define		AifReqResumeJob		106	/* Resumes a job */ 
  9.1363 +#define		AifReqSendAPIReport	107	/* API generic report requests */
  9.1364 +#define		AifReqAPIJobStart	108	/* Start a job from the API */
  9.1365 +#define		AifReqAPIJobUpdate	109	/* Update a job report from the API */
  9.1366 +#define		AifReqAPIJobFinish	110	/* Finish a job from the API */
  9.1367 +
  9.1368 +/*
  9.1369 + *	Adapter Initiated FIB command structures. Start with the adapter
  9.1370 + *	initiated FIBs that really come from the adapter, and get responded
  9.1371 + *	to by the host.
  9.1372 + */
  9.1373 +
  9.1374 +struct aac_aifcmd {
  9.1375 +	u32 command;		/* Tell host what type of notify this is */
  9.1376 +	u32 seqnum;		/* To allow ordering of reports (if necessary) */
  9.1377 +	u8 data[1];		/* Undefined length (from kernel viewpoint) */
  9.1378 +};
  9.1379 +
  9.1380 +static inline u32 fib2addr(struct hw_fib *hw)
  9.1381 +{
  9.1382 +	return (u32)hw;
  9.1383 +}
  9.1384 +
  9.1385 +static inline struct hw_fib *addr2fib(u32 addr)
  9.1386 +{
  9.1387 +	return (struct hw_fib *)addr;
  9.1388 +}
  9.1389 +
  9.1390 +const char *aac_driverinfo(struct Scsi_Host *);
  9.1391 +struct fib *fib_alloc(struct aac_dev *dev);
  9.1392 +int fib_setup(struct aac_dev *dev);
  9.1393 +void fib_map_free(struct aac_dev *dev);
  9.1394 +void fib_free(struct fib * context);
  9.1395 +void fib_init(struct fib * context);
  9.1396 +void fib_dealloc(struct fib * context);
  9.1397 +void aac_printf(struct aac_dev *dev, u32 val);
  9.1398 +int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
  9.1399 +int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
  9.1400 +int aac_consumer_avail(struct aac_dev * dev, struct aac_queue * q);
  9.1401 +void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
  9.1402 +int fib_complete(struct fib * context);
  9.1403 +#define fib_data(fibctx) ((void *)(fibctx)->fib->data)
  9.1404 +int aac_detach(struct aac_dev *dev);
  9.1405 +struct aac_dev *aac_init_adapter(struct aac_dev *dev);
  9.1406 +int aac_get_containers(struct aac_dev *dev);
  9.1407 +int aac_scsi_cmd(Scsi_Cmnd *scsi_cmnd_ptr);
  9.1408 +int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg);
  9.1409 +int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg);
  9.1410 +int aac_rx_init(struct aac_dev *dev, unsigned long devNumber);
  9.1411 +int aac_sa_init(struct aac_dev *dev, unsigned long devNumber);
  9.1412 +unsigned int aac_response_normal(struct aac_queue * q);
  9.1413 +unsigned int aac_command_normal(struct aac_queue * q);
  9.1414 +#ifdef TRY_SOFTIRQ
  9.1415 +int aac_command_thread(struct softirq_action *h); 
  9.1416 +#else
  9.1417 +int aac_command_thread(struct aac_dev * dev);
  9.1418 +#endif
  9.1419 +int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
  9.1420 +int fib_adapter_complete(struct fib * fibptr, unsigned short size);
  9.1421 +struct aac_driver_ident* aac_get_driver_ident(int devtype);
  9.1422 +int aac_get_adapter_info(struct aac_dev* dev);
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/commctrl.c	Fri Feb 21 15:10:37 2003 +0000
    10.3 @@ -0,0 +1,438 @@
    10.4 +/*
    10.5 + *	Adaptec AAC series RAID controller driver
    10.6 + *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
    10.7 + *
    10.8 + * based on the old aacraid driver that is..
    10.9 + * Adaptec aacraid device driver for Linux.
   10.10 + *
   10.11 + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
   10.12 + *
   10.13 + * This program is free software; you can redistribute it and/or modify
   10.14 + * it under the terms of the GNU General Public License as published by
   10.15 + * the Free Software Foundation; either version 2, or (at your option)
   10.16 + * any later version.
   10.17 + *
   10.18 + * This program is distributed in the hope that it will be useful,
   10.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   10.21 + * GNU General Public License for more details.
   10.22 + *
   10.23 + * You should have received a copy of the GNU General Public License
   10.24 + * along with this program; see the file COPYING.  If not, write to
   10.25 + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   10.26 + *
   10.27 + * Module Name:
   10.28 + *  commctrl.c
   10.29 + *
   10.30 + * Abstract: Contains all routines for control of the AFA comm layer
   10.31 + *
   10.32 + */
   10.33 +
   10.34 +#include <xeno/config.h>
   10.35 +/*  #include <xeno/kernel.h> */
   10.36 +#include <xeno/init.h>
   10.37 +#include <xeno/types.h>
   10.38 +#include <xeno/sched.h>
   10.39 +#include <xeno/pci.h>
   10.40 +/*  #include <xeno/spinlock.h> */
   10.41 +/*  #include <xeno/slab.h> */
   10.42 +/*  #include <xeno/completion.h> */
   10.43 +#include <xeno/blk.h>
   10.44 +/*  #include <asm/semaphore.h> */
   10.45 +#include <asm/uaccess.h>
   10.46 +#include "scsi.h"
   10.47 +#include "hosts.h"
   10.48 +
   10.49 +#include "aacraid.h"
   10.50 +
   10.51 +/**
   10.52 + *	ioctl_send_fib	-	send a FIB from userspace
   10.53 + *	@dev:	adapter is being processed
   10.54 + *	@arg:	arguments to the ioctl call
   10.55 + *	
   10.56 + *	This routine sends a fib to the adapter on behalf of a user level
   10.57 + *	program.
   10.58 + */
   10.59 + 
   10.60 +static int ioctl_send_fib(struct aac_dev * dev, void *arg)
   10.61 +{
   10.62 +	struct hw_fib * kfib;
   10.63 +	struct fib *fibptr;
   10.64 +
   10.65 +	fibptr = fib_alloc(dev);
   10.66 +	if(fibptr == NULL)
   10.67 +		return -ENOMEM;
   10.68 +		
   10.69 +	kfib = fibptr->fib;
   10.70 +	/*
   10.71 +	 *	First copy in the header so that we can check the size field.
   10.72 +	 */
   10.73 +	if (copy_from_user((void *)kfib, arg, sizeof(struct aac_fibhdr))) {
   10.74 +		fib_free(fibptr);
   10.75 +		return -EFAULT;
   10.76 +	}
   10.77 +	/*
   10.78 +	 *	Since we copy based on the fib header size, make sure that we
   10.79 +	 *	will not overrun the buffer when we copy the memory. Return
   10.80 +	 *	an error if we would.
   10.81 +	 */
   10.82 +	if(le32_to_cpu(kfib->header.Size) > sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
   10.83 +		fib_free(fibptr);
   10.84 +		return -EINVAL;
   10.85 +	}
   10.86 +
   10.87 +	if (copy_from_user((void *) kfib, arg, le32_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr))) {
   10.88 +		fib_free(fibptr);
   10.89 +		return -EFAULT;
   10.90 +	}
   10.91 +
   10.92 +	if (kfib->header.Command == cpu_to_le32(TakeABreakPt)) {
   10.93 +		aac_adapter_interrupt(dev);
   10.94 +		/*
   10.95 +		 * Since we didn't really send a fib, zero out the state to allow 
   10.96 +		 * cleanup code not to assert.
   10.97 +		 */
   10.98 +		kfib->header.XferState = 0;
   10.99 +	} else {
  10.100 +		if (fib_send(kfib->header.Command, fibptr, le32_to_cpu(kfib->header.Size) , FsaNormal,
  10.101 +			1, 1, NULL, NULL) != 0) 
  10.102 +		{
  10.103 +			fib_free(fibptr);
  10.104 +			return -EINVAL;
  10.105 +		}
  10.106 +		if (fib_complete(fibptr) != 0) {
  10.107 +			fib_free(fibptr);
  10.108 +			return -EINVAL;
  10.109 +		}
  10.110 +	}
  10.111 +	/*
  10.112 +	 *	Make sure that the size returned by the adapter (which includes
  10.113 +	 *	the header) is less than or equal to the size of a fib, so we
  10.114 +	 *	don't corrupt application data. Then copy that size to the user
  10.115 +	 *	buffer. (Don't try to add the header information again, since it
  10.116 +	 *	was already included by the adapter.)
  10.117 +	 */
  10.118 +
  10.119 +	if (copy_to_user(arg, (void *)kfib, kfib->header.Size)) {
  10.120 +		fib_free(fibptr);
  10.121 +		return -EFAULT;
  10.122 +	}
  10.123 +	fib_free(fibptr);
  10.124 +	return 0;
  10.125 +}
  10.126 +
  10.127 +/**
  10.128 + *	open_getadapter_fib	-	Get the next fib
  10.129 + *
  10.130 + *	This routine will get the next Fib, if available, from the AdapterFibContext
  10.131 + *	passed in from the user.
  10.132 + */
  10.133 +
  10.134 +static int open_getadapter_fib(struct aac_dev * dev, void *arg)
  10.135 +{
  10.136 +	struct aac_fib_context * fibctx;
  10.137 +	int status;
  10.138 +	unsigned long flags;
  10.139 +
  10.140 +	fibctx = kmalloc(sizeof(struct aac_fib_context), GFP_KERNEL);
  10.141 +	if (fibctx == NULL) {
  10.142 +		status = -ENOMEM;
  10.143 +	} else {
  10.144 +		fibctx->type = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT;
  10.145 +		fibctx->size = sizeof(struct aac_fib_context);
  10.146 +#if 0
  10.147 +		/*
  10.148 +		 *	Initialize the mutex used to wait for the next AIF.
  10.149 +		 */
  10.150 +		init_MUTEX_LOCKED(&fibctx->wait_sem);
  10.151 +#endif
  10.152 +		fibctx->wait = 0;
  10.153 +		/*
  10.154 +		 *	Initialize the fibs and set the count of fibs on
  10.155 +		 *	the list to 0.
  10.156 +		 */
  10.157 +		fibctx->count = 0;
  10.158 +		INIT_LIST_HEAD(&fibctx->fibs);
  10.159 +		fibctx->jiffies = jiffies/HZ;
  10.160 +		/*
  10.161 +		 *	Now add this context onto the adapter's 
  10.162 +		 *	AdapterFibContext list.
  10.163 +		 */
  10.164 +		spin_lock_irqsave(&dev->fib_lock, flags);
  10.165 +		list_add_tail(&fibctx->next, &dev->fib_list);
  10.166 +		spin_unlock_irqrestore(&dev->fib_lock, flags);
  10.167 +		if (copy_to_user(arg,  &fibctx, sizeof(struct aac_fib_context *))) {
  10.168 +			status = -EFAULT;
  10.169 +		} else {
  10.170 +			status = 0;
  10.171 +		}	
  10.172 +	}
  10.173 +	return status;
  10.174 +}
  10.175 +
  10.176 +/**
  10.177 + *	next_getadapter_fib	-	get the next fib
  10.178 + *	@dev: adapter to use
  10.179 + *	@arg: ioctl argument
  10.180 + *	
  10.181 + * 	This routine will get the next Fib, if available, from the AdapterFibContext
  10.182 + *	passed in from the user.
  10.183 + */
  10.184 +
  10.185 +static int next_getadapter_fib(struct aac_dev * dev, void *arg)
  10.186 +{
  10.187 +	struct fib_ioctl f;
  10.188 +	struct aac_fib_context *fibctx, *aifcp;
  10.189 +	struct hw_fib * fib;
  10.190 +	int status;
  10.191 +	struct list_head * entry;
  10.192 +	int found;
  10.193 +	unsigned long flags;
  10.194 +	
  10.195 +	if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl)))
  10.196 +		return -EFAULT;
  10.197 +	/*
  10.198 +	 *	Extract the AdapterFibContext from the Input parameters.
  10.199 +	 */
  10.200 +	fibctx = (struct aac_fib_context *) f.fibctx;
  10.201 +
  10.202 +	/*
  10.203 +	 *	Verify that the HANDLE passed in was a valid AdapterFibContext
  10.204 +	 *
  10.205 +	 *	Search the list of AdapterFibContext addresses on the adapter
  10.206 +	 *	to be sure this is a valid address
  10.207 +	 */
  10.208 +	found = 0;
  10.209 +	entry = dev->fib_list.next;
  10.210 +
  10.211 +	while(entry != &dev->fib_list) {
  10.212 +		aifcp = list_entry(entry, struct aac_fib_context, next);
  10.213 +		if(fibctx == aifcp) {   /* We found a winner */
  10.214 +			found = 1;
  10.215 +			break;
  10.216 +		}
  10.217 +		entry = entry->next;
  10.218 +	}
  10.219 +	if (found == 0)
  10.220 +		return -EINVAL;
  10.221 +
  10.222 +	if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
  10.223 +		 (fibctx->size != sizeof(struct aac_fib_context)))
  10.224 +		return -EINVAL;
  10.225 +	status = 0;
  10.226 +	spin_lock_irqsave(&dev->fib_lock, flags);
  10.227 +	/*
  10.228 +	 *	If there are no fibs to send back, then either wait or return
  10.229 +	 *	-EAGAIN
  10.230 +	 */
  10.231 +return_fib:
  10.232 +	if (!list_empty(&fibctx->fibs)) {
  10.233 +		struct list_head * entry;
  10.234 +		/*
  10.235 +		 *	Pull the next fib from the fibs
  10.236 +		 */
  10.237 +		entry = fibctx->fibs.next;
  10.238 +		list_del(entry);
  10.239 +		
  10.240 +		fib = list_entry(entry, struct hw_fib, header.FibLinks);
  10.241 +		fibctx->count--;
  10.242 +		spin_unlock_irqrestore(&dev->fib_lock, flags);
  10.243 +		if (copy_to_user(f.fib, fib, sizeof(struct hw_fib))) {
  10.244 +			kfree(fib);
  10.245 +			return -EFAULT;
  10.246 +		}	
  10.247 +		/*
  10.248 +		 *	Free the space occupied by this copy of the fib.
  10.249 +		 */
  10.250 +		kfree(fib);
  10.251 +		status = 0;
  10.252 +		fibctx->jiffies = jiffies/HZ;
  10.253 +	} else {
  10.254 +		spin_unlock_irqrestore(&dev->fib_lock, flags);
  10.255 +		if (f.wait) {
  10.256 +#if 0
  10.257 +			if(down_interruptible(&fibctx->wait_sem) < 0) {
  10.258 +				status = -EINTR;
  10.259 +			} else {
  10.260 +#else
  10.261 +			    {
  10.262 +#endif
  10.263 +				/* Lock again and retry */
  10.264 +				spin_lock_irqsave(&dev->fib_lock, flags);
  10.265 +				goto return_fib;
  10.266 +			}
  10.267 +		} else {
  10.268 +			status = -EAGAIN;
  10.269 +		}	
  10.270 +	}
  10.271 +	return status;
  10.272 +}
  10.273 +
  10.274 +int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx)
  10.275 +{
  10.276 +	struct hw_fib *fib;
  10.277 +
  10.278 +	/*
  10.279 +	 *	First free any FIBs that have not been consumed.
  10.280 +	 */
  10.281 +	while (!list_empty(&fibctx->fibs)) {
  10.282 +		struct list_head * entry;
  10.283 +		/*
  10.284 +		 *	Pull the next fib from the fibs
  10.285 +		 */
  10.286 +		entry = fibctx->fibs.next;
  10.287 +		list_del(entry);
  10.288 +		fib = list_entry(entry, struct hw_fib, header.FibLinks);
  10.289 +		fibctx->count--;
  10.290 +		/*
  10.291 +		 *	Free the space occupied by this copy of the fib.
  10.292 +		 */
  10.293 +		kfree(fib);
  10.294 +	}
  10.295 +	/*
  10.296 +	 *	Remove the Context from the AdapterFibContext List
  10.297 +	 */
  10.298 +	list_del(&fibctx->next);
  10.299 +	/*
  10.300 +	 *	Invalidate context
  10.301 +	 */
  10.302 +	fibctx->type = 0;
  10.303 +	/*
  10.304 +	 *	Free the space occupied by the Context
  10.305 +	 */
  10.306 +	kfree(fibctx);
  10.307 +	return 0;
  10.308 +}
  10.309 +
  10.310 +/**
  10.311 + *	close_getadapter_fib	-	close down user fib context
  10.312 + *	@dev: adapter
  10.313 + *	@arg: ioctl arguments
  10.314 + *
  10.315 + *	This routine will close down the fibctx passed in from the user.
  10.316 + */
  10.317 + 
  10.318 +static int close_getadapter_fib(struct aac_dev * dev, void *arg)
  10.319 +{
  10.320 +	struct aac_fib_context *fibctx, *aifcp;
  10.321 +	int status;
  10.322 +	unsigned long flags;
  10.323 +	struct list_head * entry;
  10.324 +	int found;
  10.325 +
  10.326 +	/*
  10.327 +	 *	Extract the fibctx from the input parameters
  10.328 +	 */
  10.329 +	fibctx = arg;
  10.330 +
  10.331 +	/*
  10.332 +	 *	Verify that the HANDLE passed in was a valid AdapterFibContext
  10.333 +	 *
  10.334 +	 *	Search the list of AdapterFibContext addresses on the adapter
  10.335 +	 *	to be sure this is a valid address
  10.336 +	 */
  10.337 +
  10.338 +	found = 0;
  10.339 +	entry = dev->fib_list.next;
  10.340 +
  10.341 +	while(entry != &dev->fib_list) {
  10.342 +		aifcp = list_entry(entry, struct aac_fib_context, next);
  10.343 +		if(fibctx == aifcp) {   /* We found a winner */
  10.344 +			found = 1;
  10.345 +			break;
  10.346 +		}
  10.347 +		entry = entry->next;
  10.348 +	}
  10.349 +
  10.350 +	if(found == 0)
  10.351 +		return 0; /* Already gone */
  10.352 +
  10.353 +	if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
  10.354 +		 (fibctx->size != sizeof(struct aac_fib_context)))
  10.355 +		return -EINVAL;
  10.356 +	spin_lock_irqsave(&dev->fib_lock, flags);
  10.357 +	status = aac_close_fib_context(dev, fibctx);
  10.358 +	spin_unlock_irqrestore(&dev->fib_lock, flags);
  10.359 +	return status;
  10.360 +}
  10.361 +
  10.362 +/**
  10.363 + *	check_revision	-	close down user fib context
  10.364 + *	@dev: adapter
  10.365 + *	@arg: ioctl arguments
  10.366 + *
  10.367 + *	This routine returns the firmware version.
  10.368 + *      Under Linux, there have been no version incompatibilities, so this is simple!
  10.369 + */
  10.370 +
  10.371 +static int check_revision(struct aac_dev *dev, void *arg)
  10.372 +{
  10.373 +	struct revision response;
  10.374 +
  10.375 +	response.compat = 1;
  10.376 +	response.version = dev->adapter_info.kernelrev;
  10.377 +	response.build = dev->adapter_info.kernelbuild;
  10.378 +
  10.379 +	if (copy_to_user(arg, &response, sizeof(response)))
  10.380 +		return -EFAULT;
  10.381 +	return 0;
  10.382 +}
  10.383 +
  10.384 +
  10.385 +struct aac_pci_info {
  10.386 +        u32 bus;
  10.387 +        u32 slot;
  10.388 +};
  10.389 +
  10.390 +
  10.391 +int aac_get_pci_info(struct aac_dev* dev, void* arg)
  10.392 +{
  10.393 +        struct aac_pci_info pci_info;
  10.394 +
  10.395 +	pci_info.bus = dev->pdev->bus->number;
  10.396 +	pci_info.slot = PCI_SLOT(dev->pdev->devfn);
  10.397 +
  10.398 +       if(copy_to_user( arg, (void*)&pci_info, sizeof(struct aac_pci_info)))
  10.399 +               return -EFAULT;
  10.400 +        return 0;
  10.401 + }
  10.402 + 
  10.403 +
  10.404 +int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg)
  10.405 +{
  10.406 +	int status;
  10.407 +	
  10.408 +	/*
  10.409 +	 *	HBA gets first crack
  10.410 +	 */
  10.411 +	 
  10.412 +	status = aac_dev_ioctl(dev, cmd, arg);
  10.413 +	if(status != -ENOTTY)
  10.414 +		return status;
  10.415 +
  10.416 +	switch (cmd) {
  10.417 +	case FSACTL_MINIPORT_REV_CHECK:
  10.418 +		status = check_revision(dev, arg);
  10.419 +		break;
  10.420 +	case FSACTL_SENDFIB:
  10.421 +		status = ioctl_send_fib(dev, arg);
  10.422 +		break;
  10.423 +	case FSACTL_OPEN_GET_ADAPTER_FIB:
  10.424 +		status = open_getadapter_fib(dev, arg);
  10.425 +		break;
  10.426 +	case FSACTL_GET_NEXT_ADAPTER_FIB:
  10.427 +		status = next_getadapter_fib(dev, arg);
  10.428 +		break;
  10.429 +	case FSACTL_CLOSE_GET_ADAPTER_FIB:
  10.430 +		status = close_getadapter_fib(dev, arg);
  10.431 +		break;
  10.432 +	case FSACTL_GET_PCI_INFO:
  10.433 +		status = aac_get_pci_info(dev,arg);
  10.434 +		break;
  10.435 +	default:
  10.436 +		status = -ENOTTY;
  10.437 +	  	break;	
  10.438 +	}
  10.439 +	return status;
  10.440 +}
  10.441 +
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/comminit.c	Fri Feb 21 15:10:37 2003 +0000
    11.3 @@ -0,0 +1,350 @@
    11.4 +/*
    11.5 + *	Adaptec AAC series RAID controller driver
    11.6 + *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
    11.7 + *
    11.8 + * based on the old aacraid driver that is..
    11.9 + * Adaptec aacraid device driver for Linux.
   11.10 + *
   11.11 + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
   11.12 + *
   11.13 + * This program is free software; you can redistribute it and/or modify
   11.14 + * it under the terms of the GNU General Public License as published by
   11.15 + * the Free Software Foundation; either version 2, or (at your option)
   11.16 + * any later version.
   11.17 + *
   11.18 + * This program is distributed in the hope that it will be useful,
   11.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   11.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11.21 + * GNU General Public License for more details.
   11.22 + *
   11.23 + * You should have received a copy of the GNU General Public License
   11.24 + * along with this program; see the file COPYING.  If not, write to
   11.25 + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   11.26 + *
   11.27 + * Module Name:
   11.28 + *  comminit.c
   11.29 + *
   11.30 + * Abstract: This supports the initialization of the host adapter commuication interface.
   11.31 + *    This is a platform dependent module for the pci cyclone board.
   11.32 + *
   11.33 + */
   11.34 +
   11.35 +#include <xeno/config.h>
   11.36 +/* #include <xeno/kernel.h> */
   11.37 +#include <xeno/init.h>
   11.38 +#include <xeno/types.h>
   11.39 +#include <xeno/sched.h>
   11.40 +#include <xeno/pci.h>
   11.41 +#include <xeno/spinlock.h>
   11.42 +/* #include <xeno/slab.h> */
   11.43 +#include <xeno/blk.h>
   11.44 +/* #include <xeno/completion.h> */
   11.45 +/* #include <asm/semaphore.h> */
   11.46 +#include "scsi.h"
   11.47 +#include "hosts.h"
   11.48 +
   11.49 +#include "aacraid.h"
   11.50 +
   11.51 +struct aac_common aac_config;
   11.52 +
   11.53 +static struct aac_dev *devices;
   11.54 +
   11.55 +static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long commsize, unsigned long commalign)
   11.56 +{
   11.57 +	unsigned char *base;
   11.58 +	unsigned long size, align;
   11.59 +	unsigned long fibsize = 4096;
   11.60 +	unsigned long printfbufsiz = 256;
   11.61 +	struct aac_init *init;
   11.62 +	dma_addr_t phys;
   11.63 +
   11.64 +	/* FIXME: Adaptec add 128 bytes to this value - WHY ?? */
   11.65 +	size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz;
   11.66 +
   11.67 +	base = pci_alloc_consistent(dev->pdev, size, &phys);
   11.68 +	if(base == NULL)
   11.69 +	{
   11.70 +		printk(KERN_ERR "aacraid: unable to create mapping.\n");
   11.71 +		return 0;
   11.72 +	}
   11.73 +	dev->comm_addr = (void *)base;
   11.74 +	dev->comm_phys = phys;
   11.75 +	dev->comm_size = size;
   11.76 +
   11.77 +	dev->init = (struct aac_init *)(base + fibsize);
   11.78 +	dev->init_pa = phys + fibsize;
   11.79 +
   11.80 +	/*
   11.81 +	 *	Cache the upper bits of the virtual mapping for 64bit boxes
   11.82 +	 *	FIXME: this crap should be rewritten
   11.83 +	 */
   11.84 +#if BITS_PER_LONG >= 64 
   11.85 +	dev->fib_base_va = ((ulong)base & 0xffffffff00000000);
   11.86 +#endif
   11.87 +
   11.88 +	init = dev->init;
   11.89 +
   11.90 +	init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
   11.91 +	init->MiniPortRevision = cpu_to_le32(Sa_MINIPORT_REVISION);
   11.92 +	init->fsrev = cpu_to_le32(dev->fsrev);
   11.93 +
   11.94 +	/*
   11.95 +	 *	Adapter Fibs are the first thing allocated so that they
   11.96 +	 *	start page aligned
   11.97 +	 */
   11.98 +	init->AdapterFibsVirtualAddress = cpu_to_le32((u32)base);
   11.99 +	init->AdapterFibsPhysicalAddress = cpu_to_le32(phys);
  11.100 +	init->AdapterFibsSize = cpu_to_le32(fibsize);
  11.101 +	init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
  11.102 +
  11.103 +	/*
  11.104 +	 * Increment the base address by the amount already used
  11.105 +	 */
  11.106 +	base = base + fibsize + sizeof(struct aac_init);
  11.107 +	phys = phys + fibsize + sizeof(struct aac_init);
  11.108 +	/*
  11.109 +	 *	Align the beginning of Headers to commalign
  11.110 +	 */
  11.111 +	align = (commalign - ((unsigned long)(base) & (commalign - 1)));
  11.112 +	base = base + align;
  11.113 +	phys = phys + align;
  11.114 +	/*
  11.115 +	 *	Fill in addresses of the Comm Area Headers and Queues
  11.116 +	 */
  11.117 +	*commaddr = (unsigned long *)base;
  11.118 +	init->CommHeaderAddress = cpu_to_le32(phys);
  11.119 +	/*
  11.120 +	 *	Increment the base address by the size of the CommArea
  11.121 +	 */
  11.122 +	base = base + commsize;
  11.123 +	phys = phys + commsize;
  11.124 +	/*
  11.125 +	 *	 Place the Printf buffer area after the Fast I/O comm area.
  11.126 +	 */
  11.127 +	dev->printfbuf = (void *)base;
  11.128 +	init->printfbuf = cpu_to_le32(phys);
  11.129 +	init->printfbufsiz = cpu_to_le32(printfbufsiz);
  11.130 +	memset(base, 0, printfbufsiz);
  11.131 +	return 1;
  11.132 +}
  11.133 +    
  11.134 +static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, int qsize)
  11.135 +{
  11.136 +	q->numpending = 0;
  11.137 +	q->dev = dev;
  11.138 +	INIT_LIST_HEAD(&q->pendingq);
  11.139 +#if 0
  11.140 +	init_waitqueue_head(&q->cmdready);
  11.141 +#endif
  11.142 +	INIT_LIST_HEAD(&q->cmdq);
  11.143 +#if 0
  11.144 +	init_waitqueue_head(&q->qfull);
  11.145 +#endif
  11.146 +	spin_lock_init(&q->lockdata);
  11.147 +	q->lock = &q->lockdata;
  11.148 +	q->headers.producer = mem;
  11.149 +	q->headers.consumer = mem+1;
  11.150 +	*q->headers.producer = cpu_to_le32(qsize);
  11.151 +	*q->headers.consumer = cpu_to_le32(qsize);
  11.152 +	q->entries = qsize;
  11.153 +}
  11.154 +
  11.155 +/**
  11.156 + *	aac_send_shutdown		-	shutdown an adapter
  11.157 + *	@dev: Adapter to shutdown
  11.158 + *
  11.159 + *	This routine will send a VM_CloseAll (shutdown) request to the adapter.
  11.160 + */
  11.161 +
  11.162 +static int aac_send_shutdown(struct aac_dev * dev)
  11.163 +{
  11.164 +	struct fib * fibctx;
  11.165 +	struct aac_close *cmd;
  11.166 +	int status;
  11.167 +
  11.168 +	fibctx = fib_alloc(dev);
  11.169 +	fib_init(fibctx);
  11.170 +
  11.171 +	cmd = (struct aac_close *) fib_data(fibctx);
  11.172 +
  11.173 +	cmd->command = cpu_to_le32(VM_CloseAll);
  11.174 +	cmd->cid = cpu_to_le32(0xffffffff);
  11.175 +
  11.176 +	status = fib_send(ContainerCommand,
  11.177 +			  fibctx,
  11.178 +			  sizeof(struct aac_close),
  11.179 +			  FsaNormal,
  11.180 +			  1, 1,
  11.181 +			  NULL, NULL);
  11.182 +
  11.183 +	if (status == 0)
  11.184 +		fib_complete(fibctx);
  11.185 +	fib_free(fibctx);
  11.186 +	return status;
  11.187 +}
  11.188 +
  11.189 +/**
  11.190 + *	aac_detach	-	detach adapter
  11.191 + *	@detach: adapter to disconnect
  11.192 + *
  11.193 + *	Disconnect and shutdown an AAC based adapter, freeing resources
  11.194 + *	as we go.
  11.195 + */
  11.196 +
  11.197 +int aac_detach(struct aac_dev *detach)
  11.198 +{
  11.199 +	struct aac_dev **dev = &devices;
  11.200 +	
  11.201 +	while(*dev)
  11.202 +	{
  11.203 +		if(*dev == detach)
  11.204 +		{
  11.205 +			*dev = detach->next;
  11.206 +			aac_send_shutdown(detach);
  11.207 +			fib_map_free(detach);
  11.208 +			pci_free_consistent(detach->pdev, detach->comm_size, detach->comm_addr, detach->comm_phys);
  11.209 +			kfree(detach->queues);
  11.210 +			return 1;
  11.211 +		}
  11.212 +		dev=&((*dev)->next);
  11.213 +	}
  11.214 +	BUG();
  11.215 +	return 0;
  11.216 +}
  11.217 +
  11.218 +/**
  11.219 + *	aac_comm_init	-	Initialise FSA data structures
  11.220 + *	@dev:	Adapter to intialise
  11.221 + *
  11.222 + *	Initializes the data structures that are required for the FSA commuication
  11.223 + *	interface to operate. 
  11.224 + *	Returns
  11.225 + *		1 - if we were able to init the commuication interface.
  11.226 + *		0 - If there were errors initing. This is a fatal error.
  11.227 + */
  11.228 + 
  11.229 +int aac_comm_init(struct aac_dev * dev)
  11.230 +{
  11.231 +	unsigned long hdrsize = (sizeof(u32) * NUMBER_OF_COMM_QUEUES) * 2;
  11.232 +	unsigned long queuesize = sizeof(struct aac_entry) * TOTAL_QUEUE_ENTRIES;
  11.233 +	u32 *headers;
  11.234 +	struct aac_entry * queues;
  11.235 +	unsigned long size;
  11.236 +	struct aac_queue_block * comm = dev->queues;
  11.237 +
  11.238 +	/*
  11.239 +	 *	Now allocate and initialize the zone structures used as our 
  11.240 +	 *	pool of FIB context records.  The size of the zone is based
  11.241 +	 *	on the system memory size.  We also initialize the mutex used
  11.242 +	 *	to protect the zone.
  11.243 +	 */
  11.244 +	spin_lock_init(&dev->fib_lock);
  11.245 +
  11.246 +	/*
  11.247 +	 *	Allocate the physically contigous space for the commuication
  11.248 +	 *	queue headers. 
  11.249 +	 */
  11.250 +
  11.251 +	size = hdrsize + queuesize;
  11.252 +
  11.253 +	if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT))
  11.254 +		return -ENOMEM;
  11.255 +
  11.256 +	queues = (struct aac_entry *)((unsigned char *)headers + hdrsize);
  11.257 +
  11.258 +	/* Adapter to Host normal proirity Command queue */ 
  11.259 +	comm->queue[HostNormCmdQueue].base = queues;
  11.260 +	aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES);
  11.261 +	queues += HOST_NORM_CMD_ENTRIES;
  11.262 +	headers += 2;
  11.263 +
  11.264 +	/* Adapter to Host high priority command queue */
  11.265 +	comm->queue[HostHighCmdQueue].base = queues;
  11.266 +	aac_queue_init(dev, &comm->queue[HostHighCmdQueue], headers, HOST_HIGH_CMD_ENTRIES);
  11.267 +    
  11.268 +	queues += HOST_HIGH_CMD_ENTRIES;
  11.269 +	headers +=2;
  11.270 +
  11.271 +	/* Host to adapter normal priority command queue */
  11.272 +	comm->queue[AdapNormCmdQueue].base = queues;
  11.273 +	aac_queue_init(dev, &comm->queue[AdapNormCmdQueue], headers, ADAP_NORM_CMD_ENTRIES);
  11.274 +    
  11.275 +	queues += ADAP_NORM_CMD_ENTRIES;
  11.276 +	headers += 2;
  11.277 +
  11.278 +	/* host to adapter high priority command queue */
  11.279 +	comm->queue[AdapHighCmdQueue].base = queues;
  11.280 +	aac_queue_init(dev, &comm->queue[AdapHighCmdQueue], headers, ADAP_HIGH_CMD_ENTRIES);
  11.281 +    
  11.282 +	queues += ADAP_HIGH_CMD_ENTRIES;
  11.283 +	headers += 2;
  11.284 +
  11.285 +	/* adapter to host normal priority response queue */
  11.286 +	comm->queue[HostNormRespQueue].base = queues;
  11.287 +	aac_queue_init(dev, &comm->queue[HostNormRespQueue], headers, HOST_NORM_RESP_ENTRIES);
  11.288 +    
  11.289 +	queues += HOST_NORM_RESP_ENTRIES;
  11.290 +	headers += 2;
  11.291 +
  11.292 +	/* adapter to host high priority response queue */
  11.293 +	comm->queue[HostHighRespQueue].base = queues;
  11.294 +	aac_queue_init(dev, &comm->queue[HostHighRespQueue], headers, HOST_HIGH_RESP_ENTRIES);
  11.295 +   
  11.296 +	queues += HOST_HIGH_RESP_ENTRIES;
  11.297 +	headers += 2;
  11.298 +
  11.299 +	/* host to adapter normal priority response queue */
  11.300 +	comm->queue[AdapNormRespQueue].base = queues;
  11.301 +	aac_queue_init(dev, &comm->queue[AdapNormRespQueue], headers, ADAP_NORM_RESP_ENTRIES);
  11.302 +
  11.303 +	queues += ADAP_NORM_RESP_ENTRIES;
  11.304 +	headers += 2;
  11.305 +	
  11.306 +	/* host to adapter high priority response queue */ 
  11.307 +	comm->queue[AdapHighRespQueue].base = queues;
  11.308 +	aac_queue_init(dev, &comm->queue[AdapHighRespQueue], headers, ADAP_HIGH_RESP_ENTRIES);
  11.309 +
  11.310 +	comm->queue[AdapNormCmdQueue].lock = comm->queue[HostNormRespQueue].lock;
  11.311 +	comm->queue[AdapHighCmdQueue].lock = comm->queue[HostHighRespQueue].lock;
  11.312 +	comm->queue[AdapNormRespQueue].lock = comm->queue[HostNormCmdQueue].lock;
  11.313 +	comm->queue[AdapHighRespQueue].lock = comm->queue[HostHighCmdQueue].lock;
  11.314 +
  11.315 +	return 0;
  11.316 +}
  11.317 +
  11.318 +struct aac_dev *aac_init_adapter(struct aac_dev *dev)
  11.319 +{
  11.320 +	/*
  11.321 +	 *	Ok now init the communication subsystem
  11.322 +	 */
  11.323 +	dev->queues = (struct aac_queue_block *) 
  11.324 +	    kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
  11.325 +	if (dev->queues == NULL) {
  11.326 +		printk(KERN_ERR "Error could not allocate comm region.\n");
  11.327 +		return NULL;
  11.328 +	}
  11.329 +	memset(dev->queues, 0, sizeof(struct aac_queue_block));
  11.330 +
  11.331 +	printk("aac_init_adapater, dev is %p\n", dev); 
  11.332 +	if (aac_comm_init(dev)<0)
  11.333 +		return NULL;
  11.334 +	printk("aac_init_adapater, dev->init is %p\n", dev->init); 
  11.335 +	/*
  11.336 +	 *	Initialize the list of fibs
  11.337 +	 */
  11.338 +	if(fib_setup(dev)<0)
  11.339 +	    return NULL;
  11.340 +		
  11.341 +	INIT_LIST_HEAD(&dev->fib_list);
  11.342 +#if 0
  11.343 +	init_completion(&dev->aif_completion);
  11.344 +#endif
  11.345 +	/*
  11.346 +	 *	Add this adapter in to our dev List.
  11.347 +	 */
  11.348 +	dev->next = devices;
  11.349 +	devices = dev;
  11.350 +	return dev;
  11.351 +}
  11.352 +
  11.353 +    
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/commsup.c	Fri Feb 21 15:10:37 2003 +0000
    12.3 @@ -0,0 +1,1022 @@
    12.4 +/*
    12.5 + *	Adaptec AAC series RAID controller driver
    12.6 + *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
    12.7 + *
    12.8 + * based on the old aacraid driver that is..
    12.9 +
   12.10 + * Adaptec aacraid device driver for Linux.
   12.11 + *
   12.12 + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
   12.13 + *
   12.14 + * This program is free software; you can redistribute it and/or modify
   12.15 + * it under the terms of the GNU General Public License as published by
   12.16 + * the Free Software Foundation; either version 2, or (at your option)
   12.17 + * any later version.
   12.18 + *
   12.19 + * This program is distributed in the hope that it will be useful,
   12.20 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   12.21 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   12.22 + * GNU General Public License for more details.
   12.23 + *
   12.24 + * You should have received a copy of the GNU General Public License
   12.25 + * along with this program; see the file COPYING.  If not, write to
   12.26 + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   12.27 + *
   12.28 + * Module Name:
   12.29 + *  commsup.c
   12.30 + *
   12.31 + * Abstract: Contain all routines that are required for FSA host/adapter
   12.32 + *    commuication.
   12.33 + *
   12.34 + *
   12.35 + */
   12.36 +
   12.37 +#include <xeno/config.h>
   12.38 +/* #include <xeno/kernel.h> */
   12.39 +#include <xeno/init.h>
   12.40 +#include <xeno/types.h>
   12.41 +#include <xeno/sched.h>
   12.42 +#include <xeno/pci.h>
   12.43 +#include <xeno/spinlock.h>
   12.44 +
   12.45 +#include <xeno/interrupt.h> // for softirq stuff 
   12.46 +
   12.47 +/*  #include <xeno/slab.h> */
   12.48 +/*  #include <xeno/completion.h> */
   12.49 +/*  #include <asm/semaphore.h> */
   12.50 +#include <xeno/blk.h>
   12.51 +#include <xeno/delay.h>
   12.52 +#include "scsi.h"
   12.53 +#include "hosts.h"
   12.54 +
   12.55 +#include "aacraid.h"
   12.56 +
   12.57 +/**
   12.58 + *	fib_map_alloc		-	allocate the fib objects
   12.59 + *	@dev: Adapter to allocate for
   12.60 + *
   12.61 + *	Allocate and map the shared PCI space for the FIB blocks used to
   12.62 + *	talk to the Adaptec firmware.
   12.63 + */
   12.64 + 
   12.65 +static int fib_map_alloc(struct aac_dev *dev)
   12.66 +{
   12.67 +    if((dev->hw_fib_va = 
   12.68 +	pci_alloc_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, 
   12.69 +			     &dev->hw_fib_pa))==NULL)
   12.70 +	return -ENOMEM;
   12.71 +    return 0;
   12.72 +}
   12.73 +
   12.74 +/**
   12.75 + *	fib_map_free		-	free the fib objects
   12.76 + *	@dev: Adapter to free
   12.77 + *
   12.78 + *	Free the PCI mappings and the memory allocated for FIB blocks
   12.79 + *	on this adapter.
   12.80 + */
   12.81 +
   12.82 +void fib_map_free(struct aac_dev *dev)
   12.83 +{
   12.84 +    pci_free_consistent(dev->pdev, sizeof(struct hw_fib) * AAC_NUM_FIB, 
   12.85 +			dev->hw_fib_va, dev->hw_fib_pa);
   12.86 +}
   12.87 +
   12.88 +/**
   12.89 + *	fib_setup	-	setup the fibs
   12.90 + *	@dev: Adapter to set up
   12.91 + *
   12.92 + *	Allocate the PCI space for the fibs, map it and then intialise the
   12.93 + *	fib area, the unmapped fib data and also the free list
   12.94 + */
   12.95 +
   12.96 +int fib_setup(struct aac_dev * dev)
   12.97 +{
   12.98 +    struct fib *fibptr;
   12.99 +    struct hw_fib *fib;
  12.100 +    dma_addr_t fibpa;
  12.101 +    int i;
  12.102 +    
  12.103 +    if(fib_map_alloc(dev)<0)
  12.104 +	return -ENOMEM;
  12.105 +    
  12.106 +    fib = dev->hw_fib_va;
  12.107 +    fibpa = dev->hw_fib_pa;
  12.108 +    memset(fib, 0, sizeof(struct hw_fib) * AAC_NUM_FIB);
  12.109 +    /*
  12.110 +     *	Initialise the fibs
  12.111 +     */
  12.112 +    for (i = 0, fibptr = &dev->fibs[i]; i < AAC_NUM_FIB; i++, fibptr++) 
  12.113 +    {
  12.114 +	fibptr->dev = dev;
  12.115 +	fibptr->fib = fib;
  12.116 +	fibptr->data = (void *) fibptr->fib->data;
  12.117 +	fibptr->next = fibptr+1;	/* Forward chain the fibs */
  12.118 +#if 0
  12.119 +	init_MUTEX_LOCKED(&fibptr->event_wait);
  12.120 +#endif
  12.121 +	spin_lock_init(&fibptr->event_lock);
  12.122 +	fib->header.XferState = cpu_to_le32(0xffffffff);
  12.123 +	fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
  12.124 +	fibptr->logicaladdr = (unsigned long) fibpa;
  12.125 +	fib = (struct hw_fib *)((unsigned char *)fib + sizeof(struct hw_fib));
  12.126 +	fibpa = fibpa + sizeof(struct hw_fib);
  12.127 +    }
  12.128 +    /*
  12.129 +     *	Add the fib chain to the free list
  12.130 +     */
  12.131 +    dev->fibs[AAC_NUM_FIB-1].next = NULL;
  12.132 +    /*
  12.133 +     *	Enable this to debug out of queue space
  12.134 +     */
  12.135 +    dev->free_fib = &dev->fibs[0];
  12.136 +    return 0;
  12.137 +}
  12.138 +
  12.139 +/**
  12.140 + *	fib_alloc	-	allocate a fib
  12.141 + *	@dev: Adapter to allocate the fib for
  12.142 + *
  12.143 + *	Allocate a fib from the adapter fib pool. If the pool is empty we
  12.144 + *	wait for fibs to become free.
  12.145 + */
  12.146 + 
  12.147 +struct fib * fib_alloc(struct aac_dev *dev)
  12.148 +{
  12.149 +    struct fib * fibptr;
  12.150 +    unsigned long flags;
  12.151 +    
  12.152 +    spin_lock_irqsave(&dev->fib_lock, flags);
  12.153 +    fibptr = dev->free_fib;	
  12.154 +    if(!fibptr)
  12.155 +	BUG();
  12.156 +    dev->free_fib = fibptr->next;
  12.157 +    spin_unlock_irqrestore(&dev->fib_lock, flags);
  12.158 +    /*
  12.159 +     *	Set the proper node type code and node byte size
  12.160 +     */
  12.161 +    fibptr->type = FSAFS_NTC_FIB_CONTEXT;
  12.162 +    fibptr->size = sizeof(struct fib);
  12.163 +    /*
  12.164 +     *	Null out fields that depend on being zero at the start of
  12.165 +     *	each I/O
  12.166 +     */
  12.167 +    fibptr->fib->header.XferState = cpu_to_le32(0);
  12.168 +    fibptr->callback = NULL;
  12.169 +    fibptr->callback_data = NULL;
  12.170 +    
  12.171 +    return fibptr;
  12.172 +}
  12.173 +
  12.174 +/**
  12.175 + *	fib_free	-	free a fib
  12.176 + *	@fibptr: fib to free up
  12.177 + *
  12.178 + *	Frees up a fib and places it on the appropriate queue
  12.179 + *	(either free or timed out)
  12.180 + */
  12.181 + 
  12.182 +void fib_free(struct fib * fibptr)
  12.183 +{
  12.184 +    unsigned long flags;
  12.185 +    
  12.186 +    spin_lock_irqsave(&fibptr->dev->fib_lock, flags);
  12.187 +    
  12.188 +    if (fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT) {
  12.189 +	aac_config.fib_timeouts++;
  12.190 +	fibptr->next = fibptr->dev->timeout_fib;
  12.191 +	fibptr->dev->timeout_fib = fibptr;
  12.192 +    } else {
  12.193 +	if (fibptr->fib->header.XferState != 0) {
  12.194 +	    printk(KERN_WARNING "fib_free, XferState != 0, "
  12.195 +		   "fibptr = 0x%p, XferState = 0x%x\n", 
  12.196 +		   (void *)fibptr, fibptr->fib->header.XferState);
  12.197 +	}
  12.198 +	fibptr->next = fibptr->dev->free_fib;
  12.199 +	fibptr->dev->free_fib = fibptr;
  12.200 +    }	
  12.201 +    spin_unlock_irqrestore(&fibptr->dev->fib_lock, flags);
  12.202 +}
  12.203 +
  12.204 +/**
  12.205 + *	fib_init	-	initialise a fib
  12.206 + *	@fibptr: The fib to initialize
  12.207 + *	
  12.208 + *	Set up the generic fib fields ready for use
  12.209 + */
  12.210 + 
  12.211 +void fib_init(struct fib *fibptr)
  12.212 +{
  12.213 +    struct hw_fib *fib = fibptr->fib;
  12.214 +    
  12.215 +    fib->header.StructType = FIB_MAGIC;
  12.216 +    fib->header.Size = cpu_to_le16(sizeof(struct hw_fib));
  12.217 +    fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | 
  12.218 +					FibEmpty | FastResponseCapable);
  12.219 +    fib->header.SenderFibAddress = cpu_to_le32(0);
  12.220 +    fib->header.ReceiverFibAddress = cpu_to_le32(0);
  12.221 +    fib->header.SenderSize = cpu_to_le16(sizeof(struct hw_fib));
  12.222 +}
  12.223 +
  12.224 +/**
  12.225 + *	fib_deallocate		-	deallocate a fib
  12.226 + *	@fibptr: fib to deallocate
  12.227 + *
  12.228 + *	Will deallocate and return to the free pool the FIB pointed to by the
  12.229 + *	caller.
  12.230 + */
  12.231 + 
  12.232 +void fib_dealloc(struct fib * fibptr)
  12.233 +{
  12.234 +    struct hw_fib *fib = fibptr->fib;
  12.235 +    if(fib->header.StructType != FIB_MAGIC) 
  12.236 +	BUG();
  12.237 +    fib->header.XferState = cpu_to_le32(0);        
  12.238 +}
  12.239 +
  12.240 +/*
  12.241 + *	Commuication primitives define and support the queuing method we use to
  12.242 + *	support host to adapter commuication. All queue accesses happen through
  12.243 + *	these routines and are the only routines which have a knowledge of the
  12.244 + *	 how these queues are implemented.
  12.245 + */
  12.246 + 
  12.247 +/**
  12.248 + *	aac_get_entry		-	get a queue entry
  12.249 + *	@dev: Adapter
  12.250 + *	@qid: Queue Number
  12.251 + *	@entry: Entry return
  12.252 + *	@index: Index return
  12.253 + *	@nonotify: notification control
  12.254 + *
  12.255 + *	With a priority the routine returns a queue entry if the queue has free entries. If the queue
  12.256 + *	is full(no free entries) than no entry is returned and the function returns 0 otherwise 1 is
  12.257 + *	returned.
  12.258 + */
  12.259 + 
  12.260 +static int aac_get_entry (struct aac_dev * dev, u32 qid, struct aac_entry **entry, u32 * index, unsigned long *nonotify)
  12.261 +{
  12.262 +    struct aac_queue * q;
  12.263 +
  12.264 +    /*
  12.265 +     *	All of the queues wrap when they reach the end, so we check
  12.266 +     *	to see if they have reached the end and if they have we just
  12.267 +     *	set the index back to zero. This is a wrap. You could or off
  12.268 +     *	the high bits in all updates but this is a bit faster I think.
  12.269 +     */
  12.270 +
  12.271 +    q = &dev->queues->queue[qid];
  12.272 +	
  12.273 +    *index = le32_to_cpu(*(q->headers.producer));
  12.274 +    if (*index - 2 == le32_to_cpu(*(q->headers.consumer)))
  12.275 +	*nonotify = 1; 
  12.276 +
  12.277 +    if (qid == AdapHighCmdQueue) {
  12.278 +	if (*index >= ADAP_HIGH_CMD_ENTRIES)
  12.279 +	    *index = 0;
  12.280 +    } else if (qid == AdapNormCmdQueue) {
  12.281 +	if (*index >= ADAP_NORM_CMD_ENTRIES) 
  12.282 +	    *index = 0; /* Wrap to front of the Producer Queue. */
  12.283 +    }
  12.284 +    else if (qid == AdapHighRespQueue) 
  12.285 +    {
  12.286 +	if (*index >= ADAP_HIGH_RESP_ENTRIES)
  12.287 +	    *index = 0;
  12.288 +    }
  12.289 +    else if (qid == AdapNormRespQueue) 
  12.290 +    {
  12.291 +	if (*index >= ADAP_NORM_RESP_ENTRIES) 
  12.292 +	    *index = 0; /* Wrap to front of the Producer Queue. */
  12.293 +    }
  12.294 +    else BUG();
  12.295 +
  12.296 +    if (*index + 1 == le32_to_cpu(*(q->headers.consumer))) { /* Queue full */
  12.297 +	printk(KERN_WARNING "Queue %d full, %ld outstanding.\n", 
  12.298 +	       qid, q->numpending);
  12.299 +	return 0;
  12.300 +    } else {
  12.301 +	*entry = q->base + *index;
  12.302 +	return 1;
  12.303 +    }
  12.304 +}   
  12.305 +
  12.306 +/**
  12.307 + *	aac_queue_get		-	get the next free QE
  12.308 + *	@dev: Adapter
  12.309 + *	@index: Returned index
  12.310 + *	@priority: Priority of fib
  12.311 + *	@fib: Fib to associate with the queue entry
  12.312 + *	@wait: Wait if queue full
  12.313 + *	@fibptr: Driver fib object to go with fib
  12.314 + *	@nonotify: Don't notify the adapter
  12.315 + *
  12.316 + *	Gets the next free QE off the requested priorty adapter command
  12.317 + *	queue and associates the Fib with the QE. The QE represented by
  12.318 + *	index is ready to insert on the queue when this routine returns
  12.319 + *	success.
  12.320 + */
  12.321 +
  12.322 +static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * fib, int wait, struct fib * fibptr, unsigned long *nonotify)
  12.323 +{
  12.324 +    struct aac_entry * entry = NULL;
  12.325 +    int map = 0;
  12.326 +    struct aac_queue * q = &dev->queues->queue[qid];
  12.327 +		
  12.328 +    spin_lock_irqsave(q->lock, q->SavedIrql);
  12.329 +	    
  12.330 +    if (qid == AdapHighCmdQueue || qid == AdapNormCmdQueue) 
  12.331 +    {
  12.332 +	/*  if no entries wait for some if caller wants to */
  12.333 +	while (!aac_get_entry(dev, qid, &entry, index, nonotify)) 
  12.334 +	{
  12.335 +	    printk(KERN_ERR "GetEntries failed\n");
  12.336 +	}
  12.337 +	/*
  12.338 +	 *	Setup queue entry with a command, status and fib mapped
  12.339 +	 */
  12.340 +	entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size));
  12.341 +	map = 1;
  12.342 +    }
  12.343 +    else if (qid == AdapHighRespQueue || qid == AdapNormRespQueue)
  12.344 +    {
  12.345 +	while(!aac_get_entry(dev, qid, &entry, index, nonotify)) 
  12.346 +	{
  12.347 +	    /* if no entries wait for some if caller wants to */
  12.348 +	}
  12.349 +	/*
  12.350 +	 *	Setup queue entry with command, status and fib mapped
  12.351 +	 */
  12.352 +	entry->size = cpu_to_le32(le16_to_cpu(fib->header.Size));
  12.353 +	entry->addr = cpu_to_le32(fib->header.SenderFibAddress);     		/* Restore adapters pointer to the FIB */
  12.354 +	fib->header.ReceiverFibAddress = fib->header.SenderFibAddress;		/* Let the adapter now where to find its data */
  12.355 +	map = 0;
  12.356 +    } 
  12.357 +    /*
  12.358 +     *	If MapFib is true than we need to map the Fib and put pointers
  12.359 +     *	in the queue entry.
  12.360 +     */
  12.361 +    if (map)
  12.362 +	entry->addr = cpu_to_le32((unsigned long)(fibptr->logicaladdr));
  12.363 +    return 0;
  12.364 +}
  12.365 +
  12.366 +
  12.367 +/**
  12.368 + *	aac_insert_entry	-	insert a queue entry
  12.369 + *	@dev: Adapter
  12.370 + *	@index: Index of entry to insert
  12.371 + *	@qid: Queue number
  12.372 + *	@nonotify: Suppress adapter notification
  12.373 + *
  12.374 + *	Gets the next free QE off the requested priorty adapter command
  12.375 + *	queue and associates the Fib with the QE. The QE represented by
  12.376 + *	index is ready to insert on the queue when this routine returns
  12.377 + *	success.
  12.378 + */
  12.379 + 
  12.380 +static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned long nonotify) 
  12.381 +{
  12.382 +    struct aac_queue * q = &dev->queues->queue[qid];
  12.383 +
  12.384 +    if(q == NULL)
  12.385 +	BUG();
  12.386 +    *(q->headers.producer) = cpu_to_le32(index + 1);
  12.387 +    spin_unlock_irqrestore(q->lock, q->SavedIrql);
  12.388 +
  12.389 +    if (qid == AdapHighCmdQueue ||
  12.390 +	qid == AdapNormCmdQueue ||
  12.391 +	qid == AdapHighRespQueue ||
  12.392 +	qid == AdapNormRespQueue)
  12.393 +    {
  12.394 +	if (!nonotify)
  12.395 +	    aac_adapter_notify(dev, qid);
  12.396 +    }
  12.397 +    else
  12.398 +	printk("Suprise insert!\n");
  12.399 +    return 0;
  12.400 +}
  12.401 +
  12.402 +/*
  12.403 + *	Define the highest level of host to adapter communication routines. 
  12.404 + *	These routines will support host to adapter FS commuication. These 
  12.405 + *	routines have no knowledge of the commuication method used. This level
  12.406 + *	sends and receives FIBs. This level has no knowledge of how these FIBs
  12.407 + *	get passed back and forth.
  12.408 + */
  12.409 +
  12.410 +/**
  12.411 + *	fib_send	-	send a fib to the adapter
  12.412 + *	@command: Command to send
  12.413 + *	@fibptr: The fib
  12.414 + *	@size: Size of fib data area
  12.415 + *	@priority: Priority of Fib
  12.416 + *	@wait: Async/sync select
  12.417 + *	@reply: True if a reply is wanted
  12.418 + *	@callback: Called with reply
  12.419 + *	@callback_data: Passed to callback
  12.420 + *
  12.421 + *	Sends the requested FIB to the adapter and optionally will wait for a
  12.422 + *	response FIB. If the caller does not wish to wait for a response than
  12.423 + *	an event to wait on must be supplied. This event will be set when a
  12.424 + *	response FIB is received from the adapter.
  12.425 + */
  12.426 + 
  12.427 +int fib_send(u16 command, struct fib * fibptr, unsigned long size,  int priority, int wait, int reply, fib_callback callback, void * callback_data)
  12.428 +{
  12.429 +    u32 index;
  12.430 +    u32 qid;
  12.431 +    struct aac_dev * dev = fibptr->dev;
  12.432 +    unsigned long nointr = 0;
  12.433 +    struct hw_fib * fib = fibptr->fib;
  12.434 +    struct aac_queue * q;
  12.435 +    unsigned long flags = 0;
  12.436 +
  12.437 +    if (!(le32_to_cpu(fib->header.XferState) & HostOwned))
  12.438 +	return -EBUSY;
  12.439 +    /*
  12.440 +     *	There are 5 cases with the wait and reponse requested flags. 
  12.441 +     *	The only invalid cases are if the caller requests to wait and
  12.442 +     *	does not request a response and if the caller does not want a
  12.443 +     *	response and the Fibis not allocated from pool. If a response
  12.444 +     *	is not requesed the Fib will just be deallocaed by the DPC
  12.445 +     *	routine when the response comes back from the adapter. No
  12.446 +     *	further processing will be done besides deleting the Fib. We 
  12.447 +     *	will have a debug mode where the adapter can notify the host
  12.448 +     *	it had a problem and the host can log that fact.
  12.449 +     */
  12.450 +    if (wait && !reply) {
  12.451 +	return -EINVAL;
  12.452 +    } else if (!wait && reply) {
  12.453 +	fib->header.XferState |= cpu_to_le32(Async | ResponseExpected);
  12.454 +	FIB_COUNTER_INCREMENT(aac_config.AsyncSent);
  12.455 +    } else if (!wait && !reply) {
  12.456 +	fib->header.XferState |= cpu_to_le32(NoResponseExpected);
  12.457 +	FIB_COUNTER_INCREMENT(aac_config.NoResponseSent);
  12.458 +    } else if (wait && reply) {
  12.459 +	fib->header.XferState |= cpu_to_le32(ResponseExpected);
  12.460 +	FIB_COUNTER_INCREMENT(aac_config.NormalSent);
  12.461 +    } 
  12.462 +    /*
  12.463 +     *	Map the fib into 32bits by using the fib number
  12.464 +     */
  12.465 +    fib->header.SenderData = fibptr-&dev->fibs[0];	/* for callback */
  12.466 +    /*
  12.467 +     *	Set FIB state to indicate where it came from and if we want a
  12.468 +     *	response from the adapter. Also load the command from the
  12.469 +     *	caller.
  12.470 +     *
  12.471 +     *	Map the hw fib pointer as a 32bit value
  12.472 +     */
  12.473 +    fib->header.SenderFibAddress = fib2addr(fib);
  12.474 +    fib->header.Command = cpu_to_le16(command);
  12.475 +    fib->header.XferState |= cpu_to_le32(SentFromHost);
  12.476 +    fibptr->fib->header.Flags = 0; /* Zero flags field - its internal only */
  12.477 +    /*
  12.478 +     *	Set the size of the Fib we want to send to the adapter
  12.479 +     */
  12.480 +    fib->header.Size = cpu_to_le16(sizeof(struct aac_fibhdr) + size);
  12.481 +    if (le16_to_cpu(fib->header.Size) > le16_to_cpu(fib->header.SenderSize)) {
  12.482 +	return -EMSGSIZE;
  12.483 +    }                
  12.484 +    /*
  12.485 +     *	Get a queue entry connect the FIB to it and send an notify
  12.486 +     *	the adapter a command is ready.
  12.487 +     */
  12.488 +    if (priority == FsaHigh) {
  12.489 +	fib->header.XferState |= cpu_to_le32(HighPriority);
  12.490 +	qid = AdapHighCmdQueue;
  12.491 +    } else {
  12.492 +	fib->header.XferState |= cpu_to_le32(NormalPriority);
  12.493 +	qid = AdapNormCmdQueue;
  12.494 +    }
  12.495 +    q = &dev->queues->queue[qid];
  12.496 +
  12.497 +    if(wait)
  12.498 +	spin_lock_irqsave(&fibptr->event_lock, flags);
  12.499 +
  12.500 +    if(aac_queue_get( dev, &index, qid, fib, 1, fibptr, &nointr)<0)
  12.501 +	return -EWOULDBLOCK;
  12.502 +    dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",
  12.503 +	     index));
  12.504 +    dprintk((KERN_DEBUG "Fib contents:.\n"));
  12.505 +    dprintk((KERN_DEBUG "  Command =               %d.\n", 
  12.506 +	     fib->header.Command));
  12.507 +    dprintk((KERN_DEBUG "  XferState  =            %x.\n", 
  12.508 +	     fib->header.XferState));
  12.509 +    /*
  12.510 +     *	Fill in the Callback and CallbackContext if we are not
  12.511 +     *	going to wait.
  12.512 +     */
  12.513 +    if (!wait) {
  12.514 +	fibptr->callback = callback;
  12.515 +	fibptr->callback_data = callback_data;
  12.516 +    }
  12.517 +    FIB_COUNTER_INCREMENT(aac_config.FibsSent);
  12.518 +    list_add_tail(&fibptr->queue, &q->pendingq);
  12.519 +    q->numpending++;
  12.520 +
  12.521 +    fibptr->done = 0;
  12.522 +
  12.523 +    if(aac_insert_entry(dev, index, qid, 
  12.524 +			(nointr & aac_config.irq_mod)) < 0)
  12.525 +	return -EWOULDBLOCK;
  12.526 +    /*
  12.527 +     *	If the caller wanted us to wait for response wait now. 
  12.528 +     */
  12.529 +    
  12.530 +    if (wait) {
  12.531 +	spin_unlock_irqrestore(&fibptr->event_lock, flags);
  12.532 +#if 0
  12.533 +	down(&fibptr->event_wait);
  12.534 +#endif
  12.535 +#ifdef TRY_SOFTIRQ
  12.536 +	printk("about to softirq aac_command_thread...\n"); 
  12.537 +	while (!fibptr->done) { 
  12.538 +	    raise_softirq(SCSI_LOW_SOFTIRQ); 
  12.539 +	    mdelay(100); 
  12.540 +	}
  12.541 +	printk("back from softirq cmd thread and fibptr->done!\n"); 
  12.542 +#else 
  12.543 +	printk("about to bail at aac_command_thread...\n"); 
  12.544 +	while (!fibptr->done) { 
  12.545 +	    mdelay(100); 
  12.546 +	    aac_command_thread(dev); 
  12.547 +	}
  12.548 +	printk("back from command thread and fibptr->done!\n"); 
  12.549 +#endif
  12.550 +/*  if(fibptr->done == 0) */
  12.551 +/*  			BUG(); */
  12.552 +			
  12.553 +	if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT))
  12.554 +	    return -ETIMEDOUT;
  12.555 +	else
  12.556 +	    return 0;
  12.557 +    }
  12.558 +    /*
  12.559 +     *	If the user does not want a response than return success otherwise
  12.560 +     *	return pending
  12.561 +     */
  12.562 +    if (reply)
  12.563 +	return -EINPROGRESS;
  12.564 +    else
  12.565 +	return 0;
  12.566 +}
  12.567 +
  12.568 +/** 
  12.569 + *	aac_consumer_get	-	get the top of the queue
  12.570 + *	@dev: Adapter
  12.571 + *	@q: Queue
  12.572 + *	@entry: Return entry
  12.573 + *
  12.574 + *      Will return a pointer to the entry on the top of the queue
  12.575 + * 	requested that we are a consumer of, and return the address of
  12.576 + * 	the queue entry. It does * not change the state of the queue.
  12.577 + */
  12.578 +
  12.579 +int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry)
  12.580 +{
  12.581 +    u32 index;
  12.582 +    int status;
  12.583 +
  12.584 +    if (*q->headers.producer == *q->headers.consumer) {
  12.585 +	status = 0;
  12.586 +    } else {
  12.587 +	/*
  12.588 +	 *	The consumer index must be wrapped if we have reached
  12.589 +	 *	the end of the queue, else we just use the entry
  12.590 +	 *	pointed to by the header index
  12.591 +	 */
  12.592 +	if (le32_to_cpu(*q->headers.consumer) >= q->entries) 
  12.593 +	    index = 0;		
  12.594 +	else
  12.595 +	    index = le32_to_cpu(*q->headers.consumer);
  12.596 +	*entry = q->base + index;
  12.597 +	status = 1;
  12.598 +    }
  12.599 +    return(status);
  12.600 +}
  12.601 +
  12.602 +int aac_consumer_avail(struct aac_dev *dev, struct aac_queue * q)
  12.603 +{
  12.604 +    return (*q->headers.producer != *q->headers.consumer);
  12.605 +}
  12.606 +
  12.607 +
  12.608 +/**
  12.609 + *	aac_consumer_free	-	free consumer entry
  12.610 + *	@dev: Adapter
  12.611 + *	@q: Queue
  12.612 + *	@qid: Queue ident
  12.613 + *
  12.614 + *	Frees up the current top of the queue we are a consumer of. If the
  12.615 + *	queue was full notify the producer that the queue is no longer full.
  12.616 + */
  12.617 +
  12.618 +void aac_consumer_free(struct aac_dev * dev, struct aac_queue *q, u32 qid)
  12.619 +{
  12.620 +    int wasfull = 0;
  12.621 +    u32 notify;
  12.622 +
  12.623 +    if (*q->headers.producer+1 == *q->headers.consumer)
  12.624 +	wasfull = 1;
  12.625 +        
  12.626 +    if (le32_to_cpu(*q->headers.consumer) >= q->entries)
  12.627 +	*q->headers.consumer = cpu_to_le32(1);
  12.628 +    else
  12.629 +	*q->headers.consumer = 
  12.630 +	    cpu_to_le32(le32_to_cpu(*q->headers.consumer)+1);
  12.631 +        
  12.632 +    if (wasfull) {
  12.633 +	switch (qid) {
  12.634 +
  12.635 +	case HostNormCmdQueue:
  12.636 +	    notify = HostNormCmdNotFull;
  12.637 +	    break;
  12.638 +	case HostHighCmdQueue:
  12.639 +	    notify = HostHighCmdNotFull;
  12.640 +	    break;
  12.641 +	case HostNormRespQueue:
  12.642 +	    notify = HostNormRespNotFull;
  12.643 +	    break;
  12.644 +	case HostHighRespQueue:
  12.645 +	    notify = HostHighRespNotFull;
  12.646 +	    break;
  12.647 +	default:
  12.648 +	    BUG();
  12.649 +	    return;
  12.650 +	}
  12.651 +	aac_adapter_notify(dev, notify);
  12.652 +    }
  12.653 +}        
  12.654 +
  12.655 +/**
  12.656 + *	fib_adapter_complete	-	complete adapter issued fib
  12.657 + *	@fibptr: fib to complete
  12.658 + *	@size: size of fib
  12.659 + *
  12.660 + *	Will do all necessary work to complete a FIB that was sent from
  12.661 + *	the adapter.
  12.662 + */
  12.663 +
  12.664 +int fib_adapter_complete(struct fib * fibptr, unsigned short size)
  12.665 +{
  12.666 +    struct hw_fib * fib = fibptr->fib;
  12.667 +    struct aac_dev * dev = fibptr->dev;
  12.668 +    unsigned long nointr = 0;
  12.669 +
  12.670 +    if (le32_to_cpu(fib->header.XferState) == 0)
  12.671 +	return 0;
  12.672 +    /*
  12.673 +     *	If we plan to do anything check the structure type first.
  12.674 +     */ 
  12.675 +    if ( fib->header.StructType != FIB_MAGIC ) {
  12.676 +	return -EINVAL;
  12.677 +    }
  12.678 +    /*
  12.679 +     *	This block handles the case where the adapter had sent us a
  12.680 +     *	command and we have finished processing the command. We
  12.681 +     *	call completeFib when we are done processing the command 
  12.682 +     *	and want to send a response back to the adapter. This will 
  12.683 +     *	send the completed cdb to the adapter.
  12.684 +     */
  12.685 +    if (fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
  12.686 +	fib->header.XferState |= cpu_to_le32(HostProcessed);
  12.687 +	if (fib->header.XferState & cpu_to_le32(HighPriority)) {
  12.688 +	    u32 index;
  12.689 +	    if (size) 
  12.690 +	    {
  12.691 +		size += sizeof(struct aac_fibhdr);
  12.692 +		if (size > le16_to_cpu(fib->header.SenderSize))
  12.693 +		    return -EMSGSIZE;
  12.694 +		fib->header.Size = cpu_to_le16(size);
  12.695 +	    }
  12.696 +	    if(aac_queue_get(dev, &index, AdapHighRespQueue, 
  12.697 +			     fib, 1, NULL, &nointr) < 0) {
  12.698 +		return -EWOULDBLOCK;
  12.699 +	    }
  12.700 +	    if (aac_insert_entry(dev, index, AdapHighRespQueue,  
  12.701 +				 (nointr & (int)aac_config.irq_mod)) != 0) {
  12.702 +	    }
  12.703 +	}
  12.704 +	else if (fib->header.XferState & NormalPriority) 
  12.705 +	{
  12.706 +	    u32 index;
  12.707 +
  12.708 +	    if (size) {
  12.709 +		size += sizeof(struct aac_fibhdr);
  12.710 +		if (size > le16_to_cpu(fib->header.SenderSize)) 
  12.711 +		    return -EMSGSIZE;
  12.712 +		fib->header.Size = cpu_to_le16(size);
  12.713 +	    }
  12.714 +	    if (aac_queue_get(dev, &index, AdapNormRespQueue, 
  12.715 +			      fib, 1, NULL, &nointr) < 0) 
  12.716 +		return -EWOULDBLOCK;
  12.717 +	    if (aac_insert_entry(dev, index, AdapNormRespQueue, 
  12.718 +				 (nointr & (int)aac_config.irq_mod)) != 0) 
  12.719 +	    {
  12.720 +	    }
  12.721 +	}
  12.722 +    }
  12.723 +    else 
  12.724 +    {
  12.725 +	printk(KERN_WARNING 
  12.726 +	       "fib_adapter_complete: Unknown xferstate detected.\n");
  12.727 +	BUG();
  12.728 +    }   
  12.729 +    return 0;
  12.730 +}
  12.731 +
  12.732 +/**
  12.733 + *	fib_complete	-	fib completion handler
  12.734 + *	@fib: FIB to complete
  12.735 + *
  12.736 + *	Will do all necessary work to complete a FIB.
  12.737 + */
  12.738 + 
  12.739 +int fib_complete(struct fib * fibptr)
  12.740 +{
  12.741 +    struct hw_fib * fib = fibptr->fib;
  12.742 +
  12.743 +    /*
  12.744 +     *	Check for a fib which has already been completed
  12.745 +     */
  12.746 +
  12.747 +    if (fib->header.XferState == cpu_to_le32(0))
  12.748 +	return 0;
  12.749 +    /*
  12.750 +     *	If we plan to do anything check the structure type first.
  12.751 +     */ 
  12.752 +
  12.753 +    if (fib->header.StructType != FIB_MAGIC)
  12.754 +	return -EINVAL;
  12.755 +    /*
  12.756 +     *	This block completes a cdb which orginated on the host and we 
  12.757 +     *	just need to deallocate the cdb or reinit it. At this point the
  12.758 +     *	command is complete that we had sent to the adapter and this
  12.759 +     *	cdb could be reused.
  12.760 +     */
  12.761 +    if((fib->header.XferState & cpu_to_le32(SentFromHost)) &&
  12.762 +       (fib->header.XferState & cpu_to_le32(AdapterProcessed)))
  12.763 +    {
  12.764 +	fib_dealloc(fibptr);
  12.765 +    }
  12.766 +    else if(fib->header.XferState & cpu_to_le32(SentFromHost))
  12.767 +    {
  12.768 +	/*
  12.769 +	 *	This handles the case when the host has aborted the I/O
  12.770 +	 *	to the adapter because the adapter is not responding
  12.771 +	 */
  12.772 +	fib_dealloc(fibptr);
  12.773 +    } else if(fib->header.XferState & cpu_to_le32(HostOwned)) {
  12.774 +	fib_dealloc(fibptr);
  12.775 +    } else {
  12.776 +	BUG();
  12.777 +    }   
  12.778 +    return 0;
  12.779 +}
  12.780 +
  12.781 +/**
  12.782 + *	aac_printf	-	handle printf from firmware
  12.783 + *	@dev: Adapter
  12.784 + *	@val: Message info
  12.785 + *
  12.786 + *	Print a message passed to us by the controller firmware on the
  12.787 + *	Adaptec board
  12.788 + */
  12.789 +
  12.790 +void aac_printf(struct aac_dev *dev, u32 val)
  12.791 +{
  12.792 +    int length = val & 0xffff;
  12.793 +    int level = (val >> 16) & 0xffff;
  12.794 +    char *cp = dev->printfbuf;
  12.795 +	
  12.796 +    /*
  12.797 +     *	The size of the printfbuf is set in port.c
  12.798 +     *	There is no variable or define for it
  12.799 +     */
  12.800 +    if (length > 255)
  12.801 +	length = 255;
  12.802 +    if (cp[length] != 0)
  12.803 +	cp[length] = 0;
  12.804 +    if (level == LOG_HIGH_ERROR)
  12.805 +	printk(KERN_WARNING "aacraid:%s", cp);
  12.806 +    else
  12.807 +	printk(KERN_INFO "aacraid:%s", cp);
  12.808 +    memset(cp, 0,  256);
  12.809 +}
  12.810 +
  12.811 +
  12.812 +/**
  12.813 + *	aac_handle_aif		-	Handle a message from the firmware
  12.814 + *	@dev: Which adapter this fib is from
  12.815 + *	@fibptr: Pointer to fibptr from adapter
  12.816 + *
  12.817 + *	This routine handles a driver notify fib from the adapter and
  12.818 + *	dispatches it to the appropriate routine for handling.
  12.819 + */
  12.820 +
  12.821 +static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
  12.822 +{
  12.823 +    struct hw_fib * fib = fibptr->fib;
  12.824 +    /*
  12.825 +     * Set the status of this FIB to be Invalid parameter.
  12.826 +     *
  12.827 +     *	*(u32 *)fib->data = ST_INVAL;
  12.828 +     */
  12.829 +    *(u32 *)fib->data = cpu_to_le32(ST_OK);
  12.830 +    fib_adapter_complete(fibptr, sizeof(u32));
  12.831 +}
  12.832 +
  12.833 +/**
  12.834 + *	aac_command_thread	-	command processing thread
  12.835 + *	@dev: Adapter to monitor
  12.836 + *
  12.837 + *	Waits on the commandready event in it's queue. When the event gets set
  12.838 + *	it will pull FIBs off it's queue. It will continue to pull FIBs off
  12.839 + *	until the queue is empty. When the queue is empty it will wait for
  12.840 + *	more FIBs.
  12.841 + */
  12.842 + 
  12.843 +#ifndef TRY_SOFTIRQ
  12.844 +int aac_command_thread(struct aac_dev * dev)
  12.845 +{
  12.846 +#else
  12.847 +int aac_command_thread(struct softirq_action *h)
  12.848 +{   
  12.849 +    struct aac_dev *dev = (struct aac_dev *)h->data; 
  12.850 +#endif
  12.851 +    struct hw_fib *fib, *newfib;
  12.852 +    struct fib fibptr; /* for error logging */
  12.853 +    struct aac_queue_block *queues = dev->queues;
  12.854 +    struct aac_fib_context *fibctx;
  12.855 +    unsigned long flags;
  12.856 +#if 0
  12.857 +    DECLARE_WAITQUEUE(wait, current);
  12.858 +#endif
  12.859 +
  12.860 +    /*
  12.861 +     *	We can only have one thread per adapter for AIF's.
  12.862 +     */
  12.863 +    printk("aac_command_'thread': entered.\n"); 
  12.864 +    if (dev->aif_thread)
  12.865 +	return -EINVAL;
  12.866 +
  12.867 +#if 0
  12.868 +    /*
  12.869 +     *	Set up the name that will appear in 'ps'
  12.870 +     *	stored in  task_struct.comm[16].
  12.871 +     */
  12.872 +    sprintf(current->comm, "aacraid");
  12.873 +    daemonize();
  12.874 +#endif
  12.875 +
  12.876 +    /*
  12.877 +     *	Let the DPC know it has a place to send the AIF's to.
  12.878 +     */
  12.879 +    dev->aif_thread = 1;
  12.880 +    memset(&fibptr, 0, sizeof(struct fib));
  12.881 +#if 0
  12.882 +    add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);
  12.883 +    set_current_state(TASK_INTERRUPTIBLE);
  12.884 +#endif
  12.885 +//    while(1) 
  12.886 +    {
  12.887 +
  12.888 +	printk("aac_command_thread: in 'loop'\n"); 
  12.889 +	spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
  12.890 +	printk("flags = %x\n", flags); 
  12.891 +	while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) {
  12.892 +	    struct list_head *entry;
  12.893 +	    struct aac_aifcmd * aifcmd;
  12.894 +
  12.895 +#if 0
  12.896 +	    set_current_state(TASK_RUNNING);
  12.897 +#endif
  12.898 +
  12.899 +		
  12.900 +	    entry = queues->queue[HostNormCmdQueue].cmdq.next;
  12.901 +	    list_del(entry);
  12.902 +			
  12.903 +	    spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock,flags);
  12.904 +	    fib = list_entry(entry, struct hw_fib, header.FibLinks);
  12.905 +	    printk("aac_command_thread: got fib \n"); 
  12.906 +	    /*
  12.907 +	     *	We will process the FIB here or pass it to a 
  12.908 +	     *	worker thread that is TBD. We Really can't 
  12.909 +	     *	do anything at this point since we don't have
  12.910 +	     *	anything defined for this thread to do.
  12.911 +	     */
  12.912 +	    memset(&fibptr, 0, sizeof(struct fib));
  12.913 +	    fibptr.type = FSAFS_NTC_FIB_CONTEXT;
  12.914 +	    fibptr.size = sizeof( struct fib );
  12.915 +	    fibptr.fib = fib;
  12.916 +	    fibptr.data = fib->data;
  12.917 +	    fibptr.dev = dev;
  12.918 +	    /*
  12.919 +	     *	We only handle AifRequest fibs from the adapter.
  12.920 +	     */
  12.921 +	    aifcmd = (struct aac_aifcmd *) fib->data;
  12.922 +	    if (aifcmd->command == le16_to_cpu(AifCmdDriverNotify)) {
  12.923 +		printk("aac_command_thread: handling aif... :-( \n"); 
  12.924 +		aac_handle_aif(dev, &fibptr);
  12.925 +	    } else {
  12.926 +		/* The u32 here is important and intended. We are using
  12.927 +		   32bit wrapping time to fit the adapter field */
  12.928 +		u32 time_now, time_last;
  12.929 +		unsigned long flagv;
  12.930 +		
  12.931 +		time_now = jiffies/HZ;
  12.932 +
  12.933 +		spin_lock_irqsave(&dev->fib_lock, flagv);
  12.934 +		entry = dev->fib_list.next;
  12.935 +				/*
  12.936 +				 * For each Context that is on the 
  12.937 +				 * fibctxList, make a copy of the
  12.938 +				 * fib, and then set the event to wake up the
  12.939 +				 * thread that is waiting for it.
  12.940 +				 */
  12.941 +		while (entry != &dev->fib_list) {
  12.942 +		    /*
  12.943 +		     * Extract the fibctx
  12.944 +		     */
  12.945 +		    fibctx = list_entry(entry, struct aac_fib_context, next);
  12.946 +		    /*
  12.947 +		     * Check if the queue is getting
  12.948 +		     * backlogged
  12.949 +		     */
  12.950 +		    if (fibctx->count > 20)
  12.951 +		    {
  12.952 +			time_last = fibctx->jiffies;
  12.953 +			/*
  12.954 +			 * Has it been > 2 minutes 
  12.955 +			 * since the last read off
  12.956 +			 * the queue?
  12.957 +			 */
  12.958 +			if ((time_now - time_last) > 120) {
  12.959 +			    entry = entry->next;
  12.960 +			    aac_close_fib_context(dev, fibctx);
  12.961 +			    continue;
  12.962 +			}
  12.963 +		    }
  12.964 +		    /*
  12.965 +		     * Warning: no sleep allowed while
  12.966 +		     * holding spinlock
  12.967 +		     */
  12.968 +		    newfib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);
  12.969 +		    if (newfib) {
  12.970 +			/*
  12.971 +			 * Make the copy of the FIB
  12.972 +			 */
  12.973 +			memcpy(newfib, fib, sizeof(struct hw_fib));
  12.974 +			/*
  12.975 +			 * Put the FIB onto the
  12.976 +			 * fibctx's fibs
  12.977 +			 */
  12.978 +			list_add_tail(&newfib->header.FibLinks, &fibctx->fibs);
  12.979 +			fibctx->count++;
  12.980 +#if 0
  12.981 +			/* 
  12.982 +			 * Set the event to wake up the
  12.983 +			 * thread that will waiting.
  12.984 +			 */
  12.985 +			up(&fibctx->wait_sem);
  12.986 +#endif
  12.987 +		    } else {
  12.988 +			printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
  12.989 +		    }
  12.990 +		    entry = entry->next;
  12.991 +		}
  12.992 +				/*
  12.993 +				 *	Set the status of this FIB
  12.994 +				 */
  12.995 +		*(u32 *)fib->data = cpu_to_le32(ST_OK);
  12.996 +		fib_adapter_complete(&fibptr, sizeof(u32));
  12.997 +		spin_unlock_irqrestore(&dev->fib_lock, flagv);
  12.998 +	    }
  12.999 +	    spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
 12.1000 +	}
 12.1001 +	/*
 12.1002 +	 *	There are no more AIF's
 12.1003 +	 */
 12.1004 +	spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);
 12.1005 +#if 0
 12.1006 +	schedule();
 12.1007 +
 12.1008 +	if(signal_pending(current))
 12.1009 +	    break;
 12.1010 +	set_current_state(TASK_INTERRUPTIBLE);
 12.1011 +#endif
 12.1012 +
 12.1013 +    }
 12.1014 +    
 12.1015 +#if 0
 12.1016 +    remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);
 12.1017 +    dev->aif_thread = 0;
 12.1018 +    complete_and_exit(&dev->aif_completion, 0);
 12.1019 +#else
 12.1020 +    mdelay(50); 
 12.1021 +    dev->aif_thread = 0;
 12.1022 +
 12.1023 +#endif
 12.1024 +    return 0;
 12.1025 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/dpcsup.c	Fri Feb 21 15:10:37 2003 +0000
    13.3 @@ -0,0 +1,207 @@
    13.4 +/*
    13.5 + *	Adaptec AAC series RAID controller driver
    13.6 + *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
    13.7 + *
    13.8 + * based on the old aacraid driver that is..
    13.9 + * Adaptec aacraid device driver for Linux.
   13.10 + *
   13.11 + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
   13.12 + *
   13.13 + * This program is free software; you can redistribute it and/or modify
   13.14 + * it under the terms of the GNU General Public License as published by
   13.15 + * the Free Software Foundation; either version 2, or (at your option)
   13.16 + * any later version.
   13.17 + *
   13.18 + * This program is distributed in the hope that it will be useful,
   13.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   13.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   13.21 + * GNU General Public License for more details.
   13.22 + *
   13.23 + * You should have received a copy of the GNU General Public License
   13.24 + * along with this program; see the file COPYING.  If not, write to
   13.25 + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   13.26 + *
   13.27 + * Module Name:
   13.28 + *  dpcsup.c
   13.29 + *
   13.30 + * Abstract: All DPC processing routines for the cyclone board occur here.
   13.31 + *
   13.32 + *
   13.33 + */
   13.34 +
   13.35 +#include <xeno/config.h>
   13.36 +/* #include <xeno/kernel.h> */
   13.37 +#include <xeno/init.h>
   13.38 +#include <xeno/types.h>
   13.39 +#include <xeno/sched.h>
   13.40 +#include <xeno/pci.h>
   13.41 +/*  #include <xeno/spinlock.h> */
   13.42 +/*  #include <xeno/slab.h> */
   13.43 +/*  #include <xeno/completion.h> */
   13.44 +#include <xeno/blk.h>
   13.45 +/*  #include <asm/semaphore.h> */
   13.46 +#include "scsi.h"
   13.47 +#include "hosts.h"
   13.48 +
   13.49 +#include "aacraid.h"
   13.50 +
   13.51 +/**
   13.52 + *	aac_response_normal	-	Handle command replies
   13.53 + *	@q: Queue to read from
   13.54 + *
   13.55 + *	This DPC routine will be run when the adapter interrupts us to let us
   13.56 + *	know there is a response on our normal priority queue. We will pull off
   13.57 + *	all QE there are and wake up all the waiters before exiting. We will
   13.58 + *	take a spinlock out on the queue before operating on it.
   13.59 + */
   13.60 +
   13.61 +unsigned int aac_response_normal(struct aac_queue * q)
   13.62 +{
   13.63 +	struct aac_dev * dev = q->dev;
   13.64 +	struct aac_entry *entry;
   13.65 +	struct hw_fib * hwfib;
   13.66 +	struct fib * fib;
   13.67 +	int consumed = 0;
   13.68 +	unsigned long flags;
   13.69 +
   13.70 +	spin_lock_irqsave(q->lock, flags);	
   13.71 +
   13.72 +	/*
   13.73 +	 *	Keep pulling response QEs off the response queue and waking
   13.74 +	 *	up the waiters until there are no more QEs. We then return
   13.75 +	 *	back to the system. If no response was requesed we just
   13.76 +	 *	deallocate the Fib here and continue.
   13.77 +	 */
   13.78 +	while(aac_consumer_get(dev, q, &entry))
   13.79 +	{
   13.80 +		int fast;
   13.81 +
   13.82 +		fast = (int) (entry->addr & 0x01);
   13.83 +		hwfib = addr2fib(entry->addr & ~0x01);
   13.84 +		aac_consumer_free(dev, q, HostNormRespQueue);
   13.85 +		fib = &dev->fibs[hwfib->header.SenderData];
   13.86 +		/*
   13.87 +		 *	Remove this fib from the Outstanding I/O queue.
   13.88 +		 *	But only if it has not already been timed out.
   13.89 +		 *
   13.90 +		 *	If the fib has been timed out already, then just 
   13.91 +		 *	continue. The caller has already been notified that
   13.92 +		 *	the fib timed out.
   13.93 +		 */
   13.94 +		if (!(fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
   13.95 +			list_del(&fib->queue);
   13.96 +			dev->queues->queue[AdapNormCmdQueue].numpending--;
   13.97 +		} else {
   13.98 +			printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
   13.99 +			continue;
  13.100 +		}
  13.101 +		spin_unlock_irqrestore(q->lock, flags);
  13.102 +
  13.103 +		if (fast) {
  13.104 +			/*
  13.105 +			 *	Doctor the fib
  13.106 +			 */
  13.107 +			*(u32 *)hwfib->data = cpu_to_le32(ST_OK);
  13.108 +			hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
  13.109 +		}
  13.110 +
  13.111 +		FIB_COUNTER_INCREMENT(aac_config.FibRecved);
  13.112 +
  13.113 +		if (hwfib->header.Command == cpu_to_le16(NuFileSystem))
  13.114 +		{
  13.115 +			u32 *pstatus = (u32 *)hwfib->data;
  13.116 +			if (*pstatus & cpu_to_le32(0xffff0000))
  13.117 +				*pstatus = cpu_to_le32(ST_OK);
  13.118 +		}
  13.119 +		if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async)) 
  13.120 +		{
  13.121 +	        	if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected))
  13.122 +				FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved);
  13.123 +			else 
  13.124 +				FIB_COUNTER_INCREMENT(aac_config.AsyncRecved);
  13.125 +			/*
  13.126 +			 *	NOTE:  we cannot touch the fib after this
  13.127 +			 *	    call, because it may have been deallocated.
  13.128 +			 */
  13.129 +			fib->callback(fib->callback_data, fib);
  13.130 +		} else {
  13.131 +#if 0
  13.132 +			unsigned long flagv;
  13.133 +			spin_lock_irqsave(&fib->event_lock, flagv);
  13.134 +#endif
  13.135 +			fib->done = 1;
  13.136 +#if 0
  13.137 +			up(&fib->event_wait);
  13.138 +			spin_unlock_irqrestore(&fib->event_lock, flagv);
  13.139 +#endif
  13.140 +			FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
  13.141 +		}
  13.142 +		consumed++;
  13.143 +		spin_lock_irqsave(q->lock, flags);
  13.144 +	}
  13.145 +
  13.146 +	if (consumed > aac_config.peak_fibs)
  13.147 +		aac_config.peak_fibs = consumed;
  13.148 +	if (consumed == 0) 
  13.149 +		aac_config.zero_fibs++;
  13.150 +
  13.151 +	spin_unlock_irqrestore(q->lock, flags);
  13.152 +	return 0;
  13.153 +}
  13.154 +
  13.155 +
  13.156 +/**
  13.157 + *	aac_command_normal	-	handle commands
  13.158 + *	@q: queue to process
  13.159 + *
  13.160 + *	This DPC routine will be queued when the adapter interrupts us to 
  13.161 + *	let us know there is a command on our normal priority queue. We will 
  13.162 + *	pull off all QE there are and wake up all the waiters before exiting.
  13.163 + *	We will take a spinlock out on the queue before operating on it.
  13.164 + */
  13.165 + 
  13.166 +unsigned int aac_command_normal(struct aac_queue *q)
  13.167 +{
  13.168 +	struct aac_dev * dev = q->dev;
  13.169 +	struct aac_entry *entry;
  13.170 +	unsigned long flags;
  13.171 +
  13.172 +	spin_lock_irqsave(q->lock, flags);
  13.173 +
  13.174 +	/*
  13.175 +	 *	Keep pulling response QEs off the response queue and waking
  13.176 +	 *	up the waiters until there are no more QEs. We then return
  13.177 +	 *	back to the system.
  13.178 +	 */
  13.179 +	while(aac_consumer_get(dev, q, &entry))
  13.180 +	{
  13.181 +		struct hw_fib * fib;
  13.182 +		fib = addr2fib(entry->addr);
  13.183 +
  13.184 +		if (dev->aif_thread) {
  13.185 +		        list_add_tail(&fib->header.FibLinks, &q->cmdq);
  13.186 +	 	        aac_consumer_free(dev, q, HostNormCmdQueue);
  13.187 +#if 0
  13.188 +		        wake_up_interruptible(&q->cmdready);
  13.189 +#endif
  13.190 +		} else {
  13.191 +			struct fib fibctx;
  13.192 +	 	        aac_consumer_free(dev, q, HostNormCmdQueue);
  13.193 +			spin_unlock_irqrestore(q->lock, flags);
  13.194 +			memset(&fibctx, 0, sizeof(struct fib));
  13.195 +			fibctx.type = FSAFS_NTC_FIB_CONTEXT;
  13.196 +			fibctx.size = sizeof(struct fib);
  13.197 +			fibctx.fib = fib;
  13.198 +			fibctx.data = fib->data;
  13.199 +			fibctx.dev = dev;
  13.200 +			/*
  13.201 +			 *	Set the status of this FIB
  13.202 +			 */
  13.203 +			*(u32 *)fib->data = cpu_to_le32(ST_OK);
  13.204 +			fib_adapter_complete(&fibctx, sizeof(u32));
  13.205 +			spin_lock_irqsave(q->lock, flags);
  13.206 +		}		
  13.207 +	}
  13.208 +	spin_unlock_irqrestore(q->lock, flags);
  13.209 +	return 0;
  13.210 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/linit.c	Fri Feb 21 15:10:37 2003 +0000
    14.3 @@ -0,0 +1,794 @@
    14.4 +/*
    14.5 + *	Adaptec AAC series RAID controller driver
    14.6 + *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
    14.7 + *
    14.8 + * based on the old aacraid driver that is..
    14.9 + * Adaptec aacraid device driver for Linux.
   14.10 + *
   14.11 + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
   14.12 + *
   14.13 + * This program is free software; you can redistribute it and/or modify
   14.14 + * it under the terms of the GNU General Public License as published by
   14.15 + * the Free Software Foundation; either version 2, or (at your option)
   14.16 + * any later version.
   14.17 + *
   14.18 + * This program is distributed in the hope that it will be useful,
   14.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   14.21 + * GNU General Public License for more details.
   14.22 + *
   14.23 + * You should have received a copy of the GNU General Public License
   14.24 + * along with this program; see the file COPYING.  If not, write to
   14.25 + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   14.26 + *
   14.27 + * Module Name:
   14.28 + *   linit.c
   14.29 + *
   14.30 + * Abstract: Linux Driver entry module for Adaptec RAID Array Controller
   14.31 + *				
   14.32 + *	Provides the following driver entry points:
   14.33 + *		aac_detect()
   14.34 + *		aac_release()
   14.35 + *		aac_queuecommand()
   14.36 + *		aac_resetcommand()
   14.37 + *		aac_biosparm()
   14.38 + *	
   14.39 + */
   14.40 +
   14.41 +#define AAC_DRIVER_VERSION		"0.9.9ac6-TEST"
   14.42 +#define AAC_DRIVER_BUILD_DATE		__DATE__
   14.43 +
   14.44 +#include <xeno/module.h>
   14.45 +#include <xeno/config.h>
   14.46 +#include <xeno/kernel.h>
   14.47 +#include <xeno/init.h>
   14.48 +#include <xeno/types.h>
   14.49 +#include <xeno/sched.h>
   14.50 +#include <xeno/pci.h>
   14.51 +#include <xeno/spinlock.h>
   14.52 +/*  #include <xeno/slab.h> */
   14.53 +/*  #include <xeno/completion.h> */
   14.54 +/*  #include <asm/semaphore.h> */
   14.55 +#include <xeno/blk.h>
   14.56 +#include "scsi.h"
   14.57 +#include "hosts.h"
   14.58 +
   14.59 +#include "aacraid.h"
   14.60 +#include "sd.h"
   14.61 +
   14.62 +#define AAC_DRIVERNAME	"aacraid"
   14.63 +
   14.64 +MODULE_AUTHOR("Red Hat Inc and Adaptec");
   14.65 +MODULE_DESCRIPTION("Supports Dell PERC2, 2/Si, 3/Si, 3/Di, PERC 320/DC, Adaptec 2120S, 2200S, 5400S, and HP NetRAID-4M devices. http://domsch.com/xeno/ or http://linux.adaptec.com");
   14.66 +MODULE_LICENSE("GPL");
   14.67 +MODULE_PARM(nondasd, "i");
   14.68 +MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices. 0=off, 1=on");
   14.69 +
   14.70 +static int nondasd=-1;
   14.71 +
   14.72 +struct aac_dev *aac_devices[MAXIMUM_NUM_ADAPTERS];
   14.73 +
   14.74 +static unsigned aac_count = 0;
   14.75 +static int aac_cfg_major = -1;
   14.76 +
   14.77 +/*
   14.78 + * Because of the way Linux names scsi devices, the order in this table has
   14.79 + * become important.  Check for on-board Raid first, add-in cards second.
   14.80 + *
   14.81 + * dmb - For now we add the number of channels to this structure.  
   14.82 + * In the future we should add a fib that reports the number of channels
   14.83 + * for the card.  At that time we can remove the channels from here
   14.84 + */
   14.85 + 
   14.86 +static struct aac_driver_ident aac_drivers[] = {
   14.87 +	{ 0x1028, 0x0001, 0x1028, 0x0001, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 2/Si */
   14.88 +	{ 0x1028, 0x0002, 0x1028, 0x0002, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 3/Di */
   14.89 +	{ 0x1028, 0x0003, 0x1028, 0x0003, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 3/Si */
   14.90 +	{ 0x1028, 0x0004, 0x1028, 0x00d0, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 3/Si */
   14.91 +	{ 0x1028, 0x0002, 0x1028, 0x00d1, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 3/Di */
   14.92 +	{ 0x1028, 0x0002, 0x1028, 0x00d9, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 3/Di */
   14.93 +	{ 0x1028, 0x000a, 0x1028, 0x0106, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 3/Di */
   14.94 +	{ 0x1028, 0x000a, 0x1028, 0x011b, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 3/Di */
   14.95 +	{ 0x1028, 0x000a, 0x1028, 0x0121, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* PERC 3/Di */
   14.96 +	{ 0x9005, 0x0283, 0x9005, 0x0283, aac_rx_init, "aacraid",  "ADAPTEC ", "catapult        ", 2 }, /* catapult*/
   14.97 +	{ 0x9005, 0x0284, 0x9005, 0x0284, aac_rx_init, "aacraid",  "ADAPTEC ", "tomcat          ", 2 }, /* tomcat*/
   14.98 +	{ 0x9005, 0x0285, 0x9005, 0x0286, aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2120S   ", 1 }, /* Adaptec 2120S (Crusader)*/
   14.99 +	{ 0x9005, 0x0285, 0x9005, 0x0285, aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2 }, /* Adaptec 2200S (Vulcan)*/
  14.100 +	{ 0x9005, 0x0285, 0x9005, 0x0287, aac_rx_init, "aacraid",  "ADAPTEC ", "Adaptec 2200S   ", 2 }, /* Adaptec 2200S (Vulcan-2m)*/
  14.101 +	{ 0x9005, 0x0285, 0x1028, 0x0287, aac_rx_init, "percraid", "DELL    ", "PERCRAID        ", 2 }, /* Dell PERC 320/DC */
  14.102 +	{ 0x1011, 0x0046, 0x9005, 0x0365, aac_sa_init, "aacraid",  "ADAPTEC ", "Adaptec 5400S   ", 4 }, /* Adaptec 5400S (Mustang)*/
  14.103 +	{ 0x1011, 0x0046, 0x9005, 0x0364, aac_sa_init, "aacraid",  "ADAPTEC ", "AAC-364         ", 4 }, /* Adaptec 5400S (Mustang)*/
  14.104 +	{ 0x1011, 0x0046, 0x9005, 0x1364, aac_sa_init, "percraid", "DELL    ", "PERCRAID        ", 4 }, /* Dell PERC2 "Quad Channel" */
  14.105 +	{ 0x1011, 0x0046, 0x103c, 0x10c2, aac_sa_init, "hpnraid",  "HP      ", "NetRAID-4M      ", 4 }  /* HP NetRAID-4M */
  14.106 +};
  14.107 +
  14.108 +#define NUM_AACTYPES	(sizeof(aac_drivers) / sizeof(struct aac_driver_ident))
  14.109 +static int num_aacdrivers = NUM_AACTYPES;
  14.110 +
  14.111 +#if 0
  14.112 +static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg);
  14.113 +static int aac_cfg_open(struct inode * inode, struct file * file);
  14.114 +static int aac_cfg_release(struct inode * inode,struct file * file);
  14.115 +
  14.116 +static struct file_operations aac_cfg_fops = {
  14.117 +/*	owner: THIS_MODULE, */
  14.118 +	ioctl: aac_cfg_ioctl,
  14.119 +	open: aac_cfg_open,
  14.120 +	release: aac_cfg_release
  14.121 +};
  14.122 +#endif
  14.123 +
  14.124 +static int aac_detect(Scsi_Host_Template *);
  14.125 +static int aac_release(struct Scsi_Host *);
  14.126 +static int aac_queuecommand(Scsi_Cmnd *, void (*CompletionRoutine)(Scsi_Cmnd *));
  14.127 +static int aac_biosparm(Scsi_Disk *, kdev_t, int *);
  14.128 +#ifdef CONFIG_PROC_FS
  14.129 +static int aac_procinfo(char *, char **, off_t, int, int, int);
  14.130 +#endif
  14.131 +static int aac_ioctl(Scsi_Device *, int, void *);
  14.132 +static int aac_eh_abort(Scsi_Cmnd * cmd);
  14.133 +static int aac_eh_device_reset(Scsi_Cmnd* cmd);
  14.134 +static int aac_eh_bus_reset(Scsi_Cmnd* cmd);
  14.135 +static int aac_eh_reset(Scsi_Cmnd* cmd);
  14.136 +
  14.137 +static void aac_queuedepth(struct Scsi_Host *, Scsi_Device *);
  14.138 +
  14.139 +/**
  14.140 + *	aac_detect	-	Probe for aacraid cards
  14.141 + *	@template: SCSI driver template
  14.142 + *
  14.143 + *	Probe for AAC Host Adapters initialize, register, and report the 
  14.144 + *	configuration of each AAC Host Adapter found.
  14.145 + *	Returns the number of adapters successfully initialized and 
  14.146 + *	registered.
  14.147 + *	Initializes all data necessary for this particular SCSI driver.
  14.148 + *	Notes:
  14.149 + *	The detect routine must not call any of the mid level functions 
  14.150 + *	to queue commands because things are not guaranteed to be set 
  14.151 + *	up yet. The detect routine can send commands to the host adapter 
  14.152 + *	as long as the program control will not be passed to scsi.c in 
  14.153 + *	the processing of the command. Note especially that 
  14.154 + *	scsi_malloc/scsi_free must not be called.
  14.155 + *
  14.156 + */
  14.157 +static int aac_detect(Scsi_Host_Template *template)
  14.158 +{
  14.159 +    int index;
  14.160 +    int container;
  14.161 +    u16 vendor_id, device_id;
  14.162 +    struct Scsi_Host *host_ptr;
  14.163 +    struct pci_dev *dev = NULL;
  14.164 +    struct aac_dev *aac;
  14.165 +    struct fsa_scsi_hba *fsa_dev_ptr;
  14.166 +    char *name = NULL;
  14.167 +	
  14.168 +    printk(KERN_INFO "Red Hat/Adaptec aacraid driver, %s\n", 
  14.169 +	   AAC_DRIVER_BUILD_DATE);
  14.170 +
  14.171 +
  14.172 +    /* 
  14.173 +    ** XXX SMH: we need to take interrupts during detect, but the SCSI 
  14.174 +    ** layer is holding this lock with interrupts disabled. I don't 
  14.175 +    ** know how this works on vanilla linux (we 'down' on a semaphone 
  14.176 +    ** at one point during the process -- how do we wake?) 
  14.177 +    */
  14.178 +    spin_unlock_irq(&io_request_lock);
  14.179 +
  14.180 +
  14.181 +    /* setting up the proc directory structure */
  14.182 +    template->proc_name = "aacraid";
  14.183 +
  14.184 +    for( index = 0; index != num_aacdrivers; index++ )
  14.185 +    {
  14.186 +	device_id = aac_drivers[index].device;
  14.187 +	vendor_id = aac_drivers[index].vendor;
  14.188 +	name = aac_drivers[index].name;
  14.189 +	dprintk((KERN_DEBUG "Checking %s %x/%x/%x/%x.\n", 
  14.190 +		 name, vendor_id, device_id,
  14.191 +		 aac_drivers[index].subsystem_vendor,
  14.192 +		 aac_drivers[index].subsystem_device));
  14.193 +
  14.194 +	dev = NULL;
  14.195 +	while((dev = pci_find_device(vendor_id, device_id, dev))) {
  14.196 +	    if (pci_enable_device(dev))
  14.197 +		continue;
  14.198 +	    pci_set_master(dev);
  14.199 +	    pci_set_dma_mask(dev, 0xFFFFFFFFULL);
  14.200 +
  14.201 +	    if((dev->subsystem_vendor != aac_drivers[index].subsystem_vendor) || 
  14.202 +	       (dev->subsystem_device != aac_drivers[index].subsystem_device))
  14.203 +		continue;
  14.204 +
  14.205 +	    dprintk((KERN_DEBUG "%s device detected.\n", name));
  14.206 +	    dprintk((KERN_DEBUG "%x/%x/%x/%x.\n", vendor_id, device_id, 
  14.207 +		     aac_drivers[index].subsystem_vendor, 
  14.208 +		     aac_drivers[index].subsystem_device));
  14.209 +	    /* Increment the host adapter count */
  14.210 +	    aac_count++;
  14.211 +	    /*
  14.212 +	     * scsi_register() allocates memory for a Scsi_Hosts
  14.213 +	     * structure and links it into the linked list of host
  14.214 +	     * adapters. This linked list contains the data for all
  14.215 +	     * possible <supported> scsi hosts.  This is similar to
  14.216 +	     * the Scsi_Host_Template, except that we have one entry
  14.217 +	     * for each actual physical host adapter on the system,
  14.218 +	     * stored as a linked list. If there are two AAC boards,
  14.219 +	     * then we will need to make two Scsi_Host entries, but
  14.220 +	     * there will be only one Scsi_Host_Template entry. The
  14.221 +	     * second argument to scsi_register() specifies the size
  14.222 +	     * of the extra memory we want to hold any device specific
  14.223 +	     * information.  */
  14.224 +	    host_ptr = scsi_register( template, sizeof(struct aac_dev) );
  14.225 +	    /* 
  14.226 +	     * These three parameters can be used to allow for wide SCSI 
  14.227 +	     * and for host adapters that support multiple buses.
  14.228 +	     */
  14.229 +	    host_ptr->max_id = 17;
  14.230 +	    host_ptr->max_lun = 8;
  14.231 +	    host_ptr->max_channel = 1;
  14.232 +	    host_ptr->irq = dev->irq;		/* Adapter IRQ number */
  14.233 +	    /* host_ptr->base = ( char * )(dev->resource[0].start & ~0xff); */
  14.234 +	    host_ptr->base = dev->resource[0].start;
  14.235 +	    scsi_set_pci_device(host_ptr, dev);
  14.236 +	    dprintk((KERN_DEBUG "Device base address = 0x%lx [0x%lx].\n", 
  14.237 +		     host_ptr->base, dev->resource[0].start));
  14.238 +	    dprintk((KERN_DEBUG "Device irq = 0x%x.\n", dev->irq));
  14.239 +	    /*
  14.240 +	     * The unique_id field is a unique identifier that must
  14.241 +	     * be assigned so that we have some way of identifying
  14.242 +	     * each host adapter properly and uniquely. For hosts 
  14.243 +	     * that do not support more than one card in the
  14.244 +	     * system, this does not need to be set. It is
  14.245 +	     * initialized to zero in scsi_register(). This is the 
  14.246 +	     * value returned as aac->id.
  14.247 +	     */
  14.248 +	    host_ptr->unique_id = aac_count - 1;
  14.249 +	    /*
  14.250 +	     *	This function is called after the device list has
  14.251 +	     *	been built to find the tagged queueing depth 
  14.252 +	     *	supported for each device.
  14.253 +	     */
  14.254 +	    host_ptr->select_queue_depths = aac_queuedepth;
  14.255 +	    aac = (struct aac_dev *)host_ptr->hostdata;
  14.256 +	    /* attach a pointer back to Scsi_Host */
  14.257 +	    aac->scsi_host_ptr = host_ptr;	
  14.258 +	    aac->pdev = dev;
  14.259 +	    aac->cardtype =  index;
  14.260 +	    aac->name = aac->scsi_host_ptr->hostt->name;
  14.261 +	    aac->id = aac->scsi_host_ptr->unique_id;
  14.262 +	    /* Initialize the ordinal number of the device to -1 */
  14.263 +	    fsa_dev_ptr = &(aac->fsa_dev);
  14.264 +	    for( container=0; container < MAXIMUM_NUM_CONTAINERS; container++)
  14.265 +		fsa_dev_ptr->devno[container] = -1;
  14.266 +
  14.267 +	    dprintk((KERN_DEBUG "Initializing Hardware...\n"));
  14.268 +
  14.269 +	    if((*aac_drivers[index].init)(aac , host_ptr->unique_id) != 0)
  14.270 +	    {
  14.271 +		/* device initialization failed */
  14.272 +		printk(KERN_WARNING 
  14.273 +		       "aacraid: device initialization failed.\n");
  14.274 +		scsi_unregister(host_ptr);
  14.275 +		aac_count--;
  14.276 +		continue;
  14.277 +	    } 
  14.278 +	    dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", 
  14.279 +		     name, host_ptr->unique_id));
  14.280 +	    aac_get_adapter_info(aac);
  14.281 +
  14.282 +	    dprintk((KERN_DEBUG "%s got adapter info.\n", name));
  14.283 +
  14.284 +	    if(nondasd != -1) 
  14.285 +	    {
  14.286 +		/* someone told us how to set this on the cmdline */
  14.287 +		aac->nondasd_support = (nondasd!=0);
  14.288 +	    }
  14.289 +	    if(aac->nondasd_support != 0){
  14.290 +		printk(KERN_INFO "%s%d: Non-DASD support enabled\n", 
  14.291 +		       aac->name, aac->id);
  14.292 +	    }
  14.293 +	    dprintk((KERN_DEBUG "%s:%d options flag %04x.\n", name, 
  14.294 +		     host_ptr->unique_id, aac->adapter_info.options));
  14.295 +	    if(aac->nondasd_support == 1)
  14.296 +	    {
  14.297 +		/*
  14.298 +		 * max channel will be the physical
  14.299 +		 * channels plus 1 virtual channel all
  14.300 +		 * containers are on the virtual
  14.301 +		 * channel 0 physical channels are
  14.302 +		 * address by their actual physical
  14.303 +		 * number+1 */
  14.304 +		host_ptr->max_channel = aac_drivers[index].channels+1;
  14.305 +	    } else {
  14.306 +		host_ptr->max_channel = 1;
  14.307 +	    }
  14.308 +	    dprintk((KERN_DEBUG "Device has %d logical channels\n", 
  14.309 +		     host_ptr->max_channel));
  14.310 +	    aac_get_containers(aac);
  14.311 +	    aac_devices[aac_count-1] = aac;
  14.312 +
  14.313 +	    /*
  14.314 +	     * dmb - we may need to move these 3 parms somewhere else once
  14.315 +	     * we get a fib that can report the actual numbers
  14.316 +	     */
  14.317 +	    host_ptr->max_id = AAC_MAX_TARGET;
  14.318 +	    host_ptr->max_lun = AAC_MAX_LUN;
  14.319 +			
  14.320 +	    /*
  14.321 +	     *  If we are PAE capable then our future DMA mappings
  14.322 +	     *  (for read/write commands) are 64bit clean and don't 
  14.323 +	     *  need bouncing. This assumes we do no other 32bit only
  14.324 +	     *  allocations (eg fib table expands) after this point.
  14.325 +	     */
  14.326 +			 
  14.327 +	    if(aac->pae_support)
  14.328 +		pci_set_dma_mask(dev, 0xFFFFFFFFFFFFFFFFUL);
  14.329 +	}
  14.330 +    }
  14.331 +
  14.332 +    /* XXX SMH: restore lock and IPL for SCSI layer */
  14.333 +    spin_lock_irq(&io_request_lock);
  14.334 +
  14.335 +
  14.336 +#if 0
  14.337 +    if( aac_count ){
  14.338 +	if((aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops))<0)
  14.339 +	    printk(KERN_WARNING "aacraid: unable to register 'aac' device.\n");
  14.340 +    }
  14.341 +#endif
  14.342 +
  14.343 +    template->present = aac_count; /* # of cards of this type found */
  14.344 +    printk(KERN_DEBUG "aac_detect: returning %d\n", aac_count); 
  14.345 +    return aac_count;
  14.346 +}
  14.347 +
  14.348 +/**
  14.349 + *	aac_release	-	release SCSI host resources
  14.350 + *	@host_ptr: SCSI host to clean up
  14.351 + *
  14.352 + *	Release all resources previously acquired to support a specific Host 
  14.353 + *	Adapter and unregister the AAC Host Adapter.
  14.354 + *
  14.355 + *	BUGS: Does not wait for the thread it kills to die.
  14.356 + */
  14.357 +
  14.358 +static int aac_release(struct Scsi_Host *host_ptr)
  14.359 +{
  14.360 +    struct aac_dev *dev;
  14.361 +    dprintk((KERN_DEBUG "aac_release.\n"));
  14.362 +    dev = (struct aac_dev *)host_ptr->hostdata;
  14.363 +    
  14.364 +#if 0
  14.365 +    /*
  14.366 +     *	kill any threads we started
  14.367 +     */
  14.368 +    kill_proc(dev->thread_pid, SIGKILL, 0);
  14.369 +    wait_for_completion(&dev->aif_completion);
  14.370 +#endif
  14.371 +    /*
  14.372 +     *	Call the comm layer to detach from this adapter
  14.373 +     */
  14.374 +    aac_detach(dev);
  14.375 +    /* Check free orderings... */
  14.376 +    /* remove interrupt binding */
  14.377 +    free_irq(host_ptr->irq, dev);
  14.378 +    iounmap((void * )dev->regs.sa);
  14.379 +    /* unregister adapter */
  14.380 +    scsi_unregister(host_ptr);
  14.381 +    /*
  14.382 +     *	FIXME: This assumes no hot plugging is going on...
  14.383 +     */
  14.384 +    if( aac_cfg_major >= 0 )
  14.385 +    {
  14.386 +#if 0
  14.387 +	unregister_chrdev(aac_cfg_major, "aac");
  14.388 +#endif
  14.389 +	aac_cfg_major = -1;
  14.390 +    }
  14.391 +    return 0;
  14.392 +}
  14.393 +
  14.394 +/**
  14.395 + *	aac_queuecommand	-	queue a SCSI command
  14.396 + *	@scsi_cmnd_ptr:	SCSI command to queue
  14.397 + *	@CompletionRoutine: Function to call on command completion
  14.398 + *
  14.399 + *	Queues a command for execution by the associated Host Adapter.
  14.400 + */ 
  14.401 +
  14.402 +static int aac_queuecommand(Scsi_Cmnd *scsi_cmnd_ptr, void (*complete)(Scsi_Cmnd *))
  14.403 +{
  14.404 +    int ret;
  14.405 +    
  14.406 +    scsi_cmnd_ptr->scsi_done = complete;
  14.407 +    /*
  14.408 +     *	aac_scsi_cmd() handles command processing, setting the 
  14.409 +     *	result code and calling completion routine. 
  14.410 +     */
  14.411 +    if((ret = aac_scsi_cmd(scsi_cmnd_ptr)) != 0)
  14.412 +	dprintk((KERN_DEBUG "aac_scsi_cmd failed.\n"));
  14.413 +    return ret;
  14.414 +} 
  14.415 +
  14.416 +/**
  14.417 + *	aac_driverinfo		-	Returns the host adapter name
  14.418 + *	@host_ptr:	Scsi host to report on
  14.419 + *
  14.420 + *	Returns a static string describing the device in question
  14.421 + */
  14.422 +
  14.423 +const char *aac_driverinfo(struct Scsi_Host *host_ptr)
  14.424 +{
  14.425 +    struct aac_dev *dev = (struct aac_dev *)host_ptr->hostdata;
  14.426 +    return aac_drivers[dev->cardtype].name;
  14.427 +}
  14.428 +
  14.429 +/**
  14.430 + *	aac_get_driver_ident
  14.431 + * 	@devtype: index into lookup table
  14.432 + *
  14.433 + * 	Returns a pointer to the entry in the driver lookup table.
  14.434 + */
  14.435 +struct aac_driver_ident* aac_get_driver_ident(int devtype)
  14.436 +{
  14.437 +	return  &aac_drivers[devtype];
  14.438 +}
  14.439 +
  14.440 +/**
  14.441 + *	aac_biosparm	-	return BIOS parameters for disk
  14.442 + *	@disk: SCSI disk object to process
  14.443 + *	@device: kdev_t of the disk in question
  14.444 + *	@geom: geometry block to fill in
  14.445 + *
  14.446 + *	Return the Heads/Sectors/Cylinders BIOS Disk Parameters for Disk.  
  14.447 + *	The default disk geometry is 64 heads, 32 sectors, and the appropriate 
  14.448 + *	number of cylinders so as not to exceed drive capacity.  In order for 
  14.449 + *	disks equal to or larger than 1 GB to be addressable by the BIOS
  14.450 + *	without exceeding the BIOS limitation of 1024 cylinders, Extended 
  14.451 + *	Translation should be enabled.   With Extended Translation enabled, 
  14.452 + *	drives between 1 GB inclusive and 2 GB exclusive are given a disk 
  14.453 + *	geometry of 128 heads and 32 sectors, and drives above 2 GB inclusive 
  14.454 + *	are given a disk geometry of 255 heads and 63 sectors.  However, if 
  14.455 + *	the BIOS detects that the Extended Translation setting does not match 
  14.456 + *	the geometry in the partition table, then the translation inferred 
  14.457 + *	from the partition table will be used by the BIOS, and a warning may 
  14.458 + *	be displayed.
  14.459 + */
  14.460 + 
  14.461 +static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom)
  14.462 +{
  14.463 +    struct diskparm *param = (struct diskparm *)geom;
  14.464 +    struct buffer_head * buf;
  14.465 +    
  14.466 +    dprintk((KERN_DEBUG "aac_biosparm.\n"));
  14.467 +    
  14.468 +    /*
  14.469 +     *	Assuming extended translation is enabled - #REVISIT#
  14.470 +     */
  14.471 +    if( disk->capacity >= 2 * 1024 * 1024 ) /* 1 GB in 512 byte sectors */
  14.472 +    {
  14.473 +	if( disk->capacity >= 4 * 1024 * 1024 ) /* 2 GB in 512 byte sectors */
  14.474 +	{
  14.475 +	    param->heads = 255;
  14.476 +	    param->sectors = 63;
  14.477 +	}
  14.478 +	else
  14.479 +	{
  14.480 +	    param->heads = 128;
  14.481 +	    param->sectors = 32;
  14.482 +	}
  14.483 +    }
  14.484 +    else
  14.485 +    {
  14.486 +	param->heads = 64;
  14.487 +	param->sectors = 32;
  14.488 +    }
  14.489 +    
  14.490 +    param->cylinders = disk->capacity/(param->heads * param->sectors);
  14.491 +	
  14.492 +#if 0
  14.493 +    /*
  14.494 +     *	Read the first 1024 bytes from the disk device
  14.495 +     */
  14.496 +    
  14.497 +    buf = bread(MKDEV(MAJOR(dev), MINOR(dev)&~0xf), 0, block_size(dev));
  14.498 +    if(buf == NULL)
  14.499 +	return 0;
  14.500 +    /* 
  14.501 +     *	If the boot sector partition table is valid, search for a partition 
  14.502 +     *	table entry whose end_head matches one of the standard geometry 
  14.503 +     *	translations ( 64/32, 128/32, 255/63 ).
  14.504 +     */
  14.505 +#endif
  14.506 +
  14.507 +	 
  14.508 +    if(*(unsigned short *)(buf->b_data + 0x1fe) == cpu_to_le16(0xaa55))
  14.509 +    {
  14.510 +	struct partition *first = (struct partition * )(buf->b_data + 0x1be);
  14.511 +	struct partition *entry = first;
  14.512 +	int saved_cylinders = param->cylinders;
  14.513 +	int num;
  14.514 +	unsigned char end_head, end_sec;
  14.515 +	
  14.516 +	for(num = 0; num < 4; num++)
  14.517 +	{
  14.518 +	    end_head = entry->end_head;
  14.519 +	    end_sec = entry->end_sector & 0x3f;
  14.520 +	    
  14.521 +	    if(end_head == 63)
  14.522 +	    {
  14.523 +		param->heads = 64;
  14.524 +		param->sectors = 32;
  14.525 +		break;
  14.526 +	    }
  14.527 +	    else if(end_head == 127)
  14.528 +	    {
  14.529 +		param->heads = 128;
  14.530 +		param->sectors = 32;
  14.531 +		break;
  14.532 +	    }
  14.533 +	    else if(end_head == 254) 
  14.534 +	    {
  14.535 +		param->heads = 255;
  14.536 +		param->sectors = 63;
  14.537 +		break;
  14.538 +	    }
  14.539 +	    entry++;
  14.540 +	}
  14.541 +	
  14.542 +	if(num == 4)
  14.543 +	{
  14.544 +	    end_head = first->end_head;
  14.545 +	    end_sec = first->end_sector & 0x3f;
  14.546 +	}
  14.547 +	
  14.548 +	param->cylinders = disk->capacity / (param->heads * param->sectors);
  14.549 +	
  14.550 +	if(num < 4 && end_sec == param->sectors)
  14.551 +	{
  14.552 +	    if(param->cylinders != saved_cylinders)
  14.553 +		dprintk((KERN_DEBUG "Adopting geometry: heads=%d, "
  14.554 +			 "sectors=%d from partition table %d.\n",
  14.555 +			 param->heads, param->sectors, num));
  14.556 +	}
  14.557 +	else if(end_head > 0 || end_sec > 0)
  14.558 +	{
  14.559 +	    dprintk((KERN_DEBUG "Strange geometry: heads=%d, "
  14.560 +		     "sectors=%d in partition table %d.\n",
  14.561 +		     end_head + 1, end_sec, num));
  14.562 +	    dprintk((KERN_DEBUG "Using geometry: heads=%d, sectors=%d.\n",
  14.563 +		     param->heads, param->sectors));
  14.564 +	}
  14.565 +    }
  14.566 +#if 0
  14.567 +    brelse(buf);
  14.568 +#endif
  14.569 +    return 0;
  14.570 +}
  14.571 +
  14.572 +/**
  14.573 + *	aac_queuedepth		-	compute queue depths
  14.574 + *	@host:	SCSI host in question
  14.575 + *	@dev:	SCSI device we are considering
  14.576 + *
  14.577 + *	Selects queue depths for each target device based on the host adapter's
  14.578 + *	total capacity and the queue depth supported by the target device.
  14.579 + *	A queue depth of one automatically disables tagged queueing.
  14.580 + */
  14.581 +
  14.582 +static void aac_queuedepth(struct Scsi_Host * host, Scsi_Device * dev )
  14.583 +{
  14.584 +    Scsi_Device * dptr;
  14.585 +    
  14.586 +    dprintk((KERN_DEBUG "aac_queuedepth.\n"));
  14.587 +    dprintk((KERN_DEBUG "Device #   Q Depth   Online\n"));
  14.588 +    dprintk((KERN_DEBUG "---------------------------\n"));
  14.589 +    for(dptr = dev; dptr != NULL; dptr = dptr->next)
  14.590 +    {
  14.591 +	if(dptr->host == host)
  14.592 +	{
  14.593 +	    dptr->queue_depth = 10;		
  14.594 +	    dprintk((KERN_DEBUG "  %2d         %d        %d\n", 
  14.595 +		     dptr->id, dptr->queue_depth, dptr->online));
  14.596 +	}
  14.597 +    }
  14.598 +}
  14.599 +
  14.600 +
  14.601 +/**
  14.602 + *	aac_eh_abort	-	Abort command if possible.
  14.603 + *	@cmd:	SCSI command block to abort
  14.604 + *
  14.605 + *	Called when the midlayer wishes to abort a command. We don't support
  14.606 + *	this facility, and our firmware looks after life for us. We just
  14.607 + *	report this as failing
  14.608 + */
  14.609 + 
  14.610 +static int aac_eh_abort(Scsi_Cmnd *cmd)
  14.611 +{
  14.612 +    return FAILED;
  14.613 +}
  14.614 +
  14.615 +/**
  14.616 + *	aac_eh_device_reset	-	Reset command handling
  14.617 + *	@cmd:	SCSI command block causing the reset
  14.618 + *
  14.619 + *	Issue a reset of a SCSI device. We are ourselves not truely a SCSI
  14.620 + *	controller and our firmware will do the work for us anyway. Thus this
  14.621 + *	is a no-op. We just return FAILED.
  14.622 + */
  14.623 +
  14.624 +static int aac_eh_device_reset(Scsi_Cmnd *cmd)
  14.625 +{
  14.626 +    return FAILED;
  14.627 +}
  14.628 +
  14.629 +/**
  14.630 + *	aac_eh_bus_reset	-	Reset command handling
  14.631 + *	@scsi_cmd:	SCSI command block causing the reset
  14.632 + *
  14.633 + *	Issue a reset of a SCSI bus. We are ourselves not truely a SCSI
  14.634 + *	controller and our firmware will do the work for us anyway. Thus this
  14.635 + *	is a no-op. We just return FAILED.
  14.636 + */
  14.637 +
  14.638 +static int aac_eh_bus_reset(Scsi_Cmnd* cmd)
  14.639 +{
  14.640 +    return FAILED;
  14.641 +}
  14.642 +
  14.643 +/**
  14.644 + *	aac_eh_hba_reset	-	Reset command handling
  14.645 + *	@scsi_cmd:	SCSI command block causing the reset
  14.646 + *
  14.647 + *	Issue a reset of a SCSI host. If things get this bad then arguably we should
  14.648 + *	go take a look at what the host adapter is doing and see if something really
  14.649 + *	broke (as can occur at least on my Dell QC card if a drive keeps failing spinup)
  14.650 + */
  14.651 +
  14.652 +static int aac_eh_reset(Scsi_Cmnd* cmd)
  14.653 +{
  14.654 +    printk(KERN_ERR "aacraid: Host adapter reset request. SCSI hang ?\n");
  14.655 +    return FAILED;
  14.656 +}
  14.657 +
  14.658 +/**
  14.659 + *	aac_ioctl 	-	Handle SCSI ioctls
  14.660 + *	@scsi_dev_ptr: scsi device to operate upon
  14.661 + *	@cmd: ioctl command to use issue
  14.662 + *	@arg: ioctl data pointer
  14.663 + *
  14.664 + *	Issue an ioctl on an aacraid device. Returns a standard unix error code or
  14.665 + *	zero for success
  14.666 + */
  14.667 + 
  14.668 +static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg)
  14.669 +{
  14.670 +    struct aac_dev *dev;
  14.671 +    dprintk((KERN_DEBUG "aac_ioctl.\n"));
  14.672 +    dev = (struct aac_dev *)scsi_dev_ptr->host->hostdata;
  14.673 +    return aac_do_ioctl(dev, cmd, arg);
  14.674 +}
  14.675 +
  14.676 +/**
  14.677 + *	aac_cfg_open		-	open a configuration file
  14.678 + *	@inode: inode being opened
  14.679 + *	@file: file handle attached
  14.680 + *
  14.681 + *	Called when the configuration device is opened. Does the needed
  14.682 + *	set up on the handle and then returns
  14.683 + *
  14.684 + *	Bugs: This needs extending to check a given adapter is present
  14.685 + *	so we can support hot plugging, and to ref count adapters.
  14.686 + */
  14.687 +
  14.688 +static int aac_cfg_open(struct inode * inode, struct file * file )
  14.689 +{
  14.690 +    unsigned minor_number = MINOR(inode->i_rdev);
  14.691 +    if(minor_number >= aac_count)
  14.692 +	return -ENODEV;
  14.693 +    return 0;
  14.694 +}
  14.695 +
  14.696 +/**
  14.697 + *	aac_cfg_release		-	close down an AAC config device
  14.698 + *	@inode: inode of configuration file
  14.699 + *	@file: file handle of configuration file
  14.700 + *	
  14.701 + *	Called when the last close of the configuration file handle
  14.702 + *	is performed.
  14.703 + */
  14.704 + 
  14.705 +static int aac_cfg_release(struct inode * inode, struct file * file )
  14.706 +{
  14.707 +    return 0;
  14.708 +}
  14.709 +
  14.710 +/**
  14.711 + *	aac_cfg_ioctl		-	AAC configuration request
  14.712 + *	@inode: inode of device
  14.713 + *	@file: file handle
  14.714 + *	@cmd: ioctl command code
  14.715 + *	@arg: argument
  14.716 + *
  14.717 + *	Handles a configuration ioctl. Currently this involves wrapping it
  14.718 + *	up and feeding it into the nasty windowsalike glue layer.
  14.719 + *
  14.720 + *	Bugs: Needs locking against parallel ioctls lower down
  14.721 + *	Bugs: Needs to handle hot plugging
  14.722 + */
  14.723 + 
  14.724 +static int aac_cfg_ioctl(struct inode * inode,  struct file * file, unsigned int cmd, unsigned long arg )
  14.725 +{
  14.726 +    struct aac_dev *dev = aac_devices[MINOR(inode->i_rdev)];
  14.727 +    return aac_do_ioctl(dev, cmd, (void *)arg);
  14.728 +}
  14.729 +
  14.730 +/*
  14.731 + *	To use the low level SCSI driver support using the linux kernel loadable 
  14.732 + *	module interface we should initialize the global variable driver_interface  
  14.733 + *	(datatype Scsi_Host_Template) and then include the file scsi_module.c.
  14.734 + */
  14.735 + 
  14.736 +static Scsi_Host_Template driver_template = {
  14.737 +/*	module:			THIS_MODULE, */
  14.738 +	name:           	"AAC",
  14.739 +/*	proc_info:      	aac_procinfo, */
  14.740 +	detect:         	aac_detect,
  14.741 +	release:        	aac_release,
  14.742 +	info:           	aac_driverinfo,
  14.743 +	ioctl:          	aac_ioctl,
  14.744 +	queuecommand:   	aac_queuecommand,
  14.745 +	bios_param:     	aac_biosparm,	
  14.746 +	can_queue:      	AAC_NUM_IO_FIB,	
  14.747 +	this_id:        	16,
  14.748 +	sg_tablesize:   	16,
  14.749 +	max_sectors:    	128,
  14.750 +	cmd_per_lun:    	AAC_NUM_IO_FIB,
  14.751 +	eh_abort_handler:       aac_eh_abort,
  14.752 +	eh_device_reset_handler:aac_eh_device_reset,
  14.753 +	eh_bus_reset_handler:	aac_eh_bus_reset,
  14.754 +	eh_host_reset_handler:	aac_eh_reset,
  14.755 +	use_new_eh_code:	1, 
  14.756 +
  14.757 +	use_clustering:		ENABLE_CLUSTERING,
  14.758 +};
  14.759 +
  14.760 +#include "../scsi_module.c.inc"
  14.761 +
  14.762 +#ifdef CONFIG_PROC_FS
  14.763 +/**
  14.764 + *	aac_procinfo	-	Implement /proc/scsi/<drivername>/<n>
  14.765 + *	@proc_buffer: memory buffer for I/O
  14.766 + *	@start_ptr: pointer to first valid data
  14.767 + *	@offset: offset into file
  14.768 + *	@bytes_available: space left
  14.769 + *	@host_no: scsi host ident
  14.770 + *	@write: direction of I/O
  14.771 + *
  14.772 + *	Used to export driver statistics and other infos to the world outside 
  14.773 + *	the kernel using the proc file system. Also provides an interface to
  14.774 + *	feed the driver with information.
  14.775 + *
  14.776 + *		For reads
  14.777 + *			- if offset > 0 return 0
  14.778 + *			- if offset == 0 write data to proc_buffer and set the start_ptr to
  14.779 + *			beginning of proc_buffer, return the number of characters written.
  14.780 + *		For writes
  14.781 + *			- writes currently not supported, return 0
  14.782 + *
  14.783 + *	Bugs:	Only offset zero is handled
  14.784 + */
  14.785 +
  14.786 +static int aac_procinfo(char *proc_buffer, char **start_ptr,off_t offset,
  14.787 +			int bytes_available, int host_no, int write)
  14.788 +{
  14.789 +    if(write || offset > 0)
  14.790 +	return 0;
  14.791 +    *start_ptr = proc_buffer;
  14.792 +    return sprintf(proc_buffer, "%s  %d\n", 
  14.793 +		   "Raid Controller, scsi hba number", host_no);
  14.794 +}
  14.795 +#endif
  14.796 +
  14.797 +EXPORT_NO_SYMBOLS;
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/rx.c	Fri Feb 21 15:10:37 2003 +0000
    15.3 @@ -0,0 +1,457 @@
    15.4 +/*
    15.5 + *	Adaptec AAC series RAID controller driver
    15.6 + *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
    15.7 + *
    15.8 + * based on the old aacraid driver that is..
    15.9 + * Adaptec aacraid device driver for Linux.
   15.10 + *
   15.11 + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
   15.12 + *
   15.13 + * This program is free software; you can redistribute it and/or modify
   15.14 + * it under the terms of the GNU General Public License as published by
   15.15 + * the Free Software Foundation; either version 2, or (at your option)
   15.16 + * any later version.
   15.17 + *
   15.18 + * This program is distributed in the hope that it will be useful,
   15.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15.21 + * GNU General Public License for more details.
   15.22 + *
   15.23 + * You should have received a copy of the GNU General Public License
   15.24 + * along with this program; see the file COPYING.  If not, write to
   15.25 + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   15.26 + *
   15.27 + * Module Name:
   15.28 + *  rx.c
   15.29 + *
   15.30 + * Abstract: Hardware miniport for Drawbridge specific hardware functions.
   15.31 + *
   15.32 + */
   15.33 +
   15.34 +#include <xeno/config.h>
   15.35 +#include <xeno/kernel.h>
   15.36 +#include <xeno/init.h>
   15.37 +#include <xeno/types.h>
   15.38 +#include <xeno/sched.h>
   15.39 +#include <xeno/pci.h>
   15.40 +/*  #include <xeno/spinlock.h> */
   15.41 +/*  #include <xeno/slab.h> */
   15.42 +#include <xeno/blk.h>
   15.43 +#include <xeno/delay.h>
   15.44 +/*  #include <xeno/completion.h> */
   15.45 +/*  #include <asm/semaphore.h> */
   15.46 +#include "scsi.h"
   15.47 +#include "hosts.h"
   15.48 +
   15.49 +#include "aacraid.h"
   15.50 +
   15.51 +static void aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
   15.52 +{
   15.53 +    struct aac_dev *dev = dev_id;
   15.54 +    unsigned long bellbits;
   15.55 +    u8 intstat, mask;
   15.56 +    intstat = rx_readb(dev, MUnit.OISR);
   15.57 +    /*
   15.58 +     *	Read mask and invert because drawbridge is reversed.
   15.59 +     *	This allows us to only service interrupts that have 
   15.60 +     *	been enabled.
   15.61 +     */
   15.62 +    mask = ~(rx_readb(dev, MUnit.OIMR));
   15.63 +    /* Check to see if this is our interrupt.  If it isn't just return */
   15.64 +    
   15.65 +    if (intstat & mask) 
   15.66 +    {
   15.67 +	bellbits = rx_readl(dev, OutboundDoorbellReg);
   15.68 +	if (bellbits & DoorBellPrintfReady) {
   15.69 +	    aac_printf(dev, le32_to_cpu(rx_readl (dev, IndexRegs.Mailbox[5])));
   15.70 +	    rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
   15.71 +	    rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
   15.72 +	}
   15.73 +	else if (bellbits & DoorBellAdapterNormCmdReady) {
   15.74 +	    aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
   15.75 +	    rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
   15.76 +	}
   15.77 +	else if (bellbits & DoorBellAdapterNormRespReady) {
   15.78 +	    aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
   15.79 +	    rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
   15.80 +	}
   15.81 +	else if (bellbits & DoorBellAdapterNormCmdNotFull) {
   15.82 +	    rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
   15.83 +	}
   15.84 +	else if (bellbits & DoorBellAdapterNormRespNotFull) {
   15.85 +	    rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
   15.86 +	    rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
   15.87 +	}
   15.88 +    }
   15.89 +}
   15.90 +
   15.91 +/**
   15.92 + *	aac_rx_enable_interrupt	-	Enable event reporting
   15.93 + *	@dev: Adapter
   15.94 + *	@event: Event to enable
   15.95 + *
   15.96 + *	Enable event reporting from the i960 for a given event.
   15.97 + */
   15.98 + 
   15.99 +static void aac_rx_enable_interrupt(struct aac_dev * dev, u32 event)
  15.100 +{
  15.101 +    switch (event) {
  15.102 +	
  15.103 +    case HostNormCmdQue:
  15.104 +	dev->irq_mask &= ~(OUTBOUNDDOORBELL_1);
  15.105 +	break;
  15.106 +	
  15.107 +    case HostNormRespQue:
  15.108 +	dev->irq_mask &= ~(OUTBOUNDDOORBELL_2);
  15.109 +	break;
  15.110 +	
  15.111 +    case AdapNormCmdNotFull:
  15.112 +	dev->irq_mask &= ~(OUTBOUNDDOORBELL_3);
  15.113 +	break;
  15.114 +	
  15.115 +    case AdapNormRespNotFull:
  15.116 +	dev->irq_mask &= ~(OUTBOUNDDOORBELL_4);
  15.117 +	break;
  15.118 +    }
  15.119 +}
  15.120 +
  15.121 +/**
  15.122 + *	aac_rx_disable_interrupt	-	Disable event reporting
  15.123 + *	@dev: Adapter
  15.124 + *	@event: Event to enable
  15.125 + *
  15.126 + *	Disable event reporting from the i960 for a given event.
  15.127 + */
  15.128 +
  15.129 +static void aac_rx_disable_interrupt(struct aac_dev *dev, u32 event)
  15.130 +{
  15.131 +    switch (event) {
  15.132 +	
  15.133 +    case HostNormCmdQue:
  15.134 +	dev->irq_mask |= (OUTBOUNDDOORBELL_1);
  15.135 +	break;
  15.136 +	
  15.137 +    case HostNormRespQue:
  15.138 +	dev->irq_mask |= (OUTBOUNDDOORBELL_2);
  15.139 +	break;
  15.140 +	
  15.141 +    case AdapNormCmdNotFull:
  15.142 +	dev->irq_mask |= (OUTBOUNDDOORBELL_3);
  15.143 +	break;
  15.144 +	
  15.145 +    case AdapNormRespNotFull:
  15.146 +	dev->irq_mask |= (OUTBOUNDDOORBELL_4);
  15.147 +	break;
  15.148 +    }
  15.149 +}
  15.150 +
  15.151 +/**
  15.152 + *	rx_sync_cmd	-	send a command and wait
  15.153 + *	@dev: Adapter
  15.154 + *	@command: Command to execute
  15.155 + *	@p1: first parameter
  15.156 + *	@ret: adapter status
  15.157 + *
  15.158 + *	This routine will send a synchronous comamnd to the adapter and wait 
  15.159 + *	for its	completion.
  15.160 + */
  15.161 +
  15.162 +static int rx_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *status)
  15.163 +{
  15.164 +    unsigned long start;
  15.165 +    int ok;
  15.166 +    /*
  15.167 +     *	Write the command into Mailbox 0
  15.168 +     */
  15.169 +    rx_writel(dev, InboundMailbox0, cpu_to_le32(command));
  15.170 +    /*
  15.171 +     *	Write the parameters into Mailboxes 1 - 4
  15.172 +     */
  15.173 +    rx_writel(dev, InboundMailbox1, cpu_to_le32(p1));
  15.174 +    rx_writel(dev, InboundMailbox2, 0);
  15.175 +    rx_writel(dev, InboundMailbox3, 0);
  15.176 +    rx_writel(dev, InboundMailbox4, 0);
  15.177 +    /*
  15.178 +     *	Clear the synch command doorbell to start on a clean slate.
  15.179 +     */
  15.180 +    rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
  15.181 +    /*
  15.182 +     *	Disable doorbell interrupts
  15.183 +     */
  15.184 +    rx_writeb(dev, MUnit.OIMR, rx_readb(dev, MUnit.OIMR) | 0x04);
  15.185 +    /*
  15.186 +     *	Force the completion of the mask register write before issuing
  15.187 +     *	the interrupt.
  15.188 +     */
  15.189 +    rx_readb (dev, MUnit.OIMR);
  15.190 +    /*
  15.191 +     *	Signal that there is a new synch command
  15.192 +     */
  15.193 +    rx_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0);
  15.194 +    
  15.195 +    ok = 0;
  15.196 +    start = jiffies;
  15.197 +    
  15.198 +    /*
  15.199 +     *	Wait up to 30 seconds
  15.200 +     */
  15.201 +    while (time_before(jiffies, start+30*HZ)) 
  15.202 +    {
  15.203 +	/* Delay 5 microseconds to let Mon960 get info. */
  15.204 +	udelay(5);	
  15.205 +	/*
  15.206 +	 *	Mon960 will set doorbell0 bit when its completed the command.
  15.207 +	 */
  15.208 +	if (rx_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
  15.209 +	    /*
  15.210 +	     *	Clear the doorbell.
  15.211 +	     */
  15.212 +	    rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
  15.213 +	    ok = 1;
  15.214 +	    break;
  15.215 +	}
  15.216 +#if 0
  15.217 +	/*
  15.218 +	 *	Yield the processor in case we are slow 
  15.219 +	 */
  15.220 +	set_current_state(TASK_UNINTERRUPTIBLE);
  15.221 +	schedule_timeout(1);
  15.222 +#else 
  15.223 +	/* XXX SMH: not in xen we don't */
  15.224 +	mdelay(50); 
  15.225 +#endif
  15.226 +	
  15.227 +    }
  15.228 +    if (ok != 1) {
  15.229 +	/*
  15.230 +	 *	Restore interrupt mask even though we timed out
  15.231 +	 */
  15.232 +	rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb);
  15.233 +	return -ETIMEDOUT;
  15.234 +    }
  15.235 +    /*
  15.236 +     *	Pull the synch status from Mailbox 0.
  15.237 +     */
  15.238 +    *status = le32_to_cpu(rx_readl(dev, IndexRegs.Mailbox[0]));
  15.239 +    /*
  15.240 +     *	Clear the synch command doorbell.
  15.241 +     */
  15.242 +    rx_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
  15.243 +    /*
  15.244 +     *	Restore interrupt mask
  15.245 +     */
  15.246 +    rx_writeb(dev, MUnit.OIMR, rx_readl(dev, MUnit.OIMR) & 0xfb);
  15.247 +    return 0;
  15.248 +    
  15.249 +}
  15.250 +
  15.251 +/**
  15.252 + *	aac_rx_interrupt_adapter	-	interrupt adapter
  15.253 + *	@dev: Adapter
  15.254 + *
  15.255 + *	Send an interrupt to the i960 and breakpoint it.
  15.256 + */
  15.257 +
  15.258 +static void aac_rx_interrupt_adapter(struct aac_dev *dev)
  15.259 +{
  15.260 +    u32 ret;
  15.261 +    rx_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
  15.262 +}
  15.263 +
  15.264 +/**
  15.265 + *	aac_rx_notify_adapter		-	send an event to the adapter
  15.266 + *	@dev: Adapter
  15.267 + *	@event: Event to send
  15.268 + *
  15.269 + *	Notify the i960 that something it probably cares about has
  15.270 + *	happened.
  15.271 + */
  15.272 +
  15.273 +static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
  15.274 +{
  15.275 +    switch (event) {
  15.276 +	
  15.277 +    case AdapNormCmdQue:
  15.278 +	rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1);
  15.279 +	break;
  15.280 +    case HostNormRespNotFull:
  15.281 +	rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4);
  15.282 +	break;
  15.283 +    case AdapNormRespQue:
  15.284 +	rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2);
  15.285 +	break;
  15.286 +    case HostNormCmdNotFull:
  15.287 +	rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
  15.288 +	break;
  15.289 +    case HostShutdown:
  15.290 +//		rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, &ret);
  15.291 +	break;
  15.292 +    case FastIo:
  15.293 +	rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
  15.294 +	break;
  15.295 +    case AdapPrintfDone:
  15.296 +	rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5);
  15.297 +	break;
  15.298 +    default:
  15.299 +	BUG();
  15.300 +	break;
  15.301 +    }
  15.302 +}
  15.303 +
  15.304 +/**
  15.305 + *	aac_rx_start_adapter		-	activate adapter
  15.306 + *	@dev:	Adapter
  15.307 + *
  15.308 + *	Start up processing on an i960 based AAC adapter
  15.309 + */
  15.310 +
  15.311 +static void aac_rx_start_adapter(struct aac_dev *dev)
  15.312 +{
  15.313 +    u32 status;
  15.314 +    struct aac_init *init;
  15.315 +    
  15.316 +    init = dev->init;
  15.317 +    printk("aac_rx_start: dev is %p, init is %p\n", dev, init); 
  15.318 +    init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ);
  15.319 +    /*
  15.320 +     *	Tell the adapter we are back and up and running so it will scan
  15.321 +     *	its command queues and enable our interrupts
  15.322 +     */
  15.323 +    dev->irq_mask = (DoorBellPrintfReady | OUTBOUNDDOORBELL_1 | 
  15.324 +		     OUTBOUNDDOORBELL_2 | OUTBOUNDDOORBELL_3 | 
  15.325 +		     OUTBOUNDDOORBELL_4);
  15.326 +    /*
  15.327 +     *	First clear out all interrupts.  Then enable the one's that we
  15.328 +     *	can handle.
  15.329 +     */
  15.330 +    rx_writeb(dev, MUnit.OIMR, 0xff);
  15.331 +    rx_writel(dev, MUnit.ODR, 0xffffffff);
  15.332 +//	rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
  15.333 +    rx_writeb(dev, MUnit.OIMR, 0xfb);
  15.334 +    
  15.335 +    // We can only use a 32 bit address here
  15.336 +    rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, 
  15.337 +		(u32)(ulong)dev->init_pa, &status);
  15.338 +}
  15.339 +
  15.340 +/**
  15.341 + *	aac_rx_init	-	initialize an i960 based AAC card
  15.342 + *	@dev: device to configure
  15.343 + *	@devnum: adapter number
  15.344 + *
  15.345 + *	Allocate and set up resources for the i960 based AAC variants. The 
  15.346 + *	device_interface in the commregion will be allocated and linked 
  15.347 + *	to the comm region.
  15.348 + */
  15.349 +
  15.350 +int aac_rx_init(struct aac_dev *dev, unsigned long num)
  15.351 +{
  15.352 +    unsigned long start;
  15.353 +    unsigned long status;
  15.354 +    int instance;
  15.355 +    const char * name;
  15.356 +    
  15.357 +    dev->devnum = num;
  15.358 +    instance = dev->id;
  15.359 +    name     = dev->name;
  15.360 +    
  15.361 +    dprintk((KERN_ERR "aac_rx_init called, num %ld, scsi host ptr = %p\n", 
  15.362 +	     num, (void *)(dev->scsi_host_ptr))); 
  15.363 +    
  15.364 +    dprintk((KERN_ERR "scsi_host_ptr->base is %p\n", 
  15.365 +	     (void *)dev->scsi_host_ptr->base)); 
  15.366 +    /*
  15.367 +     *	Map in the registers from the adapter.
  15.368 +     */
  15.369 +    if((dev->regs.rx = (struct rx_registers *)
  15.370 +	ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
  15.371 +    {	
  15.372 +	printk(KERN_WARNING "aacraid: unable to map i960.\n" );
  15.373 +	return -1;
  15.374 +    }
  15.375 +    
  15.376 +//	dprintk((KERN_ERR "aac_rx_init: AAA\n")); 
  15.377 +    /*
  15.378 +     *	Check to see if the board failed any self tests.
  15.379 +     */
  15.380 +    if (rx_readl(dev, IndexRegs.Mailbox[7]) & SELF_TEST_FAILED) {
  15.381 +	printk(KERN_ERR "%s%d: adapter self-test failed.\n", 
  15.382 +	       dev->name, instance);
  15.383 +	return -1;
  15.384 +    }
  15.385 +    
  15.386 +    
  15.387 +//	dprintk((KERN_ERR "aac_rx_init: BBB\n")); 
  15.388 +    /*
  15.389 +     *	Check to see if the board panic'd while booting.
  15.390 +     */
  15.391 +    if (rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_PANIC) {
  15.392 +	printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", 
  15.393 +	       dev->name, instance);
  15.394 +	return -1;
  15.395 +    }
  15.396 +    start = jiffies;
  15.397 +    
  15.398 +//	dprintk((KERN_ERR "aac_rx_init: DDD\n")); 
  15.399 +    /*
  15.400 +     *	Wait for the adapter to be up and running. Wait up to 3 minutes
  15.401 +     */
  15.402 +    while (!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING)) 
  15.403 +    {
  15.404 +	if(time_after(jiffies, start+180*HZ))
  15.405 +	{
  15.406 +	    status = rx_readl(dev, IndexRegs.Mailbox[7]) >> 16;
  15.407 +	    printk(KERN_ERR "%s%d: adapter kernel failed to start,"
  15.408 +		   "init status = %ld.\n", dev->name, 
  15.409 +		   instance, status);
  15.410 +	    return -1;
  15.411 +	}
  15.412 +// dprintk((KERN_ERR "aac_rx_init: XXX\n")); 
  15.413 +	
  15.414 +#if 0 
  15.415 +	set_current_state(TASK_UNINTERRUPTIBLE);
  15.416 +	schedule_timeout(1);
  15.417 +#else
  15.418 +	/* XXX SMH: no sleeping for us (we're the xen idle task) */
  15.419 +	mdelay(50); 
  15.420 +#endif
  15.421 +	
  15.422 +    }
  15.423 +    
  15.424 +//	dprintk((KERN_ERR "aac_rx_init: ZZZ!\n")); 
  15.425 +    if (request_irq(dev->scsi_host_ptr->irq, aac_rx_intr, 
  15.426 +		    SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev) < 0) 
  15.427 +    {
  15.428 +	printk(KERN_ERR "%s%d: Interrupt unavailable.\n", 
  15.429 +	       name, instance);
  15.430 +	return -1;
  15.431 +    }
  15.432 +    /*
  15.433 +     *	Fill in the function dispatch table.
  15.434 +     */
  15.435 +    dev->a_ops.adapter_interrupt = aac_rx_interrupt_adapter;
  15.436 +    dev->a_ops.adapter_enable_int = aac_rx_enable_interrupt;
  15.437 +    dev->a_ops.adapter_disable_int = aac_rx_disable_interrupt;
  15.438 +    dev->a_ops.adapter_notify = aac_rx_notify_adapter;
  15.439 +    dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
  15.440 +    
  15.441 +    if (aac_init_adapter(dev) == NULL)
  15.442 +	return -1;
  15.443 +#if 0
  15.444 +    /*
  15.445 +     *	Start any kernel threads needed
  15.446 +     */
  15.447 +    dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, 
  15.448 +				    dev, 0);
  15.449 +#else 
  15.450 +    /* XXX SMH: just put in a softirq handler instead... */
  15.451 +    open_softirq(SCSI_LOW_SOFTIRQ, aac_command_thread, dev); 
  15.452 +#endif
  15.453 +
  15.454 +    /*
  15.455 +     *	Tell the adapter that all is configured, and it can start
  15.456 +     *	accepting requests
  15.457 +     */
  15.458 +    aac_rx_start_adapter(dev);
  15.459 +    return 0;
  15.460 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/xen-2.4.16/drivers/scsi/aacraid/sa.c	Fri Feb 21 15:10:37 2003 +0000
    16.3 @@ -0,0 +1,406 @@
    16.4 +/*
    16.5 + *	Adaptec AAC series RAID controller driver
    16.6 + *	(c) Copyright 2001 Red Hat Inc.	<alan@redhat.com>
    16.7 + *
    16.8 + * based on the old aacraid driver that is..
    16.9 + * Adaptec aacraid device driver for Linux.
   16.10 + *
   16.11 + * Copyright (c) 2000 Adaptec, Inc. (aacraid@adaptec.com)
   16.12 + *
   16.13 + * This program is free software; you can redistribute it and/or modify
   16.14 + * it under the terms of the GNU General Public License as published by
   16.15 + * the Free Software Foundation; either version 2, or (at your option)
   16.16 + * any later version.
   16.17 + *
   16.18 + * This program is distributed in the hope that it will be useful,
   16.19 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16.20 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16.21 + * GNU General Public License for more details.
   16.22 + *
   16.23 + * You should have received a copy of the GNU General Public License
   16.24 + * along with this program; see the file COPYING.  If not, write to
   16.25 + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
   16.26 + *
   16.27 + * Module Name:
   16.28 + *  sa.c
   16.29 + *
   16.30 + * Abstract: Drawbridge specific support functions
   16.31 + *
   16.32 + */
   16.33 +
   16.34 +#include <xeno/config.h>
   16.35 +#include <xeno/kernel.h>
   16.36 +#include <xeno/init.h>
   16.37 +#include <xeno/types.h>
   16.38 +#include <xeno/sched.h>
   16.39 +/*  #include <xeno/pci.h> */
   16.40 +/*  #include <xeno/spinlock.h> */
   16.41 +/*  #include <xeno/slab.h> */
   16.42 +#include <xeno/blk.h>
   16.43 +#include <xeno/delay.h>
   16.44 +/*  #include <xeno/completion.h> */
   16.45 +/*  #include <asm/semaphore.h> */
   16.46 +#include "scsi.h"
   16.47 +#include "hosts.h"
   16.48 +
   16.49 +#include "aacraid.h"
   16.50 +
   16.51 +static void aac_sa_intr(int irq, void *dev_id, struct pt_regs *regs)
   16.52 +{
   16.53 +	struct aac_dev *dev = dev_id;
   16.54 +	unsigned short intstat, mask;
   16.55 +
   16.56 +	intstat = sa_readw(dev, DoorbellReg_p);
   16.57 +	/*
   16.58 +	 *	Read mask and invert because drawbridge is reversed.
   16.59 +	 *	This allows us to only service interrupts that have been enabled.
   16.60 +	 */
   16.61 +	mask = ~(sa_readw(dev, SaDbCSR.PRISETIRQMASK));
   16.62 +
   16.63 +	/* Check to see if this is our interrupt.  If it isn't just return */
   16.64 +
   16.65 +	if (intstat & mask) {
   16.66 +		if (intstat & PrintfReady) {
   16.67 +			aac_printf(dev, le32_to_cpu(sa_readl(dev, Mailbox5)));
   16.68 +			sa_writew(dev, DoorbellClrReg_p, PrintfReady); /* clear PrintfReady */
   16.69 +			sa_writew(dev, DoorbellReg_s, PrintfDone);
   16.70 +		} else if (intstat & DOORBELL_1) {	// dev -> Host Normal Command Ready
   16.71 +			aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
   16.72 +			sa_writew(dev, DoorbellClrReg_p, DOORBELL_1);
   16.73 +		} else if (intstat & DOORBELL_2) {	// dev -> Host Normal Response Ready
   16.74 +			aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
   16.75 +			sa_writew(dev, DoorbellClrReg_p, DOORBELL_2);
   16.76 +		} else if (intstat & DOORBELL_3) {	// dev -> Host Normal Command Not Full
   16.77 +			sa_writew(dev, DoorbellClrReg_p, DOORBELL_3);
   16.78 +		} else if (intstat & DOORBELL_4) {	// dev -> Host Normal Response Not Full
   16.79 +			sa_writew(dev, DoorbellClrReg_p, DOORBELL_4);
   16.80 +		}
   16.81 +	}
   16.82 +}
   16.83 +
   16.84 +/**
   16.85 + *	aac_sa_enable_interrupt	-	enable an interrupt event
   16.86 + *	@dev: Which adapter to enable.
   16.87 + *	@event: Which adapter event.
   16.88 + *
   16.89 + *	This routine will enable the corresponding adapter event to cause an interrupt on 
   16.90 + * 	the host.
   16.91 + */
   16.92 + 
   16.93 +void aac_sa_enable_interrupt(struct aac_dev *dev, u32 event)
   16.94 +{
   16.95 +	switch (event) {
   16.96 +
   16.97 +	case HostNormCmdQue:
   16.98 +		sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_1);
   16.99 +		break;
  16.100 +
  16.101 +	case HostNormRespQue:
  16.102 +		sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_2);
  16.103 +		break;
  16.104 +
  16.105 +	case AdapNormCmdNotFull:
  16.106 +		sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_3);
  16.107 +		break;
  16.108 +
  16.109 +	case AdapNormRespNotFull:
  16.110 +		sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, DOORBELL_4);
  16.111 +		break;
  16.112 +	}
  16.113 +}
  16.114 +
  16.115 +/**
  16.116 + *	aac_sa_disable_interrupt	-	disable an interrupt event
  16.117 + *	@dev: Which adapter to enable.
  16.118 + *	@event: Which adapter event.
  16.119 + *
  16.120 + *	This routine will enable the corresponding adapter event to cause an interrupt on 
  16.121 + * 	the host.
  16.122 + */
  16.123 +
  16.124 +void aac_sa_disable_interrupt (struct aac_dev *dev, u32 event)
  16.125 +{
  16.126 +	switch (event) {
  16.127 +
  16.128 +	case HostNormCmdQue:
  16.129 +		sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_1);
  16.130 +		break;
  16.131 +
  16.132 +	case HostNormRespQue:
  16.133 +		sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_2);
  16.134 +		break;
  16.135 +
  16.136 +	case AdapNormCmdNotFull:
  16.137 +		sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_3);
  16.138 +		break;
  16.139 +
  16.140 +	case AdapNormRespNotFull:
  16.141 +		sa_writew(dev, SaDbCSR.PRISETIRQMASK, DOORBELL_4);
  16.142 +		break;
  16.143 +	}
  16.144 +}
  16.145 +
  16.146 +/**
  16.147 + *	aac_sa_notify_adapter		-	handle adapter notification
  16.148 + *	@dev:	Adapter that notification is for
  16.149 + *	@event:	Event to notidy
  16.150 + *
  16.151 + *	Notify the adapter of an event
  16.152 + */
  16.153 + 
  16.154 +void aac_sa_notify_adapter(struct aac_dev *dev, u32 event)
  16.155 +{
  16.156 +	switch (event) {
  16.157 +
  16.158 +	case AdapNormCmdQue:
  16.159 +		sa_writew(dev, DoorbellReg_s,DOORBELL_1);
  16.160 +		break;
  16.161 +	case HostNormRespNotFull:
  16.162 +		sa_writew(dev, DoorbellReg_s,DOORBELL_4);
  16.163 +		break;
  16.164 +	case AdapNormRespQue:
  16.165 +		sa_writew(dev, DoorbellReg_s,DOORBELL_2);
  16.166 +		break;
  16.167 +	case HostNormCmdNotFull:
  16.168 +		sa_writew(dev, DoorbellReg_s,DOORBELL_3);
  16.169 +		break;
  16.170 +	case HostShutdown:
  16.171 +		//sa_sync_cmd(dev, HOST_CRASHING, 0, &ret);
  16.172 +		break;
  16.173 +	case FastIo:
  16.174 +		sa_writew(dev, DoorbellReg_s,DOORBELL_6);
  16.175 +		break;
  16.176 +	case AdapPrintfDone:
  16.177 +		sa_writew(dev, DoorbellReg_s,DOORBELL_5);
  16.178 +		break;
  16.179 +	default:
  16.180 +		BUG();
  16.181 +		break;
  16.182 +	}
  16.183 +}
  16.184 +
  16.185 +
  16.186 +/**
  16.187 + *	sa_sync_cmd	-	send a command and wait
  16.188 + *	@dev: Adapter
  16.189 + *	@command: Command to execute
  16.190 + *	@p1: first parameter
  16.191 + *	@ret: adapter status
  16.192 + *
  16.193 + *	This routine will send a synchronous comamnd to the adapter and wait 
  16.194 + *	for its	completion.
  16.195 + */
  16.196 +
  16.197 +static int sa_sync_cmd(struct aac_dev *dev, u32 command, u32 p1, u32 *ret)
  16.198 +{
  16.199 +	unsigned long start;
  16.200 + 	int ok;
  16.201 +	/*
  16.202 +	 *	Write the Command into Mailbox 0
  16.203 +	 */
  16.204 +	sa_writel(dev, Mailbox0, cpu_to_le32(command));
  16.205 +	/*
  16.206 +	 *	Write the parameters into Mailboxes 1 - 4
  16.207 +	 */
  16.208 +	sa_writel(dev, Mailbox1, cpu_to_le32(p1));
  16.209 +	sa_writel(dev, Mailbox2, 0);
  16.210 +	sa_writel(dev, Mailbox3, 0);
  16.211 +	sa_writel(dev, Mailbox4, 0);
  16.212 +	/*
  16.213 +	 *	Clear the synch command doorbell to start on a clean slate.
  16.214 +	 */
  16.215 +	sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
  16.216 +	/*
  16.217 +	 *	Signal that there is a new synch command
  16.218 +	 */
  16.219 +	sa_writew(dev, DoorbellReg_s, DOORBELL_0);
  16.220 +
  16.221 +	ok = 0;
  16.222 +	start = jiffies;
  16.223 +
  16.224 +	while(time_before(jiffies, start+30*HZ))
  16.225 +	{
  16.226 +		/*
  16.227 +		 *	Delay 5uS so that the monitor gets access
  16.228 +		 */
  16.229 +		udelay(5);
  16.230 +		/*
  16.231 +		 *	Mon110 will set doorbell0 bit when it has 
  16.232 +		 *	completed the command.
  16.233 +		 */
  16.234 +		if(sa_readw(dev, DoorbellReg_p) & DOORBELL_0)  {
  16.235 +			ok = 1;
  16.236 +			break;
  16.237 +		}
  16.238 +#if 0
  16.239 +		set_current_state(TASK_UNINTERRUPTIBLE);
  16.240 +		schedule_timeout(1);
  16.241 +#endif
  16.242 +		mdelay(100); 
  16.243 +
  16.244 +	}
  16.245 +
  16.246 +	if (ok != 1)
  16.247 +		return -ETIMEDOUT;
  16.248 +	/*
  16.249 +	 *	Clear the synch command doorbell.
  16.250 +	 */
  16.251 +	sa_writew(dev, DoorbellClrReg_p, DOORBELL_0);
  16.252 +	/*
  16.253 +	 *	Pull the synch status from Mailbox 0.
  16.254 +	 */
  16.255 +	*ret = le32_to_cpu(sa_readl(dev, Mailbox0));
  16.256 +	return 0;
  16.257 +}
  16.258 +
  16.259 +/**
  16.260 + *	aac_sa_interrupt_adapter	-	interrupt an adapter
  16.261 + *	@dev: Which adapter to enable.
  16.262 + *
  16.263 + *	Breakpoint an adapter.
  16.264 + */
  16.265 + 
  16.266 +static void aac_sa_interrupt_adapter (struct aac_dev *dev)
  16.267 +{
  16.268 +	u32 ret;
  16.269 +	sa_sync_cmd(dev, BREAKPOINT_REQUEST, 0, &ret);
  16.270 +}
  16.271 +
  16.272 +/**
  16.273 + *	aac_sa_start_adapter		-	activate adapter
  16.274 + *	@dev:	Adapter
  16.275 + *
  16.276 + *	Start up processing on an ARM based AAC adapter
  16.277 + */
  16.278 +
  16.279 +static void aac_sa_start_adapter(struct aac_dev *dev)
  16.280 +{
  16.281 +	u32 ret;
  16.282 +	struct aac_init *init;
  16.283 +	/*
  16.284 +	 * Fill in the remaining pieces of the init.
  16.285 +	 */
  16.286 +	init = dev->init;
  16.287 +	init->HostElapsedSeconds = cpu_to_le32(jiffies/HZ);
  16.288 +
  16.289 +	dprintk(("INIT\n"));
  16.290 +	/*
  16.291 +	 * Tell the adapter we are back and up and running so it will scan its command
  16.292 +	 * queues and enable our interrupts
  16.293 +	 */
  16.294 +	dev->irq_mask =	(PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4);
  16.295 +	/*
  16.296 +	 *	First clear out all interrupts.  Then enable the one's that 
  16.297 +	 *	we can handle.
  16.298 +	 */
  16.299 +	dprintk(("MASK\n"));
  16.300 +	sa_writew(dev, SaDbCSR.PRISETIRQMASK, cpu_to_le16(0xffff));
  16.301 +	sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
  16.302 +	dprintk(("SYNCCMD\n"));
  16.303 +	/* We can only use a 32 bit address here */
  16.304 +	sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, &ret);
  16.305 +}
  16.306 +
  16.307 +/**
  16.308 + *	aac_sa_init	-	initialize an ARM based AAC card
  16.309 + *	@dev: device to configure
  16.310 + *	@devnum: adapter number
  16.311 + *
  16.312 + *	Allocate and set up resources for the ARM based AAC variants. The 
  16.313 + *	device_interface in the commregion will be allocated and linked 
  16.314 + *	to the comm region.
  16.315 + */
  16.316 +
  16.317 +int aac_sa_init(struct aac_dev *dev, unsigned long devnum)
  16.318 +{
  16.319 +	unsigned long start;
  16.320 +	unsigned long status;
  16.321 +	int instance;
  16.322 +	const char *name;
  16.323 +
  16.324 +	dev->devnum = devnum;
  16.325 +
  16.326 +	dprintk(("PREINST\n"));
  16.327 +	instance = dev->id;
  16.328 +	name     = dev->name;
  16.329 +
  16.330 +	/*
  16.331 +	 *	Map in the registers from the adapter.
  16.332 +	 */
  16.333 +	dprintk(("PREMAP\n"));
  16.334 +
  16.335 +	if((dev->regs.sa = (struct sa_registers *)ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
  16.336 +	{	
  16.337 +		printk(KERN_WARNING "aacraid: unable to map ARM.\n" );
  16.338 +		return -1;
  16.339 +	}
  16.340 +	/*
  16.341 +	 *	Check to see if the board failed any self tests.
  16.342 +	 */
  16.343 +	if (sa_readl(dev, Mailbox7) & SELF_TEST_FAILED) {
  16.344 +		printk(KERN_WARNING "%s%d: adapter self-test failed.\n", name, instance);
  16.345 +		return -1;
  16.346 +	}
  16.347 +	/*
  16.348 +	 *	Check to see if the board panic'd while booting.
  16.349 +	 */
  16.350 +	if (sa_readl(dev, Mailbox7) & KERNEL_PANIC) {
  16.351 +		printk(KERN_WARNING "%s%d: adapter kernel panic'd.\n", name, instance);
  16.352 +		return -1;
  16.353 +	}
  16.354 +	start = jiffies;
  16.355 +	/*
  16.356 +	 *	Wait for the adapter to be up and running. Wait up to 3 minutes.
  16.357 +	 */
  16.358 +	while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
  16.359 +		if (time_after(start+180*HZ, jiffies)) {
  16.360 +			status = sa_readl(dev, Mailbox7) >> 16;
  16.361 +			printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status));
  16.362 +			return -1;
  16.363 +		}
  16.364 +#if 0
  16.365 +		set_current_state(TASK_UNINTERRUPTIBLE);
  16.366 +		schedule_timeout(1);
  16.367 +#endif
  16.368 +		mdelay(100); 
  16.369 +	}
  16.370 +
  16.371 +	dprintk(("ATIRQ\n"));
  16.372 +	if (request_irq(dev->scsi_host_ptr->irq, aac_sa_intr, SA_SHIRQ|SA_INTERRUPT, "aacraid", (void *)dev ) < 0) {
  16.373 +		printk(KERN_WARNING "%s%d: Interrupt unavailable.\n", name, instance);
  16.374 +		return -1;
  16.375 +	}
  16.376 +
  16.377 +	/*
  16.378 +	 *	Fill in the function dispatch table.
  16.379 +	 */
  16.380 +
  16.381 +	dev->a_ops.adapter_interrupt = aac_sa_interrupt_adapter;
  16.382 +	dev->a_ops.adapter_enable_int = aac_sa_enable_interrupt;
  16.383 +	dev->a_ops.adapter_disable_int = aac_sa_disable_interrupt;
  16.384 +	dev->a_ops.adapter_notify = aac_sa_notify_adapter;
  16.385 +	dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
  16.386 +
  16.387 +	dprintk(("FUNCDONE\n"));
  16.388 +
  16.389 +	if(aac_init_adapter(dev) == NULL)
  16.390 +		return -1;
  16.391 +
  16.392 +	dprintk(("NEWADAPTDONE\n"));
  16.393 +#if 0
  16.394 +	/*
  16.395 +	 *	Start any kernel threads needed
  16.396 +	 */
  16.397 +	dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
  16.398 +#endif
  16.399 +
  16.400 +	/*
  16.401 +	 *	Tell the adapter that all is configure, and it can start 
  16.402 +	 *	accepting requests
  16.403 +	 */
  16.404 +	dprintk(("STARTING\n"));
  16.405 +	aac_sa_start_adapter(dev);
  16.406 +	dprintk(("STARTED\n"));
  16.407 +	return 0;
  16.408 +}
  16.409 +
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/xen-2.4.16/drivers/scsi/constants.c	Fri Feb 21 15:10:37 2003 +0000
    17.3 @@ -0,0 +1,1005 @@
    17.4 +/* 
    17.5 + * ASCII values for a number of symbolic constants, printing functions,
    17.6 + * etc.
    17.7 + * Additions for SCSI 2 and Linux 2.2.x by D. Gilbert (990422)
    17.8 + *
    17.9 + */
   17.10 +
   17.11 +#define __NO_VERSION__
   17.12 +#include <xeno/module.h>
   17.13 +
   17.14 +#include <xeno/config.h>
   17.15 +#include <xeno/blk.h>
   17.16 +/*#include <linux/kernel.h> */
   17.17 +#include "scsi.h"
   17.18 +#include "hosts.h"
   17.19 +
   17.20 +#define CONST_COMMAND   0x01
   17.21 +#define CONST_STATUS    0x02
   17.22 +#define CONST_SENSE     0x04
   17.23 +#define CONST_XSENSE    0x08
   17.24 +#define CONST_CMND      0x10
   17.25 +#define CONST_MSG       0x20
   17.26 +#define CONST_HOST	0x40
   17.27 +#define CONST_DRIVER	0x80
   17.28 +
   17.29 +static const char unknown[] = "UNKNOWN";
   17.30 +
   17.31 +#ifdef CONFIG_SCSI_CONSTANTS
   17.32 +#ifdef CONSTANTS
   17.33 +#undef CONSTANTS
   17.34 +#endif
   17.35 +#define CONSTANTS (CONST_COMMAND | CONST_STATUS | CONST_SENSE | CONST_XSENSE \
   17.36 +		   | CONST_CMND | CONST_MSG | CONST_HOST | CONST_DRIVER)
   17.37 +#endif
   17.38 +
   17.39 +#if (CONSTANTS & CONST_COMMAND)
   17.40 +static const char * group_0_commands[] = {
   17.41 +/* 00-03 */ "Test Unit Ready", "Rezero Unit", unknown, "Request Sense",
   17.42 +/* 04-07 */ "Format Unit", "Read Block Limits", unknown, "Reasssign Blocks",
   17.43 +/* 08-0d */ "Read (6)", unknown, "Write (6)", "Seek (6)", unknown, unknown,
   17.44 +/* 0e-12 */ unknown, "Read Reverse", "Write Filemarks", "Space", "Inquiry",  
   17.45 +/* 13-16 */ "Verify", "Recover Buffered Data", "Mode Select", "Reserve",
   17.46 +/* 17-1b */ "Release", "Copy", "Erase", "Mode Sense", "Start/Stop Unit",
   17.47 +/* 1c-1d */ "Receive Diagnostic", "Send Diagnostic", 
   17.48 +/* 1e-1f */ "Prevent/Allow Medium Removal", unknown,
   17.49 +};
   17.50 +
   17.51 +
   17.52 +static const char *group_1_commands[] = {
   17.53 +/* 20-22 */  unknown, unknown, unknown,
   17.54 +/* 23-28 */ unknown, "Define window parameters", "Read Capacity", 
   17.55 +            unknown, unknown, "Read (10)", 
   17.56 +/* 29-2d */ "Read Generation", "Write (10)", "Seek (10)", "Erase", 
   17.57 +            "Read updated block", 
   17.58 +/* 2e-31 */ "Write Verify","Verify", "Search High", "Search Equal", 
   17.59 +/* 32-34 */ "Search Low", "Set Limits", "Prefetch or Read Position", 
   17.60 +/* 35-37 */ "Synchronize Cache","Lock/Unlock Cache", "Read Defect Data", 
   17.61 +/* 38-3c */ "Medium Scan", "Compare", "Copy Verify", "Write Buffer", 
   17.62 +            "Read Buffer", 
   17.63 +/* 3d-3f */ "Update Block", "Read Long",  "Write Long",
   17.64 +};
   17.65 +
   17.66 +
   17.67 +static const char *group_2_commands[] = {
   17.68 +/* 40-41 */ "Change Definition", "Write Same", 
   17.69 +/* 42-48 */ "Read sub-channel", "Read TOC", "Read header", 
   17.70 +            "Play audio (10)", unknown, "Play audio msf",
   17.71 +            "Play audio track/index", 
   17.72 +/* 49-4f */ "Play track relative (10)", unknown, "Pause/resume", 
   17.73 +            "Log Select", "Log Sense", unknown, unknown,
   17.74 +/* 50-55 */ unknown, unknown, unknown, unknown, unknown, "Mode Select (10)",
   17.75 +/* 56-5b */ unknown, unknown, unknown, unknown, "Mode Sense (10)", unknown,
   17.76 +/* 5c-5f */ unknown, unknown, unknown,
   17.77 +};
   17.78 +
   17.79 +
   17.80 +/* The following are 16 byte commands in group 4 */
   17.81 +static const char *group_4_commands[] = {
   17.82 +/* 80-84 */ unknown, unknown, unknown, unknown, unknown,
   17.83 +/* 85-89 */ "Memory Export In (16)", unknown, unknown, unknown,
   17.84 +            "Memory Export Out (16)",
   17.85 +/* 8a-8f */ unknown, unknown, unknown, unknown, unknown, unknown,
   17.86 +/* 90-94 */ unknown, unknown, unknown, unknown, unknown,
   17.87 +/* 95-99 */ unknown, unknown, unknown, unknown, unknown,
   17.88 +/* 9a-9f */ unknown, unknown, unknown, unknown, unknown, unknown,
   17.89 +};
   17.90 +
   17.91 +
   17.92 +/* The following are 12 byte commands in group 5 */
   17.93 +static const char *group_5_commands[] = {
   17.94 +/* a0-a5 */ unknown, unknown, unknown, unknown, unknown,
   17.95 +            "Move medium/play audio(12)",
   17.96 +/* a6-a9 */ "Exchange medium", unknown, "Read(12)", "Play track relative(12)", 
   17.97 +/* aa-ae */ "Write(12)", unknown, "Erase(12)", unknown, 
   17.98 +            "Write and verify(12)", 
   17.99 +/* af-b1 */ "Verify(12)", "Search data high(12)", "Search data equal(12)",
  17.100 +/* b2-b4 */ "Search data low(12)", "Set limits(12)", unknown,
  17.101 +/* b5-b6 */ "Request volume element address", "Send volume tag",
  17.102 +/* b7-b9 */ "Read defect data(12)", "Read element status", unknown,
  17.103 +/* ba-bf */ unknown, unknown, unknown, unknown, unknown, unknown,
  17.104 +};
  17.105 +
  17.106 +
  17.107 +
  17.108 +#define group(opcode) (((opcode) >> 5) & 7)
  17.109 +
  17.110 +#define RESERVED_GROUP  0
  17.111 +#define VENDOR_GROUP    1
  17.112 +
  17.113 +static const char **commands[] = {
  17.114 +    group_0_commands, group_1_commands, group_2_commands, 
  17.115 +    (const char **) RESERVED_GROUP, group_4_commands, 
  17.116 +    group_5_commands, (const char **) VENDOR_GROUP, 
  17.117 +    (const char **) VENDOR_GROUP
  17.118 +};
  17.119 +
  17.120 +static const char reserved[] = "RESERVED";
  17.121 +static const char vendor[] = "VENDOR SPECIFIC";
  17.122 +
  17.123 +static void print_opcode(int opcode) {
  17.124 +    const char **table = commands[ group(opcode) ];
  17.125 +    switch ((unsigned long) table) {
  17.126 +    case RESERVED_GROUP:
  17.127 +	printk("%s(0x%02x) ", reserved, opcode); 
  17.128 +	break;
  17.129 +    case VENDOR_GROUP:
  17.130 +	printk("%s(0x%02x) ", vendor, opcode); 
  17.131 +	break;
  17.132 +    default:
  17.133 +	if (table[opcode & 0x1f] != unknown)
  17.134 +	    printk("%s ",table[opcode & 0x1f]);
  17.135 +	else
  17.136 +	    printk("%s(0x%02x) ", unknown, opcode);
  17.137 +	break;
  17.138 +    }
  17.139 +}
  17.140 +#else /* CONST & CONST_COMMAND */
  17.141 +static void print_opcode(int opcode) {
  17.142 +    printk("0x%02x ", opcode);
  17.143 +}
  17.144 +#endif  
  17.145 +
  17.146 +void print_command (unsigned char *command) {
  17.147 +    int i,s;
  17.148 +    print_opcode(command[0]);
  17.149 +    for ( i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i) 
  17.150 +	printk("%02x ", command[i]);
  17.151 +    printk("\n");
  17.152 +}
  17.153 +
  17.154 +#if (CONSTANTS & CONST_STATUS)
  17.155 +static const char * statuses[] = {
  17.156 +/* 0-4 */ "Good", "Check Condition", "Condition Met", unknown, "Busy", 
  17.157 +/* 5-9 */ unknown, unknown, unknown, "Intermediate", unknown, 
  17.158 +/* a-c */ "Intermediate-Condition Met", unknown, "Reservation Conflict",
  17.159 +/* d-10 */ unknown, unknown, unknown, unknown,
  17.160 +/* 11-14 */ "Command Terminated", unknown, unknown, "Queue Full",
  17.161 +/* 15-1a */ unknown, unknown, unknown, unknown, unknown, unknown,
  17.162 +/* 1b-1f */ unknown, unknown, unknown, unknown, unknown,
  17.163 +};
  17.164 +#endif
  17.165 +
  17.166 +void print_status (int status) {
  17.167 +    status = (status >> 1) & 0x1f;
  17.168 +#if (CONSTANTS & CONST_STATUS)
  17.169 +    printk("%s ",statuses[status]);
  17.170 +#else
  17.171 +    printk("0x%0x ", status); 
  17.172 +#endif 
  17.173 +}
  17.174 +
  17.175 +#if (CONSTANTS & CONST_XSENSE)
  17.176 +#define D 0x0001  /* DIRECT ACCESS DEVICE (disk) */
  17.177 +#define T 0x0002  /* SEQUENTIAL ACCESS DEVICE (tape) */
  17.178 +#define L 0x0004  /* PRINTER DEVICE */
  17.179 +#define P 0x0008  /* PROCESSOR DEVICE */
  17.180 +#define W 0x0010  /* WRITE ONCE READ MULTIPLE DEVICE */
  17.181 +#define R 0x0020  /* READ ONLY (CD-ROM) DEVICE */
  17.182 +#define S 0x0040  /* SCANNER DEVICE */
  17.183 +#define O 0x0080  /* OPTICAL MEMORY DEVICE */
  17.184 +#define M 0x0100  /* MEDIA CHANGER DEVICE */
  17.185 +#define C 0x0200  /* COMMUNICATION DEVICE */
  17.186 +#define A 0x0400  /* ARRAY STORAGE */
  17.187 +#define E 0x0800  /* ENCLOSURE SERVICES DEVICE */
  17.188 +#define B 0x1000  /* SIMPLIFIED DIRECT ACCESS DEVICE */
  17.189 +#define K 0x2000  /* OPTICAL CARD READER/WRITER DEVICE */
  17.190 +
  17.191 +struct error_info{
  17.192 +    unsigned char code1, code2;
  17.193 +    unsigned short int devices;
  17.194 +    const char * text;
  17.195 +};
  17.196 +
  17.197 +struct error_info2{
  17.198 +    unsigned char code1, code2_min, code2_max;
  17.199 +    unsigned short int devices;
  17.200 +    const char * text;
  17.201 +};
  17.202 +
  17.203 +static struct error_info2 additional2[] =
  17.204 +{
  17.205 +  {0x40,0x00,0x7f,D,"Ram failure (%x)"},
  17.206 +  {0x40,0x80,0xff,D|T|L|P|W|R|S|O|M|C,"Diagnostic failure on component (%x)"},
  17.207 +  {0x41,0x00,0xff,D,"Data path failure (%x)"},
  17.208 +  {0x42,0x00,0xff,D,"Power-on or self-test failure (%x)"},
  17.209 +  {0, 0, 0, 0, NULL}
  17.210 +};
  17.211 +
  17.212 +static struct error_info additional[] =
  17.213 +{
  17.214 +  {0x00,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"No additional sense information"},
  17.215 +  {0x00,0x01,T,"Filemark detected"},
  17.216 +  {0x00,0x02,T|S,"End-of-partition/medium detected"},
  17.217 +  {0x00,0x03,T,"Setmark detected"},
  17.218 +  {0x00,0x04,T|S,"Beginning-of-partition/medium detected"},
  17.219 +  {0x00,0x05,T|L|S,"End-of-data detected"},
  17.220 +  {0x00,0x06,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"I/O process terminated"},
  17.221 +  {0x00,0x11,R,"Audio play operation in progress"},
  17.222 +  {0x00,0x12,R,"Audio play operation paused"},
  17.223 +  {0x00,0x13,R,"Audio play operation successfully completed"},
  17.224 +  {0x00,0x14,R,"Audio play operation stopped due to error"},
  17.225 +  {0x00,0x15,R,"No current audio status to return"},
  17.226 +  {0x00,0x16,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Operation in progress"},
  17.227 +  {0x00,0x17,D|T|L|W|R|S|O|M|A|E|B|K,"Cleaning requested"},
  17.228 +  {0x01,0x00,D|W|O|B|K,"No index/sector signal"},
  17.229 +  {0x02,0x00,D|W|R|O|M|B|K,"No seek complete"},
  17.230 +  {0x03,0x00,D|T|L|W|S|O|B|K,"Peripheral device write fault"},
  17.231 +  {0x03,0x01,T,"No write current"},
  17.232 +  {0x03,0x02,T,"Excessive write errors"},
  17.233 +  {0x04,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,cause not reportable"},
  17.234 +  {0x04,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit is in process of becoming ready"},
  17.235 +  {0x04,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,initializing cmd. required"},
  17.236 +  {0x04,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,manual intervention required"},
  17.237 +  {0x04,0x04,D|T|L|R|O|B,"Logical unit not ready,format in progress"},
  17.238 +  {0x04,0x05,D|T|W|O|M|C|A|B|K,"Logical unit not ready,rebuild in progress"},
  17.239 +  {0x04,0x06,D|T|W|O|M|C|A|B|K,"Logical unit not ready,recalculation in progress"},
  17.240 +  {0x04,0x07,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,operation in progress"},
  17.241 +  {0x04,0x08,R,"Logical unit not ready,long write in progress"},
  17.242 +  {0x04,0x09,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not ready,self-test in progress"},
  17.243 +  {0x05,0x00,D|T|L|W|R|S|O|M|C|A|E|B|K,"Logical unit does not respond to selection"},
  17.244 +  {0x06,0x00,D|W|R|O|M|B|K,"No reference position found"},
  17.245 +  {0x07,0x00,D|T|L|W|R|S|O|M|B|K,"Multiple peripheral devices selected"},
  17.246 +  {0x08,0x00,D|T|L|W|R|S|O|M|C|A|E|B|K,"Logical unit communication failure"},
  17.247 +  {0x08,0x01,D|T|L|W|R|S|O|M|C|A|E|B|K,"Logical unit communication time-out"},
  17.248 +  {0x08,0x02,D|T|L|W|R|S|O|M|C|A|E|B|K,"Logical unit communication parity error"},
  17.249 +  {0x08,0x03,D|T|R|O|M|B|K,"Logical unit communication CRC error (Ultra-DMA/32)"},
  17.250 +  {0x08,0x04,D|T|L|P|W|R|S|O|C|K,"Unreachable copy target"},
  17.251 +  {0x09,0x00,D|T|W|R|O|B,"Track following error"},
  17.252 +  {0x09,0x01,W|R|O|K,"Tracking servo failure"},
  17.253 +  {0x09,0x02,W|R|O|K,"Focus servo failure"},
  17.254 +  {0x09,0x03,W|R|O,"Spindle servo failure"},
  17.255 +  {0x09,0x04,D|T|W|R|O|B,"Head select fault"},
  17.256 +  {0x0A,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Error log overflow"},
  17.257 +  {0x0B,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Warning"},
  17.258 +  {0x0B,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Warning - specified temperature exceeded"},
  17.259 +  {0x0B,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Warning - enclosure degraded"},
  17.260 +  {0x0C,0x00,T|R|S,"Write error"},
  17.261 +  {0x0C,0x01,K,"Write error - recovered with auto reallocation"},
  17.262 +  {0x0C,0x02,D|W|O|B|K,"Write error - auto reallocation failed"},
  17.263 +  {0x0C,0x03,D|W|O|B|K,"Write error - recommend reassignment"},
  17.264 +  {0x0C,0x04,D|T|W|O|B,"Compression check miscompare error"},
  17.265 +  {0x0C,0x05,D|T|W|O|B,"Data expansion occurred during compression"},
  17.266 +  {0x0C,0x06,D|T|W|O|B,"Block not compressible"},
  17.267 +  {0x0C,0x07,R,"Write error - recovery needed"},
  17.268 +  {0x0C,0x08,R,"Write error - recovery failed"},
  17.269 +  {0x0C,0x09,R,"Write error - loss of streaming"},
  17.270 +  {0x0C,0x0A,R,"Write error - padding blocks added"},
  17.271 +  {0x10,0x00,D|W|O|B|K,"Id CRC or ECC error"},
  17.272 +  {0x11,0x00,D|T|W|R|S|O|B|K,"Unrecovered read error"},
  17.273 +  {0x11,0x01,D|T|W|R|S|O|B|K,"Read retries exhausted"},
  17.274 +  {0x11,0x02,D|T|W|R|S|O|B|K,"Error too long to correct"},
  17.275 +  {0x11,0x03,D|T|W|S|O|B|K,"Multiple read errors"},
  17.276 +  {0x11,0x04,D|W|O|B|K,"Unrecovered read error - auto reallocate failed"},
  17.277 +  {0x11,0x05,W|R|O|B,"L-EC uncorrectable error"},
  17.278 +  {0x11,0x06,W|R|O|B,"CIRC unrecovered error"},
  17.279 +  {0x11,0x07,W|O|B,"Data re-synchronization error"},
  17.280 +  {0x11,0x08,T,"Incomplete block read"},
  17.281 +  {0x11,0x09,T,"No gap found"},
  17.282 +  {0x11,0x0A,D|T|O|B|K,"Miscorrected error"},
  17.283 +  {0x11,0x0B,D|W|O|B|K,"Unrecovered read error - recommend reassignment"},
  17.284 +  {0x11,0x0C,D|W|O|B|K,"Unrecovered read error - recommend rewrite the data"},
  17.285 +  {0x11,0x0D,D|T|W|R|O|B,"De-compression CRC error"},
  17.286 +  {0x11,0x0E,D|T|W|R|O|B,"Cannot decompress using declared algorithm"},
  17.287 +  {0x11,0x0F,R,"Error reading UPC/EAN number"},
  17.288 +  {0x11,0x10,R,"Error reading ISRC number"},
  17.289 +  {0x11,0x11,R,"Read error - loss of streaming"},
  17.290 +  {0x12,0x00,D|W|O|B|K,"Address mark not found for id field"},
  17.291 +  {0x13,0x00,D|W|O|B|K,"Address mark not found for data field"},
  17.292 +  {0x14,0x00,D|T|L|W|R|S|O|B|K,"Recorded entity not found"},
  17.293 +  {0x14,0x01,D|T|W|R|O|B|K,"Record not found"},
  17.294 +  {0x14,0x02,T,"Filemark or setmark not found"},
  17.295 +  {0x14,0x03,T,"End-of-data not found"},
  17.296 +  {0x14,0x04,T,"Block sequence error"},
  17.297 +  {0x14,0x05,D|T|W|O|B|K,"Record not found - recommend reassignment"},
  17.298 +  {0x14,0x06,D|T|W|O|B|K,"Record not found - data auto-reallocated"},
  17.299 +  {0x15,0x00,D|T|L|W|R|S|O|M|B|K,"Random positioning error"},
  17.300 +  {0x15,0x01,D|T|L|W|R|S|O|M|B|K,"Mechanical positioning error"},
  17.301 +  {0x15,0x02,D|T|W|R|O|B|K,"Positioning error detected by read of medium"},
  17.302 +  {0x16,0x00,D|W|O|B|K,"Data synchronization mark error"},
  17.303 +  {0x16,0x01,D|W|O|B|K,"Data sync error - data rewritten"},
  17.304 +  {0x16,0x02,D|W|O|B|K,"Data sync error - recommend rewrite"},
  17.305 +  {0x16,0x03,D|W|O|B|K,"Data sync error - data auto-reallocated"},
  17.306 +  {0x16,0x04,D|W|O|B|K,"Data sync error - recommend reassignment"},
  17.307 +  {0x17,0x00,D|T|W|R|S|O|B|K,"Recovered data with no error correction applied"},
  17.308 +  {0x17,0x01,D|T|W|R|S|O|B|K,"Recovered data with retries"},
  17.309 +  {0x17,0x02,D|T|W|R|O|B|K,"Recovered data with positive head offset"},
  17.310 +  {0x17,0x03,D|T|W|R|O|B|K,"Recovered data with negative head offset"},
  17.311 +  {0x17,0x04,W|R|O|B,"Recovered data with retries and/or circ applied"},
  17.312 +  {0x17,0x05,D|W|R|O|B|K,"Recovered data using previous sector id"},
  17.313 +  {0x17,0x06,D|W|O|B|K,"Recovered data without ecc - data auto-reallocated"},
  17.314 +  {0x17,0x07,D|W|R|O|B|K,"Recovered data without ecc - recommend reassignment"},
  17.315 +  {0x17,0x08,D|W|R|O|B|K,"Recovered data without ecc - recommend rewrite"},
  17.316 +  {0x17,0x09,D|W|R|O|B|K,"Recovered data without ecc - data rewritten"},
  17.317 +  {0x18,0x00,D|T|W|R|O|B|K,"Recovered data with error correction applied"},
  17.318 +  {0x18,0x01,D|W|R|O|B|K,"Recovered data with error corr. & retries applied"},
  17.319 +  {0x18,0x02,D|W|R|O|B|K,"Recovered data - data auto-reallocated"},
  17.320 +  {0x18,0x03,R,"Recovered data with CIRC"},
  17.321 +  {0x18,0x04,R,"Recovered data with L-EC"},
  17.322 +  {0x18,0x05,D|W|R|O|B|K,"Recovered data - recommend reassignment"},
  17.323 +  {0x18,0x06,D|W|R|O|B|K,"Recovered data - recommend rewrite"},
  17.324 +  {0x18,0x07,D|W|O|B|K,"Recovered data with ecc - data rewritten"},
  17.325 +  {0x19,0x00,D|O|K,"Defect list error"},
  17.326 +  {0x19,0x01,D|O|K,"Defect list not available"},
  17.327 +  {0x19,0x02,D|O|K,"Defect list error in primary list"},
  17.328 +  {0x19,0x03,D|O|K,"Defect list error in grown list"},
  17.329 +  {0x1A,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Parameter list length error"},
  17.330 +  {0x1B,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Synchronous data transfer error"},
  17.331 +  {0x1C,0x00,D|O|B|K,"Defect list not found"},
  17.332 +  {0x1C,0x01,D|O|B|K,"Primary defect list not found"},
  17.333 +  {0x1C,0x02,D|O|B|K,"Grown defect list not found"},
  17.334 +  {0x1D,0x00,D|T|W|R|O|B|K,"Miscompare during verify operation"},
  17.335 +  {0x1E,0x00,D|W|O|B|K,"Recovered id with ecc correction"},
  17.336 +  {0x1F,0x00,D|O|K,"Partial defect list transfer"},
  17.337 +  {0x20,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid command operation code"},
  17.338 +  {0x21,0x00,D|T|W|R|O|M|B|K,"Logical block address out of range"},
  17.339 +  {0x21,0x01,D|T|W|R|O|M|B|K,"Invalid element address"},
  17.340 +  {0x22,0x00,D,"Illegal function (use 20 00,24 00,or 26 00)"},
  17.341 +  {0x24,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid field in cdb"},
  17.342 +  {0x24,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"CDB decryption error"},
  17.343 +  {0x25,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit not supported"},
  17.344 +  {0x26,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid field in parameter list"},
  17.345 +  {0x26,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Parameter not supported"},
  17.346 +  {0x26,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Parameter value invalid"},
  17.347 +  {0x26,0x03,D|T|L|P|W|R|S|O|M|C|A|E|K,"Threshold parameters not supported"},
  17.348 +  {0x26,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid release of persistent reservation"},
  17.349 +  {0x26,0x05,D|T|L|P|W|R|S|O|M|C|A|B|K,"Data decryption error"},
  17.350 +  {0x26,0x06,D|T|L|P|W|R|S|O|C|K,"Too many target descriptors"},
  17.351 +  {0x26,0x07,D|T|L|P|W|R|S|O|C|K,"Unsupported target descriptor type code"},
  17.352 +  {0x26,0x08,D|T|L|P|W|R|S|O|C|K,"Too many segment descriptors"},
  17.353 +  {0x26,0x09,D|T|L|P|W|R|S|O|C|K,"Unsupported segment descriptor type code"},
  17.354 +  {0x26,0x0A,D|T|L|P|W|R|S|O|C|K,"Unexpected inexact segment"},
  17.355 +  {0x26,0x0B,D|T|L|P|W|R|S|O|C|K,"Inline data length exceeded"},
  17.356 +  {0x26,0x0C,D|T|L|P|W|R|S|O|C|K,"Invalid operation for copy source or destination"},
  17.357 +  {0x26,0x0D,D|T|L|P|W|R|S|O|C|K,"Copy segment granularity violation"},
  17.358 +  {0x27,0x00,D|T|W|R|O|B|K,"Write protected"},
  17.359 +  {0x27,0x01,D|T|W|R|O|B|K,"Hardware write protected"},
  17.360 +  {0x27,0x02,D|T|W|R|O|B|K,"Logical unit software write protected"},
  17.361 +  {0x27,0x03,T|R,"Associated write protect"},
  17.362 +  {0x27,0x04,T|R,"Persistent write protect"},
  17.363 +  {0x27,0x05,T|R,"Permanent write protect"},
  17.364 +  {0x28,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Not ready to ready change,medium may have changed"},
  17.365 +  {0x28,0x01,D|T|W|R|O|M|B,"Import or export element accessed"},
  17.366 +  {0x29,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Power on,reset,or bus device reset occurred"},
  17.367 +  {0x29,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Power on occurred"},
  17.368 +  {0x29,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Scsi bus reset occurred"},
  17.369 +  {0x29,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Bus device reset function occurred"},
  17.370 +  {0x29,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Device internal reset"},
  17.371 +  {0x29,0x05,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Transceiver mode changed to single-ended"},
  17.372 +  {0x29,0x06,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Transceiver mode changed to lvd"},
  17.373 +  {0x2A,0x00,D|T|L|W|R|S|O|M|C|A|E|B|K,"Parameters changed"},
  17.374 +  {0x2A,0x01,D|T|L|W|R|S|O|M|C|A|E|B|K,"Mode parameters changed"},
  17.375 +  {0x2A,0x02,D|T|L|W|R|S|O|M|C|A|E|K,"Log parameters changed"},
  17.376 +  {0x2A,0x03,D|T|L|P|W|R|S|O|M|C|A|E|K,"Reservations preempted"},
  17.377 +  {0x2A,0x04,D|T|L|P|W|R|S|O|M|C|A|E,"Reservations released"},
  17.378 +  {0x2A,0x05,D|T|L|P|W|R|S|O|M|C|A|E,"Registrations preempted"},
  17.379 +  {0x2B,0x00,D|T|L|P|W|R|S|O|C|K,"Copy cannot execute since host cannot disconnect"},
  17.380 +  {0x2C,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Command sequence error"},
  17.381 +  {0x2C,0x01,S,"Too many windows specified"},
  17.382 +  {0x2C,0x02,S,"Invalid combination of windows specified"},
  17.383 +  {0x2C,0x03,R,"Current program area is not empty"},
  17.384 +  {0x2C,0x04,R,"Current program area is empty"},
  17.385 +  {0x2C,0x05,B,"Illegal power condition request"},
  17.386 +  {0x2D,0x00,T,"Overwrite error on update in place"},
  17.387 +  {0x2F,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Commands cleared by another initiator"},
  17.388 +  {0x30,0x00,D|T|W|R|O|M|B|K,"Incompatible medium installed"},
  17.389 +  {0x30,0x01,D|T|W|R|O|B|K,"Cannot read medium - unknown format"},
  17.390 +  {0x30,0x02,D|T|W|R|O|B|K,"Cannot read medium - incompatible format"},
  17.391 +  {0x30,0x03,D|T|R|K,"Cleaning cartridge installed"},
  17.392 +  {0x30,0x04,D|T|W|R|O|B|K,"Cannot write medium - unknown format"},
  17.393 +  {0x30,0x05,D|T|W|R|O|B|K,"Cannot write medium - incompatible format"},
  17.394 +  {0x30,0x06,D|T|W|R|O|B,"Cannot format medium - incompatible medium"},
  17.395 +  {0x30,0x07,D|T|L|W|R|S|O|M|A|E|B|K,"Cleaning failure"},
  17.396 +  {0x30,0x08,R,"Cannot write - application code mismatch"},
  17.397 +  {0x30,0x09,R,"Current session not fixated for append"},
  17.398 +  {0x31,0x00,D|T|W|R|O|B|K,"Medium format corrupted"},
  17.399 +  {0x31,0x01,D|L|R|O|B,"Format command failed"},
  17.400 +  {0x32,0x00,D|W|O|B|K,"No defect spare location available"},
  17.401 +  {0x32,0x01,D|W|O|B|K,"Defect list update failure"},
  17.402 +  {0x33,0x00,T,"Tape length error"},
  17.403 +  {0x34,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure failure"},
  17.404 +  {0x35,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure services failure"},
  17.405 +  {0x35,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Unsupported enclosure function"},
  17.406 +  {0x35,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure services unavailable"},
  17.407 +  {0x35,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure services transfer failure"},
  17.408 +  {0x35,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Enclosure services transfer refused"},
  17.409 +  {0x36,0x00,L,"Ribbon,ink,or toner failure"},
  17.410 +  {0x37,0x00,D|T|L|W|R|S|O|M|C|A|E|B|K,"Rounded parameter"},
  17.411 +  {0x38,0x00,B,"Event status notification"},
  17.412 +  {0x38,0x02,B,"Esn - power management class event"},
  17.413 +  {0x38,0x04,B,"Esn - media class event"},
  17.414 +  {0x38,0x06,B,"Esn - device busy class event"},
  17.415 +  {0x39,0x00,D|T|L|W|R|S|O|M|C|A|E|K,"Saving parameters not supported"},
  17.416 +  {0x3A,0x00,D|T|L|W|R|S|O|M|B|K,"Medium not present"},
  17.417 +  {0x3A,0x01,D|T|W|R|O|M|B|K,"Medium not present - tray closed"},
  17.418 +  {0x3A,0x02,D|T|W|R|O|M|B|K,"Medium not present - tray open"},
  17.419 +  {0x3A,0x03,D|T|W|R|O|M|B,"Medium not present - loadable"},
  17.420 +  {0x3A,0x04,D|T|W|R|O|M|B,"Medium not present - medium auxiliary memory accessible"},
  17.421 +  {0x3B,0x00,T|L,"Sequential positioning error"},
  17.422 +  {0x3B,0x01,T,"Tape position error at beginning-of-medium"},
  17.423 +  {0x3B,0x02,T,"Tape position error at end-of-medium"},
  17.424 +  {0x3B,0x03,L,"Tape or electronic vertical forms unit not ready"},
  17.425 +  {0x3B,0x04,L,"Slew failure"},
  17.426 +  {0x3B,0x05,L,"Paper jam"},
  17.427 +  {0x3B,0x06,L,"Failed to sense top-of-form"},
  17.428 +  {0x3B,0x07,L,"Failed to sense bottom-of-form"},
  17.429 +  {0x3B,0x08,T,"Reposition error"},
  17.430 +  {0x3B,0x09,S,"Read past end of medium"},
  17.431 +  {0x3B,0x0A,S,"Read past beginning of medium"},
  17.432 +  {0x3B,0x0B,S,"Position past end of medium"},
  17.433 +  {0x3B,0x0C,T|S,"Position past beginning of medium"},
  17.434 +  {0x3B,0x0D,D|T|W|R|O|M|B|K,"Medium destination element full"},
  17.435 +  {0x3B,0x0E,D|T|W|R|O|M|B|K,"Medium source element empty"},
  17.436 +  {0x3B,0x0F,R,"End of medium reached"},
  17.437 +  {0x3B,0x11,D|T|W|R|O|M|B|K,"Medium magazine not accessible"},
  17.438 +  {0x3B,0x12,D|T|W|R|O|M|B|K,"Medium magazine removed"},
  17.439 +  {0x3B,0x13,D|T|W|R|O|M|B|K,"Medium magazine inserted"},
  17.440 +  {0x3B,0x14,D|T|W|R|O|M|B|K,"Medium magazine locked"},
  17.441 +  {0x3B,0x15,D|T|W|R|O|M|B|K,"Medium magazine unlocked"},
  17.442 +  {0x3B,0x16,R,"Mechanical positioning or changer error"},
  17.443 +  {0x3D,0x00,D|T|L|P|W|R|S|O|M|C|A|E|K,"Invalid bits in identify message"},
  17.444 +  {0x3E,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit has not self-configured yet"},
  17.445 +  {0x3E,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit failure"},
  17.446 +  {0x3E,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Timeout on logical unit"},
  17.447 +  {0x3E,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit failed self-test"},
  17.448 +  {0x3E,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit unable to update self-test log"},
  17.449 +  {0x3F,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Target operating conditions have changed"},
  17.450 +  {0x3F,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Microcode has been changed"},
  17.451 +  {0x3F,0x02,D|T|L|P|W|R|S|O|M|C|B|K,"Changed operating definition"},
  17.452 +  {0x3F,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Inquiry data has changed"},
  17.453 +  {0x3F,0x04,D|T|W|R|O|M|C|A|E|B|K,"Component device attached"},
  17.454 +  {0x3F,0x05,D|T|W|R|O|M|C|A|E|B|K,"Device identifier changed"},
  17.455 +  {0x3F,0x06,D|T|W|R|O|M|C|A|E|B,"Redundancy group created or modified"},
  17.456 +  {0x3F,0x07,D|T|W|R|O|M|C|A|E|B,"Redundancy group deleted"},
  17.457 +  {0x3F,0x08,D|T|W|R|O|M|C|A|E|B,"Spare created or modified"},
  17.458 +  {0x3F,0x09,D|T|W|R|O|M|C|A|E|B,"Spare deleted"},
  17.459 +  {0x3F,0x0A,D|T|W|R|O|M|C|A|E|B|K,"Volume set created or modified"},
  17.460 +  {0x3F,0x0B,D|T|W|R|O|M|C|A|E|B|K,"Volume set deleted"},
  17.461 +  {0x3F,0x0C,D|T|W|R|O|M|C|A|E|B|K,"Volume set deassigned"},
  17.462 +  {0x3F,0x0D,D|T|W|R|O|M|C|A|E|B|K,"Volume set reassigned"},
  17.463 +  {0x3F,0x0E,D|T|L|P|W|R|S|O|M|C|A|E,"Reported luns data has changed"},
  17.464 +  {0x3F,0x10,D|T|W|R|O|M|B,"Medium loadable"},
  17.465 +  {0x3F,0x11,D|T|W|R|O|M|B,"Medium auxiliary memory accessible"},
  17.466 +  {0x40,0x00,D,"Ram failure (should use 40 nn)"},
  17.467 +  /*
  17.468 +   * FIXME(eric) - need a way to represent wildcards here.
  17.469 +   */
  17.470 +  {0x40,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Diagnostic failure on component nn (80h-ffh)"},
  17.471 +  {0x41,0x00,D,"Data path failure (should use 40 nn)"},
  17.472 +  {0x42,0x00,D,"Power-on or self-test failure (should use 40 nn)"},
  17.473 +  {0x43,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Message error"},
  17.474 +  {0x44,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Internal target failure"},
  17.475 +  {0x45,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Select or reselect failure"},
  17.476 +  {0x46,0x00,D|T|L|P|W|R|S|O|M|C|B|K,"Unsuccessful soft reset"},
  17.477 +  {0x47,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Scsi parity error"},
  17.478 +  {0x47,0x01,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Data phase CRC error detected"},
  17.479 +  {0x47,0x02,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Scsi parity error detected during st data phase"},
  17.480 +  {0x47,0x03,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Information unit CRC error detected"},
  17.481 +  {0x47,0x04,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Asynchronous information protection error detected"},
  17.482 +  {0x48,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Initiator detected error message received"},
  17.483 +  {0x49,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Invalid message error"},
  17.484 +  {0x4A,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Command phase error"},
  17.485 +  {0x4B,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Data phase error"},
  17.486 +  {0x4C,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Logical unit failed self-configuration"},
  17.487 +  /*
  17.488 +   * FIXME(eric) - need a way to represent wildcards here.
  17.489 +   */
  17.490 +  {0x4D,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Tagged overlapped commands (nn = queue tag)"},
  17.491 +  {0x4E,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Overlapped commands attempted"},
  17.492 +  {0x50,0x00,T,"Write append error"},
  17.493 +  {0x50,0x01,T,"Write append position error"},
  17.494 +  {0x50,0x02,T,"Position error related to timing"},
  17.495 +  {0x51,0x00,T|R|O,"Erase failure"},
  17.496 +  {0x52,0x00,T,"Cartridge fault"},
  17.497 +  {0x53,0x00,D|T|L|W|R|S|O|M|B|K,"Media load or eject failed"},
  17.498 +  {0x53,0x01,T,"Unload tape failure"},
  17.499 +  {0x53,0x02,D|T|W|R|O|M|B|K,"Medium removal prevented"},
  17.500 +  {0x54,0x00,P,"Scsi to host system interface failure"},
  17.501 +  {0x55,0x00,P,"System resource failure"},
  17.502 +  {0x55,0x01,D|O|B|K,"System buffer full"},
  17.503 +  {0x55,0x02,D|T|L|P|W|R|S|O|M|A|E|K,"Insufficient reservation resources"},
  17.504 +  {0x55,0x03,D|T|L|P|W|R|S|O|M|C|A|E,"Insufficient resources"},
  17.505 +  {0x55,0x04,D|T|L|P|W|R|S|O|M|A|E,"Insufficient registration resources"},
  17.506 +  {0x57,0x00,R,"Unable to recover table-of-contents"},
  17.507 +  {0x58,0x00,O,"Generation does not exist"},
  17.508 +  {0x59,0x00,O,"Updated block read"},
  17.509 +  {0x5A,0x00,D|T|L|P|W|R|S|O|M|B|K,"Operator request or state change input"},
  17.510 +  {0x5A,0x01,D|T|W|R|O|M|B|K,"Operator medium removal request"},
  17.511 +  {0x5A,0x02,D|T|W|R|O|A|B|K,"Operator selected write protect"},
  17.512 +  {0x5A,0x03,D|T|W|R|O|A|B|K,"Operator selected write permit"},
  17.513 +  {0x5B,0x00,D|T|L|P|W|R|S|O|M|K,"Log exception"},
  17.514 +  {0x5B,0x01,D|T|L|P|W|R|S|O|M|K,"Threshold condition met"},
  17.515 +  {0x5B,0x02,D|T|L|P|W|R|S|O|M|K,"Log counter at maximum"},
  17.516 +  {0x5B,0x03,D|T|L|P|W|R|S|O|M|K,"Log list codes exhausted"},
  17.517 +  {0x5C,0x00,D|O,"Rpl status change"},
  17.518 +  {0x5C,0x01,D|O,"Spindles synchronized"},
  17.519 +  {0x5C,0x02,D|O,"Spindles not synchronized"},
  17.520 +  {0x5D,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Failure prediction threshold exceeded"},
  17.521 +  {0x5D,0x01,R|B,"Media failure prediction threshold exceeded"},
  17.522 +  {0x5D,0x02,R,"Logical unit failure prediction threshold exceeded"},
  17.523 +  {0x5D,0x10,D|B,"Hardware impending failure general hard drive failure"},
  17.524 +  {0x5D,0x11,D|B,"Hardware impending failure drive error rate too high"},
  17.525 +  {0x5D,0x12,D|B,"Hardware impending failure data error rate too high"},
  17.526 +  {0x5D,0x13,D|B,"Hardware impending failure seek error rate too high"},
  17.527 +  {0x5D,0x14,D|B,"Hardware impending failure too many block reassigns"},
  17.528 +  {0x5D,0x15,D|B,"Hardware impending failure access times too high"},
  17.529 +  {0x5D,0x16,D|B,"Hardware impending failure start unit times too high"},
  17.530 +  {0x5D,0x17,D|B,"Hardware impending failure channel parametrics"},
  17.531 +  {0x5D,0x18,D|B,"Hardware impending failure controller detected"},
  17.532 +  {0x5D,0x19,D|B,"Hardware impending failure throughput performance"},
  17.533 +  {0x5D,0x1A,D|B,"Hardware impending failure seek time performance"},
  17.534 +  {0x5D,0x1B,D|B,"Hardware impending failure spin-up retry count"},
  17.535 +  {0x5D,0x1C,D|B,"Hardware impending failure drive calibration retry count"},
  17.536 +  {0x5D,0x20,D|B,"Controller impending failure general hard drive failure"},
  17.537 +  {0x5D,0x21,D|B,"Controller impending failure drive error rate too high"},
  17.538 +  {0x5D,0x22,D|B,"Controller impending failure data error rate too high"},
  17.539 +  {0x5D,0x23,D|B,"Controller impending failure seek error rate too high"},
  17.540 +  {0x5D,0x24,D|B,"Controller impending failure too many block reassigns"},
  17.541 +  {0x5D,0x25,D|B,"Controller impending failure access times too high"},
  17.542 +  {0x5D,0x26,D|B,"Controller impending failure start unit times too high"},
  17.543 +  {0x5D,0x27,D|B,"Controller impending failure channel parametrics"},
  17.544 +  {0x5D,0x28,D|B,"Controller impending failure controller detected"},
  17.545 +  {0x5D,0x29,D|B,"Controller impending failure throughput performance"},
  17.546 +  {0x5D,0x2A,D|B,"Controller impending failure seek time performance"},
  17.547 +  {0x5D,0x2B,D|B,"Controller impending failure spin-up retry count"},
  17.548 +  {0x5D,0x2C,D|B,"Controller impending failure drive calibration retry count"},
  17.549 +  {0x5D,0x30,D|B,"Data channel impending failure general hard drive failure"},
  17.550 +  {0x5D,0x31,D|B,"Data channel impending failure drive error rate too high"},
  17.551 +  {0x5D,0x32,D|B,"Data channel impending failure data error rate too high"},
  17.552 +  {0x5D,0x33,D|B,"Data channel impending failure seek error rate too high"},
  17.553 +  {0x5D,0x34,D|B,"Data channel impending failure too many block reassigns"},
  17.554 +  {0x5D,0x35,D|B,"Data channel impending failure access times too high"},
  17.555 +  {0x5D,0x36,D|B,"Data channel impending failure start unit times too high"},
  17.556 +  {0x5D,0x37,D|B,"Data channel impending failure channel parametrics"},
  17.557 +  {0x5D,0x38,D|B,"Data channel impending failure controller detected"},
  17.558 +  {0x5D,0x39,D|B,"Data channel impending failure throughput performance"},
  17.559 +  {0x5D,0x3A,D|B,"Data channel impending failure seek time performance"},
  17.560 +  {0x5D,0x3B,D|B,"Data channel impending failure spin-up retry count"},
  17.561 +  {0x5D,0x3C,D|B,"Data channel impending failure drive calibration retry count"},
  17.562 +  {0x5D,0x40,D|B,"Servo impending failure general hard drive failure"},
  17.563 +  {0x5D,0x41,D|B,"Servo impending failure drive error rate too high"},
  17.564 +  {0x5D,0x42,D|B,"Servo impending failure data error rate too high"},
  17.565 +  {0x5D,0x43,D|B,"Servo impending failure seek error rate too high"},
  17.566 +  {0x5D,0x44,D|B,"Servo impending failure too many block reassigns"},
  17.567 +  {0x5D,0x45,D|B,"Servo impending failure access times too high"},
  17.568 +  {0x5D,0x46,D|B,"Servo impending failure start unit times too high"},
  17.569 +  {0x5D,0x47,D|B,"Servo impending failure channel parametrics"},
  17.570 +  {0x5D,0x48,D|B,"Servo impending failure controller detected"},
  17.571 +  {0x5D,0x49,D|B,"Servo impending failure throughput performance"},
  17.572 +  {0x5D,0x4A,D|B,"Servo impending failure seek time performance"},
  17.573 +  {0x5D,0x4B,D|B,"Servo impending failure spin-up retry count"},
  17.574 +  {0x5D,0x4C,D|B,"Servo impending failure drive calibration retry count"},
  17.575 +  {0x5D,0x50,D|B,"Spindle impending failure general hard drive failure"},
  17.576 +  {0x5D,0x51,D|B,"Spindle impending failure drive error rate too high"},
  17.577 +  {0x5D,0x52,D|B,"Spindle impending failure data error rate too high"},
  17.578 +  {0x5D,0x53,D|B,"Spindle impending failure seek error rate too high"},
  17.579 +  {0x5D,0x54,D|B,"Spindle impending failure too many block reassigns"},
  17.580 +  {0x5D,0x55,D|B,"Spindle impending failure access times too high"},
  17.581 +  {0x5D,0x56,D|B,"Spindle impending failure start unit times too high"},
  17.582 +  {0x5D,0x57,D|B,"Spindle impending failure channel parametrics"},
  17.583 +  {0x5D,0x58,D|B,"Spindle impending failure controller detected"},
  17.584 +  {0x5D,0x59,D|B,"Spindle impending failure throughput performance"},
  17.585 +  {0x5D,0x5A,D|B,"Spindle impending failure seek time performance"},
  17.586 +  {0x5D,0x5B,D|B,"Spindle impending failure spin-up retry count"},
  17.587 +  {0x5D,0x5C,D|B,"Spindle impending failure drive calibration retry count"},
  17.588 +  {0x5D,0x60,D|B,"Firmware impending failure general hard drive failure"},
  17.589 +  {0x5D,0x61,D|B,"Firmware impending failure drive error rate too high"},
  17.590 +  {0x5D,0x62,D|B,"Firmware impending failure data error rate too high"},
  17.591 +  {0x5D,0x63,D|B,"Firmware impending failure seek error rate too high"},
  17.592 +  {0x5D,0x64,D|B,"Firmware impending failure too many block reassigns"},
  17.593 +  {0x5D,0x65,D|B,"Firmware impending failure access times too high"},
  17.594 +  {0x5D,0x66,D|B,"Firmware impending failure start unit times too high"},
  17.595 +  {0x5D,0x67,D|B,"Firmware impending failure channel parametrics"},
  17.596 +  {0x5D,0x68,D|B,"Firmware impending failure controller detected"},
  17.597 +  {0x5D,0x69,D|B,"Firmware impending failure throughput performance"},
  17.598 +  {0x5D,0x6A,D|B,"Firmware impending failure seek time performance"},
  17.599 +  {0x5D,0x6B,D|B,"Firmware impending failure spin-up retry count"},
  17.600 +  {0x5D,0x6C,D|B,"Firmware impending failure drive calibration retry count"},
  17.601 +  {0x5D,0xFF,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Failure prediction threshold exceeded (false)"},
  17.602 +  {0x5E,0x00,D|T|L|P|W|R|S|O|C|A|K,"Low power condition on"},
  17.603 +  {0x5E,0x01,D|T|L|P|W|R|S|O|C|A|K,"Idle condition activated by timer"},
  17.604 +  {0x5E,0x02,D|T|L|P|W|R|S|O|C|A|K,"Standby condition activated by timer"},
  17.605 +  {0x5E,0x03,D|T|L|P|W|R|S|O|C|A|K,"Idle condition activated by command"},
  17.606 +  {0x5E,0x04,D|T|L|P|W|R|S|O|C|A|K,"Standby condition activated by command"},
  17.607 +  {0x5E,0x41,B,"Power state change to active"},
  17.608 +  {0x5E,0x42,B,"Power state change to idle"},
  17.609 +  {0x5E,0x43,B,"Power state change to standby"},
  17.610 +  {0x5E,0x45,B,"Power state change to sleep"},
  17.611 +  {0x5E,0x47,B|K,"Power state change to device control"},
  17.612 +  {0x60,0x00,S,"Lamp failure"},
  17.613 +  {0x61,0x00,S,"Video acquisition error"},
  17.614 +  {0x61,0x01,S,"Unable to acquire video"},
  17.615 +  {0x61,0x02,S,"Out of focus"},
  17.616 +  {0x62,0x00,S,"Scan head positioning error"},
  17.617 +  {0x63,0x00,R,"End of user area encountered on this track"},
  17.618 +  {0x63,0x01,R,"Packet does not fit in available space"},
  17.619 +  {0x64,0x00,R,"Illegal mode for this track"},
  17.620 +  {0x64,0x01,R,"Invalid packet size"},
  17.621 +  {0x65,0x00,D|T|L|P|W|R|S|O|M|C|A|E|B|K,"Voltage fault"},
  17.622 +  {0x66,0x00,S,"Automatic document feeder cover up"},
  17.623 +  {0x66,0x01,S,"Automatic document feeder lift up"},
  17.624 +  {0x66,0x02,S,"Document jam in automatic document feeder"},
  17.625 +  {0x66,0x03,S,"Document miss feed automatic in document feeder"},
  17.626 +  {0x67,0x00,A,"Configuration failure"},
  17.627 +  {0x67,0x01,A,"Configuration of incapable logical units failed"},
  17.628 +  {0x67,0x02,A,"Add logical unit failed"},
  17.629 +  {0x67,0x03,A,"Modification of logical unit failed"},
  17.630 +  {0x67,0x04,A,"Exchange of logical unit failed"},
  17.631 +  {0x67,0x05,A,"Remove of logical unit failed"},
  17.632 +  {0x67,0x06,A,"Attachment of logical unit failed"},
  17.633 +  {0x67,0x07,A,"Creation of logical unit failed"},
  17.634 +  {0x67,0x08,A,"Assign failure occurred"},
  17.635 +  {0x67,0x09,A,"Multiply assigned logical unit"},
  17.636 +  {0x68,0x00,A,"Logical unit not configured"},
  17.637 +  {0x69,0x00,A,"Data loss on logical unit"},
  17.638 +  {0x69,0x01,A,"Multiple logical unit failures"},
  17.639 +  {0x69,0x02,A,"Parity/data mismatch"},
  17.640 +  {0x6A,0x00,A,"Informational,refer to log"},
  17.641 +  {0x6B,0x00,A,"State change has occurred"},
  17.642 +  {0x6B,0x01,A,"Redundancy level got better"},
  17.643 +  {0x6B,0x02,A,"Redundancy level got worse"},
  17.644 +  {0x6C,0x00,A,"Rebuild failure occurred"},
  17.645 +  {0x6D,0x00,A,"Recalculate failure occurred"},
  17.646 +  {0x6E,0x00,A,"Command to logical unit failed"},
  17.647 +  {0x6F,0x00,R,"Copy protection key exchange failure - authentication failure"},
  17.648 +  {0x6F,0x01,R,"Copy protection key exchange failure - key not present"},
  17.649 +  {0x6F,0x02,R,"Copy protection key exchange failure - key not established"},
  17.650 +  {0x6F,0x03,R,"Read of scrambled sector without authentication"},
  17.651 +  {0x6F,0x04,R,"Media region code is mismatched to logical unit region"},
  17.652 +  {0x6F,0x05,R,"Drive region must be permanent/region reset count error"},
  17.653 +  /*
  17.654 +   * FIXME(eric) - need a way to represent wildcards here.
  17.655 +   */
  17.656 +  {0x70,0x00,T,"Decompression exception short algorithm id of nn"},
  17.657 +  {0x71,0x00,T,"Decompression exception long algorithm id"},
  17.658 +  {0x72,0x00,R,"Session fixation error"},
  17.659 +  {0x72,0x01,R,"Session fixation error writing lead-in"},
  17.660 +  {0x72,0x02,R,"Session fixation error writing lead-out"},
  17.661 +  {0x72,0x03,R,"Session fixation error - incomplete track in session"},
  17.662 +  {0x72,0x04,R,"Empty or partially written reserved track"},
  17.663 +  {0x72,0x05,R,"No more track reservations allowed"},
  17.664 +  {0x73,0x00,R,"Cd control error"},
  17.665 +  {0x73,0x01,R,"Power calibration area almost full"},
  17.666 +  {0x73,0x02,R,"Power calibration area is full"},
  17.667 +  {0x73,0x03,R,"Power calibration area error"},
  17.668 +  {0x73,0x04,R,"Program memory area update failure"},
  17.669 +  {0x73,0x05,R,"Program memory area is full"},
  17.670 +  {0x73,0x06,R,"RMA/PMA is full"},
  17.671 +  {0, 0, 0, NULL}
  17.672 +};
  17.673 +#endif
  17.674 +
  17.675 +#if (CONSTANTS & CONST_SENSE)
  17.676 +static const char *snstext[] = {
  17.677 +    "None",                     /* There is no sense information */
  17.678 +    "Recovered Error",          /* The last command completed successfully
  17.679 +                                   but used error correction */
  17.680 +    "Not Ready",                /* The addressed target is not ready */
  17.681 +    "Medium Error",             /* Data error detected on the medium */
  17.682 +    "Hardware Error",           /* Controller or device failure */
  17.683 +    "Illegal Request",
  17.684 +    "Unit Attention",           /* Removable medium was changed, or
  17.685 +                                   the target has been reset */
  17.686 +    "Data Protect",             /* Access to the data is blocked */
  17.687 +    "Blank Check",              /* Reached unexpected written or unwritten
  17.688 +                                   region of the medium */
  17.689 +    "Key=9",                    /* Vendor specific */
  17.690 +    "Copy Aborted",             /* COPY or COMPARE was aborted */
  17.691 +    "Aborted Command",          /* The target aborted the command */
  17.692 +    "Equal",                    /* A SEARCH DATA command found data equal */
  17.693 +    "Volume Overflow",          /* Medium full with still data to be written */
  17.694 +    "Miscompare",               /* Source data and data on the medium
  17.695 +                                   do not agree */
  17.696 +    "Key=15"                    /* Reserved */
  17.697 +};
  17.698 +#endif
  17.699 +
  17.700 +/* Print sense information */
  17.701 +static 
  17.702 +void print_sense_internal(const char * devclass, 
  17.703 +			  const unsigned char * sense_buffer,
  17.704 +			  kdev_t dev)
  17.705 +{
  17.706 +    int i, s;
  17.707 +    int sense_class, valid, code, info;
  17.708 +    const char * error = NULL;
  17.709 +    
  17.710 +    sense_class = (sense_buffer[0] >> 4) & 0x07;
  17.711 +    code = sense_buffer[0] & 0xf;
  17.712 +    valid = sense_buffer[0] & 0x80;
  17.713 +    
  17.714 +    if (sense_class == 7) {	/* extended sense data */
  17.715 +	s = sense_buffer[7] + 8;
  17.716 +	if(s > SCSI_SENSE_BUFFERSIZE)
  17.717 +	   s = SCSI_SENSE_BUFFERSIZE;
  17.718 +	
  17.719 +	info = ((sense_buffer[3] << 24) | (sense_buffer[4] << 16) |
  17.720 +		(sense_buffer[5] << 8) | sense_buffer[6]);
  17.721 +	if (info || valid) {
  17.722 +		printk("Info fld=0x%x", info);
  17.723 +		if (!valid)	/* info data not according to standard */
  17.724 +			printk(" (nonstd)");
  17.725 +		printk(", ");
  17.726 +	}
  17.727 +	if (sense_buffer[2] & 0x80)
  17.728 +           printk( "FMK ");	/* current command has read a filemark */
  17.729 +	if (sense_buffer[2] & 0x40)
  17.730 +           printk( "EOM ");	/* end-of-medium condition exists */
  17.731 +	if (sense_buffer[2] & 0x20)
  17.732 +           printk( "ILI ");	/* incorrect block length requested */
  17.733 +	
  17.734 +	switch (code) {
  17.735 +	case 0x0:
  17.736 +	    error = "Current";	/* error concerns current command */
  17.737 +	    break;
  17.738 +	case 0x1:
  17.739 +	    error = "Deferred";	/* error concerns some earlier command */
  17.740 +            	/* e.g., an earlier write to disk cache succeeded, but
  17.741 +                   now the disk discovers that it cannot write the data */
  17.742 +	    break;
  17.743 +	default:
  17.744 +	    error = "Invalid";
  17.745 +	}
  17.746 +	
  17.747 +	printk("%s ", error);
  17.748 +	
  17.749 +#if (CONSTANTS & CONST_SENSE)
  17.750 +	printk( "%s%s: sense key %s\n", devclass,
  17.751 +	       kdevname(dev), snstext[sense_buffer[2] & 0x0f]);
  17.752 +#else
  17.753 +	printk("%s%s: sns = %2x %2x\n", devclass,
  17.754 +	       kdevname(dev), sense_buffer[0], sense_buffer[2]);
  17.755 +#endif
  17.756 +	
  17.757 +	/* Check to see if additional sense information is available */
  17.758 +	if(sense_buffer[7] + 7 < 13 ||
  17.759 +	   (sense_buffer[12] == 0  && sense_buffer[13] ==  0)) goto done;
  17.760 +	
  17.761 +#if (CONSTANTS & CONST_XSENSE)
  17.762 +	for(i=0; additional[i].text; i++)
  17.763 +	    if(additional[i].code1 == sense_buffer[12] &&
  17.764 +	       additional[i].code2 == sense_buffer[13])
  17.765 +		printk("Additional sense indicates %s\n", additional[i].text);
  17.766 +	
  17.767 +	for(i=0; additional2[i].text; i++)
  17.768 +	    if(additional2[i].code1 == sense_buffer[12] &&
  17.769 +	       additional2[i].code2_min >= sense_buffer[13]  &&
  17.770 +	       additional2[i].code2_max <= sense_buffer[13]) {
  17.771 +		printk("Additional sense indicates ");
  17.772 +		printk(additional2[i].text, sense_buffer[13]);
  17.773 +		printk("\n");
  17.774 +	    };
  17.775 +#else
  17.776 +	printk("ASC=%2x ASCQ=%2x\n", sense_buffer[12], sense_buffer[13]);
  17.777 +#endif
  17.778 +    } else {	/* non-extended sense data */
  17.779 +
  17.780 +         /*
  17.781 +          * Standard says:
  17.782 +          *    sense_buffer[0] & 0200 : address valid
  17.783 +          *    sense_buffer[0] & 0177 : vendor-specific error code
  17.784 +          *    sense_buffer[1] & 0340 : vendor-specific
  17.785 +          *    sense_buffer[1..3] : 21-bit logical block address
  17.786 +          */
  17.787 +	
  17.788 +#if (CONSTANTS & CONST_SENSE)
  17.789 +	if (sense_buffer[0] < 15)
  17.790 +	    printk("%s%s: old sense key %s\n", devclass,
  17.791 +	      kdevname(dev), snstext[sense_buffer[0] & 0x0f]);
  17.792 +	else
  17.793 +#endif
  17.794 +	    printk("%s%s: sns = %2x %2x\n", devclass,
  17.795 +	      kdevname(dev), sense_buffer[0], sense_buffer[2]);
  17.796 +	
  17.797 +	printk("Non-extended sense class %d code 0x%0x\n", sense_class, code);
  17.798 +	s = 4;
  17.799 +    }
  17.800 +    
  17.801 + done:
  17.802 +#if !(CONSTANTS & CONST_SENSE)
  17.803 +    printk("Raw sense data:");
  17.804 +    for (i = 0; i < s; ++i) 
  17.805 +	printk("0x%02x ", sense_buffer[i]);
  17.806 +    printk("\n");
  17.807 +#endif
  17.808 +    return;
  17.809 +}
  17.810 +
  17.811 +void print_sense(const char * devclass, Scsi_Cmnd * SCpnt)
  17.812 +{
  17.813 +	print_sense_internal(devclass, SCpnt->sense_buffer,
  17.814 +			     SCpnt->request.rq_dev);
  17.815 +}
  17.816 +
  17.817 +void print_req_sense(const char * devclass, Scsi_Request * SRpnt)
  17.818 +{
  17.819 +	print_sense_internal(devclass, SRpnt->sr_sense_buffer,
  17.820 +			     SRpnt->sr_request.rq_dev);
  17.821 +}
  17.822 +
  17.823 +#if (CONSTANTS & CONST_MSG) 
  17.824 +static const char *one_byte_msgs[] = {
  17.825 +/* 0x00 */ "Command Complete", NULL, "Save Pointers",
  17.826 +/* 0x03 */ "Restore Pointers", "Disconnect", "Initiator Error", 
  17.827 +/* 0x06 */ "Abort", "Message Reject", "Nop", "Message Parity Error",
  17.828 +/* 0x0a */ "Linked Command Complete", "Linked Command Complete w/flag",
  17.829 +/* 0x0c */ "Bus device reset", "Abort Tag", "Clear Queue", 
  17.830 +/* 0x0f */ "Initiate Recovery", "Release Recovery"
  17.831 +};
  17.832 +
  17.833 +#define NO_ONE_BYTE_MSGS (sizeof(one_byte_msgs)  / sizeof (const char *))
  17.834 +
  17.835 +static const char *two_byte_msgs[] = {
  17.836 +/* 0x20 */ "Simple Queue Tag", "Head of Queue Tag", "Ordered Queue Tag"
  17.837 +/* 0x23 */ "Ignore Wide Residue"
  17.838 +};
  17.839 +
  17.840 +#define NO_TWO_BYTE_MSGS (sizeof(two_byte_msgs)  / sizeof (const char *))
  17.841 +
  17.842 +static const char *extended_msgs[] = {
  17.843 +/* 0x00 */ "Modify Data Pointer", "Synchronous Data Transfer Request",
  17.844 +/* 0x02 */ "SCSI-I Extended Identify", "Wide Data Transfer Request"
  17.845 +};
  17.846 +
  17.847 +#define NO_EXTENDED_MSGS (sizeof(two_byte_msgs)  / sizeof (const char *))
  17.848 +#endif /* (CONSTANTS & CONST_MSG) */
  17.849 +
  17.850 +int print_msg (const unsigned char *msg) {
  17.851 +    int len = 0, i;
  17.852 +    if (msg[0] == EXTENDED_MESSAGE) {
  17.853 +	len = 3 + msg[1];
  17.854 +#if (CONSTANTS & CONST_MSG)
  17.855 +	if (msg[2] < NO_EXTENDED_MSGS)
  17.856 +	    printk ("%s ", extended_msgs[msg[2]]); 
  17.857 +	else 
  17.858 +	    printk ("Extended Message, reserved code (0x%02x) ", (int) msg[2]);
  17.859 +	switch (msg[2]) {
  17.860 +	case EXTENDED_MODIFY_DATA_POINTER:
  17.861 +	    printk("pointer = %d", (int) (msg[3] << 24) | (msg[4] << 16) | 
  17.862 +		   (msg[5] << 8) | msg[6]);
  17.863 +	    break;
  17.864 +	case EXTENDED_SDTR:
  17.865 +	    printk("period = %d ns, offset = %d", (int) msg[3] * 4, (int) 
  17.866 +		   msg[4]);
  17.867 +	    break;
  17.868 +	case EXTENDED_WDTR:
  17.869 +	    printk("width = 2^%d bytes", msg[3]);
  17.870 +	    break;
  17.871 +	default:
  17.872 +	    for (i = 2; i < len; ++i) 
  17.873 +		printk("%02x ", msg[i]);
  17.874 +	}
  17.875 +#else
  17.876 +	for (i = 0; i < len; ++i)
  17.877 +	    printk("%02x ", msg[i]);
  17.878 +#endif
  17.879 +	/* Identify */
  17.880 +    } else if (msg[0] & 0x80) {
  17.881 +#if (CONSTANTS & CONST_MSG)
  17.882 +	printk("Identify disconnect %sallowed %s %d ",
  17.883 +	       (msg[0] & 0x40) ? "" : "not ",
  17.884 +	       (msg[0] & 0x20) ? "target routine" : "lun",
  17.885 +	       msg[0] & 0x7);
  17.886 +#else
  17.887 +	printk("%02x ", msg[0]);
  17.888 +#endif
  17.889 +	len = 1;
  17.890 +	/* Normal One byte */
  17.891 +    } else if (msg[0] < 0x1f) {
  17.892 +#if (CONSTANTS & CONST_MSG)
  17.893 +	if (msg[0] < NO_ONE_BYTE_MSGS)
  17.894 +	    printk(one_byte_msgs[msg[0]]);
  17.895 +	else
  17.896 +	    printk("reserved (%02x) ", msg[0]);
  17.897 +#else
  17.898 +	printk("%02x ", msg[0]);
  17.899 +#endif
  17.900 +	len = 1;
  17.901 +	/* Two byte */
  17.902 +    } else if (msg[0] <= 0x2f) {
  17.903 +#if (CONSTANTS & CONST_MSG)
  17.904 +	if ((msg[0] - 0x20) < NO_TWO_BYTE_MSGS)
  17.905 +	    printk("%s %02x ", two_byte_msgs[msg[0] - 0x20], 
  17.906 +		   msg[1]);
  17.907 +	else 
  17.908 +	    printk("reserved two byte (%02x %02x) ", 
  17.909 +		   msg[0], msg[1]);
  17.910 +#else
  17.911 +	printk("%02x %02x", msg[0], msg[1]);
  17.912 +#endif
  17.913 +	len = 2;
  17.914 +    } else 
  17.915 +#if (CONSTANTS & CONST_MSG)
  17.916 +	printk(reserved);
  17.917 +#else
  17.918 +    printk("%02x ", msg[0]);
  17.919 +#endif
  17.920 +    return len;
  17.921 +}
  17.922 +
  17.923 +void print_Scsi_Cmnd (Scsi_Cmnd *cmd) {
  17.924 +    printk("scsi%d : destination target %d, lun %d\n", 
  17.925 +	   cmd->host->host_no, 
  17.926 +	   cmd->target, 
  17.927 +	   cmd->lun);
  17.928 +    printk("        command = ");
  17.929 +    print_command (cmd->cmnd);
  17.930 +}
  17.931 +
  17.932 +#if (CONSTANTS & CONST_HOST)
  17.933 +static const char * hostbyte_table[]={
  17.934 +"DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", "DID_BAD_TARGET", 
  17.935 +"DID_ABORT", "DID_PARITY", "DID_ERROR", "DID_RESET", "DID_BAD_INTR",
  17.936 +"DID_PASSTHROUGH", "DID_SOFT_ERROR", NULL};
  17.937 +
  17.938 +void print_hostbyte(int scsiresult)
  17.939 +{   static int maxcode=0;
  17.940 +    int i;
  17.941 +   
  17.942 +    if(!maxcode) {
  17.943 +	for(i=0;hostbyte_table[i];i++) ;
  17.944 +	maxcode=i-1;
  17.945 +    }
  17.946 +    printk("Hostbyte=0x%02x",host_byte(scsiresult));
  17.947 +    if(host_byte(scsiresult)>maxcode) {
  17.948 +	printk("is invalid "); 
  17.949 +	return;
  17.950 +    }
  17.951 +    printk("(%s) ",hostbyte_table[host_byte(scsiresult)]);
  17.952 +}
  17.953 +#else
  17.954 +void print_hostbyte(int scsiresult)
  17.955 +{   printk("Hostbyte=0x%02x ",host_byte(scsiresult));
  17.956 +}
  17.957 +#endif
  17.958 +
  17.959 +#if (CONSTANTS & CONST_DRIVER)
  17.960 +static const char * driverbyte_table[]={
  17.961 +"DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT",  "DRIVER_MEDIA", "DRIVER_ERROR", 
  17.962 +"DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD",NULL };
  17.963 +
  17.964 +static const char * driversuggest_table[]={"SUGGEST_OK",
  17.965 +"SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", "SUGGEST_DIE",
  17.966 +unknown,unknown,unknown, "SUGGEST_SENSE",NULL};
  17.967 +
  17.968 +
  17.969 +void print_driverbyte(int scsiresult)
  17.970 +{   static int driver_max=0,suggest_max=0;
  17.971 +    int i,dr=driver_byte(scsiresult)&DRIVER_MASK, 
  17.972 +	su=(driver_byte(scsiresult)&SUGGEST_MASK)>>4;
  17.973 +
  17.974 +    if(!driver_max) {
  17.975 +        for(i=0;driverbyte_table[i];i++) ;
  17.976 +        driver_max=i;
  17.977 +	for(i=0;driversuggest_table[i];i++) ;
  17.978 +	suggest_max=i;
  17.979 +    }
  17.980 +    printk("Driverbyte=0x%02x",driver_byte(scsiresult));
  17.981 +    printk("(%s,%s) ",
  17.982 +	dr<driver_max  ? driverbyte_table[dr]:"invalid",
  17.983 +	su<suggest_max ? driversuggest_table[su]:"invalid");
  17.984 +}
  17.985 +#else
  17.986 +void print_driverbyte(int scsiresult)
  17.987 +{   printk("Driverbyte=0x%02x ",driver_byte(scsiresult));
  17.988 +}
  17.989 +#endif
  17.990 +
  17.991 +/*
  17.992 + * Overrides for Emacs so that we almost follow Linus's tabbing style.
  17.993 + * Emacs will notice this stuff at the end of the file and automatically
  17.994 + * adjust the settings for this buffer only.  This must remain at the end
  17.995 + * of the file.
  17.996 + * ---------------------------------------------------------------------------
  17.997 + * Local variables:
  17.998 + * c-indent-level: 4
  17.999 + * c-brace-imaginary-offset: 0
 17.1000 + * c-brace-offset: -4
 17.1001 + * c-argdecl-indent: 4
 17.1002 + * c-label-offset: -4
 17.1003 + * c-continued-statement-offset: 4
 17.1004 + * c-continued-brace-offset: 0
 17.1005 + * indent-tabs-mode: nil
 17.1006 + * tab-width: 8
 17.1007 + * End:
 17.1008 + */
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/xen-2.4.16/drivers/scsi/hosts.c	Fri Feb 21 15:10:37 2003 +0000
    18.3 @@ -0,0 +1,316 @@
    18.4 +/*
    18.5 + *  hosts.c Copyright (C) 1992 Drew Eckhardt
    18.6 + *          Copyright (C) 1993, 1994, 1995 Eric Youngdale
    18.7 + *
    18.8 + *  mid to lowlevel SCSI driver interface
    18.9 + *      Initial versions: Drew Eckhardt
   18.10 + *      Subsequent revisions: Eric Youngdale
   18.11 + *
   18.12 + *  <drew@colorado.edu>
   18.13 + *
   18.14 + *  Jiffies wrap fixes (host->resetting), 3 Dec 1998 Andrea Arcangeli
   18.15 + *  Added QLOGIC QLA1280 SCSI controller kernel host support. 
   18.16 + *     August 4, 1999 Fred Lewis, Intel DuPont
   18.17 + *
   18.18 + *  Updated to reflect the new initialization scheme for the higher 
   18.19 + *  level of scsi drivers (sd/sr/st)
   18.20 + *  September 17, 2000 Torben Mathiasen <tmm@image.dk>
   18.21 + */
   18.22 +
   18.23 +
   18.24 +/*
   18.25 + *  This file contains the medium level SCSI
   18.26 + *  host interface initialization, as well as the scsi_hosts array of SCSI
   18.27 + *  hosts currently present in the system.
   18.28 + */
   18.29 +
   18.30 +#define __NO_VERSION__
   18.31 +#include <xeno/module.h>
   18.32 +#include <xeno/blk.h>
   18.33 +/*  #include <xeno/kernel.h> */
   18.34 +/*  #include <xeno/string.h> */
   18.35 +/*  #include <xeno/mm.h> */
   18.36 +/*  #include <xeno/proc_fs.h> */
   18.37 +#include <xeno/init.h>
   18.38 +
   18.39 +#define __KERNEL_SYSCALLS__
   18.40 +
   18.41 +/* #include <xeno/unistd.h> */
   18.42 +
   18.43 +#include "scsi.h"
   18.44 +#include "hosts.h"
   18.45 +
   18.46 +/*
   18.47 +static const char RCSid[] = "$Header: /vger/u4/cvs/linux/drivers/scsi/hosts.c,v 1.20 1996/12/12 19:18:32 davem Exp $";
   18.48 +*/
   18.49 +
   18.50 +/*
   18.51 + *  The scsi host entries should be in the order you wish the
   18.52 + *  cards to be detected.  A driver may appear more than once IFF
   18.53 + *  it can deal with being detected (and therefore initialized)
   18.54 + *  with more than one simultaneous host number, can handle being
   18.55 + *  reentrant, etc.
   18.56 + *
   18.57 + *  They may appear in any order, as each SCSI host is told which host 
   18.58 + *  number it is during detection.
   18.59 + */
   18.60 +
   18.61 +/* This is a placeholder for controllers that are not configured into
   18.62 + * the system - we do this to ensure that the controller numbering is
   18.63 + * always consistent, no matter how the kernel is configured. */
   18.64 +
   18.65 +#define NO_CONTROLLER {NULL, NULL, NULL, NULL, NULL, NULL, NULL, \
   18.66 +			   NULL, NULL, 0, 0, 0, 0, 0, 0}
   18.67 +
   18.68 +/*
   18.69 + *  When figure is run, we don't want to link to any object code.  Since
   18.70 + *  the macro for each host will contain function pointers, we cannot
   18.71 + *  use it and instead must use a "blank" that does no such
   18.72 + *  idiocy.
   18.73 + */
   18.74 +
   18.75 +Scsi_Host_Template * scsi_hosts;
   18.76 +
   18.77 +
   18.78 +/*
   18.79 + *  Our semaphores and timeout counters, where size depends on 
   18.80 + *      MAX_SCSI_HOSTS here.
   18.81 + */
   18.82 +
   18.83 +Scsi_Host_Name * scsi_host_no_list;
   18.84 +struct Scsi_Host * scsi_hostlist;
   18.85 +struct Scsi_Device_Template * scsi_devicelist;
   18.86 +
   18.87 +int max_scsi_hosts;
   18.88 +int next_scsi_host;
   18.89 +
   18.90 +void
   18.91 +scsi_unregister(struct Scsi_Host * sh){
   18.92 +    struct Scsi_Host * shpnt;
   18.93 +    Scsi_Host_Name *shn;
   18.94 +        
   18.95 +    if(scsi_hostlist == sh)
   18.96 +	scsi_hostlist = sh->next;
   18.97 +    else {
   18.98 +	shpnt = scsi_hostlist;
   18.99 +	while(shpnt->next != sh) shpnt = shpnt->next;
  18.100 +	shpnt->next = shpnt->next->next;
  18.101 +    }
  18.102 +
  18.103 +    /*
  18.104 +     * We have to unregister the host from the scsi_host_no_list as well.
  18.105 +     * Decide by the host_no not by the name because most host drivers are
  18.106 +     * able to handle more than one adapters from the same kind (or family).
  18.107 +     */
  18.108 +    for ( shn=scsi_host_no_list; shn && (sh->host_no != shn->host_no);
  18.109 +	  shn=shn->next);
  18.110 +    if (shn) shn->host_registered = 0;
  18.111 +    /* else {} : This should not happen, we should panic here... */
  18.112 +    
  18.113 +    /* If we are removing the last host registered, it is safe to reuse
  18.114 +     * its host number (this avoids "holes" at boot time) (DB) 
  18.115 +     * It is also safe to reuse those of numbers directly below which have
  18.116 +     * been released earlier (to avoid some holes in numbering).
  18.117 +     */
  18.118 +    if(sh->host_no == max_scsi_hosts - 1) {
  18.119 +	while(--max_scsi_hosts >= next_scsi_host) {
  18.120 +	    shpnt = scsi_hostlist;
  18.121 +	    while(shpnt && shpnt->host_no != max_scsi_hosts - 1)
  18.122 +		shpnt = shpnt->next;
  18.123 +	    if(shpnt)
  18.124 +		break;
  18.125 +	}
  18.126 +    }
  18.127 +    next_scsi_host--;
  18.128 +    kfree((char *) sh);
  18.129 +}
  18.130 +
  18.131 +/* We call this when we come across a new host adapter. We only do this
  18.132 + * once we are 100% sure that we want to use this host adapter -  it is a
  18.133 + * pain to reverse this, so we try to avoid it 
  18.134 + */
  18.135 +
  18.136 +struct Scsi_Host * scsi_register(Scsi_Host_Template * tpnt, int j){
  18.137 +    struct Scsi_Host * retval, *shpnt, *o_shp;
  18.138 +    Scsi_Host_Name *shn, *shn2;
  18.139 +    int flag_new = 1;
  18.140 +    const char * hname;
  18.141 +    size_t hname_len;
  18.142 +    retval = (struct Scsi_Host *)kmalloc(sizeof(struct Scsi_Host) + j,
  18.143 +					 (tpnt->unchecked_isa_dma && j ? 
  18.144 +					  GFP_DMA : 0) | GFP_ATOMIC);
  18.145 +    if(retval == NULL)
  18.146 +    {
  18.147 +        printk("scsi: out of memory in scsi_register.\n");
  18.148 +    	return NULL;
  18.149 +    }
  18.150 +    	
  18.151 +    memset(retval, 0, sizeof(struct Scsi_Host) + j);
  18.152 +
  18.153 +    /* trying to find a reserved entry (host_no) */
  18.154 +    hname = (tpnt->proc_name) ?  tpnt->proc_name : "";
  18.155 +    hname_len = strlen(hname);
  18.156 +    for (shn = scsi_host_no_list;shn;shn = shn->next) {
  18.157 +	if (!(shn->host_registered) && 
  18.158 +	    (hname_len > 0) && (0 == strncmp(hname, shn->name, hname_len))) {
  18.159 +	    flag_new = 0;
  18.160 +	    retval->host_no = shn->host_no;
  18.161 +	    shn->host_registered = 1;
  18.162 +	    shn->loaded_as_module = 1;
  18.163 +	    break;
  18.164 +	}
  18.165 +    }
  18.166 +    atomic_set(&retval->host_active,0);
  18.167 +    retval->host_busy = 0;
  18.168 +    retval->host_failed = 0;
  18.169 +    if(j > 0xffff) panic("Too many extra bytes requested\n");
  18.170 +    retval->extra_bytes = j;
  18.171 +    retval->loaded_as_module = 1;
  18.172 +    if (flag_new) {
  18.173 +	shn = (Scsi_Host_Name *) kmalloc(sizeof(Scsi_Host_Name), GFP_ATOMIC);
  18.174 +        if (!shn) {
  18.175 +                kfree(retval);
  18.176 +                printk(KERN_ERR "scsi: out of memory(2) in scsi_register.\n");
  18.177 +                return NULL;
  18.178 +        }
  18.179 +	shn->name = kmalloc(hname_len + 1, GFP_ATOMIC);
  18.180 +	if (hname_len > 0)
  18.181 +	    strncpy(shn->name, hname, hname_len);
  18.182 +	shn->name[hname_len] = 0;
  18.183 +	shn->host_no = max_scsi_hosts++;
  18.184 +	shn->host_registered = 1;
  18.185 +	shn->loaded_as_module = 1;
  18.186 +	shn->next = NULL;
  18.187 +	if (scsi_host_no_list) {
  18.188 +	    for (shn2 = scsi_host_no_list;shn2->next;shn2 = shn2->next)
  18.189 +		;
  18.190 +	    shn2->next = shn;
  18.191 +	}
  18.192 +	else
  18.193 +	    scsi_host_no_list = shn;
  18.194 +	retval->host_no = shn->host_no;
  18.195 +    }
  18.196 +    next_scsi_host++;
  18.197 +    retval->host_queue = NULL;
  18.198 +#if 0
  18.199 +    init_waitqueue_head(&retval->host_wait);
  18.200 +#endif
  18.201 +    retval->resetting = 0;
  18.202 +    retval->last_reset = 0;
  18.203 +    retval->irq = 0;
  18.204 +    retval->dma_channel = 0xff;
  18.205 +
  18.206 +    /* These three are default values which can be overridden */
  18.207 +    retval->max_channel = 0; 
  18.208 +    retval->max_id = 8;      
  18.209 +    retval->max_lun = 8;
  18.210 +
  18.211 +    /*
  18.212 +     * All drivers right now should be able to handle 12 byte commands.
  18.213 +     * Every so often there are requests for 16 byte commands, but individual
  18.214 +     * low-level drivers need to certify that they actually do something
  18.215 +     * sensible with such commands.
  18.216 +     */
  18.217 +    retval->max_cmd_len = 12;
  18.218 +
  18.219 +    retval->unique_id = 0;
  18.220 +    retval->io_port = 0;
  18.221 +    retval->hostt = tpnt;
  18.222 +    retval->next = NULL;
  18.223 +    retval->in_recovery = 0;
  18.224 +    retval->ehandler = NULL;    /* Initial value until the thing starts up. */
  18.225 +    retval->eh_notify   = NULL;    /* Who we notify when we exit. */
  18.226 +
  18.227 +
  18.228 +    retval->host_blocked = FALSE;
  18.229 +    retval->host_self_blocked = FALSE;
  18.230 +
  18.231 +#ifdef DEBUG
  18.232 +    printk("Register %x %x: %d\n", (int)retval, (int)retval->hostt, j);
  18.233 +#endif
  18.234 +
  18.235 +    /* The next six are the default values which can be overridden
  18.236 +     * if need be */
  18.237 +    retval->this_id = tpnt->this_id;
  18.238 +    retval->can_queue = tpnt->can_queue;
  18.239 +    retval->sg_tablesize = tpnt->sg_tablesize;
  18.240 +    retval->cmd_per_lun = tpnt->cmd_per_lun;
  18.241 +    retval->unchecked_isa_dma = tpnt->unchecked_isa_dma;
  18.242 +    retval->use_clustering = tpnt->use_clustering;   
  18.243 +
  18.244 +    retval->select_queue_depths = tpnt->select_queue_depths;
  18.245 +    retval->max_sectors = tpnt->max_sectors;
  18.246 +
  18.247 +    if(!scsi_hostlist)
  18.248 +	scsi_hostlist = retval;
  18.249 +    else {
  18.250 +	shpnt = scsi_hostlist;
  18.251 +	if (retval->host_no < shpnt->host_no) {
  18.252 +	    retval->next = shpnt;
  18.253 +	    wmb(); /* want all to see these writes in this order */
  18.254 +	    scsi_hostlist = retval;
  18.255 +	}
  18.256 +	else {
  18.257 +	    for (o_shp = shpnt, shpnt = shpnt->next; shpnt; 
  18.258 +		 o_shp = shpnt, shpnt = shpnt->next) {
  18.259 +		if (retval->host_no < shpnt->host_no) {
  18.260 +		    retval->next = shpnt;
  18.261 +		    wmb();
  18.262 +		    o_shp->next = retval;
  18.263 +		    break;
  18.264 +		}
  18.265 +	    }
  18.266 +	    if (! shpnt)
  18.267 +		o_shp->next = retval;
  18.268 +        }
  18.269 +    }
  18.270 +    
  18.271 +    return retval;
  18.272 +}
  18.273 +
  18.274 +int
  18.275 +scsi_register_device(struct Scsi_Device_Template * sdpnt)
  18.276 +{
  18.277 +    if(sdpnt->next) panic("Device already registered");
  18.278 +    sdpnt->next = scsi_devicelist;
  18.279 +    scsi_devicelist = sdpnt;
  18.280 +    return 0;
  18.281 +}
  18.282 +
  18.283 +void
  18.284 +scsi_deregister_device(struct Scsi_Device_Template * tpnt)
  18.285 +{
  18.286 +    struct Scsi_Device_Template *spnt;
  18.287 +    struct Scsi_Device_Template *prev_spnt;
  18.288 +
  18.289 +    spnt = scsi_devicelist;
  18.290 +    prev_spnt = NULL;
  18.291 +    while (spnt != tpnt) {
  18.292 +    prev_spnt = spnt;
  18.293 +    spnt = spnt->next;
  18.294 +    }
  18.295 +    if (prev_spnt == NULL)
  18.296 +        scsi_devicelist = tpnt->next;
  18.297 +    else
  18.298 +        prev_spnt->next = spnt->next;
  18.299 +}
  18.300 +
  18.301 +
  18.302 +/*
  18.303 + * Overrides for Emacs so that we follow Linus's tabbing style.
  18.304 + * Emacs will notice this stuff at the end of the file and automatically
  18.305 + * adjust the settings for this buffer only.  This must remain at the end
  18.306 + * of the file.
  18.307 + * ---------------------------------------------------------------------------
  18.308 + * Local variables:
  18.309 + * c-indent-level: 4
  18.310 + * c-brace-imaginary-offset: 0
  18.311 + * c-brace-offset: -4
  18.312 + * c-argdecl-indent: 4
  18.313 + * c-label-offset: -4
  18.314 + * c-continued-statement-offset: 4
  18.315 + * c-continued-brace-offset: 0
  18.316 + * indent-tabs-mode: nil
  18.317 + * tab-width: 8
  18.318 + * End:
  18.319 + */
    19.1 --- a/xen-2.4.16/drivers/scsi/hosts.h	Fri Feb 21 14:25:47 2003 +0000
    19.2 +++ b/xen-2.4.16/drivers/scsi/hosts.h	Fri Feb 21 15:10:37 2003 +0000
    19.3 @@ -64,6 +64,7 @@ typedef struct	SHT
    19.4      /* Used with loadable modules so that we know when it is safe to unload */
    19.5      struct module * module;
    19.6  
    19.7 +#ifdef CONFIG_PROC_FS
    19.8      /* The pointer to the /proc/scsi directory entry */
    19.9      struct proc_dir_entry *proc_dir;
   19.10  
   19.11 @@ -73,6 +74,7 @@ typedef struct	SHT
   19.12       * to feed the driver with information. Check eata_dma_proc.c for reference
   19.13       */
   19.14      int (*proc_info)(char *, char **, off_t, int, int, int);
   19.15 +#endif
   19.16  
   19.17      /*
   19.18       * The name pointer is a pointer to the name of the SCSI
   19.19 @@ -326,7 +328,9 @@ struct Scsi_Host
   19.20                                            host. */
   19.21      unsigned int            eh_active:1; /* Indicates the eh thread is awake and active if
   19.22                                            this is true. */
   19.23 +#if 0 
   19.24      wait_queue_head_t       host_wait;
   19.25 +#endif
   19.26      Scsi_Host_Template    * hostt;
   19.27      atomic_t                host_active; /* commands checked out */
   19.28      volatile unsigned short host_busy;   /* commands actually active on low-level */
   19.29 @@ -528,9 +532,11 @@ void  scsi_initialize_queue(Scsi_Device 
   19.30  int scsi_register_device(struct Scsi_Device_Template * sdpnt);
   19.31  void scsi_deregister_device(struct Scsi_Device_Template * tpnt);
   19.32  
   19.33 +#if 0 
   19.34  /* These are used by loadable modules */
   19.35  extern int scsi_register_module(int, void *);
   19.36  extern int scsi_unregister_module(int, void *);
   19.37 +#endif
   19.38  
   19.39  /* The different types of modules that we can load and unload */
   19.40  #define MODULE_SCSI_HA 1
    20.1 --- a/xen-2.4.16/drivers/scsi/scsi.c	Fri Feb 21 14:25:47 2003 +0000
    20.2 +++ b/xen-2.4.16/drivers/scsi/scsi.c	Fri Feb 21 15:10:37 2003 +0000
    20.3 @@ -149,6 +149,7 @@ const char *const scsi_device_types[MAX_
    20.4  extern void scsi_times_out(Scsi_Cmnd * SCpnt);
    20.5  void scsi_build_commandblocks(Scsi_Device * SDpnt);
    20.6  
    20.7 +#if 0
    20.8  /*
    20.9   * These are the interface to the old error handling code.  It should go away
   20.10   * someday soon.
   20.11 @@ -156,6 +157,7 @@ void scsi_build_commandblocks(Scsi_Devic
   20.12  extern void scsi_old_done(Scsi_Cmnd * SCpnt);
   20.13  extern void scsi_old_times_out(Scsi_Cmnd * SCpnt);
   20.14  extern int scsi_old_reset(Scsi_Cmnd *SCpnt, unsigned int flag);
   20.15 +#endif
   20.16  
   20.17  /* 
   20.18   * Private interface into the new error handling code.
   20.19 @@ -201,21 +203,24 @@ MODULE_PARM(scsi_logging_level, "i");
   20.20  MODULE_PARM_DESC(scsi_logging_level, "SCSI logging level; should be zero or nonzero");
   20.21  
   20.22  #else
   20.23 -
   20.24  static int __init scsi_logging_setup(char *str)
   20.25  {
   20.26 -	int tmp;
   20.27 +#if 0
   20.28 +    int tmp;
   20.29 +    
   20.30 +    if (get_option(&str, &tmp) == 1) {
   20.31 +        scsi_logging_level = (tmp ? ~0 : 0);
   20.32 +        return 1;
   20.33 +    } else {
   20.34 +        printk(KERN_INFO "scsi_logging_setup : usage scsi_logging_level=n "
   20.35 +               "(n should be 0 or non-zero)\n");
   20.36 +        return 0;
   20.37 +    }
   20.38 +#else
   20.39 +    return 0; 
   20.40 +#endif
   20.41  
   20.42 -	if (get_option(&str, &tmp) == 1) {
   20.43 -		scsi_logging_level = (tmp ? ~0 : 0);
   20.44 -		return 1;
   20.45 -	} else {
   20.46 -		printk(KERN_INFO "scsi_logging_setup : usage scsi_logging_level=n "
   20.47 -		       "(n should be 0 or non-zero)\n");
   20.48 -		return 0;
   20.49 -	}
   20.50  }
   20.51 -
   20.52  __setup("scsi_logging=", scsi_logging_setup);
   20.53  
   20.54  #endif
   20.55 @@ -226,14 +231,16 @@ static int __init scsi_logging_setup(cha
   20.56   
   20.57  static void scsi_wait_done(Scsi_Cmnd * SCpnt)
   20.58  {
   20.59 -	struct request *req;
   20.60 -
   20.61 -	req = &SCpnt->request;
   20.62 -	req->rq_status = RQ_SCSI_DONE;	/* Busy, but indicate request done */
   20.63 -
   20.64 -	if (req->waiting != NULL) {
   20.65 -		complete(req->waiting);
   20.66 -	}
   20.67 +    struct request *req;
   20.68 +    
   20.69 +    req = &SCpnt->request;
   20.70 +    req->rq_status = RQ_SCSI_DONE;	/* Busy, but indicate request done */
   20.71 +    
   20.72 +#if 0
   20.73 +    if (req->waiting != NULL) {
   20.74 +        complete(req->waiting);
   20.75 +    }
   20.76 +#endif
   20.77  }
   20.78  
   20.79  /*
   20.80 @@ -269,24 +276,24 @@ static spinlock_t scsi_bhqueue_lock = SP
   20.81  
   20.82  Scsi_Request *scsi_allocate_request(Scsi_Device * device)
   20.83  {
   20.84 -  	Scsi_Request *SRpnt = NULL;
   20.85 -  
   20.86 -  	if (!device)
   20.87 -  		panic("No device passed to scsi_allocate_request().\n");
   20.88 -  
   20.89 -	SRpnt = (Scsi_Request *) kmalloc(sizeof(Scsi_Request), GFP_ATOMIC);
   20.90 -	if( SRpnt == NULL )
   20.91 -	{
   20.92 -		return NULL;
   20.93 -	}
   20.94 -
   20.95 -	memset(SRpnt, 0, sizeof(Scsi_Request));
   20.96 -	SRpnt->sr_device = device;
   20.97 -	SRpnt->sr_host = device->host;
   20.98 -	SRpnt->sr_magic = SCSI_REQ_MAGIC;
   20.99 -	SRpnt->sr_data_direction = SCSI_DATA_UNKNOWN;
  20.100 -
  20.101 -	return SRpnt;
  20.102 +    Scsi_Request *SRpnt = NULL;
  20.103 +    
  20.104 +    if (!device)
  20.105 +        panic("No device passed to scsi_allocate_request().\n");
  20.106 +    
  20.107 +    SRpnt = (Scsi_Request *) kmalloc(sizeof(Scsi_Request), GFP_ATOMIC);
  20.108 +    if( SRpnt == NULL )
  20.109 +    {
  20.110 +        return NULL;
  20.111 +    }
  20.112 +    
  20.113 +    memset(SRpnt, 0, sizeof(Scsi_Request));
  20.114 +    SRpnt->sr_device = device;
  20.115 +    SRpnt->sr_host = device->host;
  20.116 +    SRpnt->sr_magic = SCSI_REQ_MAGIC;
  20.117 +    SRpnt->sr_data_direction = SCSI_DATA_UNKNOWN;
  20.118 +    
  20.119 +    return SRpnt;
  20.120  }
  20.121  
  20.122  /*
  20.123 @@ -308,13 +315,20 @@ Scsi_Request *scsi_allocate_request(Scsi
  20.124   */
  20.125  void scsi_release_request(Scsi_Request * req)
  20.126  {
  20.127 -	if( req->sr_command != NULL )
  20.128 -	{
  20.129 -		scsi_release_command(req->sr_command);
  20.130 -		req->sr_command = NULL;
  20.131 -	}
  20.132 -
  20.133 -	kfree(req);
  20.134 +    if( req->sr_command != NULL )
  20.135 +    {
  20.136 +#ifdef SMH_DEBUG
  20.137 +        printk("scsi_release_request: req->sr_command = %p\n", 
  20.138 +                   req->sr_command); 
  20.139 +#endif
  20.140 +        scsi_release_command(req->sr_command);
  20.141 +        req->sr_command = NULL;
  20.142 +#ifdef SMHHACK 
  20.143 +        req->freeaddr = 0x1234; 
  20.144 +#endif
  20.145 +    }
  20.146 +    
  20.147 +    kfree(req);
  20.148  }
  20.149  
  20.150  /*
  20.151 @@ -425,6 +439,9 @@ Scsi_Cmnd *scsi_allocate_device(Scsi_Dev
  20.152  		 * wait here.
  20.153  		 */
  20.154  		if (wait) {
  20.155 +                    printk("XXX smh: scsi cannot wait for free cmd block.\n"); 
  20.156 +                    BUG(); 
  20.157 +#if 0 
  20.158                          DECLARE_WAITQUEUE(wait, current);
  20.159  
  20.160                          /*
  20.161 @@ -471,6 +488,7 @@ Scsi_Cmnd *scsi_allocate_device(Scsi_Dev
  20.162                                          return NULL;
  20.163                                  }
  20.164                          }
  20.165 +#endif
  20.166  		} else {
  20.167                          spin_unlock_irqrestore(&device_request_lock, flags);
  20.168  			return NULL;
  20.169 @@ -546,17 +564,22 @@ inline void __scsi_release_command(Scsi_
  20.170  	    && SCpnt->host->host_busy == SCpnt->host->host_failed) {
  20.171  		SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n",
  20.172  			     atomic_read(&SCpnt->host->eh_wait->count)));
  20.173 +#if 0
  20.174  		up(SCpnt->host->eh_wait);
  20.175 +#endif
  20.176  	}
  20.177  
  20.178  	spin_unlock_irqrestore(&device_request_lock, flags);
  20.179  
  20.180 +#if 0
  20.181          /*
  20.182           * Wake up anyone waiting for this device.  Do this after we
  20.183           * have released the lock, as they will need it as soon as
  20.184           * they wake up.  
  20.185           */
  20.186  	wake_up(&SDpnt->scpnt_wait);
  20.187 +#endif
  20.188 +
  20.189  }
  20.190  
  20.191  /*
  20.192 @@ -667,8 +690,10 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
  20.193  	if (host->hostt->use_new_eh_code) {
  20.194  		scsi_add_timer(SCpnt, SCpnt->timeout_per_command, scsi_times_out);
  20.195  	} else {
  20.196 +#if 0
  20.197  		scsi_add_timer(SCpnt, SCpnt->timeout_per_command,
  20.198  			       scsi_old_times_out);
  20.199 +#endif
  20.200  	}
  20.201  
  20.202  	/*
  20.203 @@ -717,7 +742,8 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
  20.204  			 * Before we queue this command, check if the command
  20.205  			 * length exceeds what the host adapter can handle.
  20.206  			 */
  20.207 -			if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
  20.208 +#if 0
  20.209 +                    if (CDB_SIZE(SCpnt) <= SCpnt->host->max_cmd_len) {
  20.210  				spin_lock_irqsave(&io_request_lock, flags);
  20.211  				host->hostt->queuecommand(SCpnt, scsi_old_done);
  20.212  				spin_unlock_irqrestore(&io_request_lock, flags);
  20.213 @@ -729,6 +755,8 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
  20.214  				spin_unlock_irqrestore(&io_request_lock, flags);
  20.215  				rtn = 1;
  20.216  			}
  20.217 +#endif
  20.218 +
  20.219  		}
  20.220  	} else {
  20.221  		int temp;
  20.222 @@ -751,7 +779,9 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
  20.223  		if (host->hostt->use_new_eh_code) {
  20.224  			scsi_done(SCpnt);
  20.225  		} else {
  20.226 +#if 0
  20.227  			scsi_old_done(SCpnt);
  20.228 +#endif
  20.229  		}
  20.230                  spin_unlock_irqrestore(&io_request_lock, flags);
  20.231  	}
  20.232 @@ -759,7 +789,9 @@ int scsi_dispatch_cmd(Scsi_Cmnd * SCpnt)
  20.233  	return rtn;
  20.234  }
  20.235  
  20.236 +#ifdef DEVFS_MUST_DIE
  20.237  devfs_handle_t scsi_devfs_handle;
  20.238 +#endif
  20.239  
  20.240  /*
  20.241   * scsi_do_cmd sends all the commands out to the low-level driver.  It
  20.242 @@ -772,22 +804,50 @@ void scsi_wait_req (Scsi_Request * SRpnt
  20.243   		  void *buffer, unsigned bufflen, 
  20.244   		  int timeout, int retries)
  20.245  {
  20.246 -	DECLARE_COMPLETION(wait);
  20.247 -	request_queue_t *q = &SRpnt->sr_device->request_queue;
  20.248 -	
  20.249 -	SRpnt->sr_request.waiting = &wait;
  20.250 -	SRpnt->sr_request.rq_status = RQ_SCSI_BUSY;
  20.251 -	scsi_do_req (SRpnt, (void *) cmnd,
  20.252 -		buffer, bufflen, scsi_wait_done, timeout, retries);
  20.253 -	generic_unplug_device(q);
  20.254 -	wait_for_completion(&wait);
  20.255 -	SRpnt->sr_request.waiting = NULL;
  20.256 -	if( SRpnt->sr_command != NULL )
  20.257 -	{
  20.258 -		scsi_release_command(SRpnt->sr_command);
  20.259 -		SRpnt->sr_command = NULL;
  20.260 -	}
  20.261 +#if 0
  20.262 +    DECLARE_COMPLETION(wait);
  20.263 +#endif
  20.264 +
  20.265 +
  20.266 +    request_queue_t *q = &SRpnt->sr_device->request_queue;
  20.267 +    
  20.268 +#if 0
  20.269 +    SRpnt->sr_request.waiting = &wait;
  20.270 +#endif
  20.271 +
  20.272 +
  20.273 +    SRpnt->sr_request.rq_status = RQ_SCSI_BUSY;
  20.274 +    scsi_do_req (SRpnt, (void *) cmnd,
  20.275 +                 buffer, bufflen, scsi_wait_done, timeout, retries);
  20.276 +    generic_unplug_device(q);
  20.277 +
  20.278 +
  20.279 +#if 0
  20.280 +    wait_for_completion(&wait);
  20.281 +#endif
  20.282  
  20.283 +    /* XXX SMH: in 'standard' driver we think everythings ok here since
  20.284 +       we've waited on &wait -- hence we deallocate the command structure
  20.285 +       if it hasn't been done already. This is not the correct behaviour 
  20.286 +       in xen ... hmm .. how to fix? */
  20.287 +    mdelay(500); 
  20.288 +
  20.289 +
  20.290 +    SRpnt->sr_request.waiting = NULL;
  20.291 +
  20.292 +    if( SRpnt->sr_command != NULL )
  20.293 +    {
  20.294 +#ifdef SMH_DEBUG
  20.295 +        printk("scsi_wait_req: releasing SRpnt->sr_command = %p\n", 
  20.296 +               SRpnt->sr_command); 
  20.297 +#endif
  20.298 +        scsi_release_command(SRpnt->sr_command);
  20.299 +        SRpnt->sr_command = NULL;
  20.300 +#ifdef SMHHACK 
  20.301 +        SRpnt->freeaddr = 0x99991234; 
  20.302 +#endif
  20.303 +    }
  20.304 +    
  20.305  }
  20.306   
  20.307  /*
  20.308 @@ -850,29 +910,40 @@ void scsi_do_req(Scsi_Request * SRpnt, c
  20.309  	 * be allocated later when this request is getting queued.
  20.310  	 */
  20.311  	if( SRpnt->sr_command != NULL )
  20.312 -	{
  20.313 +	{ 
  20.314 +#ifdef SMH_DEBUG
  20.315 +           printk("scsi_do_req: releasing SRpnt->sr_command = %p\n", 
  20.316 +                   SRpnt->sr_command); 
  20.317 +#endif
  20.318  		scsi_release_command(SRpnt->sr_command);
  20.319  		SRpnt->sr_command = NULL;
  20.320 +#ifdef SMHHACK
  20.321 +                SRpnt->freeaddr = 0xabbadead;
  20.322 +#endif
  20.323  	}
  20.324  
  20.325  	/*
  20.326 -	 * We must prevent reentrancy to the lowlevel host driver.  This prevents
  20.327 -	 * it - we enter a loop until the host we want to talk to is not busy.
  20.328 -	 * Race conditions are prevented, as interrupts are disabled in between the
  20.329 -	 * time we check for the host being not busy, and the time we mark it busy
  20.330 -	 * ourselves.
  20.331 -	 */
  20.332 +	 * We must prevent reentrancy to the lowlevel host driver.
  20.333 +	 * This prevents it - we enter a loop until the host we want
  20.334 +	 * to talk to is not busy.  Race conditions are prevented, as
  20.335 +	 * interrupts are disabled in between the time we check for
  20.336 +	 * the host being not busy, and the time we mark it busy
  20.337 +	 * ourselves.  */
  20.338  
  20.339  
  20.340  	/*
  20.341 -	 * Our own function scsi_done (which marks the host as not busy, disables
  20.342 -	 * the timeout counter, etc) will be called by us or by the
  20.343 -	 * scsi_hosts[host].queuecommand() function needs to also call
  20.344 -	 * the completion function for the high level driver.
  20.345 -	 */
  20.346 +	 * Our own function scsi_done (which marks the host as not
  20.347 +	 * busy, disables the timeout counter, etc) will be called by
  20.348 +	 * us or by the scsi_hosts[host].queuecommand() function needs
  20.349 +	 * to also call the completion function for the high level
  20.350 +	 * driver.  */
  20.351  
  20.352  	memcpy((void *) SRpnt->sr_cmnd, (const void *) cmnd, 
  20.353  	       sizeof(SRpnt->sr_cmnd));
  20.354 +#ifdef SMHHACK
  20.355 +        SRpnt->freeaddr = 0x1111; 
  20.356 +#endif
  20.357 +
  20.358  	SRpnt->sr_bufflen = bufflen;
  20.359  	SRpnt->sr_buffer = buffer;
  20.360  	SRpnt->sr_allowed = retries;
  20.361 @@ -924,6 +995,10 @@ void scsi_init_cmd_from_req(Scsi_Cmnd * 
  20.362  
  20.363  	SCpnt->owner = SCSI_OWNER_MIDLEVEL;
  20.364  	SRpnt->sr_command = SCpnt;
  20.365 +#ifdef SMH_DEBUG
  20.366 +        printk("scsi_init_cmd_from_req: SRpnt = %p, SRpnt->sr_command = %p\n", 
  20.367 +               SRpnt, SRpnt->sr_command); 
  20.368 +#endif        
  20.369  
  20.370  	if (!host) {
  20.371  		panic("Invalid or not present host.\n");
  20.372 @@ -1218,103 +1293,113 @@ void scsi_done(Scsi_Cmnd * SCpnt)
  20.373   */
  20.374  void scsi_bottom_half_handler(void)
  20.375  {
  20.376 -	Scsi_Cmnd *SCpnt;
  20.377 -	Scsi_Cmnd *SCnext;
  20.378 -	unsigned long flags;
  20.379 +    Scsi_Cmnd *SCpnt;
  20.380 +    Scsi_Cmnd *SCnext;
  20.381 +    unsigned long flags;
  20.382  
  20.383  
  20.384 -	while (1 == 1) {
  20.385 -		spin_lock_irqsave(&scsi_bhqueue_lock, flags);
  20.386 -		SCpnt = scsi_bh_queue_head;
  20.387 -		scsi_bh_queue_head = NULL;
  20.388 -		spin_unlock_irqrestore(&scsi_bhqueue_lock, flags);
  20.389 +    while (1 == 1) {
  20.390 +        spin_lock_irqsave(&scsi_bhqueue_lock, flags);
  20.391 +        SCpnt = scsi_bh_queue_head;
  20.392 +        scsi_bh_queue_head = NULL;
  20.393 +        spin_unlock_irqrestore(&scsi_bhqueue_lock, flags);
  20.394  
  20.395 -		if (SCpnt == NULL) {
  20.396 -			return;
  20.397 -		}
  20.398 -		SCnext = SCpnt->bh_next;
  20.399 +        if (SCpnt == NULL) {
  20.400 +            return;
  20.401 +        }
  20.402 +        SCnext = SCpnt->bh_next;
  20.403  
  20.404 -		for (; SCpnt; SCpnt = SCnext) {
  20.405 -			SCnext = SCpnt->bh_next;
  20.406 +        for (; SCpnt; SCpnt = SCnext) {
  20.407 +            SCnext = SCpnt->bh_next;
  20.408  
  20.409 -			switch (scsi_decide_disposition(SCpnt)) {
  20.410 -			case SUCCESS:
  20.411 -				/*
  20.412 -				 * Add to BH queue.
  20.413 -				 */
  20.414 -				SCSI_LOG_MLCOMPLETE(3, printk("Command finished %d %d 0x%x\n", SCpnt->host->host_busy,
  20.415 -						SCpnt->host->host_failed,
  20.416 -							 SCpnt->result));
  20.417 -
  20.418 -				scsi_finish_command(SCpnt);
  20.419 -				break;
  20.420 -			case NEEDS_RETRY:
  20.421 -				/*
  20.422 -				 * We only come in here if we want to retry a command.  The
  20.423 -				 * test to see whether the command should be retried should be
  20.424 -				 * keeping track of the number of tries, so we don't end up looping,
  20.425 -				 * of course.
  20.426 -				 */
  20.427 -				SCSI_LOG_MLCOMPLETE(3, printk("Command needs retry %d %d 0x%x\n", SCpnt->host->host_busy,
  20.428 -				SCpnt->host->host_failed, SCpnt->result));
  20.429 +            switch (scsi_decide_disposition(SCpnt)) {
  20.430 +            case SUCCESS:
  20.431 +                /*
  20.432 +                 * Add to BH queue.
  20.433 +                 */
  20.434 +                SCSI_LOG_MLCOMPLETE(3, 
  20.435 +                                    printk("Command finished %d %d 0x%x\n", 
  20.436 +                                           SCpnt->host->host_busy,
  20.437 +                                           SCpnt->host->host_failed,
  20.438 +                                           SCpnt->result));
  20.439 +                
  20.440 +                scsi_finish_command(SCpnt);
  20.441 +                break;
  20.442 +            case NEEDS_RETRY:
  20.443 +                /*
  20.444 +                 * We only come in here if we want to retry a command.
  20.445 +                 * The test to see whether the command should be
  20.446 +                 * retried should be keeping track of the number of
  20.447 +                 * tries, so we don't end up looping, of course.  */
  20.448 +                SCSI_LOG_MLCOMPLETE(3, 
  20.449 +                                    printk("Command needs retry %d %d 0x%x\n",
  20.450 +                                           SCpnt->host->host_busy, 
  20.451 +                                           SCpnt->host->host_failed, 
  20.452 +                                           SCpnt->result));
  20.453  
  20.454 -				scsi_retry_command(SCpnt);
  20.455 -				break;
  20.456 -			case ADD_TO_MLQUEUE:
  20.457 -				/* 
  20.458 -				 * This typically happens for a QUEUE_FULL message -
  20.459 -				 * typically only when the queue depth is only
  20.460 -				 * approximate for a given device.  Adding a command
  20.461 -				 * to the queue for the device will prevent further commands
  20.462 -				 * from being sent to the device, so we shouldn't end up
  20.463 -				 * with tons of things being sent down that shouldn't be.
  20.464 -				 */
  20.465 -				SCSI_LOG_MLCOMPLETE(3, printk("Command rejected as device queue full, put on ml queue %p\n",
  20.466 -                                                              SCpnt));
  20.467 -				scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY);
  20.468 -				break;
  20.469 -			default:
  20.470 -				/*
  20.471 -				 * Here we have a fatal error of some sort.  Turn it over to
  20.472 -				 * the error handler.
  20.473 -				 */
  20.474 -				SCSI_LOG_MLCOMPLETE(3, printk("Command failed %p %x active=%d busy=%d failed=%d\n",
  20.475 -						    SCpnt, SCpnt->result,
  20.476 -				  atomic_read(&SCpnt->host->host_active),
  20.477 -						  SCpnt->host->host_busy,
  20.478 -					      SCpnt->host->host_failed));
  20.479 -
  20.480 -				/*
  20.481 -				 * Dump the sense information too.
  20.482 -				 */
  20.483 -				if ((status_byte(SCpnt->result) & CHECK_CONDITION) != 0) {
  20.484 -					SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt));
  20.485 -				}
  20.486 -				if (SCpnt->host->eh_wait != NULL) {
  20.487 -					SCpnt->host->host_failed++;
  20.488 -					SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
  20.489 -					SCpnt->state = SCSI_STATE_FAILED;
  20.490 -					SCpnt->host->in_recovery = 1;
  20.491 -					/*
  20.492 -					 * If the host is having troubles, then look to see if this was the last
  20.493 -					 * command that might have failed.  If so, wake up the error handler.
  20.494 -					 */
  20.495 -					if (SCpnt->host->host_busy == SCpnt->host->host_failed) {
  20.496 -						SCSI_LOG_ERROR_RECOVERY(5, printk("Waking error handler thread (%d)\n",
  20.497 -										  atomic_read(&SCpnt->host->eh_wait->count)));
  20.498 -						up(SCpnt->host->eh_wait);
  20.499 -					}
  20.500 -				} else {
  20.501 -					/*
  20.502 -					 * We only get here if the error recovery thread has died.
  20.503 -					 */
  20.504 -					scsi_finish_command(SCpnt);
  20.505 -				}
  20.506 -			}
  20.507 -		}		/* for(; SCpnt...) */
  20.508 -
  20.509 -	}			/* while(1==1) */
  20.510 -
  20.511 +                scsi_retry_command(SCpnt);
  20.512 +                break;
  20.513 +            case ADD_TO_MLQUEUE:
  20.514 +                /* 
  20.515 +                 * This typically happens for a QUEUE_FULL message -
  20.516 +                 * typically only when the queue depth is only
  20.517 +                 * approximate for a given device.  Adding a command
  20.518 +                 * to the queue for the device will prevent further commands
  20.519 +                 * from being sent to the device, so we shouldn't end up
  20.520 +                 * with tons of things being sent down that shouldn't be.
  20.521 +                 */
  20.522 +                SCSI_LOG_MLCOMPLETE(3, printk(
  20.523 +                    "Cmnd rejected as device queue full, put on ml queue %p\n",
  20.524 +                    SCpnt));
  20.525 +                scsi_mlqueue_insert(SCpnt, SCSI_MLQUEUE_DEVICE_BUSY);
  20.526 +                break;
  20.527 +            default:
  20.528 +                /*
  20.529 +                 * Here we have a fatal error of some sort.  Turn it over to
  20.530 +                 * the error handler.
  20.531 +                 */
  20.532 +                SCSI_LOG_MLCOMPLETE(3, printk(
  20.533 +                    "Command failed %p %x active=%d busy=%d failed=%d\n",
  20.534 +                    SCpnt, SCpnt->result,
  20.535 +                    atomic_read(&SCpnt->host->host_active),
  20.536 +                    SCpnt->host->host_busy,
  20.537 +                    SCpnt->host->host_failed));
  20.538 +                
  20.539 +                /*
  20.540 +                 * Dump the sense information too.
  20.541 +                 */
  20.542 +                if ((status_byte(SCpnt->result) & CHECK_CONDITION) != 0) {
  20.543 +                    SCSI_LOG_MLCOMPLETE(3, print_sense("bh", SCpnt));
  20.544 +                }
  20.545 +                if (SCpnt->host->eh_wait != NULL) {
  20.546 +                    SCpnt->host->host_failed++;
  20.547 +                    SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
  20.548 +                    SCpnt->state = SCSI_STATE_FAILED;
  20.549 +                    SCpnt->host->in_recovery = 1;
  20.550 +                    /*
  20.551 +                     * If the host is having troubles, then look to
  20.552 +                     * see if this was the last command that might
  20.553 +                     * have failed.  If so, wake up the error handler.  */
  20.554 +                    if (SCpnt->host->host_busy == SCpnt->host->host_failed) {
  20.555 +                        SCSI_LOG_ERROR_RECOVERY(5, printk(
  20.556 +                            "Waking error handler thread (%d)\n",
  20.557 +                            atomic_read(&SCpnt->host->eh_wait->count)));
  20.558 +#if 0
  20.559 +                        up(SCpnt->host->eh_wait);
  20.560 +#endif
  20.561 +                    }
  20.562 +                } else {
  20.563 +                    /*
  20.564 +                     * We only get here if the error recovery thread has died.
  20.565 +                     */
  20.566 +                    printk("scsi_bh: error finish\n"); 
  20.567 +                    scsi_finish_command(SCpnt);
  20.568 +                }
  20.569 +            }
  20.570 +        }		/* for(; SCpnt...) */
  20.571 +        
  20.572 +    }			/* while(1==1) */
  20.573 +    
  20.574  }
  20.575  
  20.576  /*
  20.577 @@ -1356,68 +1441,77 @@ int scsi_retry_command(Scsi_Cmnd * SCpnt
  20.578   */
  20.579  void scsi_finish_command(Scsi_Cmnd * SCpnt)
  20.580  {
  20.581 -	struct Scsi_Host *host;
  20.582 -	Scsi_Device *device;
  20.583 -	Scsi_Request * SRpnt;
  20.584 -	unsigned long flags;
  20.585 -
  20.586 -	ASSERT_LOCK(&io_request_lock, 0);
  20.587 -
  20.588 -	host = SCpnt->host;
  20.589 -	device = SCpnt->device;
  20.590 +    struct Scsi_Host *host;
  20.591 +    Scsi_Device *device;
  20.592 +    Scsi_Request * SRpnt;
  20.593 +    unsigned long flags;
  20.594  
  20.595 -        /*
  20.596 -         * We need to protect the decrement, as otherwise a race condition
  20.597 -         * would exist.  Fiddling with SCpnt isn't a problem as the
  20.598 -         * design only allows a single SCpnt to be active in only
  20.599 -         * one execution context, but the device and host structures are
  20.600 -         * shared.
  20.601 -         */
  20.602 -	spin_lock_irqsave(&io_request_lock, flags);
  20.603 -	host->host_busy--;	/* Indicate that we are free */
  20.604 -	device->device_busy--;	/* Decrement device usage counter. */
  20.605 -	spin_unlock_irqrestore(&io_request_lock, flags);
  20.606 +    ASSERT_LOCK(&io_request_lock, 0);
  20.607  
  20.608 -        /*
  20.609 -         * Clear the flags which say that the device/host is no longer
  20.610 -         * capable of accepting new commands.  These are set in scsi_queue.c
  20.611 -         * for both the queue full condition on a device, and for a
  20.612 -         * host full condition on the host.
  20.613 -         */
  20.614 -        host->host_blocked = FALSE;
  20.615 -        device->device_blocked = FALSE;
  20.616 +    host = SCpnt->host;
  20.617 +    device = SCpnt->device;
  20.618  
  20.619 -	/*
  20.620 -	 * If we have valid sense information, then some kind of recovery
  20.621 -	 * must have taken place.  Make a note of this.
  20.622 -	 */
  20.623 -	if (scsi_sense_valid(SCpnt)) {
  20.624 -		SCpnt->result |= (DRIVER_SENSE << 24);
  20.625 -	}
  20.626 -	SCSI_LOG_MLCOMPLETE(3, printk("Notifying upper driver of completion for device %d %x\n",
  20.627 -				      SCpnt->device->id, SCpnt->result));
  20.628 -
  20.629 -	SCpnt->owner = SCSI_OWNER_HIGHLEVEL;
  20.630 -	SCpnt->state = SCSI_STATE_FINISHED;
  20.631 -
  20.632 -	/* We can get here with use_sg=0, causing a panic in the upper level (DB) */
  20.633 -	SCpnt->use_sg = SCpnt->old_use_sg;
  20.634 +    /*
  20.635 +     * We need to protect the decrement, as otherwise a race condition
  20.636 +     * would exist.  Fiddling with SCpnt isn't a problem as the
  20.637 +     * design only allows a single SCpnt to be active in only
  20.638 +     * one execution context, but the device and host structures are
  20.639 +     * shared.
  20.640 +     */
  20.641 +    spin_lock_irqsave(&io_request_lock, flags);
  20.642 +    host->host_busy--;	/* Indicate that we are free */
  20.643 +    device->device_busy--;	/* Decrement device usage counter. */
  20.644 +    spin_unlock_irqrestore(&io_request_lock, flags);
  20.645 +    
  20.646 +    /*
  20.647 +     * Clear the flags which say that the device/host is no longer
  20.648 +     * capable of accepting new commands.  These are set in scsi_queue.c
  20.649 +     * for both the queue full condition on a device, and for a
  20.650 +     * host full condition on the host.
  20.651 +     */
  20.652 +    host->host_blocked = FALSE;
  20.653 +    device->device_blocked = FALSE;
  20.654 +    
  20.655 +    /*
  20.656 +     * If we have valid sense information, then some kind of recovery
  20.657 +     * must have taken place.  Make a note of this.
  20.658 +     */
  20.659 +    if (scsi_sense_valid(SCpnt)) {
  20.660 +        SCpnt->result |= (DRIVER_SENSE << 24);
  20.661 +    }
  20.662 +    SCSI_LOG_MLCOMPLETE(3, printk(
  20.663 +        "Notifying upper driver of completion for device %d %x\n",
  20.664 +        SCpnt->device->id, SCpnt->result));
  20.665  
  20.666 -       /*
  20.667 -	* If there is an associated request structure, copy the data over before we call the
  20.668 -	* completion function.
  20.669 -	*/
  20.670 -	SRpnt = SCpnt->sc_request;
  20.671 -	if( SRpnt != NULL ) {
  20.672 -	       SRpnt->sr_result = SRpnt->sr_command->result;
  20.673 -	       if( SRpnt->sr_result != 0 ) {
  20.674 -		       memcpy(SRpnt->sr_sense_buffer,
  20.675 -			      SRpnt->sr_command->sense_buffer,
  20.676 -			      sizeof(SRpnt->sr_sense_buffer));
  20.677 -	       }
  20.678 -	}
  20.679 +    SCpnt->owner = SCSI_OWNER_HIGHLEVEL;
  20.680 +    SCpnt->state = SCSI_STATE_FINISHED;
  20.681 +    
  20.682 +    /* We can get here with use_sg=0, causing a panic in the 
  20.683 +       upper level (DB) */
  20.684 +    SCpnt->use_sg = SCpnt->old_use_sg;
  20.685 +
  20.686 +    /*
  20.687 +     * If there is an associated request structure, copy the data over 
  20.688 +     * before we call the * completion function.
  20.689 +     */
  20.690 +    SRpnt = SCpnt->sc_request;
  20.691  
  20.692 -	SCpnt->done(SCpnt);
  20.693 +    if( SRpnt != NULL ) {
  20.694 +        if(!SRpnt->sr_command) { 
  20.695 +            printk("scsi_finish_command: SRpnt=%p, SRpnt->sr_command=%p\n", 
  20.696 +                   SRpnt, SRpnt->sr_command); 
  20.697 +            printk("SRpnt->freeaddr = %p\n", SRpnt->freeaddr); 
  20.698 +            BUG(); 
  20.699 +        }
  20.700 +        SRpnt->sr_result = SRpnt->sr_command->result;
  20.701 +        if( SRpnt->sr_result != 0 ) {
  20.702 +            memcpy(SRpnt->sr_sense_buffer,
  20.703 +                   SRpnt->sr_command->sense_buffer,
  20.704 +                   sizeof(SRpnt->sr_sense_buffer));
  20.705 +        }
  20.706 +    }
  20.707 +
  20.708 +    SCpnt->done(SCpnt);
  20.709  }
  20.710  
  20.711  static int scsi_register_host(Scsi_Host_Template *);
  20.712 @@ -1826,7 +1920,9 @@ static int proc_scsi_gen_write(struct fi
  20.713  			 */
  20.714                          if (HBA_ptr->hostt->revoke)
  20.715                                  HBA_ptr->hostt->revoke(scd);
  20.716 +#ifdef DEVFS_MUST_DIE
  20.717  			devfs_unregister (scd->de);
  20.718 +#endif
  20.719  			scsi_release_commandblocks(scd);
  20.720  
  20.721  			/* Now we can remove the device structure */
  20.722 @@ -1859,164 +1955,168 @@ out:
  20.723   */
  20.724  static int scsi_register_host(Scsi_Host_Template * tpnt)
  20.725  {
  20.726 -	int pcount;
  20.727 -	struct Scsi_Host *shpnt;
  20.728 -	Scsi_Device *SDpnt;
  20.729 -	struct Scsi_Device_Template *sdtpnt;
  20.730 -	const char *name;
  20.731 -	unsigned long flags;
  20.732 -	int out_of_space = 0;
  20.733 +    int pcount;
  20.734 +    struct Scsi_Host *shpnt;
  20.735 +    Scsi_Device *SDpnt;
  20.736 +    struct Scsi_Device_Template *sdtpnt;
  20.737 +    const char *name;
  20.738 +    unsigned long flags;
  20.739 +    int out_of_space = 0;
  20.740  
  20.741 -	if (tpnt->next || !tpnt->detect)
  20.742 -		return 1;	/* Must be already loaded, or
  20.743 -				 * no detect routine available
  20.744 -				 */
  20.745 +    if (tpnt->next || !tpnt->detect)
  20.746 +        return 1;	/* Must be already loaded, or
  20.747 +                         * no detect routine available
  20.748 +                         */
  20.749  
  20.750 -	/* If max_sectors isn't set, default to max */
  20.751 -	if (!tpnt->max_sectors)
  20.752 -		tpnt->max_sectors = MAX_SECTORS;
  20.753 +    /* If max_sectors isn't set, default to max */
  20.754 +    if (!tpnt->max_sectors)
  20.755 +        tpnt->max_sectors = MAX_SECTORS;
  20.756  
  20.757 -	pcount = next_scsi_host;
  20.758 +    pcount = next_scsi_host;
  20.759  
  20.760 -	MOD_INC_USE_COUNT;
  20.761 +    MOD_INC_USE_COUNT;
  20.762  
  20.763 -	/* The detect routine must carefully spinunlock/spinlock if 
  20.764 -	   it enables interrupts, since all interrupt handlers do 
  20.765 -	   spinlock as well.
  20.766 -	   All lame drivers are going to fail due to the following 
  20.767 -	   spinlock. For the time beeing let's use it only for drivers 
  20.768 -	   using the new scsi code. NOTE: the detect routine could
  20.769 -	   redefine the value tpnt->use_new_eh_code. (DB, 13 May 1998) */
  20.770 +    /* The detect routine must carefully spinunlock/spinlock if 
  20.771 +       it enables interrupts, since all interrupt handlers do 
  20.772 +       spinlock as well.
  20.773 +       All lame drivers are going to fail due to the following 
  20.774 +       spinlock. For the time beeing let's use it only for drivers 
  20.775 +       using the new scsi code. NOTE: the detect routine could
  20.776 +       redefine the value tpnt->use_new_eh_code. (DB, 13 May 1998) */
  20.777  
  20.778 -	if (tpnt->use_new_eh_code) {
  20.779 -		spin_lock_irqsave(&io_request_lock, flags);
  20.780 -		tpnt->present = tpnt->detect(tpnt);
  20.781 -		spin_unlock_irqrestore(&io_request_lock, flags);
  20.782 -	} else
  20.783 -		tpnt->present = tpnt->detect(tpnt);
  20.784 +    if (tpnt->use_new_eh_code) {
  20.785 +        spin_lock_irqsave(&io_request_lock, flags);
  20.786 +        tpnt->present = tpnt->detect(tpnt);
  20.787 +        spin_unlock_irqrestore(&io_request_lock, flags);
  20.788 +    } else
  20.789 +        tpnt->present = tpnt->detect(tpnt);
  20.790  
  20.791 -	if (tpnt->present) {
  20.792 -		if (pcount == next_scsi_host) {
  20.793 -			if (tpnt->present > 1) {
  20.794 -				printk(KERN_ERR "scsi: Failure to register low-level scsi driver");
  20.795 -				scsi_unregister_host(tpnt);
  20.796 -				return 1;
  20.797 -			}
  20.798 -			/* 
  20.799 -			 * The low-level driver failed to register a driver.
  20.800 -			 * We can do this now.
  20.801 -			 */
  20.802 -			if(scsi_register(tpnt, 0)==NULL)
  20.803 -			{
  20.804 -				printk(KERN_ERR "scsi: register failed.\n");
  20.805 -				scsi_unregister_host(tpnt);
  20.806 -				return 1;
  20.807 -			}
  20.808 -		}
  20.809 -		tpnt->next = scsi_hosts;	/* Add to the linked list */
  20.810 -		scsi_hosts = tpnt;
  20.811 +    if (tpnt->present) {
  20.812 +        if (pcount == next_scsi_host) {
  20.813 +            if (tpnt->present > 1) {
  20.814 +                printk(KERN_ERR "scsi: Failure to register low-level "
  20.815 +                       "scsi driver");
  20.816 +                scsi_unregister_host(tpnt);
  20.817 +                return 1;
  20.818 +            }
  20.819 +            /* 
  20.820 +             * The low-level driver failed to register a driver.
  20.821 +             * We can do this now.
  20.822 +             */
  20.823 +            if(scsi_register(tpnt, 0)==NULL)
  20.824 +            {
  20.825 +                printk(KERN_ERR "scsi: register failed.\n");
  20.826 +                scsi_unregister_host(tpnt);
  20.827 +                return 1;
  20.828 +            }
  20.829 +        }
  20.830 +        tpnt->next = scsi_hosts;	/* Add to the linked list */
  20.831 +        scsi_hosts = tpnt;
  20.832  
  20.833 -		/* Add the new driver to /proc/scsi */
  20.834 +        /* Add the new driver to /proc/scsi */
  20.835  #ifdef CONFIG_PROC_FS
  20.836 -		build_proc_dir_entries(tpnt);
  20.837 +        build_proc_dir_entries(tpnt);
  20.838  #endif
  20.839  
  20.840  
  20.841 -		/*
  20.842 -		 * Add the kernel threads for each host adapter that will
  20.843 -		 * handle error correction.
  20.844 -		 */
  20.845 -		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  20.846 -			if (shpnt->hostt == tpnt && shpnt->hostt->use_new_eh_code) {
  20.847 -				DECLARE_MUTEX_LOCKED(sem);
  20.848 +#if 0
  20.849 +        /*
  20.850 +         * Add the kernel threads for each host adapter that will
  20.851 +         * handle error correction.
  20.852 +         */
  20.853 +        for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  20.854 +            if (shpnt->hostt == tpnt && shpnt->hostt->use_new_eh_code) {
  20.855 +                DECLARE_MUTEX_LOCKED(sem);
  20.856  
  20.857 -				shpnt->eh_notify = &sem;
  20.858 -				kernel_thread((int (*)(void *)) scsi_error_handler,
  20.859 -					      (void *) shpnt, 0);
  20.860 +                shpnt->eh_notify = &sem;
  20.861 +                kernel_thread((int (*)(void *)) scsi_error_handler,
  20.862 +                              (void *) shpnt, 0);
  20.863  
  20.864  				/*
  20.865  				 * Now wait for the kernel error thread to initialize itself
  20.866  				 * as it might be needed when we scan the bus.
  20.867  				 */
  20.868 -				down(&sem);
  20.869 -				shpnt->eh_notify = NULL;
  20.870 -			}
  20.871 -		}
  20.872 +                down(&sem);
  20.873 +                shpnt->eh_notify = NULL;
  20.874 +            }
  20.875 +        }
  20.876 +#endif
  20.877  
  20.878 -		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  20.879 -			if (shpnt->hostt == tpnt) {
  20.880 -				if (tpnt->info) {
  20.881 -					name = tpnt->info(shpnt);
  20.882 -				} else {
  20.883 -					name = tpnt->name;
  20.884 -				}
  20.885 -				printk(KERN_INFO "scsi%d : %s\n",		/* And print a little message */
  20.886 -				       shpnt->host_no, name);
  20.887 -			}
  20.888 -		}
  20.889 +        for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  20.890 +            if (shpnt->hostt == tpnt) {
  20.891 +                if (tpnt->info) {
  20.892 +                    name = tpnt->info(shpnt);
  20.893 +                } else {
  20.894 +                    name = tpnt->name;
  20.895 +                }
  20.896 +                printk(KERN_INFO "scsi%d : %s\n",		/* And print a little message */
  20.897 +                       shpnt->host_no, name);
  20.898 +            }
  20.899 +        }
  20.900  
  20.901 -		/* The next step is to call scan_scsis here.  This generates the
  20.902 -		 * Scsi_Devices entries
  20.903 -		 */
  20.904 -		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  20.905 -			if (shpnt->hostt == tpnt) {
  20.906 -				scan_scsis(shpnt, 0, 0, 0, 0);
  20.907 -				if (shpnt->select_queue_depths != NULL) {
  20.908 -					(shpnt->select_queue_depths) (shpnt, shpnt->host_queue);
  20.909 -				}
  20.910 -			}
  20.911 -		}
  20.912 +        /* The next step is to call scan_scsis here.  This generates the
  20.913 +         * Scsi_Devices entries
  20.914 +         */
  20.915 +        for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  20.916 +            if (shpnt->hostt == tpnt) {
  20.917 +                scan_scsis(shpnt, 0, 0, 0, 0);
  20.918 +                if (shpnt->select_queue_depths != NULL) {
  20.919 +                    (shpnt->select_queue_depths) (shpnt, shpnt->host_queue);
  20.920 +                }
  20.921 +            }
  20.922 +        }
  20.923  
  20.924 -		for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
  20.925 -			if (sdtpnt->init && sdtpnt->dev_noticed)
  20.926 -				(*sdtpnt->init) ();
  20.927 -		}
  20.928 +        for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
  20.929 +            if (sdtpnt->init && sdtpnt->dev_noticed)
  20.930 +                (*sdtpnt->init) ();
  20.931 +        }
  20.932  
  20.933 -		/*
  20.934 -		 * Next we create the Scsi_Cmnd structures for this host 
  20.935 -		 */
  20.936 -		for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  20.937 -			for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next)
  20.938 -				if (SDpnt->host->hostt == tpnt) {
  20.939 -					for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
  20.940 -						if (sdtpnt->attach)
  20.941 -							(*sdtpnt->attach) (SDpnt);
  20.942 -					if (SDpnt->attached) {
  20.943 -						scsi_build_commandblocks(SDpnt);
  20.944 -						if (0 == SDpnt->has_cmdblocks)
  20.945 -							out_of_space = 1;
  20.946 -					}
  20.947 -				}
  20.948 -		}
  20.949 +        /*
  20.950 +         * Next we create the Scsi_Cmnd structures for this host 
  20.951 +         */
  20.952 +        for (shpnt = scsi_hostlist; shpnt; shpnt = shpnt->next) {
  20.953 +            for (SDpnt = shpnt->host_queue; SDpnt; SDpnt = SDpnt->next)
  20.954 +                if (SDpnt->host->hostt == tpnt) {
  20.955 +                    for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next)
  20.956 +                        if (sdtpnt->attach)
  20.957 +                            (*sdtpnt->attach) (SDpnt);
  20.958 +                    if (SDpnt->attached) {
  20.959 +                        scsi_build_commandblocks(SDpnt);
  20.960 +                        if (0 == SDpnt->has_cmdblocks)
  20.961 +                            out_of_space = 1;
  20.962 +                    }
  20.963 +                }
  20.964 +        }
  20.965  
  20.966 -		/*
  20.967 -		 * Now that we have all of the devices, resize the DMA pool,
  20.968 -		 * as required.  */
  20.969 -		if (!out_of_space)
  20.970 -			scsi_resize_dma_pool();
  20.971 +        /*
  20.972 +         * Now that we have all of the devices, resize the DMA pool,
  20.973 +         * as required.  */
  20.974 +        if (!out_of_space)
  20.975 +            scsi_resize_dma_pool();
  20.976  
  20.977  
  20.978 -		/* This does any final handling that is required. */
  20.979 -		for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
  20.980 -			if (sdtpnt->finish && sdtpnt->nr_dev) {
  20.981 -				(*sdtpnt->finish) ();
  20.982 -			}
  20.983 -		}
  20.984 -	}
  20.985 +        /* This does any final handling that is required. */
  20.986 +        for (sdtpnt = scsi_devicelist; sdtpnt; sdtpnt = sdtpnt->next) {
  20.987 +            if (sdtpnt->finish && sdtpnt->nr_dev) {
  20.988 +                (*sdtpnt->finish) ();
  20.989 +            }
  20.990 +        }
  20.991 +    }
  20.992  #if defined(USE_STATIC_SCSI_MEMORY)
  20.993 -	printk("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n",
  20.994 -	       (scsi_memory_upper_value - scsi_memory_lower_value) / 1024,
  20.995 -	       (scsi_init_memory_start - scsi_memory_lower_value) / 1024,
  20.996 -	       (scsi_memory_upper_value - scsi_init_memory_start) / 1024);
  20.997 +    printk("SCSI memory: total %ldKb, used %ldKb, free %ldKb.\n",
  20.998 +           (scsi_memory_upper_value - scsi_memory_lower_value) / 1024,
  20.999 +           (scsi_init_memory_start - scsi_memory_lower_value) / 1024,
 20.1000 +           (scsi_memory_upper_value - scsi_init_memory_start) / 1024);
 20.1001  #endif
 20.1002  
 20.1003 -	if (out_of_space) {
 20.1004 -		scsi_unregister_host(tpnt);	/* easiest way to clean up?? */
 20.1005 -		return 1;
 20.1006 -	} else
 20.1007 -		return 0;
 20.1008 +    if (out_of_space) {
 20.1009 +        scsi_unregister_host(tpnt);	/* easiest way to clean up?? */
 20.1010 +        return 1;
 20.1011 +    } else
 20.1012 +        return 0;
 20.1013  }
 20.1014  
 20.1015 +
 20.1016  /*
 20.1017   * Similarly, this entry point should be called by a loadable module if it
 20.1018   * is trying to remove a low level scsi driver from the system.
 20.1019 @@ -2033,8 +2133,10 @@ static int scsi_unregister_host(Scsi_Hos
 20.1020  	struct Scsi_Host *shpnt;
 20.1021  	char name[10];	/* host_no>=10^9? I don't think so. */
 20.1022  
 20.1023 +#if 0
 20.1024  	/* get the big kernel lock, so we don't race with open() */
 20.1025  	lock_kernel();
 20.1026 +#endif
 20.1027  
 20.1028  	/*
 20.1029  	 * First verify that this host adapter is completely free with no pending
 20.1030 @@ -2126,10 +2228,13 @@ static int scsi_unregister_host(Scsi_Hos
 20.1031  				printk(KERN_ERR "Attached usage count = %d\n", SDpnt->attached);
 20.1032  				goto err_out;
 20.1033  			}
 20.1034 +#ifdef DEVFS_MUST_DIE
 20.1035  			devfs_unregister (SDpnt->de);
 20.1036 +#endif
 20.1037  		}
 20.1038  	}
 20.1039  
 20.1040 +#if 0
 20.1041  	/*
 20.1042  	 * Next, kill the kernel error recovery thread for this host.
 20.1043  	 */
 20.1044 @@ -2145,6 +2250,7 @@ static int scsi_unregister_host(Scsi_Hos
 20.1045  			shpnt->eh_notify = NULL;
 20.1046  		}
 20.1047  	}
 20.1048 +#endif
 20.1049  
 20.1050  	/* Next we free up the Scsi_Cmnd structures for this host */
 20.1051  
 20.1052 @@ -2175,7 +2281,9 @@ static int scsi_unregister_host(Scsi_Hos
 20.1053  		pcount = next_scsi_host;
 20.1054  		/* Remove the /proc/scsi directory entry */
 20.1055  		sprintf(name,"%d",shpnt->host_no);
 20.1056 +#ifdef CONFIG_PROC_FS
 20.1057  		remove_proc_entry(name, tpnt->proc_dir);
 20.1058 +#endif
 20.1059  		if (tpnt->release)
 20.1060  			(*tpnt->release) (shpnt);
 20.1061  		else {
 20.1062 @@ -2185,8 +2293,11 @@ static int scsi_unregister_host(Scsi_Hos
 20.1063  			 */
 20.1064  			if (shpnt->irq)
 20.1065  				free_irq(shpnt->irq, NULL);
 20.1066 +
 20.1067 +#if 0
 20.1068  			if (shpnt->dma_channel != 0xff)
 20.1069  				free_dma(shpnt->dma_channel);
 20.1070 +#endif
 20.1071  			if (shpnt->io_port && shpnt->n_io_port)
 20.1072  				release_region(shpnt->io_port, shpnt->n_io_port);
 20.1073  		}
 20.1074 @@ -2225,7 +2336,9 @@ static int scsi_unregister_host(Scsi_Hos
 20.1075  		while ((SHT = *SHTp) != NULL) {
 20.1076  			if (SHT == tpnt) {
 20.1077  				*SHTp = SHT->next;
 20.1078 +#ifdef CONFIG_PROC_FS
 20.1079  				remove_proc_entry(tpnt->proc_name, proc_scsi);
 20.1080 +#endif
 20.1081  				break;
 20.1082  			}
 20.1083  			SHTp = &SHT->next;
 20.1084 @@ -2233,11 +2346,16 @@ static int scsi_unregister_host(Scsi_Hos
 20.1085  	}
 20.1086  	MOD_DEC_USE_COUNT;
 20.1087  
 20.1088 +#if 0
 20.1089  	unlock_kernel();
 20.1090 +#endif
 20.1091  	return 0;
 20.1092  
 20.1093  err_out:
 20.1094 +
 20.1095 +#if 0
 20.1096  	unlock_kernel();
 20.1097 +#endif
 20.1098  	return -1;
 20.1099  }
 20.1100  
 20.1101 @@ -2331,7 +2449,9 @@ static int scsi_unregister_device(struct
 20.1102  	Scsi_Device *SDpnt;
 20.1103  	struct Scsi_Host *shpnt;
 20.1104  
 20.1105 +#if 0
 20.1106  	lock_kernel();
 20.1107 +#endif
 20.1108  	/*
 20.1109  	 * If we are busy, this is not going to fly.
 20.1110  	 */
 20.1111 @@ -2364,14 +2484,19 @@ static int scsi_unregister_device(struct
 20.1112  	scsi_deregister_device(tpnt);
 20.1113  
 20.1114  	MOD_DEC_USE_COUNT;
 20.1115 +#if 0
 20.1116  	unlock_kernel();
 20.1117 +#endif
 20.1118 +
 20.1119  	/*
 20.1120  	 * Final cleanup for the driver is done in the driver sources in the
 20.1121  	 * cleanup function.
 20.1122  	 */
 20.1123  	return 0;
 20.1124  error_out:
 20.1125 +#if 0
 20.1126  	unlock_kernel();
 20.1127 +#endif
 20.1128  	return -1;
 20.1129  }
 20.1130  
 20.1131 @@ -2571,21 +2696,33 @@ int __init scsi_setup(char *str)
 20.1132  __setup("scsihosts=", scsi_setup);
 20.1133  #endif
 20.1134  
 20.1135 +static spinlock_t slock2 = SPIN_LOCK_UNLOCKED; 
 20.1136 +
 20.1137  static int __init init_scsi(void)
 20.1138  {
 20.1139 +#ifdef CONFIG_PROC_FS
 20.1140  	struct proc_dir_entry *generic;
 20.1141 +#endif
 20.1142  
 20.1143  	printk(KERN_INFO "SCSI subsystem driver " REVISION "\n");
 20.1144  
 20.1145 +        {
 20.1146 +            unsigned long flags; 
 20.1147 +            
 20.1148 +            spin_lock_irqsave(&slock2, flags); 
 20.1149 +            spin_unlock_irqrestore(&slock2, flags); 
 20.1150 +            printk("SCSI start of day -- flags = %lx\n", flags); 
 20.1151 +        }
 20.1152 +
 20.1153          if( scsi_init_minimal_dma_pool() != 0 )
 20.1154          {
 20.1155                  return 1;
 20.1156          }
 20.1157  
 20.1158 +#ifdef CONFIG_PROC_FS
 20.1159  	/*
 20.1160  	 * This makes /proc/scsi and /proc/scsi/scsi visible.
 20.1161  	 */
 20.1162 -#ifdef CONFIG_PROC_FS
 20.1163  	proc_scsi = proc_mkdir("scsi", 0);
 20.1164  	if (!proc_scsi) {
 20.1165  		printk (KERN_ERR "cannot init /proc/scsi\n");
 20.1166 @@ -2600,7 +2737,9 @@ static int __init init_scsi(void)
 20.1167  	generic->write_proc = proc_scsi_gen_write;
 20.1168  #endif
 20.1169  
 20.1170 +#ifdef DEVFS_MUST_DIE
 20.1171          scsi_devfs_handle = devfs_mk_dir (NULL, "scsi", NULL);
 20.1172 +#endif
 20.1173          if (scsihosts)
 20.1174  		printk(KERN_INFO "scsi: host order: %s\n", scsihosts);	
 20.1175  	scsi_host_no_init (scsihosts);
 20.1176 @@ -2610,6 +2749,15 @@ static int __init init_scsi(void)
 20.1177  	 */
 20.1178  	init_bh(SCSI_BH, scsi_bottom_half_handler);
 20.1179  
 20.1180 +        {
 20.1181 +            unsigned long flags; 
 20.1182 +            
 20.1183 +            spin_lock_irqsave(&slock2, flags); 
 20.1184 +            spin_unlock_irqrestore(&slock2, flags); 
 20.1185 +            printk("SCSI end of day -- flags = %lx\n", flags); 
 20.1186 +        }
 20.1187 +
 20.1188 +
 20.1189  	return 0;
 20.1190  }
 20.1191  
 20.1192 @@ -2619,7 +2767,9 @@ static void __exit exit_scsi(void)
 20.1193  
 20.1194  	remove_bh(SCSI_BH);
 20.1195  
 20.1196 +#ifdef DEVFS_MUST_DIE
 20.1197          devfs_unregister (scsi_devfs_handle);
 20.1198 +#endif
 20.1199          for (shn = scsi_host_no_list;shn;shn = shn->next) {
 20.1200  		if (shn->name)
 20.1201  			kfree(shn->name);
 20.1202 @@ -2692,10 +2842,12 @@ Scsi_Device * scsi_get_host_dev(struct S
 20.1203  
 20.1204  	SDpnt->online = TRUE;
 20.1205  
 20.1206 +#if 0
 20.1207          /*
 20.1208           * Initialize the object that we will use to wait for command blocks.
 20.1209           */
 20.1210  	init_waitqueue_head(&SDpnt->scpnt_wait);
 20.1211 +#endif
 20.1212          return SDpnt;
 20.1213  }
 20.1214  
 20.1215 @@ -2814,11 +2966,13 @@ scsi_reset_provider(Scsi_Device *dev, in
 20.1216  	if (dev->host->hostt->use_new_eh_code) {
 20.1217  		rtn = scsi_new_reset(SCpnt, flag);
 20.1218  	} else {
 20.1219 +#if 0
 20.1220  		unsigned long flags;
 20.1221  
 20.1222  		spin_lock_irqsave(&io_request_lock, flags);
 20.1223  		rtn = scsi_old_reset(SCpnt, flag);
 20.1224  		spin_unlock_irqrestore(&io_request_lock, flags);
 20.1225 +#endif
 20.1226  	}
 20.1227  
 20.1228  	scsi_delete_timer(SCpnt);
    21.1 --- a/xen-2.4.16/drivers/scsi/scsi.h	Fri Feb 21 14:25:47 2003 +0000
    21.2 +++ b/xen-2.4.16/drivers/scsi/scsi.h	Fri Feb 21 15:10:37 2003 +0000
    21.3 @@ -558,8 +558,11 @@ struct scsi_device {
    21.4  	 */
    21.5  	struct scsi_device *next;	/* Used for linked list */
    21.6  	struct scsi_device *prev;	/* Used for linked list */
    21.7 +#if 0
    21.8  	wait_queue_head_t   scpnt_wait;	/* Used to wait if
    21.9  					   device is busy */
   21.10 +#endif
   21.11 +
   21.12  	struct Scsi_Host *host;
   21.13  	request_queue_t request_queue;
   21.14          atomic_t                device_active; /* commands checked out for device */
   21.15 @@ -580,7 +583,9 @@ struct scsi_device {
   21.16  	int access_count;	/* Count of open channels/mounts */
   21.17  
   21.18  	void *hostdata;		/* available to low-level driver */
   21.19 +#if 0
   21.20  	devfs_handle_t de;      /* directory for the device      */
   21.21 +#endif
   21.22  	char type;
   21.23  	char scsi_level;
   21.24  	char vendor[8], model[16], rev[4];
   21.25 @@ -650,29 +655,32 @@ typedef struct scsi_pointer {
   21.26   * of the queue and being sent to the driver.
   21.27   */
   21.28  struct scsi_request {
   21.29 -	int     sr_magic;
   21.30 -	int     sr_result;	/* Status code from lower level driver */
   21.31 -	unsigned char sr_sense_buffer[SCSI_SENSE_BUFFERSIZE];		/* obtained by REQUEST SENSE
   21.32 -						 * when CHECK CONDITION is
   21.33 -						 * received on original command 
   21.34 -						 * (auto-sense) */
   21.35 -
   21.36 -	struct Scsi_Host *sr_host;
   21.37 -	Scsi_Device *sr_device;
   21.38 -	Scsi_Cmnd *sr_command;
   21.39 -	struct request sr_request;	/* A copy of the command we are
   21.40 +    int     sr_magic;
   21.41 +    int     sr_result;	/* Status code from lower level driver */
   21.42 +    unsigned char sr_sense_buffer[SCSI_SENSE_BUFFERSIZE]; 
   21.43 +    /* obtained by REQUEST SENSE when CHECK CONDITION is received 
   21.44 +       on original command (auto-sense) */
   21.45 +    
   21.46 +    struct Scsi_Host *sr_host;
   21.47 +    Scsi_Device *sr_device;
   21.48 +    Scsi_Cmnd *sr_command;
   21.49 +#define SMHHACK
   21.50 +#ifdef SMHHACK 
   21.51 +    void *freeaddr; 
   21.52 +#endif
   21.53 +    struct request sr_request;	/* A copy of the command we are
   21.54  				   working on */
   21.55 -	unsigned sr_bufflen;	/* Size of data buffer */
   21.56 -	void *sr_buffer;		/* Data buffer */
   21.57 -	int sr_allowed;
   21.58 -	unsigned char sr_data_direction;
   21.59 -	unsigned char sr_cmd_len;
   21.60 -	unsigned char sr_cmnd[MAX_COMMAND_SIZE];
   21.61 -	void (*sr_done) (struct scsi_cmnd *);	/* Mid-level done function */
   21.62 -	int sr_timeout_per_command;
   21.63 -	unsigned short sr_use_sg;	/* Number of pieces of scatter-gather */
   21.64 -	unsigned short sr_sglist_len;	/* size of malloc'd scatter-gather list */
   21.65 -	unsigned sr_underflow;	/* Return error if less than
   21.66 +    unsigned sr_bufflen;	/* Size of data buffer */
   21.67 +    void *sr_buffer;		/* Data buffer */
   21.68 +    int sr_allowed;
   21.69 +    unsigned char sr_data_direction;
   21.70 +    unsigned char sr_cmd_len;
   21.71 +    unsigned char sr_cmnd[MAX_COMMAND_SIZE];
   21.72 +    void (*sr_done) (struct scsi_cmnd *);	/* Mid-level done function */
   21.73 +    int sr_timeout_per_command;
   21.74 +    unsigned short sr_use_sg;	/* Number of pieces of scatter-gather */
   21.75 +    unsigned short sr_sglist_len;	/* size of malloc'd scatter-gather list */
   21.76 +    unsigned sr_underflow;	/* Return error if less than
   21.77  				   this amount is transferred */
   21.78  };
   21.79  
   21.80 @@ -830,6 +838,7 @@ struct scsi_cmnd {
   21.81  #define SCSI_MLQUEUE_HOST_BUSY   0x1055
   21.82  #define SCSI_MLQUEUE_DEVICE_BUSY 0x1056
   21.83  
   21.84 +#if 0
   21.85  #define SCSI_SLEEP(QUEUE, CONDITION) {		    \
   21.86      if (CONDITION) {			            \
   21.87  	DECLARE_WAITQUEUE(wait, current);	    \
   21.88 @@ -848,6 +857,12 @@ struct scsi_cmnd {
   21.89  	remove_wait_queue(QUEUE, &wait);\
   21.90  	current->state = TASK_RUNNING;	\
   21.91      }; }
   21.92 +#else
   21.93 +#define SCSI_SLEEP(QUEUE, CONDITION) { printk("SCSI_SLEEP!\n"); BUG(); } 
   21.94 +#endif
   21.95 +
   21.96 +
   21.97 +
   21.98  
   21.99  /*
  21.100   * old style reset request from external source
    22.1 --- a/xen-2.4.16/drivers/scsi/scsi_dma.c	Fri Feb 21 14:25:47 2003 +0000
    22.2 +++ b/xen-2.4.16/drivers/scsi/scsi_dma.c	Fri Feb 21 15:10:37 2003 +0000
    22.3 @@ -6,9 +6,9 @@
    22.4   */
    22.5  
    22.6  #define __NO_VERSION__
    22.7 -#include <linux/config.h>
    22.8 -#include <linux/module.h>
    22.9 -#include <linux/blk.h>
   22.10 +#include <xeno/config.h>
   22.11 +#include <xeno/module.h>
   22.12 +#include <xeno/blk.h>
   22.13  
   22.14  
   22.15  #include "scsi.h"
   22.16 @@ -165,6 +165,7 @@ int scsi_free(void *obj, unsigned int le
   22.17  		}
   22.18  	}
   22.19  	panic("scsi_free:Bad offset");
   22.20 +	return -1; 
   22.21  }
   22.22  
   22.23  
   22.24 @@ -206,7 +207,8 @@ void scsi_resize_dma_pool(void)
   22.25  		 * Free up the DMA pool.
   22.26  		 */
   22.27  		if (scsi_dma_free_sectors != dma_sectors)
   22.28 -			panic("SCSI DMA pool memory leak %d %d\n", scsi_dma_free_sectors, dma_sectors);
   22.29 +			panic("SCSI DMA pool memory leak %d %d\n", 
   22.30 +			      scsi_dma_free_sectors, dma_sectors);
   22.31  
   22.32  		for (i = 0; i < dma_sectors / SECTORS_PER_PAGE; i++)
   22.33  			free_pages((unsigned long) dma_malloc_pages[i], 0);
   22.34 @@ -225,9 +227,11 @@ void scsi_resize_dma_pool(void)
   22.35  
   22.36  	new_dma_sectors = 2 * SECTORS_PER_PAGE;		/* Base value we use */
   22.37  
   22.38 +#if 0 
   22.39  	if (__pa(high_memory) - 1 > ISA_DMA_THRESHOLD)
   22.40  		need_isa_bounce_buffers = 1;
   22.41  	else
   22.42 +#endif
   22.43  		need_isa_bounce_buffers = 0;
   22.44  
   22.45  	if (scsi_devicelist)
    23.1 --- a/xen-2.4.16/drivers/scsi/scsi_error.c	Fri Feb 21 14:25:47 2003 +0000
    23.2 +++ b/xen-2.4.16/drivers/scsi/scsi_error.c	Fri Feb 21 15:10:37 2003 +0000
    23.3 @@ -9,23 +9,23 @@
    23.4   */
    23.5  
    23.6  #define __NO_VERSION__
    23.7 -#include <linux/module.h>
    23.8 +#include <xeno/module.h>
    23.9  
   23.10 -#include <linux/sched.h>
   23.11 -#include <linux/timer.h>
   23.12 -#include <linux/string.h>
   23.13 -#include <linux/slab.h>
   23.14 -#include <linux/ioport.h>
   23.15 -#include <linux/kernel.h>
   23.16 -#include <linux/stat.h>
   23.17 -#include <linux/blk.h>
   23.18 -#include <linux/interrupt.h>
   23.19 -#include <linux/delay.h>
   23.20 -#include <linux/smp_lock.h>
   23.21 +#include <xeno/sched.h>
   23.22 +#include <xeno/timer.h>
   23.23 +/*#include <xeno/string.h>*/
   23.24 +#include <xeno/slab.h>
   23.25 +#include <xeno/ioport.h>
   23.26 +#include <xeno/kernel.h>
   23.27 +/*#include <xeno/stat.h>*/
   23.28 +#include <xeno/blk.h>
   23.29 +#include <xeno/interrupt.h>
   23.30 +#include <xeno/delay.h>
   23.31 +/*#include <xeno/smp_lock.h>*/
   23.32  
   23.33  #define __KERNEL_SYSCALLS__
   23.34  
   23.35 -#include <linux/unistd.h>
   23.36 +/*#include <xeno/unistd.h>*/
   23.37  
   23.38  #include <asm/system.h>
   23.39  #include <asm/irq.h>
   23.40 @@ -226,6 +226,7 @@ void scsi_times_out(Scsi_Cmnd * SCpnt)
   23.41  				   SCpnt->host->host_busy,
   23.42  				   SCpnt->host->host_failed));
   23.43  
   23.44 +#if 0
   23.45  	/*
   23.46  	 * If the host is having troubles, then look to see if this was the last
   23.47  	 * command that might have failed.  If so, wake up the error handler.
   23.48 @@ -237,6 +238,7 @@ void scsi_times_out(Scsi_Cmnd * SCpnt)
   23.49  	if (SCpnt->host->host_busy == SCpnt->host->host_failed) {
   23.50  		up(SCpnt->host->eh_wait);
   23.51  	}
   23.52 +#endif
   23.53  }
   23.54  
   23.55  /*
   23.56 @@ -283,9 +285,11 @@ void scsi_eh_times_out(Scsi_Cmnd * SCpnt
   23.57  	SCpnt->eh_state = SCSI_STATE_TIMEOUT;
   23.58  	SCSI_LOG_ERROR_RECOVERY(5, printk("In scsi_eh_times_out %p\n", SCpnt));
   23.59  
   23.60 +#if 0
   23.61  	if (SCpnt->host->eh_action != NULL)
   23.62  		up(SCpnt->host->eh_action);
   23.63  	else
   23.64 +#endif
   23.65  		printk("Missing scsi error handler thread\n");
   23.66  }
   23.67  
   23.68 @@ -329,8 +333,10 @@ void scsi_eh_done(Scsi_Cmnd * SCpnt)
   23.69  	SCSI_LOG_ERROR_RECOVERY(5, printk("In eh_done %p result:%x\n", SCpnt,
   23.70  					  SCpnt->result));
   23.71  
   23.72 +#if 0
   23.73  	if (SCpnt->host->eh_action != NULL)
   23.74  		up(SCpnt->host->eh_action);
   23.75 +#endif
   23.76  }
   23.77  
   23.78  /*
   23.79 @@ -352,9 +358,10 @@ void scsi_eh_action_done(Scsi_Cmnd * SCp
   23.80  
   23.81  	SCpnt->owner = SCSI_OWNER_ERROR_HANDLER;
   23.82  	SCpnt->eh_state = (answer ? SUCCESS : FAILED);
   23.83 -
   23.84 +#if 0
   23.85  	if (SCpnt->host->eh_action != NULL)
   23.86  		up(SCpnt->host->eh_action);
   23.87 +#endif
   23.88  }
   23.89  
   23.90  /*
   23.91 @@ -548,18 +555,26 @@ STATIC int scsi_test_unit_ready(Scsi_Cmn
   23.92  STATIC
   23.93  void scsi_sleep_done(struct semaphore *sem)
   23.94  {
   23.95 +#if 0
   23.96  	if (sem != NU